Mark Wielaard 6cc1e8
From f3521f1d69312eb476c53eea06ee1187844efe18 Mon Sep 17 00:00:00 2001
Mark Wielaard 6cc1e8
From: Mark Wielaard <mark@klomp.org>
Mark Wielaard 6cc1e8
Date: Sat, 9 Dec 2017 23:01:29 +0100
Mark Wielaard 6cc1e8
Subject: [PATCH] Fix gnu debug alt file resolving.
Mark Wielaard 6cc1e8
Mark Wielaard 6cc1e8
The path to the alt file is relative to the actual debug file.
Mark Wielaard 6cc1e8
Make sure that we got the real file, not a (build-id) symlink.
Mark Wielaard 6cc1e8
---
Mark Wielaard 6cc1e8
 coregrind/m_debuginfo/readelf.c | 57 +++++++++++++++++++++++++++++++++++++++--
Mark Wielaard 6cc1e8
 1 file changed, 55 insertions(+), 2 deletions(-)
Mark Wielaard 6cc1e8
Mark Wielaard 6cc1e8
diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
Mark Wielaard 6cc1e8
index e612250..2d52322 100644
Mark Wielaard 6cc1e8
--- a/coregrind/m_debuginfo/readelf.c
Mark Wielaard 6cc1e8
+++ b/coregrind/m_debuginfo/readelf.c
Mark Wielaard 6cc1e8
@@ -33,6 +33,7 @@
Mark Wielaard 6cc1e8
 
Mark Wielaard 6cc1e8
 #include "pub_core_basics.h"
Mark Wielaard 6cc1e8
 #include "pub_core_vki.h"
Mark Wielaard 6cc1e8
+#include "pub_core_vkiscnums.h"
Mark Wielaard 6cc1e8
 #include "pub_core_debuginfo.h"
Mark Wielaard 6cc1e8
 #include "pub_core_libcbase.h"
Mark Wielaard 6cc1e8
 #include "pub_core_libcprint.h"
Mark Wielaard 6cc1e8
@@ -40,6 +41,7 @@
Mark Wielaard 6cc1e8
 #include "pub_core_machine.h"      /* VG_ELF_CLASS */
Mark Wielaard 6cc1e8
 #include "pub_core_options.h"
Mark Wielaard 6cc1e8
 #include "pub_core_oset.h"
Mark Wielaard 6cc1e8
+#include "pub_core_syscall.h"
Mark Wielaard 6cc1e8
 #include "pub_core_tooliface.h"    /* VG_(needs) */
Mark Wielaard 6cc1e8
 #include "pub_core_xarray.h"
Mark Wielaard 6cc1e8
 #include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
Mark Wielaard 6cc1e8
@@ -1527,6 +1529,51 @@ static Bool check_compression(ElfXX_Shdr* h, DiSlice* s) {
Mark Wielaard 6cc1e8
     return True;
Mark Wielaard 6cc1e8
 }
Mark Wielaard 6cc1e8
 
