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