The dladdr() function is supposed to return 0 if no shared library was found containing the given address, and we neglected to do this and always returned 1. So this patch fixes the return value of dladdr() to match the Linux one, and return 0 when it needs to.
One consequence of this bug was that PR_GetLibraryFilePathname() from the nspr4 library assumed that when dladdr() returned 1, it also returned a non-null filename, and it could strlen() it. Our wrong return value broke this assumption. This patch also fixes the underlying OSv-specific method object::lookup_addr() to set the returned fname and base to the object's values when the address belongs to this object - even if not to any known symbol, because we need this behavior in dladdr(). Fixes #878, but openjdk8-fedora+tomcat still does not work, because of yet another bug. Signed-off-by: Nadav Har'El <[email protected]> --- core/elf.cc | 4 ++-- libc/dlfcn.cc | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/elf.cc b/core/elf.cc index 8eab695..2a413a4 100644 --- a/core/elf.cc +++ b/core/elf.cc @@ -827,6 +827,8 @@ dladdr_info object::lookup_addr(const void* addr) if (addr < _base || addr >= _end) { return ret; } + ret.fname = _pathname.c_str(); + ret.base = _base; auto strtab = dynamic_ptr<char>(DT_STRTAB); auto symtab = dynamic_ptr<Elf64_Sym>(DT_SYMTAB); auto len = symtab_len(); @@ -853,8 +855,6 @@ dladdr_info object::lookup_addr(const void* addr) if (!best.symbol || addr > best.relocated_addr() + best.size()) { return ret; } - ret.fname = _pathname.c_str(); - ret.base = _base; ret.sym = strtab + best.symbol->st_name; ret.addr = best.relocated_addr(); return ret; diff --git a/libc/dlfcn.cc b/libc/dlfcn.cc index 2c28075..ba6bcce 100644 --- a/libc/dlfcn.cc +++ b/libc/dlfcn.cc @@ -123,8 +123,11 @@ extern "C" int dladdr(void *addr, Dl_info *info) info->dli_fbase = ei.base; info->dli_sname = ei.sym; info->dli_saddr = ei.addr; - /* dladdr returns non-zero on success and 0 on error */ - return 1; + // dladdr() should return 0 only when the address is not contained in a + // shared object. It should return 1 when we were able to find the object + // (dli_fname, dli_fbase) even if we couldn't find the specific symbol + // (dli_sname, dli_saddr). + return ei.base ? 1 : 0; } extern "C" char *dlerror(void) -- 2.9.4 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
