This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
[PATCH v2] libdw: Try .gnu_debugaltlink paths relative to the debug file
- From: Josh Stone <jistone at redhat dot com>
- To: elfutils-devel at lists dot fedorahosted dot org
- Date: Mon, 16 Dec 2013 15:21:53 -0800
- Subject: [PATCH v2] libdw: Try .gnu_debugaltlink paths relative to the debug file
The existing code was first trying .gnu_debugaltlink paths directly, so
relative paths would start from the current program's working directory.
That's unlikely to be useful, so it was almost always falling back to a
build-id based path.
In Fedora, these paths are relative to the debug file itself, so that's
a better thing to try first. We don't actually have the debug path in
libdw, but we can usually find it from elf->fildes and /proc/self/fd/.
Signed-off-by: Josh Stone <jistone@redhat.com>
---
PS - Mark tipped me to use git-merge-changelog, but that doesn't seem to
worry about keeping dates in order. It's not the first such case in
the ChangeLogs, but I can reorder or re-date mine if desired.
---
libdw/ChangeLog | 5 +++++
libdw/dwarf_begin_elf.c | 42 +++++++++++++++++++++++++++++++++++++++---
tests/ChangeLog | 4 ++++
tests/run-allfcts-multi.sh | 14 ++++++++++----
4 files changed, 58 insertions(+), 7 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 8b1e2c0839be..a61efb8bf763 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-14 Josh Stone <jistone@redhat.com>
+
+ * dwarf_begin_elf.c (build_rel_debugaltlink): New function.
+ (open_debugaltlink): Use it.
+
2013-12-16 Mark Wielaard <mjw@redhat.com>
* libdw.map (ELFUTILS_0.158): Add dwfl_module_getsymtab_first_global.
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index 6cf3aa17855d..3161ef46212d 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -42,8 +42,10 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <libgen.h>
#include "libdwP.h"
+#include "libelfP.h"
#if USE_ZLIB
# include <endian.h>
@@ -136,14 +138,48 @@ try_debugaltlink (Dwarf *result, const char *try_name,
return NULL;
}
+/* Make relative links into an absolute path. */
+static char *
+build_rel_debugaltlink (Dwarf *result, const char *alt_name)
+{
+ if (alt_name[0] == '/' || result->elf->fildes < 0)
+ return NULL;
+
+ char *fd_link;
+ if (asprintf (&fd_link, "/proc/self/fd/%d", result->elf->fildes) == -1)
+ return NULL;
+
+ char *fd_name = canonicalize_file_name (fd_link);
+ free (fd_link);
+ if (fd_name == NULL)
+ return NULL;
+
+ char *rel_name;
+ if (asprintf (&rel_name, "%s/%s", dirname (fd_name), alt_name) == -1)
+ rel_name = NULL;
+ free (fd_name);
+
+ return rel_name;
+}
+
/* For dwz multifile support, ignore if it looks wrong. */
static Dwarf *
open_debugaltlink (Dwarf *result, const char *alt_name,
const uint8_t *build_id, const size_t id_len)
{
- /* First try the name itself, it is either an absolute path or
- a relative one. Sadly we don't know relative from where at
- this point. */
+ /* First try it relative to the debug file. */
+ char *rel_name = build_rel_debugaltlink (result, alt_name);
+ if (rel_name != NULL)
+ {
+ Dwarf *alt = try_debugaltlink (result, rel_name, build_id, id_len);
+ free (rel_name);
+ if (alt != NULL)
+ return result;
+ }
+
+ /* Then try the name itself, it is either an absolute path or
+ a relative one. (Using a path relative to the tool's cwd
+ doesn't make much sense in general, but it's also harmless.) */
if (try_debugaltlink (result, alt_name, build_id, id_len) != NULL)
return result;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index f7007e5a0a4d..297a588c1dbd 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2013-12-14 Josh Stone <jistone@redhat.com>
+
+ * run-allfcts-multi.sh: Test relative altlinks.
+
2013-12-15 Jan Kratochvil <jan.kratochvil@redhat.com>
unwinder: ppc
diff --git a/tests/run-allfcts-multi.sh b/tests/run-allfcts-multi.sh
index 727b76ee5c72..35e3177a57ae 100755
--- a/tests/run-allfcts-multi.sh
+++ b/tests/run-allfcts-multi.sh
@@ -42,15 +42,21 @@ EOF
# dwz test-offset-loop test-offset-loop2 -m test-offset-loop.alt
testfiles test-offset-loop test-offset-loop.alt
-tempfiles allfcts.out
+tempfiles allfcts.in allfcts.out
-# Use head to capture output because the output could be infinite...
-testrun ${abs_builddir}/allfcts test-offset-loop | head -n 20 > allfcts.out
-testrun_compare cat allfcts.out <<\EOF
+cat >allfcts.in <<\EOF
/tmp/test-offset-loop.c:6:get_errno
/tmp/test-offset-loop.c:5:is_error
/tmp/test-offset-loop.c:4:padding
/tmp/test-offset-loop.c:7:main
EOF
+# Use head to capture output because the output could be infinite...
+testrun ${abs_builddir}/allfcts test-offset-loop | head -n 20 > allfcts.out
+testrun_compare cat allfcts.out <allfcts.in
+
+# Repeat from a different directory for relative .gnu_debugaltlink
+(cd / && testrun ${abs_builddir}/allfcts $OLDPWD/test-offset-loop) | head -n 20 > allfcts.out
+testrun_compare cat allfcts.out <allfcts.in
+
exit 0
--
1.8.4.2