#include "pub_core_basics.h"
#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
#include "pub_core_debuginfo.h"
#include "pub_core_libcbase.h"
#include "pub_core_libcprint.h"
#include "pub_core_machine.h" /* VG_ELF_CLASS */
#include "pub_core_options.h"
#include "pub_core_oset.h"
+#include "pub_core_syscall.h"
#include "pub_core_tooliface.h" /* VG_(needs) */
#include "pub_core_xarray.h"
#include "priv_misc.h" /* dinfo_zalloc/free/strdup */
+ (extrapath ? VG_(strlen)(extrapath) : 0)
+ (serverpath ? VG_(strlen)(serverpath) : 0));
+ if (debugname[0] == '/') {
+ VG_(sprintf)(debugpath, "%s", debugname);
+ dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL);
+ if (dimg != NULL) goto dimg_ok;
+ }
+
VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
dimg = open_debug_file(debugpath, buildid, crc, rel_ok, NULL);
if (dimg != NULL) goto dimg_ok;
return True;
}
+/* Helper function to get the readlink path. Returns a copy of path if the
+ file wasn't a symbolic link. Returns NULL on error. Unless NULL is
+ returned the result needs to be released with dinfo_free.
+*/
+static HChar* readlink_path (const HChar *path)
+{
+ SizeT bufsiz = VG_(strlen)(path);
+ HChar *buf = ML_(dinfo_strdup)("readlink_path.strdup", path);
+ UInt tries = 6;
+
+ while (tries > 0) {
+ SysRes res;
+#if defined(VGP_arm64_linux)
+ res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
+ (UWord)path, (UWord)buf, bufsiz);
+#elif defined(VGO_linux) || defined(VGO_darwin)
+ res = VG_(do_syscall3)(__NR_readlink, (UWord)path, (UWord)buf, bufsiz);
+#elif defined(VGO_solaris)
+ res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD, (UWord)path,
+ (UWord)buf, bufsiz);
+#else
+# error Unknown OS
+#endif
+ if (sr_isError(res)) {
+ if (sr_Err(res) == VKI_EINVAL)
+ return buf; // It wasn't a symbolic link, return the strdup result.
+ ML_(dinfo_free)(buf);
+ return NULL;
+ }
+
+ SSizeT r = sr_Res(res);
+ if (r < 0) break;
+ if (r == bufsiz) { // buffer too small; increase and retry
+ bufsiz *= 2 + 16;
+ buf = ML_(dinfo_realloc)("readlink_path.realloc", buf, bufsiz);
+ tries--;
+ continue;
+ }
+ buf[r] = '\0';
+ break;
+ }
+
+ if (tries == 0) { // We tried, but weird long path?
+ ML_(dinfo_free)(buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
/* The central function for reading ELF debug info. For the
object/exe specified by the DebugInfo, find ELF sections, then read
the symbols, line number info, file name info, CFA (stack-unwind
(debugaltlink_escn.szB - buildid_offset)
* 2 + 1);
- /* The altfile might be relative to the debug file or main file. */
+ /* The altfile might be relative to the debug file or main file.
+ Make sure that we got the real file, not a symlink. */
HChar *dbgname = di->fsm.dbgname ? di->fsm.dbgname : di->fsm.filename;
+ HChar* rdbgname = readlink_path (dbgname);
+ if (rdbgname == NULL)
+ rdbgname = ML_(dinfo_strdup)("rdbgname", dbgname);
for (j = 0; j < debugaltlink_escn.szB - buildid_offset; j++)
VG_(sprintf)(
+ buildid_offset + j));
/* See if we can find a matching debug file */
- aimg = find_debug_file( di, dbgname, altbuildid,
+ aimg = find_debug_file( di, rdbgname, altbuildid,
altfile_str_m, 0, True );
+ ML_(dinfo_free)(rdbgname);
+
if (altfile_str_m)
ML_(dinfo_free)(altfile_str_m);
ML_(dinfo_free)(altbuildid);