summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2023-01-22 00:31:57 +0100
committerMark Wielaard <mark@klomp.org>2023-01-30 22:05:41 +0100
commitb7c7d8776ed46e2237d18fb15c6b72e83cfa259b (patch)
tree880bcb194268909ebac5147a0d10b23fc508f856
parentc6b38c2d670f7db732a34fd8e65e94942801c0f8 (diff)
downloadelfutils-b7c7d8776ed46e2237d18fb15c6b72e83cfa259b.tar.gz
libdw: Search for abstract origin in the correct CU
With gcc -flto the abstract origin of an inlined subroutine could be in a different CU. dwarf_getscopes might return an empty scope if it cannot find the abstract origin scope. So make sure to search in the We also tried to add the origin match in pc_record directly in the current inlined scope. This always failed, causing to do a needless traversal, followed by the full CU scan in dwarf_getscopes. Just always stop the pc_record search and then do the CU origin_match in dwarf_getscopes. Signed-off-by: Mark Wielaard <mark@klomp.org>
-rw-r--r--libdw/ChangeLog6
-rw-r--r--libdw/dwarf_getscopes.c18
-rw-r--r--tests/ChangeLog6
-rw-r--r--tests/Makefile.am1
-rwxr-xr-xtests/run-addr2line-i-test.sh43
-rwxr-xr-xtests/testfile-inlines-lto.bz2bin0 -> 2838 bytes
6 files changed, 66 insertions, 8 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 4c7af94e..71e96c88 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,9 @@
+2023-01-22 Mark Wielaard <mark@klomp.org>
+
+ * dwarf_getscopes.c (pc_record): Return nscopes when done.
+ (dwarf_getscopes): Call __libdw_visit_scopes with
+ inlined_origin CU.
+
2022-12-20 Mark Wielaard <mark@klomp.org>
* Makefile.am (AM_CPPFLAGS): Add -I$(srcdir)/../libebl.
diff --git a/libdw/dwarf_getscopes.c b/libdw/dwarf_getscopes.c
index 5662eecf..833f1ac5 100644
--- a/libdw/dwarf_getscopes.c
+++ b/libdw/dwarf_getscopes.c
@@ -1,5 +1,6 @@
/* Return scope DIEs containing PC address.
Copyright (C) 2005, 2007, 2015 Red Hat, Inc.
+ Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -173,12 +174,8 @@ pc_record (unsigned int depth, struct Dwarf_Die_Chain *die, void *arg)
/* Not there yet. */
return 0;
- /* Now we are in a scope that contains the concrete inlined instance.
- Search it for the inline function's abstract definition.
- If we don't find it, return to search the containing scope.
- If we do find it, the nonzero return value will bail us out
- of the postorder traversal. */
- return __libdw_visit_scopes (depth, die, NULL, &origin_match, NULL, a);
+ /* This is the innermost inline scope, we are done here. */
+ return a->nscopes;
}
@@ -193,8 +190,13 @@ dwarf_getscopes (Dwarf_Die *cudie, Dwarf_Addr pc, Dwarf_Die **scopes)
int result = __libdw_visit_scopes (0, &cu, NULL, &pc_match, &pc_record, &a);
- if (result == 0 && a.scopes != NULL)
- result = __libdw_visit_scopes (0, &cu, NULL, &origin_match, NULL, &a);
+ if (result >= 0 && a.scopes != NULL && a.inlined > 0)
+ {
+ /* We like the find the inline function's abstract definition
+ scope, but that might be in a different CU. */
+ cu.die = CUDIE (a.inlined_origin.cu);
+ result = __libdw_visit_scopes (0, &cu, NULL, &origin_match, NULL, &a);
+ }
if (result > 0)
*scopes = a.scopes;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 14b901b9..6c51eb3b 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2023-01-22 Mark Wielaard <mark@klomp.org>
+
+ * testfile-inlines-lto.bz2: New testfile.
+ * run-addr2line-i-test.sh: Add new lto inlines test.
+ * Makefile.am (EXTRA_DIST): Add testfile-inlines-lto.bz2.
+
2023-01-19 Mark Wielaard <mark@klomp.org>
* run-addr2line-C-test.sh: New test.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index fa7c30ef..36823d94 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -428,6 +428,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
test-core.exec.bz2 run-addr2line-test.sh \
run-addr2line-C-test.sh \
run-addr2line-i-test.sh testfile-inlines.bz2 \
+ testfile-inlines-lto.bz2 \
run-addr2line-i-lex-test.sh testfile-lex-inlines.bz2 \
run-addr2line-i-demangle-test.sh run-addr2line-alt-debugpath.sh \
testfileppc32.bz2 testfileppc64.bz2 \
diff --git a/tests/run-addr2line-i-test.sh b/tests/run-addr2line-i-test.sh
index d08f3cba..4f63e487 100755
--- a/tests/run-addr2line-i-test.sh
+++ b/tests/run-addr2line-i-test.sh
@@ -220,4 +220,47 @@ testrun_compare ${abs_top_builddir}/src/addr2line --pretty-print -a -f -i -e tes
(inlined by) _Z2fuv at /tmp/x.cpp:33
EOF
+# == x.cpp ==
+# g++ x.cpp -g -fPIC -olibx.so -shared -O0 -flto
+#
+# __attribute__((always_inline)) inline
+# int foobar(int i)
+# {
+# return i + 1;
+# }
+#
+# __attribute__((always_inline)) inline
+# int fubar(int i)
+# {
+# return i + 1;
+# }
+#
+# __attribute__((always_inline)) inline
+# int bar(int i)
+# {
+# return fubar(i++);
+# }
+#
+# __attribute__((always_inline)) inline
+# int foo(int i)
+# {
+# return foobar(i++);
+# }
+#
+# int fu(int i)
+# {
+# return foo(i++) + bar(i++);
+# }
+
+testfiles testfile-inlines-lto
+
+testrun_compare ${abs_top_builddir}/src/addr2line --pretty -fiC -e testfile-inlines-lto 0x1118 0x1137 <<\EOF
+foobar(int) at /tmp/x.cpp:4:14
+ (inlined by) foo(int) at /tmp/x.cpp:22:16
+ (inlined by) fu(int) at /tmp/x.cpp:27:13
+fubar(int) at /tmp/x.cpp:10:14
+ (inlined by) bar(int) at /tmp/x.cpp:16:15
+ (inlined by) fu(int) at /tmp/x.cpp:27:24
+EOF
+
exit 0
diff --git a/tests/testfile-inlines-lto.bz2 b/tests/testfile-inlines-lto.bz2
new file mode 100755
index 00000000..7e2e2bfd
--- /dev/null
+++ b/tests/testfile-inlines-lto.bz2
Binary files differ