# HG changeset patch # User Tassilo Philipp # Date 1573589818 -3600 # Node ID 3df50603afa961f34f418c924cf3955c7a95ddde # Parent dc8bbffc39e6d4064b6549593011d1a4cac372f6 - dynload fix to get proc name when elf relocation is in use diff -r dc8bbffc39e6 -r 3df50603afa9 dynload/dynload.3 --- 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 diff -r dc8bbffc39e6 -r 3df50603afa9 dynload/dynload_unix.c --- 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); } }