diff options
| author | Omar Sandoval <[email protected]> | 2023-12-06 01:22:16 -0800 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2024-02-15 18:33:17 +0100 |
| commit | 985112bc7d0f4eabbaa8a33fdcb241832db54642 (patch) | |
| tree | 4bf7dca434d3fa791bd0ae732598d1e9488159ca /tests | |
| parent | acd9525e93d75d6f0e34c9302051cfebbb8f783f (diff) | |
libdw: Parse DWARF package file index sections
The .debug_cu_index and .debug_tu_index sections in DWARF package files
are basically hash tables mapping a unit's 8 byte signature to an offset
and size in each section used by that unit [1]. Add support for parsing
and doing lookups in the index sections.
We look up a unit in the index when we intern it and cache its hash
table row in Dwarf_CU. Then, a new function, dwarf_cu_dwp_section_info,
can be used to look up the section offsets and sizes for a unit. This
will mostly be used internally in libdw, but it will also be needed in
static inline functions shared with eu-readelf. Additionally, making it
public it makes dwp support much easier for external tools that do their
own low-level parsing of DWARF information, like drgn [2].
1: https://gcc.gnu.org/wiki/DebugFissionDWP#Format_of_the_CU_and_TU_Index_Sections
2: https://github.com/osandov/drgn
* libdw/dwarf.h: Add DW_SECT_TYPES.
* libdw/libdwP.h (Dwarf): Add cu_index and tu_index.
(Dwarf_CU): Add dwp_row.
(Dwarf_Package_Index): New type.
(__libdw_dwp_find_unit): New declaration.
(dwarf_cu_dwp_section_info): New INTDECL.
Add DWARF_E_UNKNOWN_SECTION.
* libdw/Makefile.am (libdw_a_SOURCES): Add
dwarf_cu_dwp_section_info.c.
* libdw/dwarf_end.c (dwarf_end): Free dwarf->cu_index and
dwarf->tu_index.
* libdw/dwarf_error.c (errmsgs): Add DWARF_E_UNKNOWN_SECTION.
* libdw/libdw.h (dwarf_cu_dwp_section_info): New declaration.
* libdw/libdw.map (ELFUTILS_0.190): Add
dwarf_cu_dwp_section_info.
* libdw/libdw_findcu.c (__libdw_intern_next_unit): Call
__libdw_dwp_find_unit, and use it to adjust abbrev_offset and
assign newp->dwp_row.
* libdw/dwarf_cu_dwp_section_info.c: New file.
* tests/Makefile.am (check_PROGRAMS): Add cu-dwp-section-info.
(TESTS): Add run-cu-dwp-section-info.sh
(EXTRA_DIST): Add run-cu-dwp-section-info.sh and new test files.
(cu_dwp_section_info_LDADD): New variable.
* tests/cu-dwp-section-info.c: New test.
* tests/run-cu-dwp-section-info.sh: New test.
* tests/testfile-dwp-4-strict.bz2: New test file.
* tests/testfile-dwp-4-strict.dwp.bz2: New test file.
* tests/testfile-dwp-4.bz2: New test file.
* tests/testfile-dwp-4.dwp.bz2: New test file.
* tests/testfile-dwp-5.bz2: New test file.
* tests/testfile-dwp-5.dwp.bz2: New test file.
* tests/testfile-dwp.source: New file.
Signed-off-by: Omar Sandoval <[email protected]>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/.gitignore | 1 | ||||
| -rw-r--r-- | tests/Makefile.am | 10 | ||||
| -rw-r--r-- | tests/cu-dwp-section-info.c | 73 | ||||
| -rwxr-xr-x | tests/run-cu-dwp-section-info.sh | 168 | ||||
| -rwxr-xr-x | tests/testfile-dwp-4-strict.bz2 | bin | 0 -> 4169 bytes | |||
| -rw-r--r-- | tests/testfile-dwp-4-strict.dwp.bz2 | bin | 0 -> 6871 bytes | |||
| -rwxr-xr-x | tests/testfile-dwp-4.bz2 | bin | 0 -> 4194 bytes | |||
| -rw-r--r-- | tests/testfile-dwp-4.dwp.bz2 | bin | 0 -> 10098 bytes | |||
| -rwxr-xr-x | tests/testfile-dwp-5.bz2 | bin | 0 -> 4223 bytes | |||
| -rw-r--r-- | tests/testfile-dwp-5.dwp.bz2 | bin | 0 -> 10313 bytes | |||
| -rw-r--r-- | tests/testfile-dwp.source | 102 |
11 files changed, 352 insertions, 2 deletions
diff --git a/tests/.gitignore b/tests/.gitignore index d00a883e..d38f0f9e 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -28,6 +28,7 @@ /backtrace-dwarf /buildid /core-dump-backtrace.lock +/cu-dwp-section-info /debugaltlink /debuginfod_build_id_find /debuglink diff --git a/tests/Makefile.am b/tests/Makefile.am index b075e3c3..d7c53144 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -63,6 +63,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ getphdrnum leb128 read_unaligned \ msg_tst system-elf-libelf-test system-elf-gelf-test \ nvidia_extended_linemap_libdw elf-print-reloc-syms \ + cu-dwp-section-info \ $(asm_TESTS) asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ @@ -212,7 +213,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ $(asm_TESTS) run-disasm-bpf.sh run-low_high_pc-dw-form-indirect.sh \ run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \ run-readelf-dw-form-indirect.sh run-strip-largealign.sh \ - run-readelf-Dd.sh run-dwfl-core-noncontig.sh + run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh if !BIARCH export ELFUTILS_DISABLE_BIARCH = 1 @@ -635,7 +636,11 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ run-funcretval++11.sh \ test-ar-duplicates.a.bz2 \ run-dwfl-core-noncontig.sh testcore-noncontig.bz2 \ - testfile-dwarf5-line-clang.bz2 + testfile-dwarf5-line-clang.bz2 \ + testfile-dwp-4.bz2 testfile-dwp-4.dwp.bz2 \ + testfile-dwp-4-strict.bz2 testfile-dwp-4-strict.dwp.bz2 \ + testfile-dwp-5.bz2 testfile-dwp-5.dwp.bz2 testfile-dwp.source \ + run-cu-dwp-section-info.sh if USE_VALGRIND @@ -812,6 +817,7 @@ leb128_LDADD = $(libelf) $(libdw) read_unaligned_LDADD = $(libelf) $(libdw) nvidia_extended_linemap_libdw_LDADD = $(libelf) $(libdw) elf_print_reloc_syms_LDADD = $(libelf) +cu_dwp_section_info_LDADD = $(libdw) # We want to test the libelf headers against the system elf.h header. # Don't include any -I CPPFLAGS. Except when we install our own elf.h. diff --git a/tests/cu-dwp-section-info.c b/tests/cu-dwp-section-info.c new file mode 100644 index 00000000..f1756979 --- /dev/null +++ b/tests/cu-dwp-section-info.c @@ -0,0 +1,73 @@ +/* Test program for dwarf_cu_dwp_section_info + Copyright (c) 2023 Meta Platforms, Inc. and affiliates. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdio.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include <dwarf.h> +#include ELFUTILS_HEADER(dw) + +int +main (int argc, char *argv[]) +{ + for (int i = 1; i < argc; i++) + { + printf ("file: %s\n", argv[i]); + int fd = open (argv[i], O_RDONLY); + Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); + if (dbg == NULL) + { + printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1)); + return -1; + } + + Dwarf_CU *cu = NULL; + while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0) + { +#define SECTION_INFO(section) do { \ + printf (#section ": "); \ + Dwarf_Off offset, size; \ + if (dwarf_cu_dwp_section_info (cu, DW_SECT_##section, \ + &offset, &size) == 0) \ + printf ("0x%" PRIx64 " 0x%" PRIx64 "\n", offset, size); \ + else \ + printf ("%s\n", dwarf_errmsg (-1)); \ + } while (0) + SECTION_INFO (INFO); + SECTION_INFO (TYPES); + SECTION_INFO (ABBREV); + SECTION_INFO (LINE); + SECTION_INFO (LOCLISTS); + SECTION_INFO (STR_OFFSETS); + SECTION_INFO (MACRO); + SECTION_INFO (RNGLISTS); + printf ("\n"); + } + + dwarf_end (dbg); + close (fd); + } + + return 0; +} diff --git a/tests/run-cu-dwp-section-info.sh b/tests/run-cu-dwp-section-info.sh new file mode 100755 index 00000000..202319c6 --- /dev/null +++ b/tests/run-cu-dwp-section-info.sh @@ -0,0 +1,168 @@ +#! /bin/sh +# Copyright (c) 2023 Meta Platforms, Inc. and affiliates. +# This file is part of elfutils. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# elfutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +. $srcdir/test-subr.sh + +# See testfile-dwp.source. +testfiles testfile-dwp-5.dwp testfile-dwp-4.dwp testfile-dwp-4-strict.dwp + +testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-5.dwp << EOF +file: testfile-dwp-5.dwp +INFO: 0x0 0x70 +TYPES: 0x0 0x0 +ABBREV: 0x0 0x160 +LINE: 0x0 0x7f +LOCLISTS: 0x0 0xdb +STR_OFFSETS: 0x0 0x75c +MACRO: 0x0 0x6c6 +RNGLISTS: 0x0 0x22 + +INFO: 0x70 0x108 +TYPES: 0x0 0x0 +ABBREV: 0x0 0x160 +LINE: 0x0 0x7f +LOCLISTS: 0x0 0xdb +STR_OFFSETS: 0x0 0x75c +MACRO: 0x0 0x6c6 +RNGLISTS: 0x0 0x22 + +INFO: 0x178 0x6e +TYPES: 0x0 0x0 +ABBREV: 0x160 0xca +LINE: 0x7f 0x7f +LOCLISTS: 0x0 0x0 +STR_OFFSETS: 0x75c 0x758 +MACRO: 0x6c6 0x6c5 +RNGLISTS: 0x0 0x0 + +INFO: 0x1e6 0x78 +TYPES: 0x0 0x0 +ABBREV: 0x160 0xca +LINE: 0x7f 0x7f +LOCLISTS: 0x0 0x0 +STR_OFFSETS: 0x75c 0x758 +MACRO: 0x6c6 0x6c5 +RNGLISTS: 0x0 0x0 + +INFO: 0x25e 0x193 +TYPES: 0x0 0x0 +ABBREV: 0x22a 0x18a +LINE: 0xfe 0x81 +LOCLISTS: 0xdb 0xc9 +STR_OFFSETS: 0xeb4 0x77c +MACRO: 0xd8b 0x6c6 +RNGLISTS: 0x22 0x43 + +EOF + +testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-4.dwp << EOF +file: testfile-dwp-4.dwp +INFO: 0x0 0x11e +TYPES: 0x0 0x0 +ABBREV: 0x0 0x172 +LINE: 0x0 0x52 +LOCLISTS: 0x0 0x11b +STR_OFFSETS: 0x0 0x754 +MACRO: 0x0 0x6c7 +RNGLISTS: 0x0 0x0 + +INFO: 0x11e 0x76 +TYPES: 0x0 0x0 +ABBREV: 0x172 0xd7 +LINE: 0x52 0x52 +LOCLISTS: 0x0 0x0 +STR_OFFSETS: 0x754 0x750 +MACRO: 0x6c7 0x6c6 +RNGLISTS: 0x0 0x0 + +INFO: 0x194 0x1c5 +TYPES: 0x0 0x0 +ABBREV: 0x249 0x19e +LINE: 0xa4 0x53 +LOCLISTS: 0x11b 0xf1 +STR_OFFSETS: 0xea4 0x774 +MACRO: 0xd8d 0x6c7 +RNGLISTS: 0x0 0x0 + +INFO: 0x0 0x0 +TYPES: 0x0 0x6f +ABBREV: 0x0 0x172 +LINE: 0x0 0x52 +LOCLISTS: 0x0 0x11b +STR_OFFSETS: 0x0 0x754 +MACRO: 0x0 0x6c7 +RNGLISTS: 0x0 0x0 + +INFO: 0x0 0x0 +TYPES: 0x6f 0x6d +ABBREV: 0x172 0xd7 +LINE: 0x52 0x52 +LOCLISTS: 0x0 0x0 +STR_OFFSETS: 0x754 0x750 +MACRO: 0x6c7 0x6c6 +RNGLISTS: 0x0 0x0 + +EOF + +testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-4-strict.dwp << EOF +file: testfile-dwp-4-strict.dwp +INFO: 0x0 0x105 +TYPES: 0x0 0x0 +ABBREV: 0x0 0x15f +LINE: 0x0 0x52 +LOCLISTS: 0x0 0xe2 +STR_OFFSETS: 0x0 0x24 +MACRO: 0x0 0x38e4 +RNGLISTS: 0x0 0x0 + +INFO: 0x105 0x72 +TYPES: 0x0 0x0 +ABBREV: 0x15f 0xd3 +LINE: 0x52 0x52 +LOCLISTS: 0x0 0x0 +STR_OFFSETS: 0x24 0x20 +MACRO: 0x38e4 0x38db +RNGLISTS: 0x0 0x0 + +INFO: 0x177 0x17b +TYPES: 0x0 0x0 +ABBREV: 0x232 0x157 +LINE: 0xa4 0x53 +LOCLISTS: 0xe2 0xb1 +STR_OFFSETS: 0x44 0x44 +MACRO: 0x71bf 0x38f5 +RNGLISTS: 0x0 0x0 + +INFO: 0x0 0x0 +TYPES: 0x0 0x6e +ABBREV: 0x0 0x15f +LINE: 0x0 0x52 +LOCLISTS: 0x0 0xe2 +STR_OFFSETS: 0x0 0x24 +MACRO: 0x0 0x38e4 +RNGLISTS: 0x0 0x0 + +INFO: 0x0 0x0 +TYPES: 0x6e 0x6b +ABBREV: 0x15f 0xd3 +LINE: 0x52 0x52 +LOCLISTS: 0x0 0x0 +STR_OFFSETS: 0x24 0x20 +MACRO: 0x38e4 0x38db +RNGLISTS: 0x0 0x0 + +EOF diff --git a/tests/testfile-dwp-4-strict.bz2 b/tests/testfile-dwp-4-strict.bz2 Binary files differnew file mode 100755 index 00000000..4f419c07 --- /dev/null +++ b/tests/testfile-dwp-4-strict.bz2 diff --git a/tests/testfile-dwp-4-strict.dwp.bz2 b/tests/testfile-dwp-4-strict.dwp.bz2 Binary files differnew file mode 100644 index 00000000..8cc1bbe2 --- /dev/null +++ b/tests/testfile-dwp-4-strict.dwp.bz2 diff --git a/tests/testfile-dwp-4.bz2 b/tests/testfile-dwp-4.bz2 Binary files differnew file mode 100755 index 00000000..ece5817b --- /dev/null +++ b/tests/testfile-dwp-4.bz2 diff --git a/tests/testfile-dwp-4.dwp.bz2 b/tests/testfile-dwp-4.dwp.bz2 Binary files differnew file mode 100644 index 00000000..1a63b42d --- /dev/null +++ b/tests/testfile-dwp-4.dwp.bz2 diff --git a/tests/testfile-dwp-5.bz2 b/tests/testfile-dwp-5.bz2 Binary files differnew file mode 100755 index 00000000..2c768eac --- /dev/null +++ b/tests/testfile-dwp-5.bz2 diff --git a/tests/testfile-dwp-5.dwp.bz2 b/tests/testfile-dwp-5.dwp.bz2 Binary files differnew file mode 100644 index 00000000..ba28e501 --- /dev/null +++ b/tests/testfile-dwp-5.dwp.bz2 diff --git a/tests/testfile-dwp.source b/tests/testfile-dwp.source new file mode 100644 index 00000000..b0b0a97c --- /dev/null +++ b/tests/testfile-dwp.source @@ -0,0 +1,102 @@ +# Nonsensical program used to generate example DWARF package files with type +# units, location lists, range lists, and macros. + +# = foobar.h = + +struct Foo +{ + int a, b; + int foo (); +}; + +struct Bar +{ + long a, b; + long bar (); +}; + +#define FROB(x) ((x) ^ 0x2a2a2a2a) +#define FRY(x) ((x) * 0x100000001b3) + +inline long +fibonacci (unsigned int n) +{ + if (n == 0) + return 0; + else + { + long a = 0; + long b = 1; + for (unsigned int i = 2; i < n; i++) + { + long tmp = a + b; + a = b; + b = tmp; + } + return b; + } +} + +# = foo.cc = + +#include "foobar.h" + +#define ZERO() (1 - 1) + +int +x_x (int x) +{ + for (int i = x; i > ZERO(); i--) + x *= x; + return x; +} + +int +Foo::foo () +{ + int x = a; + if (a > b) + x -= b; + return FROB (x_x (x)); +} + +# = bar.cc = + +#include "foobar.h" + +#define ONE 1 + +long +Bar::bar () +{ + if (a == b) + return ONE; + else + return a > b ? b : a; +} + +# = main.cc = + +#include "foobar.h" + +#define MAIN_ARGS int argc, char **argv + +int +main(MAIN_ARGS) +{ + struct Foo myfoo { argc, FROB (argc) }; + struct Bar mybar { fibonacci (argc), FRY (argc) }; + return myfoo.foo() + mybar.bar(); +} + +# Built with GCC at commit 80048aa13a6b ("debug/111409 - don't generate COMDAT +# macro sections for split DWARF"). +$ g++ -gdwarf-5 -gsplit-dwarf -fdebug-types-section -g3 -O2 foo.cc bar.cc main.cc -o testfile-dwp-5 +# GNU dwp as of binutils 2.41 only supports DWARF 4. +$ llvm-dwp -e testfile-dwp-5 -o testfile-dwp-5.dwp + +$ g++ -gdwarf-4 -gsplit-dwarf -fdebug-types-section -g3 -O2 foo.cc bar.cc main.cc -o testfile-dwp-4 +$ dwp -e testfile-dwp-4 + +$ g++ -gdwarf-4 -gstrict-dwarf -gsplit-dwarf -fdebug-types-section -g3 -O2 foo.cc bar.cc main.cc -o testfile-dwp-4-strict +$ dwp -e testfile-dwp-4-strict |
