changeset 317:3df50603afa9

- dynload fix to get proc name when elf relocation is in use
author Tassilo Philipp
date Tue, 12 Nov 2019 21:16:58 +0100
parents dc8bbffc39e6
children 3124f4c4f293
files dynload/dynload.3 dynload/dynload_unix.c
diffstat 2 files changed, 16 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/dynload/dynload.3	Sat Nov 09 20:34:09 2019 +0100
+++ b/dynload/dynload.3	Tue Nov 12 21:16:58 2019 +0100
@@ -82,7 +82,7 @@
 .Ar sOut .
 If it returns 0, the library name wasn't able to be found. Please note that this might happen in some rare cases, so make sure to always check. Passing a null pointer as
 .Ar pLib
-returns the path to the executable (not guaranteed to be absolute).
+returns the path to the executable (not guaranteed to be absolute - if it isn't it's relative to the working directory the process was started in, not the current one).
 .Pp
 The dlSyms* functions can be used to iterate over symbols. Since they can be used on libraries that are not linked, they are made
 for symbol name lookups, not to get symbols' addresses. For that refer to
--- a/dynload/dynload_unix.c	Sat Nov 09 20:34:09 2019 +0100
+++ b/dynload/dynload_unix.c	Tue Nov 12 21:16:58 2019 +0100
@@ -182,6 +182,7 @@
     /* unable to relate info->dlpi_addr directly to our dlopen handle, let's
      * do what we do on macOS above, re-dlopen the already loaded lib (just
      * increases ref count) and compare handles */
+	/* @@@ might be b/c it's the reloc addr... see below */
     lib = dlopen(info->dlpi_name, RTLD_LIGHTEST);
     if(lib)
       dlclose(lib);
@@ -192,12 +193,20 @@
   if(lib == (void*)d->pLib) {
     l = dl_strlen_strcpy(d->sOut, info->dlpi_name, d->bufSize);
 
-    /* on some platforms (e.g. Linux) dlpi_name is empty for the main process'
-       object, but dlpi_addr is given, in that case lookup name via dladdr */
-    if(l == 0 && d->pLib == NULL && (void*)info->dlpi_addr != NULL) {
-      Dl_info i;
-      if(dladdr((void*)info->dlpi_addr, &i) != 0)
-        l = dl_strlen_strcpy(d->sOut, i.dli_fname, d->bufSize);
+    /* if dlpi_name is empty, lookup name via dladdr(proc_load_addr, ...) */
+    if(l == 0 && d->pLib == NULL) {
+      /* dlpi_addr is the reloc base (0 if PIE), find real virtual load addr */
+      void* vladdr = (void*)info->dlpi_addr;
+      int i = 0;
+      for(; i < info->dlpi_phnum; ++i) {
+        if(info->dlpi_phdr[i].p_type == PT_LOAD) {
+          vladdr = (void*)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
+          break;
+        }
+      }
+      Dl_info di;
+      if(dladdr(vladdr, &di) != 0)
+        l = dl_strlen_strcpy(d->sOut, di.dli_fname, d->bufSize);
     }
   }