diff options
-rw-r--r-- | ldso/include/dl-defs.h | 8 | ||||
-rw-r--r-- | ldso/libdl/libdl.c | 12 |
2 files changed, 18 insertions, 2 deletions
diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h index 791d068bb..4eb14f7a2 100644 --- a/ldso/include/dl-defs.h +++ b/ldso/include/dl-defs.h @@ -179,6 +179,14 @@ typedef struct { #define DL_LOOKUP_ADDRESS(ADDRESS) (ADDRESS) #endif +/* On some architectures dladdr can't use st_size of all symbols this way. */ +#define DL_ADDR_SYM_MATCH(SYM_ADDR, SYM, MATCHSYM, ADDR) \ + ((ADDR) >= (SYM_ADDR) \ + && ((((SYM)->st_shndx == SHN_UNDEF || (SYM)->st_size == 0) \ + && (ADDR) == (SYM_ADDR)) \ + || (ADDR) < (SYM_ADDR) + (SYM)->st_size) \ + && (!(MATCHSYM) || MATCHSYM < (SYM_ADDR))) + /* Use this macro to convert a pointer to a function's entry point to * a pointer to function. The pointer is assumed to have already been * relocated. LOADADDR is passed because it may contain additional diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 05a68ddcc..b3271a181 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -1063,7 +1063,11 @@ int dladdr(const void *__address, Dl_info * __info) ElfW(Addr) symbol_addr; symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value); - if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) { + if ((symtab[si].st_shndx != SHN_UNDEF + || symtab[si].st_value != 0) + && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS + && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa, + (ElfW(Addr)) __address)) { sa = symbol_addr; sn = si; sf = 1; @@ -1079,7 +1083,11 @@ int dladdr(const void *__address, Dl_info * __info) ElfW(Addr) symbol_addr; symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value); - if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) { + if ((symtab[si].st_shndx != SHN_UNDEF + || symtab[si].st_value != 0) + && ELF_ST_TYPE(symtab[si].st_info) != STT_TLS + && DL_ADDR_SYM_MATCH(symbol_addr, &symtab[si], sa, + (ElfW(Addr)) __address)) { sa = symbol_addr; sn = si; sf = 1; |