summaryrefslogtreecommitdiff
path: root/libdw
Commit message (Collapse)AuthorAgeFilesLines
* libdw: check memory access in get_(u|s)leb128Aleksei Vetrov2023-02-141-2/+8
| | | | | | | | | | __libdw_get_uleb128 and __libdw_get_sleb128 should check if addrp has already reached the end before unrolling the first step. It is done by moving __libdw_max_len to the beginning of the function, which can notice, that addrp is beyond the end. Then we just check the result of this function. Signed-off-by: Aleksei Vetrov <vvvvvv@google.com>
* configure: Add --enable-sanitize-memoryIlya Leoshkevich2023-02-141-1/+2
| | | | | | | | | | | | | | | | | | | | Add support for clang Memory Sanitizer [1], which detects the usage of uninitialized values. While elfutils itself is already checked with valgrind, checking code that depends on elfutils requires elfutils to be built with MSan. MSan is not linked into shared libraries, and is linked into executables statically. Therefore, unlike the other sanitizers, MSan needs to be configured fairly early, since we need to drop -D_FORTIFY_SOURCE [2], -Wl,-z,defs and --no-undefined. Disable a few tests that run for more than 5 minutes due to test files being statically linked with MSan. [1] https://clang.llvm.org/docs/MemorySanitizer.html [2] https://github.com/google/sanitizers/issues/247 Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
* libdw: Search for abstract origin in the correct CUMark Wielaard2023-01-302-8/+16
| | | | | | | | | | | | | | | With gcc -flto the abstract origin of an inlined subroutine could be in a different CU. dwarf_getscopes might return an empty scope if it cannot find the abstract origin scope. So make sure to search in the We also tried to add the origin match in pc_record directly in the current inlined scope. This always failed, causing to do a needless traversal, followed by the full CU scan in dwarf_getscopes. Just always stop the pc_record search and then do the CU origin_match in dwarf_getscopes. Signed-off-by: Mark Wielaard <mark@klomp.org>
* Do not use relative include paths in library files.Mark Wielaard2022-12-205-4/+11
| | | | | | | | | Rely on include dirs being set up correctly. Setup libdw AM_CPPFLAGS to include libebl directory. In libdwfl note that debuginfod.h is a generated file in the builddir. Only include it in the one file debuginfod-client.c that really needs it. Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Change typeof -> __typeof in memory-access.hYonggang Luo2022-12-122-5/+12
| | | | Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
* libdw: Don't dereference and assign values we are skippingMark Wielaard2022-11-032-1/+6
| | | | | | | We don't use the FDE address encoding byte, so no reason to read and store it. Just skip past it. Signed-off-by: Mark Wielaard <mark@klomp.org>
* lib{asm,cpu,dw,dwfl,dwelf}: Move platform depended include into system.hYonggang Luo2022-10-285-6/+7
| | | | Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
* readelf: Handle DW_LLE_GNU_view_pairMark Wielaard2022-10-272-1/+9
| | | | | | | | DW_LLE_GNU_view_pair is used by gcc -gvariable-location-views=incompat5. As described in http://www.fsfla.org/~lxoliva/papers/sfn/dwarf6-sfn-lvu.txt and proposed for DWARF6 https://dwarfstd.org/ShowIssue.php?issue=170427.1 Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Use #include <system.h> instead of <endian.h> in memory-access.hYonggang Luo2022-10-272-2/+6
| | | | Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
* Strip __ prefix from __BYTE_ORDER __LITTLE_ENDIAN and __BIG_ENDIANYonggang Luo2022-10-172-4/+8
| | | | | | | | __BYTE_ORDER, __LITTLE_ENDIAN and __BIG_ENDIAN are defined by the gcc/clang preprocessor. BYTE_ORDER, LITTLE_ENDIAN and BIG_ENDIAN are defined in <endian.h>. Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
* Move the #include <libintl.h> into eu-config.hYonggang Luo2022-10-161-1/+0
| | | | | | | | | | So we do not need include in each file. And indeed the macro #define _(Str) dgettext ("elfutils", Str) access libintl function dgettext, so it's make more sense #include <libintl.h> in file eu-config.h Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
* libdwfl: add dwfl_report_offline_memoryAleksei Vetrov2022-10-162-0/+5
| | | | | | | | | | | | | This method allows to read and report ELF from memory instead of opening a file. That way arbitrary memory can be worked with, e.g. when coming from a stream without the need to persist. Another useful application is for fuzzing, because fuzzers might be able to track accesses to the memory and change the fuzzer input to cover more edge cases through more targeted input. Hence, add a new function along with a test case. Signed-off-by: Aleksei Vetrov <vvvvvv@google.com>
* Fill in fde_augmentation_data_size in dwarf_next_cfiUlrich Drepper2022-08-112-20/+46
| | | | | (dwarf_next_cfi): Don't skip processing the augmentation string. Be more stringent what to accept.
* libdwfl: Add new function dwfl_frame_regDi Chen2022-07-312-0/+5
| | | | | | | | | | | | | | Dwfl has most of the infrastructure to keep the full unwind state, including the state of unwound registers per frame using Dwfl_Thread_Callbacks. But there is no public API to access the state, except for the PC (dwfl_frame_pc). This commit adds a new function dwfl_frame_reg to get the value of the DWARF register number in the given frame. https://sourceware.org/bugzilla/show_bug.cgi?id=28579 Signed-off-by: Di Chen <dichen@redhat.com>
* Move dwfl_get_debuginfod_client to ELFUTILS_0.188Mark Wielaard2022-07-132-1/+6
| | | | | | | 0.187 was already released, so add new function to 0.188. Also add NEWS entry and INTUSE. Signed-off-by: Mark Wielaard <mark@klomp.org>
* Introduce public dwfl_get_debuginfod_client APIMilian Wolff2022-07-131-0/+5
| | | | | | | | | | | | | | | | | Dwfl can use debuginfod internally, which was so far totally opaque to the outside. While the functionality is great for users of the dwfl API, the long wait times induced by downloading of data over debuginfod lead to complaints by endusers. To offer them a bit more insight into the internal ongoings, one can now use e.g. `debuginfod_set_progressfn` on the handle returned by `dwfl_get_debuginfod_client` to report download progress. Rename get_client to dwfl_get_debuginfod_client and make it public. Unconditionally compile debuginfod-client.c and stub the new public function and always return NULL when debuginfod integration was disabled. Signed-off-by: Milian Wolff <mail@milianw.de>
* libdw: Add sanity check to store_implicit_valueMark Wielaard2022-05-142-1/+8
| | | | | | | Don't just skip the block length, but check it is equal to the op->number that we are going to use as length. Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Remove unused atomics.h include from libdwP.hMark Wielaard2022-04-172-1/+4
| | | | Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Add DWARF5 package file section identifiers, DW_SECT_*Mark Wielaard2022-04-132-0/+18
| | | | | | | | | This only adds the constants. There is no handling of DWARF package file (dwp) files for now. https://sourceware.org/bugzilla/show_bug.cgi?id=29048 Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw, readelf: Read inlining info in NVIDIA extended line mapJohn M Mellor-Crummey2021-11-109-2/+173
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As of CUDA 11.2, NVIDIA added extensions to the line map section of CUDA binaries to represent inlined functions. These extensions include - two new fields in a line table row to represent inline information: context, and functionname, - two new DWARF extended opcodes: DW_LNE_NVIDIA_inlined_call, DW_LNE_NVIDIA_set_function_name, - an additional word in the line table header that indicates the offset in the .debug_str function where the function names for this line table begin, and A line table row for an inlined function contains a non-zero "context" value. The “context” field indicates the index of the line table row that serves as the call site for an inlined context. The "functionname" field in a line table row is only meaningful if the "context" field of the row is non-zero. A meaningful "functionname" field contains an index into the .debug_str section relative to the base offset established in the line table header; the position in the .debug_str section indicates the name of the inlined function. These extensions resemble the proposed DWARF extensions (http://dwarfstd.org/ShowIssue.php?issue=140906.1) by Cary Coutant, but are not identical. This commit integrates support for handling NVIDIA's extended line maps into elfutil's libdw library, by adding two functions dwarf_linecontext and dwarf_linefunctionname, and the readelf --debug-dump=line command line utility. Signed-off-by: John M Mellor-Crummey <johnmc@rice.edu> Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: dwarf_elf_begin should use either plain, dwo or lto DWARF sections.Mark Wielaard2021-11-093-5/+99
| | | | | | | | | | | When opening an ELF file that contained a mix of plain, dwo or lto .debug sections the result could be confusing. Add a check to pick just the plain .debug sections, or the .dwo sections or the .gnu.debuglto_.debug sections (in that order of preference). That way there is always a consistent set. https://sourceware.org/bugzilla/show_bug.cgi?id=27367 Signed-off-by: Mark Wielaard <mark@klomp.org>
* Improve building with LTOAlexander Miller2021-11-0810-11/+22
| | | | | | | | | | | | | | Use symver attribute for symbol versioning instead of .symver assembler directive when available. Convert to use double @ syntax for default version in all cases (required when using the attribute). Add the attributes externally_visible, no_reorder if available when using assembler directives to improve the situation for < gcc-10. This is not 100% reliable, though; -flto-partition=none may still be needed in some cases. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24498 Signed-off-by: Alexander Miller <alex.miller@gmx.de>
* libdw: Don't pass NULL to dwarf_peel_typeMark Wielaard2021-10-182-1/+6
| | | | | | | | | | | | | commit c3a6a9dfc "libdw: Use signedness of subrange type to determine array bounds" introduced a type check on a DIE which exposed a latent bug in the get_type function. Even if the type of a DIE couldn't be determined it would call dwarf_peel_type on it. The gcc undefined sanitizer would flag this as being undefined behaviour because the second argument of the function is marked as non-NULL. Fix this by checking we actually have a non-NULL type DIE. Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Use signedness of subrange type to determine array boundsMark Wielaard2021-10-182-6/+44
| | | | | | | | | | | | | When calculating the array size check if the subrange has an associate type, if it does then check the type to determine whether the upper and lower values need to be interpreted as signed of unsigned values. We default to signed because that is what the testcase run-aggregate-size.sh testfile-size4 expects (this is an hardwritten testcase, we could have chosen a different default). https://sourceware.org/bugzilla/show_bug.cgi?id=28294 Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: set address size, offset size and version on fake CUsMark Wielaard2021-09-122-6/+31
| | | | | | | | | | | | | | | | | | There are three "fake CUs" that are associated with .debug_loc, .debug_loclist and .debug_addr. These fake CUs are used for "fake attributes" to provide values that are stored in these sections instead of in the .debug_info section. These fake CUs didn't have the address size, offset size and DWARF version set. This meant that values that depended on those properties might not be interpreted correctly. One example was the value associated with a DW_OP_addrx (which comes from the .debug_addr section). Add a testcase using varlocs to test that addresses can correctly be retrieved for gcc/clang, DWARF4/5 and 32/64 bits objects. https://sourceware.org/bugzilla/show_bug.cgi?id=28220 Signed-off-by: Mark Wielaard <mark@klomp.org>
* Remove redundant casts of memory allocating functions returning void *Dmitry V. Levin2021-09-094-8/+16
| | | | | | | Return values of functions returning "void *", e.g. calloc, malloc, realloc, xcalloc, xmalloc, and xrealloc, do not need explicit casts. Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
* Come up with startswith function.Martin Liska2021-05-122-1/+7
| | | | | | | New function in system.h that returns true if a string has a given prefix, false otherwise. Use it in place of strncmp. Signed-off-by: Martin Liška <mliska@suse.cz>
* libdw: Document and handle DW_FORM_indirect in __libdw_form_val_compute_lenMark Wielaard2021-05-062-1/+10
| | | | | | | | Update the documentation in __libdw_form_val_compute_len for handling DW_FORM_indirect and make sure the indirect form isn't DW_FORM_indirect itself or DW_FORM_implicit_const. Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: handle DW_FORM_indirect when reading attributesOmar Sandoval2021-05-013-0/+31
| | | | | | | | | | | | | Whenever we encounter an attribute with DW_FORM_indirect, we need to read its true form from the DIE data. Then, we can continue normally. This adds support to the most obvious places: __libdw_find_attr() and dwarf_getattrs(). There may be more places that need to be updated. I encountered this when inspecting a file that was processed by our BOLT tool: https://github.com/facebookincubator/BOLT. This also adds a couple of test cases using a file generated by that tool. Signed-off-by: Omar Sandoval <osandov@fb.com>
* readelf, libdw: blocks aren't expressions for DWARF version 4Mark Wielaard2021-02-172-0/+23
| | | | | | | | For DWARF version 4 or higher a block form really encodes a block, not an expression location. Also constant offsets can be expressed as DW_FORM_implicit_const in DWARF version 5. Signed-off-by: Mark Wielaard <mark@klomp.org>
* Split the top level .gitignore fileDmitry V. Levin2020-12-202-0/+5
| | | | | | | | | | Move subdirectory parts of the top level .gitignore into appropriate subdirectories. This would be consistent with ChangeLog files, currently one has to update the top level ChangeLog file when the top level .gitignore file is changed in a way that affects a specific subdirectory only. Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
* Consistently define _(Str) using dgettext ("elfutils", Str)Dmitry V. Levin2020-12-162-4/+4
| | | | | | | | | | | | | | Move the definition of _(Str) macro to lib/eu-config.h which already provides a definition of N_(Str) macro. Since lib/eu-config.h is appended to config.h, it is included into every compilation unit and therefore both macros are now universally available. Remove all other definitions of N_(Str) and _(Str) macros from other files to avoid conflicts and redundancies. The next step is to replace all uses of gettext(Str) with _(Str). Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
* libdw: fix spelling typos in comments and ChangeLogDmitry V. Levin2020-12-127-13/+22
| | | | | | | | | | | | | | | Retieve -> Retrieve apporiate -> appropriate distinquish -> distinguish dynamicly -> dynamically indeces -> indices lenght -> length minium -> minimum occured -> occurred setion -> section unknow -> unknown Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
* Fix automake warningsDmitry V. Levin2020-12-102-3/+8
| | | | | | | | | | | | | | | | | | | Apparently, commit 2f02e81510946a4c8e9157ad0b72d92894b9acd7 that removed $(EXEEXT) suffix from shared libraries was incomplete: it missed the fact that some libraries were included into noinst_PROGRAMS, resulting to the following automake warnings: libasm/Makefile.am:66: warning: deprecated feature: target 'libasm.so' overrides 'libasm.so$(EXEEXT)' libdw/Makefile.am:114: warning: deprecated feature: target 'libdw.so' overrides 'libdw.so$(EXEEXT)' libelf/Makefile.am:116: warning: deprecated feature: target 'libelf.so' overrides 'libelf.so$(EXEEXT)' Fix this by renaming noinst_PROGRAMS to noinst_DATA and removing no longer needed lib{asm,dw,elf}_so_SOURCES variables and add lib{asm,dw,elf).so to CLEANFILES. Fixes: 2f02e8151094 ("Drop $(EXEEXT) suffix from shared libraries") Signed-off-by: Dmitry V. Levin <ldv@altlinux.org> Signed-off-by: Mark Wielaard <mark@klomp.org>
* Drop $(EXEEXT) suffix from shared librariesDmitry V. Levin2020-12-062-1/+5
| | | | | | | | | According to GNU Automake documentation [1], $(EXEEXT) is the suffix that should be used for executables, it is not applicable for shared libraries. [1] https://www.gnu.org/software/automake/manual/html_node/EXEEXT.html Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
* Support building when fts and obstack aren't part of libc.Érico Rolim2020-11-032-1/+5
| | | | | | | | - Make configure.ac test for fts and obstack availability; - Add fts and obstack ldflags to all files that need them; - Add missing argp ldflags to programs in debuginfod/. Signed-off-by: Érico Rolim <erico.erc@gmail.com>
* Fix leb128 readingTom Tromey2020-10-293-8/+49
| | | | | | | | | | | | PR 26773 points out that some sleb128 values are decoded incorrectly. This version of the fix only examines the sleb128 conversion. Overlong encodings are not handled, and the uleb128 decoders are not touched. The approach taken here is to do the work in an unsigned type, and then rely on an implementation-defined cast to convert to signed. Signed-off-by: Tom Tromey <tom@tromey.com>
* libdw: dwarf_frame_register takes an array of at least 3 Dwarf_OpsMark Wielaard2020-10-263-4/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | GCC11 will warn about a mismatch in the declaration of dwarf_frame_register: dwarf_frame_register.c:37:61: error: argument 3 of type ‘Dwarf_Op *’ declared as a pointer [-Werror=array-parameter=] 37 | dwarf_frame_register (Dwarf_Frame *fs, int regno, Dwarf_Op *ops_mem, | ~~~~~~~~~~^~~~~~~ libdw.h:1068:43: note: previously declared as an array ‘Dwarf_Op[3]’ 1068 | Dwarf_Op ops_mem[3], | ~~~~~~~~~^~~~~~~~~~ When fixing that it will show an actual bug in the addrcfi testcase: addrcfi.c:98:16: error: ‘dwarf_frame_register’ accessing 96 bytes in a region of size 64 [-Werror=stringop-overflow=] 98 | int result = dwarf_frame_register (stuff->frame, regno, ops_mem, &ops, &nops); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ addrcfi.c:98:16: note: referencing argument 3 of type ‘Dwarf_Op *’ 1069 | extern int dwarf_frame_register (Dwarf_Frame *frame, int regno, | ^~~~~~~~~~~~~~~~~~~~ Fix the declaration, fix the bug and add an extra comment to the description in libdw.h. Signed-off-by: Mark Wielaard <mark@klomp.org>
* Fix bug in read_3ubyte_unaligned_incTom Tromey2020-10-242-1/+6
| | | | | | | The read_3ubyte_unaligned_inc macro calls read_2ubyte_unaligned, but it should call read_3ubyte_unaligned. Signed-off-by: Tom Tromey <tom@tromey.com>
* libdw,readelf: Recognize DW_CFA_AARCH64_negate_ra_stateMark Wielaard2020-09-076-18/+51
| | | | | | | | | | | | | | | | | | | | DW_CFA_AARCH64_negate_ra_state is used on aarch64 to indicate whether or not the return address is mangled or not. This has the same value as the DW_CFA_GNU_window_save. So we have to pass around the e_machine value of the process or core we are inspecting to know which one to use. Note that it isn't actually implemented yet. It needs ARMv8.3 hardware. If we don't have such hardware it is enough to simply ignore the DW_CFA_AARCH64_negate_ra_state (and not confuse it with DW_CFA_GNU_window_save) to get backtraces to work on aarch64. Add a testcase for eu-readelf --debug-dump=frames to show the value is correctly recognized. Also don't warn we cannot find any DWARF if we are just dumping frames (those will come from .eh_frame if there is no .debug_frame). Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Remove duplicate local wildcards from map file.Mark Wielaard2020-09-032-10/+8
| | | | | | We only need one local: * entry to capture all private local symbols. Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Rename check_constant_offset to is_constant_offset.Mark Wielaard2020-08-252-9/+18
| | | | | | | | | The check_constant_offset code in dwarf_getlocation.c code is not very intuitive, rename it to is_constant_offset and update the documentation. https://sourceware.org/bugzilla/show_bug.cgi?id=26321 Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdwfl: read_address should use increasing address in intuit_kernel_boundsMark Wielaard2020-06-281-0/+5
| | | | | | | | | | | | | | | | In kernels from 4.14 up to 4.19 in /proc/kallsyms there are special __entry_SYSCALL_64_trampoline symbols. The problem is that they come after the last kernel address, but before the module addresses. And they are (much) smaller than the start address we found. This confuses intuit_kernel_bounds and makes it fail. Make sure to check read_address returns an increasing address when searching for the end. https://sourceware.org/bugzilla/show_bug.cgi?id=26177 Reported-by: Vitaly Chikunov <vt@altlinux.org> Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Add missing FALLTHROUGH in execute_cfi.Mark Wielaard2020-06-192-0/+5
| | | | Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Skip imported compiler_units in libdw_visit_scopes walking DIE treeMark Wielaard2020-05-082-1/+10
| | | | | | | | | | | Some gcc -flto versions imported other top-level compile units, skip those. Otherwise we'll visit various DIE trees multiple times. Note in the testcase that with newer GCC versions function foo is fully inlined and does appear only once (as declared, but not as separate subprogram). Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Use correct CU to resolve file names in dwarf_decl_file.Mark Wielaard2020-05-084-2/+21
| | | | | | | | | | | | | dwarf_decl_file uses dwarf_attr_integrate to get the DW_AT_decl_file attribute. This means the attribute might come from a different DIE in a different CU. If so, we need to use the CU associated with the attribute, not the original DIE, to resolve the file name. Also add a bit more documentation to dwarf_attr_integrate explaining that the attribute returned might come from a different CU (and even different Dwarf). Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw: Call Dwarf oom_handler() when malloc fails in __libdw_alloc_tail.Mark Wielaard2020-04-262-0/+10
| | | | | | | | | GCC10 -fanalyzer found a possibly-NULL dereference after a failed malloc in __libdw_alloc_tail. In this case we should call the Dwarf oom_handler as is done in other places where an essential malloc call fails. The oom_handler cannot return and will likely just abort. Signed-off-by: Mark Wielaard <mark@klomp.org>
* libdw, readelf: Handle GCC LTO .gnu.debuglto_ prefix.Mark Wielaard2020-04-222-0/+8
| | | | | | | | | GCC puts (partial) DWARF debuginfo into sections prefixed with .gnu.debuglto_. Handle those sections as if they are normal .debug sections (which they are). This allows showing the DWARF that gcc puts into ET_REL files compiled with -flto. Signed-off-by: Mark Wielaard <mark@klomp.org>
* debuginfod 1/2: client sideAaron Merey2019-11-222-1/+5
| | | | | | | | | | | | Introduce the debuginfod/ subdirectory, containing the client for a new debuginfo-over-http service, in shared-library and command-line forms. Two functions in libdwfl make calls into the client library to fetch elf/dwarf files by buildid, as a fallback. Instead of normal dynamic linking (thus pulling in a variety of curl dependencies), the libdwfl hooks use dlopen/dlsym. Server & tests coming in patch 2. Signed-off-by: Aaron Merey <amerey@redhat.com> Signed-off-by: Frank Ch. Eigler <fche@redhat.com>
* libdw: Introduce libdw_unalloc to stop Dwarf_Abbrev leaks.Mark Wielaard2019-11-124-1/+43
| | | | | | | | | In the case of reading an invalid abbrev or when reading an abbrev concurrently the Dwarf_Abbrev just created might leak because it isn't needed after all. Introduce libdw_unalloc and libdw_typed_unalloc to unallocate such Dwarf_Abbrevs so they don't leak. Signed-off-by: Mark Wielaard <mark@klomp.org>