This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]