aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2024-02-26 11:32:48 -0800
committerMark Wielaard <mark@klomp.org>2024-02-29 22:57:09 +0100
commit2ceed6d40ff1606622b51ce0c8ece3d13454ef23 (patch)
treeccdffa8201054964fa5cef9bf1456a7509393d08
parent05bea78f46f6a0cbe13402dca0b5a363ecf66cb1 (diff)
downloadelfutils-2ceed6d40ff1606622b51ce0c8ece3d13454ef23.tar.gz
libdw: Handle split DWARF in dwarf_decl_file
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 <osandov@fb.com>
-rw-r--r--libdw/dwarf_decl_file.c30
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.am8
-rw-r--r--tests/declfiles.c90
-rwxr-xr-xtests/run-declfiles.sh233
5 files changed, 335 insertions, 27 deletions
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;
-
- /* 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);
+ Dwarf_Files *files;
+ size_t nfiles;
+ if (INTUSE(dwarf_getsrcfiles) (&CUDIE (attr_mem.cu), &files, &nfiles) != 0)
+ return NULL;
- 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