From: Omar Sandoval <osan...@fb.com> Calling dwarf_decl_file on a split DWARF DIE fails this assertion:
dwarf_decl_file.c:72: dwarf_decl_file: Assertion `cu->files != NULL && cu->files != (void *) -1l' failed. This is because dwarf_decl_file calls dwarf_getsrclines to populate cu->files. For normal units, cu->files is cached by dwarf_getsrclines when it parses the line number information. However, for split units, the line number information is parsed for the skeleton unit, then copied to the split unit's cu->lines. Split units have their own file name table, so cu->files is not copied. The obvious solution is to use dwarf_getsrcfiles instead of relying on implicit caching. Also add a test case for dwarf_decl_file. * libdw/dwarf_decl_file.c (dwarf_decl_file): Use dwarf_getsrcfiles instead of dwarf_getsrclines. * tests/Makefile.am (check_PROGRAMS): Add declfiles. (TESTS): Add run-declfiles.sh. (EXTRA_DIST): Add run-declfiles.sh. (declfiles_LDADD): New variable. * tests/declfiles.c: New test. * tests/run-declfiles.sh: New test. Signed-off-by: Omar Sandoval <osan...@fb.com> --- libdw/dwarf_decl_file.c | 30 ++---- tests/.gitignore | 1 + tests/Makefile.am | 8 +- tests/declfiles.c | 90 ++++++++++++++++ tests/run-declfiles.sh | 233 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 335 insertions(+), 27 deletions(-) create mode 100644 tests/declfiles.c create mode 100755 tests/run-declfiles.sh diff --git a/libdw/dwarf_decl_file.c b/libdw/dwarf_decl_file.c index 7dde4af0..1b91a4e9 100644 --- a/libdw/dwarf_decl_file.c +++ b/libdw/dwarf_decl_file.c @@ -48,35 +48,17 @@ dwarf_decl_file (Dwarf_Die *die) &idx) != 0) return NULL; - /* Get the array of source files for the CU. */ - struct Dwarf_CU *cu = attr_mem.cu; - if (cu->lines == NULL) - { - Dwarf_Lines *lines; - size_t nlines; + Dwarf_Files *files; + size_t nfiles; + if (INTUSE(dwarf_getsrcfiles) (&CUDIE (attr_mem.cu), &files, &nfiles) != 0) + return NULL; - /* Let the more generic function do the work. It'll create more - data but that will be needed in an real program anyway. */ - (void) INTUSE(dwarf_getsrclines) (&CUDIE (cu), &lines, &nlines); - assert (cu->lines != NULL); - } - - if (cu->lines == (void *) -1l) - { - /* If DW_AT_decl_file was present, there should be file information - available. */ - __libdw_seterrno (DWARF_E_INVALID_DWARF); - return NULL; - } - - assert (cu->files != NULL && cu->files != (void *) -1l); - - if (idx >= cu->files->nfiles) + if (idx >= nfiles) { __libdw_seterrno (DWARF_E_INVALID_DWARF); return NULL; } - return cu->files->info[idx].name; + return files->info[idx].name; } OLD_VERSION (dwarf_decl_file, ELFUTILS_0.122) diff --git a/tests/.gitignore b/tests/.gitignore index d38f0f9e..0289959d 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -32,6 +32,7 @@ /debugaltlink /debuginfod_build_id_find /debuglink +/declfiles /deleted /dwarf-die-addr-die /dwarf-getmacros diff --git a/tests/Makefile.am b/tests/Makefile.am index d7c53144..3f80c451 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -63,7 +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 \ + cu-dwp-section-info declfiles \ $(asm_TESTS) asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ @@ -213,7 +213,8 @@ 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-cu-dwp-section-info.sh + run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \ + run-declfiles.sh if !BIARCH export ELFUTILS_DISABLE_BIARCH = 1 @@ -640,7 +641,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ 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 + run-cu-dwp-section-info.sh run-declfiles.sh if USE_VALGRIND @@ -818,6 +819,7 @@ read_unaligned_LDADD = $(libelf) $(libdw) nvidia_extended_linemap_libdw_LDADD = $(libelf) $(libdw) elf_print_reloc_syms_LDADD = $(libelf) cu_dwp_section_info_LDADD = $(libdw) +declfiles_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/declfiles.c b/tests/declfiles.c new file mode 100644 index 00000000..0842d637 --- /dev/null +++ b/tests/declfiles.c @@ -0,0 +1,90 @@ +/* Test program for dwarf_decl_file + Copyright (c) 2024 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 <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +#include <dwarf.h> +#include ELFUTILS_HEADER(dw) + +static void +walk_tree (Dwarf_Die *dwarf_die, int indent) +{ + Dwarf_Die die = *dwarf_die; + do + { + int child_indent = indent; + const char *file = dwarf_decl_file (&die); + if (file != NULL) + { + printf("%*s", indent, ""); + const char *name = dwarf_diename (&die) ?: "???"; + int line, column; + if (dwarf_decl_line (&die, &line) == 0) + { + if (dwarf_decl_column (&die, &column) == 0) + printf ("%s@%s:%d:%d\n", name, file, line, column); + else + printf ("%s@%s:%d\n", name, file, line); + } + else + printf ("%s@%s\n", name, file); + child_indent++; + } + + Dwarf_Die child; + if (dwarf_child (&die, &child) == 0) + walk_tree (&child, child_indent); + } + while (dwarf_siblingof (&die, &die) == 0); +} + +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; + Dwarf_Die cudie, subdie; + uint8_t unit_type; + while (dwarf_get_units (dbg, cu, &cu, NULL, &unit_type, &cudie, &subdie) + == 0) + { + Dwarf_Die *die = unit_type == DW_UT_skeleton ? &subdie : &cudie; + printf (" cu: %s\n", dwarf_diename (die) ?: "???"); + walk_tree (die, 2); + } + + dwarf_end (dbg); + close (fd); + } + + return 0; +} diff --git a/tests/run-declfiles.sh b/tests/run-declfiles.sh new file mode 100755 index 00000000..faba7078 --- /dev/null +++ b/tests/run-declfiles.sh @@ -0,0 +1,233 @@ +#! /bin/sh +# Copyright (c) 2024 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 tests/testfile-dwarf-45.source +testfiles testfile-dwarf-4 testfile-dwarf-5 +testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo +testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo + +testrun_compare ${abs_builddir}/declfiles testfile-dwarf-4 << EOF +file: testfile-dwarf-4 + cu: hello.c + wchar_t@/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h:328:24 + m@/var/tmp/hello/hello.h:1:12 + m@/var/tmp/hello/hello.c:5:5 + foo@/var/tmp/hello/hello.c:20:1 + f@/var/tmp/hello/hello.c:20:14 + baz@/var/tmp/hello/hello.c:8:5 + x@/var/tmp/hello/hello.c:8:14 + r@/var/tmp/hello/hello.c:10:7 + frob@/var/tmp/hello/hello.h:5:1 + a@/var/tmp/hello/hello.h:5:11 + b@/var/tmp/hello/hello.h:5:18 + c@/var/tmp/hello/hello.h:7:7 + foo@/var/tmp/hello/hello.c:20:1 + f@/var/tmp/hello/hello.c:20:14 + frob@/var/tmp/hello/hello.h:5:1 + b@/var/tmp/hello/hello.h:5:18 + a@/var/tmp/hello/hello.h:5:11 + c@/var/tmp/hello/hello.h:7:7 + baz@/var/tmp/hello/hello.c:8:5 + x@/var/tmp/hello/hello.c:8:14 + r@/var/tmp/hello/hello.c:10:7 + foo@/var/tmp/hello/hello.c:20:1 + f@/var/tmp/hello/hello.c:20:14 + main@/var/tmp/hello/hello.c:4:12 + baz@/var/tmp/hello/hello.c:8:5 + x@/var/tmp/hello/hello.c:8:14 + r@/var/tmp/hello/hello.c:10:7 + foo@/var/tmp/hello/hello.c:20:1 + main@/var/tmp/hello/hello.c:4:12 + cu: world.c + m@/var/tmp/hello/hello.h:1:12 + main@/var/tmp/hello/world.c:14:1 + argc@/var/tmp/hello/world.c:14:11 + argv@/var/tmp/hello/world.c:14:30 + n@/var/tmp/hello/world.c:16:15 + calc@/var/tmp/hello/world.c:5:1 + exit@/usr/include/stdlib.h:542:13 + calc@/var/tmp/hello/world.c:5:1 + word@/var/tmp/hello/world.c:5:19 + frob@/var/tmp/hello/hello.h:5:1 + b@/var/tmp/hello/hello.h:5:18 + a@/var/tmp/hello/hello.h:5:11 + c@/var/tmp/hello/hello.h:7:7 + baz@/var/tmp/hello/hello.h:2:12 + frob@/var/tmp/hello/hello.h:5:1 + a@/var/tmp/hello/hello.h:5:11 + b@/var/tmp/hello/hello.h:5:18 + c@/var/tmp/hello/hello.h:7:7 + exit@/usr/include/stdlib.h:542:13 + baz@/var/tmp/hello/hello.h:2:12 +EOF + +testrun_compare ${abs_builddir}/declfiles testfile-dwarf-5 << EOF +file: testfile-dwarf-5 + cu: hello.c + wchar_t@/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h:328:24 + m@/var/tmp/hello/hello.h:1:12 + m@/var/tmp/hello/hello.c:5:5 + foo@/var/tmp/hello/hello.c:20:1 + f@/var/tmp/hello/hello.c:20:14 + baz@/var/tmp/hello/hello.c:8:5 + x@/var/tmp/hello/hello.c:8:14 + r@/var/tmp/hello/hello.c:10:7 + frob@/var/tmp/hello/hello.h:5:1 + a@/var/tmp/hello/hello.h:5:11 + b@/var/tmp/hello/hello.h:5:18 + c@/var/tmp/hello/hello.h:7:7 + foo@/var/tmp/hello/hello.c:20:1 + f@/var/tmp/hello/hello.c:20:14 + frob@/var/tmp/hello/hello.h:5:1 + b@/var/tmp/hello/hello.h:5:18 + a@/var/tmp/hello/hello.h:5:11 + c@/var/tmp/hello/hello.h:7:7 + baz@/var/tmp/hello/hello.c:8:5 + x@/var/tmp/hello/hello.c:8:14 + r@/var/tmp/hello/hello.c:10:7 + foo@/var/tmp/hello/hello.c:20:1 + f@/var/tmp/hello/hello.c:20:14 + baz@/var/tmp/hello/hello.c:8:5 + x@/var/tmp/hello/hello.c:8:14 + r@/var/tmp/hello/hello.c:10:7 + main@/var/tmp/hello/hello.c:4:12 + cu: world.c + m@/var/tmp/hello/hello.h:1:12 + main@/var/tmp/hello/world.c:14:1 + argc@/var/tmp/hello/world.c:14:11 + argv@/var/tmp/hello/world.c:14:30 + n@/var/tmp/hello/world.c:16:15 + calc@/var/tmp/hello/world.c:5:1 + word@/var/tmp/hello/world.c:5:19 + frob@/var/tmp/hello/hello.h:5:1 + b@/var/tmp/hello/hello.h:5:18 + a@/var/tmp/hello/hello.h:5:11 + c@/var/tmp/hello/hello.h:7:7 + frob@/var/tmp/hello/hello.h:5:1 + a@/var/tmp/hello/hello.h:5:11 + b@/var/tmp/hello/hello.h:5:18 + c@/var/tmp/hello/hello.h:7:7 + exit@/usr/include/stdlib.h:542:13 + baz@/var/tmp/hello/hello.h:2:12 +EOF + +testrun_compare ${abs_builddir}/declfiles testfile-splitdwarf-4 << EOF +file: testfile-splitdwarf-4 + cu: hello.c + wchar_t@/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h:328:24 + m@/home/mark/src/elfutils/tests/hello.h:1:12 + m@/home/mark/src/elfutils/tests/hello.c:5:5 + foo@/home/mark/src/elfutils/tests/hello.c:20:1 + f@/home/mark/src/elfutils/tests/hello.c:20:14 + baz@/home/mark/src/elfutils/tests/hello.c:8:5 + x@/home/mark/src/elfutils/tests/hello.c:8:14 + r@/home/mark/src/elfutils/tests/hello.c:10:7 + frob@/home/mark/src/elfutils/tests/hello.h:5:1 + a@/home/mark/src/elfutils/tests/hello.h:5:11 + b@/home/mark/src/elfutils/tests/hello.h:5:18 + c@/home/mark/src/elfutils/tests/hello.h:7:7 + foo@/home/mark/src/elfutils/tests/hello.c:20:1 + f@/home/mark/src/elfutils/tests/hello.c:20:14 + frob@/home/mark/src/elfutils/tests/hello.h:5:1 + b@/home/mark/src/elfutils/tests/hello.h:5:18 + a@/home/mark/src/elfutils/tests/hello.h:5:11 + c@/home/mark/src/elfutils/tests/hello.h:7:7 + baz@/home/mark/src/elfutils/tests/hello.c:8:5 + x@/home/mark/src/elfutils/tests/hello.c:8:14 + r@/home/mark/src/elfutils/tests/hello.c:10:7 + foo@/home/mark/src/elfutils/tests/hello.c:20:1 + f@/home/mark/src/elfutils/tests/hello.c:20:14 + main@/home/mark/src/elfutils/tests/hello.c:4:12 + baz@/home/mark/src/elfutils/tests/hello.c:8:5 + x@/home/mark/src/elfutils/tests/hello.c:8:14 + r@/home/mark/src/elfutils/tests/hello.c:10:7 + foo@/home/mark/src/elfutils/tests/hello.c:20:1 + main@/home/mark/src/elfutils/tests/hello.c:4:12 + cu: world.c + m@/home/mark/src/elfutils/tests/hello.h:1:12 + main@/home/mark/src/elfutils/tests/world.c:14:1 + argc@/home/mark/src/elfutils/tests/world.c:14:11 + argv@/home/mark/src/elfutils/tests/world.c:14:30 + n@/home/mark/src/elfutils/tests/world.c:16:15 + calc@/home/mark/src/elfutils/tests/world.c:5:1 + exit@/usr/include/stdlib.h:542:13 + calc@/home/mark/src/elfutils/tests/world.c:5:1 + word@/home/mark/src/elfutils/tests/world.c:5:19 + frob@/home/mark/src/elfutils/tests/hello.h:5:1 + b@/home/mark/src/elfutils/tests/hello.h:5:18 + a@/home/mark/src/elfutils/tests/hello.h:5:11 + c@/home/mark/src/elfutils/tests/hello.h:7:7 + baz@/home/mark/src/elfutils/tests/hello.h:2:12 + frob@/home/mark/src/elfutils/tests/hello.h:5:1 + a@/home/mark/src/elfutils/tests/hello.h:5:11 + b@/home/mark/src/elfutils/tests/hello.h:5:18 + c@/home/mark/src/elfutils/tests/hello.h:7:7 + exit@/usr/include/stdlib.h:542:13 + baz@/home/mark/src/elfutils/tests/hello.h:2:12 +EOF + +testrun_compare ${abs_builddir}/declfiles testfile-splitdwarf-5 << EOF +file: testfile-splitdwarf-5 + cu: hello.c + wchar_t@/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h:328:24 + m@/home/mark/src/elfutils/tests/hello.h:1:12 + m@/home/mark/src/elfutils/tests/hello.c:5:5 + foo@/home/mark/src/elfutils/tests/hello.c:20:1 + f@/home/mark/src/elfutils/tests/hello.c:20:14 + baz@/home/mark/src/elfutils/tests/hello.c:8:5 + x@/home/mark/src/elfutils/tests/hello.c:8:14 + r@/home/mark/src/elfutils/tests/hello.c:10:7 + frob@/home/mark/src/elfutils/tests/hello.h:5:1 + a@/home/mark/src/elfutils/tests/hello.h:5:11 + b@/home/mark/src/elfutils/tests/hello.h:5:18 + c@/home/mark/src/elfutils/tests/hello.h:7:7 + foo@/home/mark/src/elfutils/tests/hello.c:20:1 + f@/home/mark/src/elfutils/tests/hello.c:20:14 + frob@/home/mark/src/elfutils/tests/hello.h:5:1 + b@/home/mark/src/elfutils/tests/hello.h:5:18 + a@/home/mark/src/elfutils/tests/hello.h:5:11 + c@/home/mark/src/elfutils/tests/hello.h:7:7 + baz@/home/mark/src/elfutils/tests/hello.c:8:5 + x@/home/mark/src/elfutils/tests/hello.c:8:14 + r@/home/mark/src/elfutils/tests/hello.c:10:7 + foo@/home/mark/src/elfutils/tests/hello.c:20:1 + f@/home/mark/src/elfutils/tests/hello.c:20:14 + baz@/home/mark/src/elfutils/tests/hello.c:8:5 + x@/home/mark/src/elfutils/tests/hello.c:8:14 + r@/home/mark/src/elfutils/tests/hello.c:10:7 + main@/home/mark/src/elfutils/tests/hello.c:4:12 + cu: world.c + m@/home/mark/src/elfutils/tests/hello.h:1:12 + main@/home/mark/src/elfutils/tests/world.c:14:1 + argc@/home/mark/src/elfutils/tests/world.c:14:11 + argv@/home/mark/src/elfutils/tests/world.c:14:30 + n@/home/mark/src/elfutils/tests/world.c:16:15 + calc@/home/mark/src/elfutils/tests/world.c:5:1 + word@/home/mark/src/elfutils/tests/world.c:5:19 + frob@/home/mark/src/elfutils/tests/hello.h:5:1 + b@/home/mark/src/elfutils/tests/hello.h:5:18 + a@/home/mark/src/elfutils/tests/hello.h:5:11 + c@/home/mark/src/elfutils/tests/hello.h:7:7 + frob@/home/mark/src/elfutils/tests/hello.h:5:1 + a@/home/mark/src/elfutils/tests/hello.h:5:11 + b@/home/mark/src/elfutils/tests/hello.h:5:18 + c@/home/mark/src/elfutils/tests/hello.h:7:7 + exit@/usr/include/stdlib.h:542:13 + baz@/home/mark/src/elfutils/tests/hello.h:2:12 +EOF -- 2.43.2