| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
| |
- 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>
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
| |
We only need one local: * entry to capture all private local symbols.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
| |
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
| |
Pthread's thread-local variables are highly limited, which makes
it difficult to use many Dwarfs. This replaces that with a
less efficient (or elegant) but more robust method.
Signed-off-by: Jonathon Anderson <jma14@rice.edu>
|
|
|
|
|
| |
Signed-off-by: Srđan Milaković <sm108@rice.edu>
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
| |
fake_{loc,loclists,addr}_cu are Dwarf_CUs that are created separate from
all the others, so their contents are minimal and mostly initialized by
a calloc. On dwarf_end however, they are freed through the same code path
as all the others, so they call DAH_free like all the others. This changes
that so that these three are exempt from DAH and split-DWARF matters, and
swaps the calloc for a malloc so Memcheck will catch any others.
Signed-off-by: Jonathon Anderson <jma14@rice.edu>
|
|
|
|
| |
Signed-off-by: Jonathon Anderson <jma14@rice.edu>
|
|
|
|
|
|
|
|
|
|
|
|
| |
Currently, architecture-specific code for libebl exists in separate
libebl_$ARCH.so libraries which libebl loads with dlopen() at runtime.
This makes it impossible to have standalone, statically-linked binaries
which use libdwfl if they depend on any architecture-specific
functionality. Additionally, when these libraries cannot be found, the
failure modes are non-obvious. So, let's get rid of libebl_$arch.so and
move it all into libdw.so/libdw.a, which simplifies things considerably.
Signed-off-by: Omar Sandoval <osandov@fb.com>
|
|
|
|
|
|
|
|
|
| |
Currently, libcpu and libebl are always compiled as PIC. An upcoming
change will add the objects from libcpu.a and libebl.a to libdw.a, which
should not be PIC unless configured that way. So, make libcpu.a and
libebl.a non-PIC and add libcpu_pic.a and libebl_pic.a.
Signed-off-by: Omar Sandoval <osandov@fb.com>
|
|
|
|
| |
Signed-off-by: Jonathon Anderson <jma14@rice.edu>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
dwelf_elf_begin was slightly different from elf_begin in case the file
turned out to not be an ELF file. elf_begin would return an Elf handle
with ELF_K_NONE. But dwelf_elf_begin would return NULL. This made it
impossible to tell the difference between a file or decompression error
and a (decompressed) file not being an ELF file.
Since dwelf_elf_begin could still return different kinds of ELF files
(ELF_K_ELF or ELF_K_AR - and theoretically ELF_K_COFF) this was not
really useful anyway. So make it so that dwelf_elf_begin always returns
an Elf handle unless there was a real error reading or decompressing
the file. Otherwise return NULL to make clear there was a real error.
Make sure that the decompression function returns DWFL_E_BADELF only
when the file isn't compressed. In which case the Elf handle won't
be replaced and can be returned (as ELF_K_NONE).
Add a new version to dwelf_elf_begin so programs can rely on it
returning NULL only for real errors.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
To print eh human readable description of the ELF e_machine header field
we used the ebl name. But this is not set for most EM constants. Introduce
a new function dwelf_elf_e_machine_string that does work for all known
EM values. Use that in eu-readelf to print a string representation of the
e_machine value.
Since this was the only usage of ebl->name, remove that from struct ebl.
Also add a testcase that makes sure dwelf_elf_e_machine_string works for
all EM values in the libelf/elf.h header so we will immediately notice
when a new value appears.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
| |
https://sourceware.org/bugzilla/show_bug.cgi?id=24550
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
| |
We immediately reassign the value of addr after declaration.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
| |
In dwarf_getlocation_addr pass the pointers to llbufs and listlens
indirectly by passing a pointer to the first array element. Simplify the
code by passing the pointers directly.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
| |
When we encounter a DW_OP_implicit_value we call store_implicit_value ()
which will try to store the value as part of the Dwarf dbg. But if we are
examining CFI there will be no Dwarf dbg. And DW_OP_implicit_value should
not be part of CFI. So explicitly reject it in store_implicit_value if
dbg is NULL.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
| |
We only checked we could read the initial length and after knowing the
version and type whether the unit header was the right size. Also check
there are at least enough bytes to read the 64bit length, version and
unit type bytes.
https://sourceware.org/bugzilla/show_bug.cgi?id=24140
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
For DWARF version < 5 the .debug_line directory and file tables consist
of a terminating NUL byte after all strings. The code used to just skip
this without checking it actually existed. This could case a spurious
read past the end of data.
Fix the same issue in readelf.
https://sourceware.org/bugzilla/show_bug.cgi?id=24102
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
|
| |
When building with -Og gcc is unable to see that __libdw_dieabbrev ()
will initialize what the second argument points to when no error occurs
as called by dwarf_child and dwarf_getattrs. Causing an possibly
uninitialized error. Just initialize readp/die_addr to NULL, which is
the value we would return if an error occurs anyway.
https://sourceware.org/bugzilla/show_bug.cgi?id=23914
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This introduces a new function dwelf_elf_begin which creates a (read-only)
ELF handle from a possibly compressed file handle or a file that start
with a linux kernel header. This can be used in eu-readelf to (re)open a
(pure) ELF.
eu-readelf uses libdwfl to relocate addresses in the original file in
case it is ET_REL. But to show the "raw" data it might need to (re)open
the file. Which could fail if the file was compressed. And produced an
obscure error message: "cannot create EBL handle".
This rewrites __libdw_open_file a little so that the given file handle
will never be closed (whether on success or failure) and introduces a
new internal function __libdw_open_elf that dwelf_elf_begin wraps.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
On my system with g++ (GCC) 8.2.1 20180831 with GNU gold (GNU Binutils
2.31.1) 1.16, the .eh_frame section does not have type PROGBITS
but rather is using X86_64_UNWIND nowadays:
```
$ echo "int main(){ return 0; }" > test.c
$ gcc test.c
$ readelf --sections a.out | grep .eh_frame
[14] .eh_frame X86_64_UNWIND 0000000000000670 00000670
[15] .eh_frame_hdr X86_64_UNWIND 0000000000000724 00000724
```
Without this patch, libdw refuses to use the available unwind
information, leading to broken backtraces while unwinding. With the
patch applied, unwinding works once more in such situations.
Signed-off-by: Milian Wolff <milian.wolff@kdab.com>
Signed-off-by: Mark Wielaard <mark@klomp.org>
Tested-by: Milian Wolff <milian.wolff@kdab.com>
|
|
|
|
|
|
|
|
|
|
|
| |
dwarf_begin_elf used the Ehdr e_shstrndx to get the shdr string table
section. This does not work for ELF files with more than SHN_LORESERVE
sections. Use elf_getshdrstrndx, and don't pass around the ehdr.
Add a simple testcase that fails before the patch because dwarf_begin
return an error.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
dwarf_child (__libdw_find_attr), dwarf_getabbrevattr[_data] and
dwarf_getattrs all assume the end of the attribute list is when
both the name (code) and form of the attribute are zero.
dwarf_getabbrev (__libdw_getabbrev) and dwarf_hasattr assume the
end of the attribute list is when either the name (code) or the
form of the attribute is zero.
The DWARF spec says: "The series of attribute specifications ends
with an entry containing 0 for the name and 0 for the form." So
the first check is correct.
Make sure dwarf_getabbrev and dwarf_hasattr use the same check.
This is important since all other functions expect dwarf_getabbrev
(__libdw_getabbrev) to have done a data sanity check of the attribute.
So if the ending condition is different it could cause a crash.
https://sourceware.org/bugzilla/show_bug.cgi?id=23529
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
| |
dwarf_getaranges didn't check if there was enough data left to read both
the address and segment size. readelf didn't check there was enough data
left to read the segment size.
https://sourceware.org/bugzilla/show_bug.cgi?id=23541
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
| |
error.h isn't standard and so isn't part of the musl C library.
To easy future porting, consolidate the inclusion of error.h into system.h.
https://sourceware.org/bugzilla/show_bug.cgi?id=21008
Signed-off-by: Ross Burton <ross.burton@intel.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When the length is zero this is a the zero terminator that ends the
frame table. Return 1 (end of table) instead of -1 (error) in that case.
We cannot update next_off and don't want to caller to try again.
Add testcase for dwarf_next_cfi to show both .eh_frame and .debug_frame
tables and check consistency (FDEs should point to existing CIEs).
Also add a self check to make sure we can read the table from the just
build elfutils binaries.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
| |
.debug_frame is useful independent from the other .debug sections.
Add a simplified variant of the addrcfi testcase dwarfcfi.
dwarfcfi only uses dwarf_frame calls and no dwfl helpers.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
| |
This function was never actually implemented/provided by libdw.
And it doesn't look like something we really want to implement.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It is sometimes useful to read .debug_line tables on their own without
having an associated CU DIE. DWARF5 line tables are self-contained.
Adjust dwarf_begin_elf to accept ELF files with just a .debug_line.
Add a new function dwarf_next_lines that returns the Dwarf_Files and
Dwarf_Lines while iterating over just the .debug_lines section. Since
we parse and cache the information it also will try to match the CU
a table is associated with. This is only necessary for DWARF4 line
tables (we will need at least the compilation dir from the CU) and
won't be done for DWARF5 line tables. It also isn't an error if there
is no associated CU (but will mean for DWARF4 line tables the dir list
and the file paths might not be complete).
A typical way to call this new function is:
Dwarf_Off off, next_off = 0;
Dwarf_CU *cu = NULL;
Dwarf_Files *files;
size_t nfiles;
Dwarf_Lines *lines;
size_t nlines;
int res;
while ((res = dwarf_next_lines (dbg, off = next_off, &next_off, &cu,
&files, &nfiles, &lines, &nlines)) == 0)
{
/* ... handle files and lines ... */
}
if (res < 0)
printf ("BAD dwarf_next_lines: %s\n", dwarf_errmsg (-1));
See libdw.h for the full documentation. For more examples on how to use
the function see the new testcases next-files and next-lines.
Also adjust the file paths for line tables missing a comp_dir.
They are no longer made "absolute" by prepending a slash '/' in front
of them. This really was not useful and didn't happen in any of the
testcases. They are now just kept relative.
Make eu-readelf --debug-dump=decodedline use dwarf_next_lines instead
of iterating over the CUs to show the (decoded) line tables. This allows
it to show decoded line tables even if there is no .debug_info section.
New tests have been added that mimic the get-files and get-lines tests
but use dwarf_next_lines instead of iterating over all CUs. They produce
identical output (modulo the CU information). Also add a new test file
that contains only a .debug_line section.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
| |
The length field could be so big that it would wrap around the next_offset.
We don't really care that length is bogus, but we don't want to use it to
calculate the next offset if it is.
Found by afl-fuzz.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
| |
Found by afl-fuzz. An array type (indirectly) referring to itself in the
DIE tree could blow up the stack when dwarf_aggregate_size was called.
Limit the recursion depth to MAX_DEPTH (256) entries.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
| |
Limit the number of chained modifiers to 64 (that is 8 chains for all
8 modifiers, most of which cannot be chained). This prevents loops in
the DWARF DIE DW_AT_type references.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
| |
aggregate_size can be called recursively with the result of get_type.
get_type can return NULL when dwarf_peel_type fails. Found by afl-fuzz.
dwarf_aggregate_size when called directly doesn't need a NULL check
because it calls and checks the result of dwarf_peel_type directly.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I'm getting this error with 0.172:
dwarf_getsrclines.c: In function 'read_srclines':
dwarf_getsrclines.c:1074:7: error: 'filelist' may be used uninitialized in this function [-Werror=maybe-uninitialized]
free (filelist);
^~~~~~~~~~~~~~~
It seems that gcc is right here as there is "ifs" that go to "out"
(where filelist is freed) before freelist is initialized.
Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
|
|
|
|
|
|
|
|
|
|
|
| |
Also found by afl-fuzz on the varlocs testcase.
DW_FORM_data16 is constant form according to the DWARF5 spec.
But since it is 128bits it isn't really representable as Dwarf_Word.
So we treat it as block form. But we cannot treat it as an expression
block. Make sure readelf prints it as a regular block and that
dwarf_getlocation[s|_addr] doesn't treat it as location expression.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
|
|
|
|
|
|
|
|
|
| |
Found by afl-fuzz. When printing DW_FORM_strx[1234] data eu-readelf didn't
increase readp which meant eu-readelf would keep printing the same line
dirs or files encoded with strx[1234] names. This meant that for insane
large dir or file counts eu-readelf would just keep printing endlessly
because we never reached and of the .debug_line buffer.
Signed-off-by: Mark Wielaard <mark@klomp.org>
|