Mark Wielaard 6cc1e8
+/* Helper function to get the readlink path. Returns NULL on error.
Mark Wielaard 6cc1e8
+   Otherwise the result needs to be released with dinfo_free.
Mark Wielaard 6cc1e8
+*/
Mark Wielaard 6cc1e8
+static HChar* readlink_path (const HChar *path)
Mark Wielaard 6cc1e8
+{
Mark Wielaard 6cc1e8
+   SizeT bufsiz = VG_(strlen)(path);
Mark Wielaard 6cc1e8
+   HChar *buf = ML_(dinfo_strdup)("readlink_path.strdup", path);
Mark Wielaard 6cc1e8
+   UInt   tries = 8;
Mark Wielaard 6cc1e8
+
Mark Wielaard 6cc1e8
+   while (tries > 0) {
Mark Wielaard 6cc1e8
+      SysRes res;
Mark Wielaard 6cc1e8
+#if defined(VGP_arm64_linux)
Mark Wielaard 6cc1e8
+      res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
Mark Wielaard 6cc1e8
+                                              (UWord)path, (UWord)buf, bufsiz);
Mark Wielaard 6cc1e8
+#elif defined(VGO_linux) || defined(VGO_darwin)
Mark Wielaard 6cc1e8
+      res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
Mark Wielaard 6cc1e8
+#elif defined(VGO_solaris)
Mark Wielaard 6cc1e8
+      res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
Mark Wielaard 6cc1e8
+                             (UWord)buf, bufsiz);
Mark Wielaard 6cc1e8
+#else
Mark Wielaard 6cc1e8
+#       error Unknown OS
Mark Wielaard 6cc1e8
+#endif
Mark Wielaard 6cc1e8
+   if (sr_isError(res))
Mark Wielaard 6cc1e8
+      return NULL;
Mark Wielaard 6cc1e8
+
Mark Wielaard 6cc1e8
+   SSizeT r = sr_Res(res);
Mark Wielaard 6cc1e8
+   if (r < 0) break;
Mark Wielaard 6cc1e8
+      if (r == bufsiz) {  // buffer too small; increase and retry
Mark Wielaard 6cc1e8
+         bufsiz *= 2 + 16;
Mark Wielaard 6cc1e8
+         buf = ML_(dinfo_realloc)("readlink_path.realloc", buf, bufsiz);
Mark Wielaard 6cc1e8
+         tries--;
Mark Wielaard 6cc1e8
+         continue;
Mark Wielaard 6cc1e8
+      }
Mark Wielaard 6cc1e8
+      buf[r] = '\0';
Mark Wielaard 6cc1e8
+      break;
Mark Wielaard 6cc1e8
+   }
Mark Wielaard 6cc1e8
+
Mark Wielaard 6cc1e8
+   if (tries == 0) { // We tried, but weird long path?
Mark Wielaard 6cc1e8
+      ML_(dinfo_free)(buf);
Mark Wielaard 6cc1e8
+      return NULL;
Mark Wielaard 6cc1e8
+   }
Mark Wielaard 6cc1e8
+
Mark Wielaard 6cc1e8
+  return buf;
Mark Wielaard 6cc1e8
+}
Mark Wielaard 6cc1e8
+
Mark Wielaard 6cc1e8
 /* The central function for reading ELF debug info.  For the
Mark Wielaard 6cc1e8
    object/exe specified by the DebugInfo, find ELF sections, then read
Mark Wielaard 6cc1e8
    the symbols, line number info, file name info, CFA (stack-unwind
Mark Wielaard 6cc1e8
@@ -2926,8 +2973,12 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
Mark Wielaard 6cc1e8
                                 (debugaltlink_escn.szB - buildid_offset)
Mark Wielaard 6cc1e8
                                 * 2 + 1);
Mark Wielaard 6cc1e8
 
Mark Wielaard 6cc1e8
-         /* The altfile might be relative to the debug file or main file. */
Mark Wielaard 6cc1e8
+         /* The altfile might be relative to the debug file or main file.
Mark Wielaard 6cc1e8
+	    Make sure that we got the real file, not a symlink.  */
Mark Wielaard 6cc1e8
          HChar *dbgname = di->fsm.dbgname ? di->fsm.dbgname : di->fsm.filename;
Mark Wielaard 6cc1e8
+         HChar* rdbgname = readlink_path (dbgname);
Mark Wielaard 6cc1e8
+         if (rdbgname == NULL)
Mark Wielaard 6cc1e8
+            rdbgname = ML_(dinfo_strdup)("rdbgname", dbgname);
Mark Wielaard 6cc1e8
 
Mark Wielaard 6cc1e8
          for (j = 0; j < debugaltlink_escn.szB - buildid_offset; j++)
Mark Wielaard 6cc1e8
             VG_(sprintf)(
Mark Wielaard 6cc1e8
@@ -2937,9 +2988,11 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
Mark Wielaard 6cc1e8
                                         + buildid_offset + j));
Mark Wielaard 6cc1e8
 
Mark Wielaard 6cc1e8
          /* See if we can find a matching debug file */
Mark Wielaard 6cc1e8
-         aimg = find_debug_file( di, dbgname, altbuildid,
Mark Wielaard 6cc1e8
+         aimg = find_debug_file( di, rdbgname, altbuildid,
Mark Wielaard 6cc1e8
                                  altfile_str_m, 0, True );
Mark Wielaard 6cc1e8
 
Mark Wielaard 6cc1e8
+         ML_(dinfo_free)(rdbgname);
Mark Wielaard 6cc1e8
+
Mark Wielaard 6cc1e8
          if (altfile_str_m)
Mark Wielaard 6cc1e8
             ML_(dinfo_free)(altfile_str_m);
Mark Wielaard 6cc1e8
          ML_(dinfo_free)(altbuildid);
Mark Wielaard 6cc1e8
-- 
Mark Wielaard 6cc1e8
1.8.3.1
Mark Wielaard 6cc1e8