platform/upstream/elfutils.git
6 years agobackends,bpf: add proper relocation support
Yonghong Song [Sat, 16 Jun 2018 20:02:43 +0000 (13:02 -0700)]
backends,bpf: add proper relocation support

Due to libdw does not have proper BPF relocation support,
the pahole cannot display filenames correctly for objects
with default llvm options. So we have to invent
a special option "llc -march=bpf -mattr=dwarfris" to
prevent llvm from generating cross-section dwarf relocation
records (https://reviews.llvm.org/rL326505).
The pahole related discussion is in linux netdev
mailing list (http://lists.openwall.net/netdev/2018/06/15/38, etc.)

We would like to add proper BPF relocation support
to libdw so eventually we could retire the special llc bpf
flag "-mattr=dwarfris".

The bpf relocations are defined in
llvm_repo:include/llvm/BinaryFormat/ELFRelocs/BPF.def:
  ELF_RELOC(R_BPF_NONE,        0)
  ELF_RELOC(R_BPF_64_64,       1)
  ELF_RELOC(R_BPF_64_32,      10)

Removed the relocation type R_BPF_MAP_FD whoes name does not
confirm to llvm definition and replaced it with R_BPF_64_64.
The BPF object is just a relocatible object, not an executable or
a shared library, so assign ELF type to REL only in bpf_reloc.def.

Signed-off-by: Yonghong Song <yhs@fb.com>
6 years agolibelf: Sync elf.h from glibc.
Mark Wielaard [Thu, 21 Jun 2018 16:52:53 +0000 (18:52 +0200)]
libelf: Sync elf.h from glibc.

Add NT_PPC_PKEY, R_BPF_64_64 and R_BPF_64_32. Remove R_BPF_MAP_FD.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Break dwarf_aggregate_size recursion because of type cycles.
Mark Wielaard [Sun, 17 Jun 2018 22:58:24 +0000 (00:58 +0200)]
libdw: Break dwarf_aggregate_size recursion because of type cycles.

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>
6 years agolibdw: dwarf_peel_type break long chains/cycles.
Mark Wielaard [Sun, 17 Jun 2018 22:23:48 +0000 (00:23 +0200)]
libdw: dwarf_peel_type break long chains/cycles.

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>
6 years agolibdw: aggregate_size check NULL result from get_type.
Mark Wielaard [Sun, 17 Jun 2018 22:23:23 +0000 (00:23 +0200)]
libdw: aggregate_size check NULL result from get_type.

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>
6 years agobackends: add abi_cfi and register_info callbacks for RISC-V
Andreas Schwab [Wed, 13 Jun 2018 10:28:00 +0000 (12:28 +0200)]
backends: add abi_cfi and register_info callbacks for RISC-V

From
https://github.com/riscv/riscv-isa-manual/raw/master/release/riscv-spec-v2.2.pdf
and GCC source.

Signed-off-by: Andreas Schwab <schwab@suse.de>
6 years agolibdw: Initialize filelist earlier in dwarf_getsrclines.c read_srclines.
Luiz Angelo Daros de Luca [Sun, 17 Jun 2018 09:34:08 +0000 (11:34 +0200)]
libdw: Initialize filelist earlier in dwarf_getsrclines.c read_srclines.

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>
6 years agolibdw, readelf: Don't handle DW_FORM_data16 as expression block/location.
Mark Wielaard [Fri, 15 Jun 2018 14:25:15 +0000 (16:25 +0200)]
libdw, readelf: Don't handle DW_FORM_data16 as expression block/location.

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>
6 years agoreadelf: Check there are at least 4 bytes available for DWARF_FORM_block4.
Mark Wielaard [Tue, 12 Jun 2018 12:36:50 +0000 (14:36 +0200)]
readelf: Check there are at least 4 bytes available for DWARF_FORM_block4.

Found by afl-fuzz. When printing a DWARF_FORM_block4 we checked there
were only 2 bytes available (copy/paste from DW_FORM_block2 right
before). Obviously we need at least 4 bytes to read the length of a
DW_FORM_block4.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Make sure print_form_data always consumes DW_FORM_strx[1234] data.
Mark Wielaard [Tue, 12 Jun 2018 10:22:13 +0000 (12:22 +0200)]
readelf: Make sure print_form_data always consumes DW_FORM_strx[1234] data.

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>
6 years agolibdw: Make __libdw_dieabbrev more robust on failure.
Mark Wielaard [Tue, 12 Jun 2018 10:18:31 +0000 (12:18 +0200)]
libdw: Make __libdw_dieabbrev more robust on failure.

Make sure to always set die->abbrev to DWARF_END_ABBREV on failure.
DWARF_END_ABBREV is also what the function reports on failure. And it
will prevent trying to lookup the abbrev ever again.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: While printing .debug_loc make sure that next_off doesn't overflow.
Mark Wielaard [Wed, 13 Jun 2018 13:21:37 +0000 (15:21 +0200)]
readelf: While printing .debug_loc make sure that next_off doesn't overflow.

Found by the afl fuzzer. The next offset (after a locview) comes from a
DIE loclist attribute. This could be a bogus value so large it overflows
the buffer and makes us print past the end of buffer.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Handle signedness of DW_FORM_implicit_const and DW_AT_const_value.
Mark Wielaard [Wed, 13 Jun 2018 12:03:24 +0000 (14:03 +0200)]
readelf: Handle signedness of DW_FORM_implicit_const and DW_AT_const_value.

We only handles DW_FORM_sdata as a signed form, but DW_FORM_implicit_const
is also signed by default. For DW_AT_const_value we can do a little better.
GCC encodes some const_values with signed forms, even though the type
is unsigned. Lookup the (base) type of the DIE and display the const value
as their (signed) type/size (if we can determine that).

Add a new testcase run-readelf-const-values.sh that shows that.
With the new testcase the const values would come out as follows:

  name                 (string) "i"
  const_value          (implicit_const) 18446744073709551615
  name                 (string) "j"
  const_value          (implicit_const) 18446744073709551615

  name                 (string) "sc"
  const_value          (sdata) -2
  name                 (string) "uc"
  const_value          (sdata) -2
  name                 (string) "ss"
  const_value          (sdata) -16
  name                 (string) "us"
  const_value          (sdata) -16
  name                 (string) "si"
  const_value          (sdata) -3
  name                 (string) "ui"
  const_value          (sdata) -94967296
  name                 (string) "sl"
  const_value          (sdata) -1
  name                 (string) "ul"
  const_value          (sdata) -1

With this patch they show up as:

  name                 (string) "i"
  const_value          (implicit_const) -1
  name                 (string) "j"
  const_value          (implicit_const) -1

  name                 (string) "sc"
  const_value          (sdata) -2
  name                 (string) "uc"
  const_value          (sdata) 254 (-2)
  name                 (string) "ss"
  const_value          (sdata) -16
  name                 (string) "us"
  const_value          (sdata) 65520 (-16)
  name                 (string) "si"
  const_value          (sdata) -3
  name                 (string) "ui"
  const_value          (sdata) 4200000000 (-94967296)
  name                 (string) "sl"
  const_value          (sdata) -1
  name                 (string) "ul"
  const_value          (sdata) 18446744073709551615 (-1)

(for signed/unsigned int char, short and long)

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoPrepare for 0.172. elfutils-0.172
Mark Wielaard [Mon, 11 Jun 2018 15:14:39 +0000 (17:14 +0200)]
Prepare for 0.172.

It has been only 10 days since the previous release and there are
no functional changes compared to 0.171. The speedup of eu-readelf -N
is pretty nice. And ~25 patches fix various bugs (hangs and crashes)
in dealing with bad DWARF5 data. Most have been found by running the
afl fuzzer on eu-readelf and various testcases.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Return correct readp (or readendp) from print_form_data.
Mark Wielaard [Mon, 11 Jun 2018 09:22:36 +0000 (11:22 +0200)]
readelf: Return correct readp (or readendp) from print_form_data.

print_form_data returns the new readp (or readendp on error) to show how
much data was consumed. But when reading the .debug_str_offsets section
we would reuse readp and readendp. This meant the wrong readp would be
returned to the caller.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Fix bounds check in print_form_data.
Mark Wielaard [Mon, 11 Jun 2018 00:14:34 +0000 (02:14 +0200)]
readelf: Fix bounds check in print_form_data.

The afl fuzzer found that we did a wrong check in print_form_data when
comparing the remaining bytes in the buffer to an (unsigned) value read.
We were casting the value to ptrdiff_t which is a signed value and so
might turn a really big unsigned value into a negative number. Since we
know the difference between readendp and readp is zero or greater, we
should cast the pointer difference to size_t (and unsigned type) instead
before comparing with the unsigned value.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Break long or circular DIE ref chains in dwarf_[has]attr_integrate.
Mark Wielaard [Sun, 10 Jun 2018 14:59:12 +0000 (16:59 +0200)]
libdw: Break long or circular DIE ref chains in dwarf_[has]attr_integrate.

Bad DWARF could create a very long or circular DIE ref chain by linking
DW_AT_abstract_origin or DW_AT_specification to the DIE itself. Break
the chain after seeing a large number (16) of DIEs.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Calculate max_entries instead of needed bytes (and overflowing).
Mark Wielaard [Fri, 8 Jun 2018 21:30:37 +0000 (23:30 +0200)]
readelf: Calculate max_entries instead of needed bytes (and overflowing).

The afl fuzzer found that we would overflow the needed bytes when
calculating how many index entries would fit in the .debug_loclists
and .debug_rnglists tables. To fix this just calculate the max number
of entries. If the offset entry count is larger than that, do emit
an error, but print up to max_entries of offsets (so the user can
more clearly see what is wrong with their table).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agotests: Don't assert on bad DW_OP_GNU_parameter_ref target in varlocs.
Mark Wielaard [Fri, 8 Jun 2018 19:13:25 +0000 (21:13 +0200)]
tests: Don't assert on bad DW_OP_GNU_parameter_ref target in varlocs.

If the target of a DW_OP_GNU_parameter_ref isn't a DW_TAG_formal_parameter
that is bad data (which varlocs should error on). But it isn't an internal
consistency check (for which varlocs should assert).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Check validity of dwarf_getabbrev arguments.
Mark Wielaard [Fri, 8 Jun 2018 18:45:48 +0000 (20:45 +0200)]
libdw: Check validity of dwarf_getabbrev arguments.

When the given Dwarf_Die was invalid we might crash and when the offset
was totally bogus we might succeed with a random abbrev.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: dwarf_get_units should handle existing failure to open Dwarf.
Mark Wielaard [Fri, 8 Jun 2018 18:14:58 +0000 (20:14 +0200)]
libdw: dwarf_get_units should handle existing failure to open Dwarf.

The other dwarf unit/cu iterators handle a NULL Dwarf handle as an
existing error and return NULL. Don't crash.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Detect bad DWARF in store_implicit_value.
Mark Wielaard [Fri, 8 Jun 2018 13:10:43 +0000 (15:10 +0200)]
libdw: Detect bad DWARF in store_implicit_value.

The afl fuzzer running against the varlocs test detected we didn't report
the value block of a DW_OP_implicit_value consistently when the DWARF was
bad. Although this doesn't cause a crash it might result in consumers
using dwarf_getlocation_implicit_value seeing an inconsistent block length
value. To fix this detect and report bad DWARF data earlier.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agotests: Fix cfi_debug_bias assert in varlocs.
Mark Wielaard [Fri, 8 Jun 2018 13:07:16 +0000 (15:07 +0200)]
tests: Fix cfi_debug_bias assert in varlocs.

It is only a consistency issue if we actually have an cfi_debug and the
cfi_debug_bias is not zero (because they come from the same file as the
other debug data).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf, libdw: Handle too many directories or files in the line table better.
Mark Wielaard [Fri, 8 Jun 2018 12:04:40 +0000 (14:04 +0200)]
readelf, libdw: Handle too many directories or files in the line table better.

The afl fuzzer found that the way we handle "too many" directories or files
in the (DWARF5 style) line table badly. In the case of eu-readelf we would
print an endless stream of "bad directory" or "bad file". Just stop printing
when the end of data is reached. In the case of dwarf_getsrclines we would
allocate a giant amount of memory, even if there was no data to actually
read in. Sanity check that the directory and file counts seem reasonable
compared to the amount of data left (assume we need at least 1 byte of
data per form describing the dirs or files).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Return an error in dwarf_getlocation_attr for missing .debug_addr.
Mark Wielaard [Fri, 8 Jun 2018 00:11:44 +0000 (02:11 +0200)]
libdw: Return an error in dwarf_getlocation_attr for missing .debug_addr.

When constructing a "fake" Dwarf_Attribute for DW_OP_GNU_const_index,
DW_OP_constx, DW_OP_GNU_addr_index or DW_OP_addrx, we would create a
fake attribute pointing to the actual data in the .debug_addr section.

We would even do that if there was no .debug_addr section assuming
dwarf_formaddr or dwarf_formudata would generate an error. But when
there is no .debug_addr there is also no fake_addr_cu, so the
dwarf_form* functions cannot check the value is correct (and crash).

Fix by returning an error early from dwarf_getlocation_attr indicating
bad DWARF data.

Found by the afl fuzzer running on the varlocs testcase.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Turn format_print_dwarf into print_dwarf_addr.
Mark Wielaard [Thu, 7 Jun 2018 21:09:41 +0000 (23:09 +0200)]
readelf: Turn format_print_dwarf into print_dwarf_addr.

We don't really need to setup a buffer, print into it and then print it
out to stdout. Simplify the code by directly printing the address (and
symbol name).

This also showed a small error in the output of DW_LLE_startx_length.
It had two unintended trailing dots.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Make sure that address_size and offset_size are 4 or 8 bytes.
Mark Wielaard [Wed, 6 Jun 2018 23:23:05 +0000 (01:23 +0200)]
libdw: Make sure that address_size and offset_size are 4 or 8 bytes.

When interning a CU make sure that address_size and offset_size are
either 4 or 8 bytes. We really don't (want to) handle any other size.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Check DIE address fall inside the CU before reading abbrev code.
Mark Wielaard [Thu, 7 Jun 2018 14:57:23 +0000 (16:57 +0200)]
libdw: Check DIE address fall inside the CU before reading abbrev code.

The afl fuzzer found a case where we tried reading an uleb for the DIE
abbrev code without properly checking the DIE address is inside the CU.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Report error in dwarf_getlocation_die for bogus opcode offset.
Mark Wielaard [Wed, 6 Jun 2018 21:51:12 +0000 (23:51 +0200)]
libdw: Report error in dwarf_getlocation_die for bogus opcode offset.

Found by afl fuzzer on varlocs test. varlocs sanity checks that the
given offset in the opcode corresponds to the cuoffset of the returned
DIE. In case the opcode offset was bogus this might fail because we
might wrap around and return a random DIE instead of reporting an error.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agotests: Use error, not assert, when trying to print a non-base type DIE.
Mark Wielaard [Wed, 6 Jun 2018 21:35:35 +0000 (23:35 +0200)]
tests: Use error, not assert, when trying to print a non-base type DIE.

When using the varlocs test with a fuzzer using assert for internal
sanity checks is great to find issues. But when encountering bad data
using an assert is wrong. Just use error to show we handle the data
correctly (by reporting it is bad, instead of crashing).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Explicitly check we could decode diridx in dwarf_getsrclines.
Mark Wielaard [Tue, 5 Jun 2018 21:34:46 +0000 (23:34 +0200)]
libdw: Explicitly check we could decode diridx in dwarf_getsrclines.

It is highly unlikely dwarf_formudata fails because we setup the attribute
ourselves, but better to explicitly mark diridx as bad if it does.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Always initialize .debug_addr unit_length, even without a header.
Mark Wielaard [Tue, 5 Jun 2018 21:21:05 +0000 (23:21 +0200)]
readelf: Always initialize .debug_addr unit_length, even without a header.

We would print a "fake" .debug_addr header, but didn't always setup the
unit_length (in case there was a mix of GNU DebugFission and DWARF5 tables).
Make sure to always set the unit_length (we do always calculate the next
unit offset already).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Set begin properly for DW_LLE_GNU_start_end_entry on addrx failure.
Mark Wielaard [Tue, 5 Jun 2018 20:50:43 +0000 (22:50 +0200)]
readelf: Set begin properly for DW_LLE_GNU_start_end_entry on addrx failure.

When printing the GNU DebugFission location entries we want to print the
start idx as begin, if we cannot find the address index.
A copy/paste error set up end instead of begin in that case causing us
to print garbage (in the unlikely event the .debug_addr table wasn't
found for this entry).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Don't leak arange if we cannot figure out which CU it belongs to.
Mark Wielaard [Tue, 5 Jun 2018 20:41:45 +0000 (22:41 +0200)]
libdw: Don't leak arange if we cannot figure out which CU it belongs to.

In the unlikely case that __libdw_findcu fails to find the associated
CU we would leak one arange because it wasn't linked into the arangelist
list yet. Make sure to free it immediately.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Make sure dirarray is always properly freed in dwarf_getsrclines.
Mark Wielaard [Tue, 5 Jun 2018 20:27:25 +0000 (22:27 +0200)]
libdw: Make sure dirarray is always properly freed in dwarf_getsrclines.

If there were more than 256 directories in the table and there was
illegal DWARF before we read them all, then we might not free the
dirarray (or the wrong one). Fix by defining the dirarray early
(before the first data sanity check) and making sure it is not
(still) equal to dirstack before freeing.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Don't leak lengths array when detecting an invalid hash chain.
Mark Wielaard [Tue, 5 Jun 2018 19:52:46 +0000 (21:52 +0200)]
readelf: Don't leak lengths array when detecting an invalid hash chain.

In both handle_sysv_hash and handle_sysv_hash64 we check the has chain
isn't too long. If it is we would report an error and leak the lengths
array. Just clean up the array even in the error case.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Make sure id_path can contain max number of build id bytes.
Mark Wielaard [Tue, 5 Jun 2018 19:29:27 +0000 (21:29 +0200)]
libdw: Make sure id_path can contain max number of build id bytes.

The MAX_BUILD_ID_BYTES is fairly large (64), while normally build-ids
are only 20 bytes long. But if we would encounter a jumbo build-id we
should have enough room to construct the full build-id path.

We used to substract 2 bytes from the max, because 2 chars are used
as subdir. But that should be 1 (2 hex chars is just one 8 bit byte).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Make room for DW_MACRO_hi_user opcode if used.
Mark Wielaard [Tue, 5 Jun 2018 19:04:05 +0000 (21:04 +0200)]
readelf: Make room for DW_MACRO_hi_user opcode if used.

The vendor array should have room for all vendor opcode, including
DW_MACRO_hi_user if used.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdwfl: Make __libdwfl_addrsym a static function in dwfl_module_addrsym.c
Mark Wielaard [Mon, 4 Jun 2018 20:23:48 +0000 (22:23 +0200)]
libdwfl: Make __libdwfl_addrsym a static function in dwfl_module_addrsym.c

__libdwfl_addrsym is only used in the dwfl_module_addrsym.c source.
There is no need to mark this as a (shared) internal function.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Lookup "no" translation for no_str, not "yes".
Mark Wielaard [Thu, 7 Jun 2018 17:42:43 +0000 (19:42 +0200)]
readelf: Lookup "no" translation for no_str, not "yes".

Also use yes_str and no_str in print_debug_abbrev_section
and print_form_data.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Don't allocate string with asprintf, but reuse buffer with sprintf.
Mark Wielaard [Sat, 2 Jun 2018 02:24:01 +0000 (04:24 +0200)]
readelf: Don't allocate string with asprintf, but reuse buffer with sprintf.

Since we are single threaded we can just use a static result buffer for
format_dwarf_addr as long as we make sure to print the result before
calling format_dwarf_addr again. This removes lots of malloc/free calls.

On my machine eu-readelf -N --debug-dump=info libxul.so
goes from 57 seconds to 55 seconds.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Lookup gettext "yes" and "no" only once.
Mark Wielaard [Mon, 4 Jun 2018 09:06:44 +0000 (11:06 +0200)]
readelf: Lookup gettext "yes" and "no" only once.

On my machine eu-readelf -N --debug-dump=info libxul.so > /dev/null
goes from 63 seconds to 57 seconds.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Call __fsetlocking (stdout, FSETLOCKING_BYCALLER).
Mark Wielaard [Sun, 3 Jun 2018 07:28:10 +0000 (09:28 +0200)]
readelf: Call __fsetlocking (stdout, FSETLOCKING_BYCALLER).

We only call printf on stdout from one thread, so we don't need internal
stdio locking for stdout.

On my machine eu-readelf -N --debug-dump=info libxul.so > /dev/null
goes from 65 seconds to 63 seconds.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agotests: Drop shared libraries from self_test_files_exe.
Mark Wielaard [Sat, 2 Jun 2018 12:56:43 +0000 (14:56 +0200)]
tests: Drop shared libraries from self_test_files_exe.

Commit 00d89086 "tests: Split self_test_files into an exe, lib and obj
list" accidentially left the shared libraries in the self_test_files_exe.
Causing all shared libraries to be tested twice. Drop them and keep just
four ET_EXE files: addr2line, elfcmp, objdump and readelf.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoPrepare for 0.171. elfutils-0.171
Mark Wielaard [Fri, 1 Jun 2018 19:16:56 +0000 (21:16 +0200)]
Prepare for 0.171.

Set version to 0.171. Update po/*.po files.
Mention DWARF5, split dwarf and GNU DebugFission support in NEWS.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Try both the relative and absolute paths when finding a .dwo file.
Mark Wielaard [Thu, 31 May 2018 14:57:09 +0000 (16:57 +0200)]
libdw: Try both the relative and absolute paths when finding a .dwo file.

We would give up if one of them failed. With this fixed a self-test with
make check succeeds when building elfutils itself with CFLAGS set to
"-gdwarf-4 -gdwarf-split -O2".

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Fix .debug_types printing with implicit section_info.
Mark Wielaard [Fri, 1 Jun 2018 01:46:10 +0000 (03:46 +0200)]
readelf: Fix .debug_types printing with implicit section_info.

Commit 314e9d7d "readelf: Handle .debug_info first if any other debug
section needs it" disabled section_info printing if it was already
handled. But section_types was an alias for section_info. So unless
section_info was explicitly printed, .debug_types wasn't.

Make section_types its own thing to print .debug_types and make
section_info imply section_types. Add a testcase to make sure
.debug_types is now printed.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Deal with combined normal and split dwarf DebugFission .debug_loc.
Mark Wielaard [Fri, 1 Jun 2018 00:23:37 +0000 (02:23 +0200)]
readelf: Deal with combined normal and split dwarf DebugFission .debug_loc.

Normal and split dwarf from GNU DebugFission look the same, but should
be treated competely separtely. When having a file with both skeletons
and real compile units only note the secoffsets into the real .debug_loc
in readelf. Otherwise or known_locslistptr will get confused.

Add a testfile that combines an normal -gdwarf-4 object with a
-gsplit-dwarf object. libdw already got this right, but add a
run-varlocs.sh test to make sure.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agotests: Split self_test_files into an exe, lib and obj list.
Mark Wielaard [Thu, 31 May 2018 12:35:34 +0000 (14:35 +0200)]
tests: Split self_test_files into an exe, lib and obj list.

Introduce testrun_on_self_exe and testrun_on_self_lib.
Some tests cannot handle (unrelocated) ET_REL object files.
run-get-units-split.sh and run-unit-info.sh only handle executables
and shared libraries. This allows running the whole testsuite on an
elfutils build done with CFLAGS="-gdwarf-4 -gsplit-dwarf -O2".

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agotests: Run run-low_high_pc.sh testcase on split dwarf files.
Mark Wielaard [Thu, 31 May 2018 12:00:27 +0000 (14:00 +0200)]
tests: Run run-low_high_pc.sh testcase on split dwarf files.

Test that the low high pc attributes can be properly resolved also
in split dwarf setups.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Fix overflow warning on 32bit systems with GCC8 in dwarf_getsrclines.
Mark Wielaard [Wed, 30 May 2018 13:51:12 +0000 (15:51 +0200)]
libdw: Fix overflow warning on 32bit systems with GCC8 in dwarf_getsrclines.

ndirs is read from the debug data and should be size checked before use.

https://sourceware.org/bugzilla/show_bug.cgi?id=23248

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Use correct listptr when looking up next loc for locview attr.
Mark Wielaard [Wed, 30 May 2018 09:54:31 +0000 (11:54 +0200)]
readelf: Use correct listptr when looking up next loc for locview attr.

We were using loclistsptr instead of locsptr in print_debug_loc_section.

https://sourceware.org/bugzilla/show_bug.cgi?id=23247

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Don't crash on invalid die in dwarf_dieoffset.
Mark Wielaard [Thu, 31 May 2018 11:01:39 +0000 (13:01 +0200)]
libdw: Don't crash on invalid die in dwarf_dieoffset.

Add explicit test in get-units-invalid for dwarf_cuoffset and
dwarf_dieoffset. Make sure dwarf_dieoffset returns (Dwarf_Off) -1
on failure.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Handle split Dwarf Dies in dwarf_die_addr_die.
Mark Wielaard [Tue, 29 May 2018 21:49:21 +0000 (23:49 +0200)]
libdw: Handle split Dwarf Dies in dwarf_die_addr_die.

dwarf_die_addr_die can be used to turn an Dwarf_Die addr back into a
full Dwarf_Die, just given the original Dwarf debug handle. This now
also works for Dwarf_Dies which originated from a split Dwarf. Whenever
a split Dwarf_CU is found the Dwarf it originated from is registered
with the Dwarf that the skeleton Dwarf_CU came from. All registered
split Dwarfs are then searched by dwarf_die_addr_die if the addr didn't
match the main Dwarf or the alt Dwarf.

One limitation in this implementation is that only DIEs that come from
the main .debug_info in the .dwo are supported. Theoretically there could
also be DIEs in an .debug_type or from other/multiple (comdat) sections.

New tests are added for dwarf-4, dwarf-5, split-dwarf-4, split-dwarf-5
and version 4 and 5 dwo files.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf, libdw: Add GNU DebugFission .debug_loc support.
Mark Wielaard [Mon, 28 May 2018 22:59:28 +0000 (00:59 +0200)]
readelf, libdw: Add GNU DebugFission .debug_loc support.

GNU DebugFission .debug_loc location lists uses the .debug_loc section
in the split dwarf .dwo file. The encoding is a mix of old style DWARF
.debug_loc and new style .debug_loclists.

Add two testcases for the readelf and libdw decoders.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Fix regression with multiple files and implicit debug_info reading.
Mark Wielaard [Tue, 29 May 2018 07:44:38 +0000 (09:44 +0200)]
readelf: Fix regression with multiple files and implicit debug_info reading.

Commit 314e9d7d "readelf: Handle .debug_info first if any other debug
section needs it" introduced a regression when handling multiple files.
The implicit and explicit printing of debuginfo weren't reset and so
the second file would not show (or scan) the .debug_info section when
needed.

Fix by resetting the implicit and explicit section printing flags.
Add a testcase that prints the .debug_loc section for two files and
check that the CUs are resolved.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Fix memory corruption in libdw_find_split_unit.
Mark Wielaard [Sun, 20 May 2018 19:57:39 +0000 (21:57 +0200)]
libdw: Fix memory corruption in libdw_find_split_unit.

Found by valgrind when trying to match a split unit from a .dwo file
that doesn't contain the split unit (as first) match. We would close
the split Dwarf too early, before we had inspected all units in it.

Add a testcase that simulates this. Which failed (at least under valgrind
as run by make distcheck) before the fix.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Handle .debug_str_offsets.
Mark Wielaard [Mon, 30 Apr 2018 00:54:07 +0000 (02:54 +0200)]
readelf: Handle .debug_str_offsets.

The .debug_str_offsets tables are indirect string offsets into the
.debug_str section. For DWARF5 they can be in both the main, skeleton
and split dwarf (.dwo) files.

For DWARF4 with the GNU DebugFission extension the tables will not have
an header and they will only be in the split DWARF (.dwo) file, never in
the main (skeleton) file.

For DWARF5 the (non-split) unit DIE will have a DW_AT_str_offsets_base
attribute pointing at the actual index (after the header). The split
unit will never have this attribute (and use the table at offset zero).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf handle .debug_addr section.
Mark Wielaard [Fri, 27 Apr 2018 22:10:41 +0000 (00:10 +0200)]
readelf handle .debug_addr section.

Add debug-dump=addr which will show the .debug_addr section tables.
The only tricky bit is the fact that GNU DebugFission, a DWARF4
extension, didn't produce unit table headers. So if we see a mixed
DWARF4/5 .debug_addr table we have to reconstruct the table length
from the CU DIE DW_AT_[GNU_]_addr_base offsets.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Handle .debug_loclists in dwarf_getlocation.
Mark Wielaard [Sat, 7 Apr 2018 21:48:27 +0000 (23:48 +0200)]
libdw: Handle .debug_loclists in dwarf_getlocation.

Handle all new DW_LLE opcodes in .debug_loclists in dwarf_getlocation.
__libdw_read_begin_end_pair_inc now also handles a default location
(which is simply the range [0,-1]). Since expression blocks can now
also come from the .debug_loclists section add a new fake_loclists_cu
necessary for checking bounds while parsing expression blocks.

Adapt varlocs test to handle debug-only files.
Test testfileranges5.debug and testfilesplitranges5.debug with it.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Handle .debug_loclists.
Mark Wielaard [Fri, 24 Nov 2017 18:29:57 +0000 (19:29 +0100)]
readelf: Handle .debug_loclists.

The new DWARF5 .debug_loclists sections are like .debug_rnglists, but
plus locations. For Split Dwarf GCC generates the .debug_loclists fully
in the split .dwo file. Any references to addresses need to be resolved
through the skeleton .debug_addr section.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdwfl: Allow partial relocations also for debug files.
Mark Wielaard [Sun, 27 May 2018 12:05:21 +0000 (14:05 +0200)]
libdwfl: Allow partial relocations also for debug files.

__libdwfl_relocate is called for get_dwarf and get_elf. We allow not all
relocations to be resolved for Elf files, but required all relocations
(in the debug sections) to be fully resoled in Dwarf files. This used to
mostly work out with .o ET_REL files when the main Elf was gotten before
the Dwarf. But with .dwo files, we (readelf) might open the .o file just
for the (skeleton) Dwarf. In this case it could happen not all relocations
in the debug sections could be resolved (.debug_info and .debug_addr might
contain referenes to undefined symbols). So allow partial relocations
also for debug files.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Find skeleton units when inspecting split .dwo (--dwarf-skeleton).
Mark Wielaard [Sun, 8 Apr 2018 22:03:43 +0000 (00:03 +0200)]
readelf: Find skeleton units when inspecting split .dwo (--dwarf-skeleton).

To get the right context (especially addresses) when looking at a .dwo file
we really need the skeleton file.  If we can find it (simply replace .dwo
with .o) then use that to get to the split DWARF units so that libdw sets
up all relevant information to resolve.

Also adds a --dwarf-skeleton option so the user can explicitly give a
skeleton file to use (for example when all .o files are linked and removed
already).  Unfortunately this might not work if libdw cannot get from the
skeleton file to the .dwo file (because they have been moved around).
In that case eu-readelf "cheats", it will link up the libdw datastructures
so that the skeleton and split DWARF units are setup correctly anyway.
This does introduce a problem when trying to cleanup the Dwarf handle
ownership graph. So we will deliberately leak memory by not closing the
underlying Dwfl in that case.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Handle .debug_rnglists in dwarf_ranges.
Mark Wielaard [Fri, 6 Apr 2018 16:53:34 +0000 (18:53 +0200)]
libdw: Handle .debug_rnglists in dwarf_ranges.

Handle all new DW_RLE opcodes in .debug_rnglists in dwarf_ranges. Extract
code for reading .debug_addr indexes from dwarf_formaddr as __libdw_addrx
to reuse in __libdw_read_begin_end_pair_inc. And add new testcase for
"plain" DWARF5 and add a new test all-dwarf-ranges to test split DWARF5.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Add .debug_rnglists support.
Mark Wielaard [Fri, 24 Nov 2017 10:16:06 +0000 (11:16 +0100)]
readelf: Add .debug_rnglists support.

Parse the .debug_rnglists section for DWARF5 --debug-dump=ranges.
Add testcase to show both "normal" and "split" DWARF variants are
handled for DWARF4 and DWARF5.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years ago__libdw_cu_addr_base: Cast offset to uintptr_t before returning as pointer.
Mark Wielaard [Fri, 25 May 2018 13:46:09 +0000 (15:46 +0200)]
__libdw_cu_addr_base: Cast offset to uintptr_t before returning as pointer.

Fixes a GCC compile issue on the elfutils-debian-i686 buildbot builder:

dwarf_getlocation_attr.c: In function â€˜addr_valp’:
dwarf_getlocation_attr.c:62:12: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
     return (unsigned char *) offset;
            ^
cc1: all warnings being treated as errors

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Handle all address FORMs for dwarf_highpc, handle errors better.
Mark Wielaard [Tue, 22 May 2018 12:34:06 +0000 (14:34 +0200)]
libdw: Handle all address FORMs for dwarf_highpc, handle errors better.

dwarf_highpc can use any address FORM, not just DW_FORM_addr. Just try
whether the address can be resolved as address. Always set error when
attribute couldn't be found or resolved. When calculating the base
address for a CU don't try to second guess the error code, just treat
an error the same as the attribute not being there.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Support DW_OP_addrx/constx and split DWARF addrx/constx support.
Mark Wielaard [Sun, 20 May 2018 21:30:01 +0000 (23:30 +0200)]
libdw: Support DW_OP_addrx/constx and split DWARF addrx/constx support.

DW_OP_addrx/constx and GNU DebugFission DW_OP_GNU_addr/const_index take
as argument an index into the .debug_addr section for the associated CU.
This index gets resolved through dwarf_getlocation_attr. A new fake addr
CU is created per Dwarf for use with this new attribute. For split DWARF
files, the IDX_debug_addr gets replaced with the skeleton section and the
addr base is resolved immediately when constructing the split DWARF CU.
Move __libdw_cu_addr_base to libdwP.h to share with eu-readelf. Also
make it possible to resolve addrx[1234]/GNU_addr_index also as constant
indexes to (also) show when displaying these attributes in eu-readelf.

A new varlocs tests is added to test the resolving for both the DWARF4
and DWARF5 DW_OP variants. And now that addrx forms are resolved in
split DWARF files add the new DIEs with "single ranges" (those DIEs that
have a lowpc/highpc attribute pair) to run-all-dwarf-ranges.sh.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: print split CUs when given --debug-dump=info+
Mark Wielaard [Fri, 19 Jan 2018 14:45:16 +0000 (15:45 +0100)]
readelf: print split CUs when given --debug-dump=info+

To show the difference between "regular" CUs and split CUs print
offsets and references between { and } instead of [ and ].

When --debug-dump=info+ is given (implied by -w) instead of
--debug-dump=info any skeleton unit will be immediately followed
by the corresponding split compile unit (from the .dwo file).

DWARF section [27] '.debug_info' at offset 0x1075:
 [Offset]
 Compilation unit at offset 0:
 Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
 Unit type: skeleton (4), Unit id: 0xc152129eb4b99599
 [     b]  compile_unit         abbrev: 1
           ranges               (sec_offset) range list [     0]
           low_pc               (addr) +000000000000000000
           stmt_list            (sec_offset) 0
           GNU_dwo_name         (strp) "foo.dwo"
           comp_dir             (strp) "/tmp"
           GNU_pubnames         (flag_present) yes
           GNU_addr_base        (sec_offset) 0
           GNU_dwo_id           (data8) 0xc152129eb4b99599
           GNU_ranges_base      (sec_offset) 0
 Split compilation unit at offset 0:
 Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
 Unit type: skeleton (4), Unit id: 0xc152129eb4b99599
 {     b}  compile_unit         abbrev: 1
           producer             (GNU_str_index) "GNU C11 7.3.0 -gsplit-dwarf -g"
           language             (data1) C99 (12)
           name                 (GNU_str_index) "foo.c"
           comp_dir             (GNU_str_index) "/tmp"
           GNU_dwo_id           (data8) 0xc152129eb4b99599
 {    18}    subprogram           abbrev: 2
             external             (flag_present) yes
             name                 (GNU_str_index) "main"
             decl_file            (data1) foo.c (1)
             decl_line            (data1) 1
             type                 (ref4) {    2b}
             high_pc              (data8) 3
             frame_base           (exprloc)
              [ 0] call_frame_cfa
             GNU_all_call_sites   (flag_present) yes
 {    2b}    base_type            abbrev: 3
             byte_size            (data1) 4
             encoding             (data1) signed (5)
             name                 (string) "int"

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Add new dwarf_cu_info function.
Mark Wielaard [Sun, 20 May 2018 08:35:34 +0000 (10:35 +0200)]
libdw: Add new dwarf_cu_info function.

This allows getting a (split) subdie lazily, only when needed.
All arguments to dwarf_get_units are optional. When not given
then unit DIE and sub DIE are not looked up. This new function
allows them to be looked up when not immediately retrieved with
dwarf_get_units, or for a Dwarf_CU gotten through some other way.

Add a new testcase to make sure the results of calling dwarf_cu_info
and dwarf_get_units are consistent.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Initialize ranges_base, add invalid DWARF test and fix expected output.
Mark Wielaard [Thu, 24 May 2018 13:20:25 +0000 (15:20 +0200)]
libdw: Initialize ranges_base, add invalid DWARF test and fix expected output.

We never initialized the CU ranges_base, which meant we didn't actually
calculate it correctly. This caused bad ranges on some DIEs. The expected
output in the testcase was wrong. We also crashed on invalid dwarf.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Handle GNU DebugFission split ranges.
Mark Wielaard [Fri, 18 May 2018 22:46:02 +0000 (00:46 +0200)]
libdw: Handle GNU DebugFission split ranges.

GNU DebugFission split dwarf handles DW_FORM_sec_offset specially for
attributes that point to ranges. The .debug_ranges section is not in
the .dwo file, but in the main/skeleton object file. The sec_offset is
not relocated (in the ELF file), but is an offset against the skeleton
DIE DW_AT_GNU_ranges_base attribute. dwarf_formudata is changed so it
still looks like a normal offset ptr into the .debug_ranges section.
dwarf_ranges is adapted to look for the .debug_ranges in the main object
file. dwarf_highpc and dwarf_lowpc now handle the highpc and lowpc
attributes being inherited for the split unit DIE from the skeleton.

A new testcase is added to iterate over all ranges in a split GNU
DebugFission file.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Handle split dwarf debuglines.
Mark Wielaard [Thu, 17 May 2018 22:26:56 +0000 (00:26 +0200)]
libdw: Handle split dwarf debuglines.

Split DWARF .dwo files do contain a .debug_line section, but only with
the file table, there is no actual line program. Also split DWARF CU DIEs
don't have a DW_AT_stmt_list attribute. To get at the file (and dir) table
for a split unit DIE take just the files from the .debug_line section
(at offset zero). To get the full line table use the skeleton DIE (which
does have a DW_AT_stmt_list).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Cache ELF directory early. Explicitly set it in dwfl.
Mark Wielaard [Thu, 17 May 2018 17:23:46 +0000 (19:23 +0200)]
libdw: Cache ELF directory early. Explicitly set it in dwfl.

The logic that finds alt files and dwo files relies on having an open
file descriptor. But after all needed ELF data has been read the
underlying Elf file descriptor can be closed. libdwfl in particular
closes file descriptor fairly aggressively. So capture the directory
early on. And make dwfl set it if it has recorded it. Which it will
do now before closing a file descriptor for the main Dwfl_Module file.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Search skeleton DIE for split compile unit DIE attributes.
Mark Wielaard [Mon, 14 May 2018 21:58:25 +0000 (23:58 +0200)]
libdw: Search skeleton DIE for split compile unit DIE attributes.

dwarf_attr_integrate and dwarf_hasattr_integrate should also search
for attributes from the skeleton DIE in case the given DIE is a split
compile unit DIE. Split compile unit DIEs inherit various attributes
from their skeleton unit DIE in DWARF5.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoMark __libdw_find_split_unit mark as internal_function.
Mark Wielaard [Sat, 19 May 2018 16:35:51 +0000 (18:35 +0200)]
Mark __libdw_find_split_unit mark as internal_function.

The prototype and definition should match. On i386 this is important
because it changes the calling convention.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: dwarf_get_units find split units from .dwo.
Mark Wielaard [Thu, 18 Jan 2018 14:03:43 +0000 (15:03 +0100)]
libdw: dwarf_get_units find split units from .dwo.

For a skeleton DIE dwarf_get_units should provide the split DIE as subdie.
This implements that by trying to find the (named) .dwo file and finding
the matching CU in it. The .dwo file is search relative to the current
DWARF or using the comp_dir of the skeleton DIE.

Also fixes a small issue with str_offsets_base_off which is tested in the
new testcase (by getting the name of the split CU DIE).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Recognize GNU DebugFission split units.
Mark Wielaard [Mon, 14 May 2018 15:29:05 +0000 (17:29 +0200)]
libdw: Recognize GNU DebugFission split units.

The split dwarf dwo unit id and type are not in the CU header itself, but
can be found in the CU DIE DW_AT_GNU_dwo attributes. Use this to set the
correct unit_type and id for GNU DebugFission split units. Also show this
information in eu-readelf when printing units.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Add GNU DebugFission attributes, tags, forms and operands.
Mark Wielaard [Mon, 14 May 2018 15:18:11 +0000 (17:18 +0200)]
libdw: Add GNU DebugFission attributes, tags, forms and operands.

Most are handled just like their DWARF5 counterparts.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw, readelf: Handle .debug_*.dwo section name variants.
Mark Wielaard [Sat, 12 May 2018 22:05:10 +0000 (00:05 +0200)]
libdw, readelf: Handle .debug_*.dwo section name variants.

The .debug_*.dwo section names are handled just like their none .dwo
variants.  The section contents is the same as sections without the .dwo
name, but they are only found in split-dwarf files.  This patch allows
opening and inspecting split-dwarf files.  It doesn't yet connect the
split-dwarf with their skeleton (or the other way around).  It also
doesn't yet handle any special split-dwarf attributes or tags.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoelflint: fix typo in error diagnostics
Dmitry V. Levin [Tue, 15 May 2018 20:18:43 +0000 (23:18 +0300)]
elflint: fix typo in error diagnostics

Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
6 years agobackends: add checks for _GLOBAL_OFFSET_TABLE_ and __global_pointer$ on riscv
Andreas Schwab [Tue, 15 May 2018 11:47:02 +0000 (13:47 +0200)]
backends: add checks for _GLOBAL_OFFSET_TABLE_ and __global_pointer$ on riscv

Signed-off-by: Andreas Schwab <schwab@suse.de>
6 years agoreadelf: Fix 32bit compile issues.
Mark Wielaard [Tue, 15 May 2018 09:47:08 +0000 (11:47 +0200)]
readelf: Fix 32bit compile issues.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf, libdw: Handle DWARF5 .debug_macro.
Mark Wielaard [Wed, 6 Dec 2017 11:30:12 +0000 (12:30 +0100)]
readelf, libdw: Handle DWARF5 .debug_macro.

Almost identical to GNU .debug_macro extension. Just accept and use
DW_AT_macros where we accept or use DW_AT_GNU_macros. And be a little
stricter in which FORMs we accept (this could have caused problems
with the GNU variant too). Deals with DW_FORM_strx[1234], but not yet
with imported macros through DW_MACRO_import_sup.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Add DWARF5 .debug_line support.
Mark Wielaard [Thu, 26 Apr 2018 09:53:49 +0000 (11:53 +0200)]
readelf: Add DWARF5 .debug_line support.

This only changes the parsing of the directory and file name tables.
It does this by sharing the printing of (non-CU based) from data from
the .debug_macro code. Adding support for printing strx[1234] form data
by sharing the code that detects the correct str_offsets_base in libdw.

The header format is also cleaned up a bit so that it better lines out.
Testcases adjusted and new ones added.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Fix crashing on illegal/zero Dwarf_Die.
Mark Wielaard [Wed, 9 May 2018 21:27:12 +0000 (23:27 +0200)]
libdw: Fix crashing on illegal/zero Dwarf_Die.

In some cases we create an illegal Dwarf_Die by clearing all fields.
The idea is that dwarf_tag () on such a Dwarf_Die will return
DW_TAG_invalid, to indicate that the Dwarf_Die is unusable (and other
functions will also return errors).  But when "reconstructing" the
Dwarf_Die addr we might use the cu before realizing the Dwarf_Die is
invalid.  Fix this with an explicit NULL check and add a testcase.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoaddr2line: Add explicit fflush for stdout when reading from stdin.
Mark Wielaard [Sat, 12 May 2018 19:30:17 +0000 (21:30 +0200)]
addr2line: Add explicit fflush for stdout when reading from stdin.

To make it possible to use eu-addr2line interactively through a pipe we
need to explicitly flush stdout after handling each line from stdin.

https://sourceware.org/bugzilla/show_bug.cgi?id=23173

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Use raw section data if nothing is available through libdw.
Mark Wielaard [Tue, 24 Apr 2018 14:14:19 +0000 (16:14 +0200)]
readelf: Use raw section data if nothing is available through libdw.

For various debug data sections readelf has its own parsers that don't
rely on libdw data structures or functions. But we still like to get the
data through libdw since that will be uncompressed and/or relocated.
But there can be reasons for libdw to have rejected the section data.
In that case we want to try to parse the "raw" section data.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Handle .debug_info first if any other debug section needs it.
Mark Wielaard [Sat, 28 Apr 2018 21:02:41 +0000 (23:02 +0200)]
readelf: Handle .debug_info first if any other debug section needs it.

Some debug sections need information from the CU DIEs to properly
parse the data. Normally the .debug_info section is one of the first.
But some DWARF producers reorder the sections and put it after some
other debug sections. Make sure we first handle .debug_info if it
is needed by any other debug section.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Handle DW_FORM_[ref|strp]_sup[48] as DW_FORM_GNU_[ref|strp]_alt.
Mark Wielaard [Tue, 8 May 2018 13:34:03 +0000 (15:34 +0200)]
libdw: Handle DW_FORM_[ref|strp]_sup[48] as DW_FORM_GNU_[ref|strp]_alt.

Although we don't yet handle DWARF5 supplemental files, they are like
mostly like GNU alt files.  This way using any of the supplemental files
will at least generate an appropriate error message.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Handle DWARF5 line tables in dwarf_getsrclines.
Mark Wielaard [Sat, 5 May 2018 22:33:27 +0000 (00:33 +0200)]
libdw: Handle DWARF5 line tables in dwarf_getsrclines.

In DWARF5 the actual line number table format doesn't change, except for
not allowing DW_LNE_define_file (but we still just accept it). The
changes are the header having new fields for address and segment
selector sizes, and new formats for the directory and file names tables.

The directory and file name tables are much more flexible in DWARF5, but
we only interpret the actual names and file/dir index relationships,
skipping/ignoring any other information. There also is no new interface
yet to get at the new directory and file properties.

There is some small confusion about the file name table indexing. Older
DWARF versions explicitly called the first file name table 1. DWARF5
implies the first index is 0 (but for file attributes, zero means not
associated with a file). We get away with that by having an actual zero
index for older DWARF versions (the null_fill). It looks like gcc gets
around it by explicitly duplicating the first (0) and second (1) file
name entry in the table. This can also be seen in the new testcase.

The patch looks big because of moving a few initializations around
and because the code that is different for older/newer DWARF got moved
under if statements. But the original old DWARF code path didn't really
change.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibebl: Add new DWARF5 debug section names to default_debugscn_p.
Mark Wielaard [Wed, 25 Apr 2018 10:54:24 +0000 (12:54 +0200)]
libebl: Add new DWARF5 debug section names to default_debugscn_p.

This adds the new DWARF5 debug section names .debug_addr, .debug_line_str,
.debug_loclists, .debug_names, .debug_rnglists and .debug_str_offsets. This
makes sure eu-strip knows to strip them away.

Note that it doesn't add the .dwo variants, nor the .dwp only section
names .debug_cu_index and .debug_tu_index, nor the .debug_sup section
for supplemental DWARF files.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Handle .debug_line_str section.
Mark Wielaard [Wed, 25 Apr 2018 10:40:38 +0000 (12:40 +0200)]
readelf: Handle .debug_line_str section.

It is just a .debug_str section with another name.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agolibdw: Handle DW_FORM_line_strp.
Mark Wielaard [Wed, 25 Apr 2018 10:31:42 +0000 (12:31 +0200)]
libdw: Handle DW_FORM_line_strp.

DW_FORM_line_strp strings come from a separate .debug_line_str section.
Make error messages more distinct (no .debug_str, no .debug_line_str or
not a string form).

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoAdd support for RISC-V
Andreas Schwab [Thu, 19 Apr 2018 15:47:52 +0000 (17:47 +0200)]
Add support for RISC-V

This implements initial support for the RISC-V architecture.  It has
been tested with qemu linux-user emulation
<https://build.opensuse.org/package/live_build_log/openSUSE:Factory:RISCV/elfutils/standard/riscv64>,
with the following unresolved issues

FAIL: run-strip-strmerge.sh
===========================

elflint /home/abuild/rpmbuild/BUILD/elfutils-0.170/tests/elfstrmerge
section [32] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0x51c0 does not match .got section address 0x5010
section [32] '.symtab': symbol 119: st_value out of bounds
FAIL run-strip-strmerge.sh (exit status: 1)

FAIL: run-elflint-self.sh
=========================

section [33] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0x6220 does not match .got section address 0x6008
section [33] '.symtab': symbol 135: st_value out of bounds
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/addr2line
section [33] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0x91d8 does not match .got section address 0x9040
section [33] '.symtab': symbol 163: st_value out of bounds
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elfcmp
section [33] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0x1a2a0 does not match .got section address 0x1a040
section [33] '.symtab': symbol 267: st_value out of bounds
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint
section [33] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0xd418 does not match .got section address 0xd0f0
section [33] '.symtab': symbol 238: st_value out of bounds
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/nm
section [33] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0xa2d0 does not match .got section address 0xa0b0
section [33] '.symtab': symbol 193: st_value out of bounds
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/objdump
section [33] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0x2e5b8 does not match .got section address 0x2e058
section [33] '.symtab': symbol 410: st_value out of bounds
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/readelf
section [32] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0x171b8 does not match .got section address 0x17010
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/libelf/libelf.so
section [32] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0x3a5b0 does not match .got section address 0x3a0d8
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/libdw/libdw.so
section [31] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0xd0c8 does not match .got section address 0xd008
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/backends/libebl_i386.so
section [31] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol value 0xf0c8 does not match .got section address 0xf008
*** failure in /home/abuild/rpmbuild/BUILD/elfutils-0.170/src/elflint --quiet --gnu-ld /home/abuild/rpmbuild/BUILD/elfutils-0.170/backends/libebl_x86_64.so
FAIL run-elflint-self.sh (exit status: 1)

FAIL: run-native-test.sh
========================

/home/abuild/rpmbuild/BUILD/elfutils-0.170/tests/allregs: dwfl_module_register_names: no backend registers known
FAIL run-native-test.sh (exit status: 1)

FAIL: run-backtrace-native-core.sh
==================================

backtrace: backtrace.c:111: callback_verify: Assertion `symname && strcmp (symname, "raise") == 0' failed.
./test-subr.sh: line 84: 26040 Aborted                 (core dumped) LD_LIBRARY_PATH="${built_library_path}${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH" $VALGRIND_CMD "$@"
backtrace-child-core.26027: no main
rmdir: failed to remove 'test-26016': Directory not empty
FAIL run-backtrace-native-core.sh (exit status: 1)

In addition, all tests that use ptrace are failing as linux-user
emulation does not implement it.

There are no regressions for a x86_64 build.

Signed-off-by: Andreas Schwab <schwab@suse.de>
6 years agolibelf: Sync elf.h from glibc
Andreas Schwab [Thu, 19 Apr 2018 15:47:47 +0000 (17:47 +0200)]
libelf: Sync elf.h from glibc

Signed-off-by: Andreas Schwab <schwab@suse.de>
6 years agotests: Test readelf --debug-dump=[decoded]line with min_inst_len > 1.
Mark Wielaard [Mon, 16 Apr 2018 09:40:22 +0000 (11:40 +0200)]
tests: Test readelf --debug-dump=[decoded]line with min_inst_len > 1.

This testcase tests the fix for the readelf --debug-dump=line bug fixed
in commit 40b1f18 "readelf: Fix advance_pc to use op_addr_advance, not
just op_advance."

This tests both the --debug-dump=line (readelf) implementation and the
--debug-dump=decodedline (libdw) implementation. The first fails without
the bug fix. The second was already correct.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Fix advance_pc to use op_addr_advance, not just op_advance.
Mark Wielaard [Mon, 16 Apr 2018 08:25:35 +0000 (10:25 +0200)]
readelf: Fix advance_pc to use op_addr_advance, not just op_advance.

Found by John Mellor-Crummey.

The reason this bug wasn't found earlier is because gcc fixes
minimum_instr_len and max_ops_per_instr to 1 for all architectures
(in theory max_ops_per_instr could be overridden, but I didn't find
any architecture that does). And op_index always seems zero (it looks
like it is really only for special VLWI architectures).

So in all cases I saw it means that:

op_addr_advance = minimum_instr_len * ((op_index + op_advance)
                                       / max_ops_per_instr)
                = 1 * ((0 + op_advance) / 1)
                = op_advance

Completely masking the bug.

The libdw dwarf_getsrclines.c implementation does get this right.
Because it doesn't care about the data representation and so does
the calculation directly.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoreadelf: Only lookup files and show errors in attr_callback when not silent.
Mark Wielaard [Fri, 13 Apr 2018 12:56:48 +0000 (14:56 +0200)]
readelf: Only lookup files and show errors in attr_callback when not silent.

We recently added a couple more sanity checks and show an error when
attributes that represent files cannot be resolved. We should only do
this when the attr_callback should print the attribute information.
When not (for example when not showing the .debug_info section, but
only collecting information about the CUs containing pointers into
other sections) we don't need to lookup the file names, nor print
the errors/warnings.

Signed-off-by: Mark Wielaard <mark@klomp.org>
6 years agoaarch64: Add default cfi rule to restore SP from CFA address.
Mark Wielaard [Wed, 11 Apr 2018 08:37:45 +0000 (10:37 +0200)]
aarch64: Add default cfi rule to restore SP from CFA address.

The CFA is set by default to the stack pointer of the previous frame.
So that is also how we can always restore the SP. This default aarch64
CFI rule is necessary on Fedora 28 with GCC8 to make the run-deleted.sh
and run-backtrace-dwarf.sh testcases work.

Signed-off-by: Mark Wielaard <mark@klomp.org>