hrev43953 adds 1 changeset to branch 'master' old head: 71cfb0c8d0a3af846e71cfff8e14eb6412c4b364 new head: 43e7b1c2b0e1c657aa4904a55fe942704f6e4b6b ---------------------------------------------------------------------------- 43e7b1c: Fix dladdr behaviour * If dladdr can't find an exact match, it returns the nearest symbol less than the given address. * If no suitable symbol can be found, but the address is within a loaded library, dladdr returns the library name and base address. Signed-off-by: Ingo Weinhold <ingo_weinhold@xxxxxx> [ Hamish Morrison <hamish@xxxxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev43953 Commit: 43e7b1c2b0e1c657aa4904a55fe942704f6e4b6b URL: http://cgit.haiku-os.org/haiku/commit/?id=43e7b1c Author: Hamish Morrison <hamish@xxxxxxxxxxx> Date: Sat Mar 31 17:47:08 2012 UTC Committer: Ingo Weinhold <ingo_weinhold@xxxxxx> Commit-Date: Thu Apr 5 10:32:31 2012 UTC ---------------------------------------------------------------------------- 5 files changed, 55 insertions(+), 41 deletions(-) headers/private/runtime_loader/runtime_loader.h | 5 +- src/system/libroot/posix/dlfcn.c | 16 ++-- src/system/runtime_loader/elf.cpp | 69 ++++++++++------ src/system/runtime_loader/export.cpp | 2 +- src/system/runtime_loader/runtime_loader_private.h | 4 +- ---------------------------------------------------------------------------- diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h index 05a2d74..132a674 100644 --- a/headers/private/runtime_loader/runtime_loader.h +++ b/headers/private/runtime_loader/runtime_loader.h @@ -36,8 +36,9 @@ struct rld_export { status_t (*get_nth_image_symbol)(image_id imageID, int32 num, char *symbolName, int32 *nameLength, int32 *symbolType, void **_location); - status_t (*get_symbol_at_address)(void* address, image_id* _imageID, - char* nameBuffer, int32* _nameLength, int32* _type, void** _location); + status_t (*get_nearest_symbol_at_address)(void* address, + image_id* _imageID, char** _imagePath, char** _symbolName, + int32* _type, void** _location); status_t (*test_executable)(const char *path, char *interpreter); status_t (*get_next_image_dependency)(image_id id, uint32 *cookie, const char **_name); diff --git a/src/system/libroot/posix/dlfcn.c b/src/system/libroot/posix/dlfcn.c index 837eb3a..d85c649 100644 --- a/src/system/libroot/posix/dlfcn.c +++ b/src/system/libroot/posix/dlfcn.c @@ -74,15 +74,14 @@ dlerror(void) int dladdr(void *address, Dl_info *info) { - static char sImageName[MAXPATHLEN]; - static char sSymbolName[NAME_MAX]; - image_id image; - int32 nameLength = sizeof(sSymbolName); + char* imagePath; + char* symbolName; void* location; image_info imageInfo; - sStatus = __gRuntimeLoader->get_symbol_at_address(address, &image, - sSymbolName, &nameLength, NULL, &location); + + sStatus = __gRuntimeLoader->get_nearest_symbol_at_address(address, &image, + &imagePath, &symbolName, NULL, &location); if (sStatus != B_OK) return 0; @@ -90,10 +89,9 @@ dladdr(void *address, Dl_info *info) if (sStatus != B_OK) return 0; - strlcpy(sImageName, imageInfo.name, MAXPATHLEN); - info->dli_fname = sImageName; + info->dli_fname = imagePath; info->dli_fbase = imageInfo.text; - info->dli_sname = sSymbolName; + info->dli_sname = symbolName; info->dli_saddr = location; return 1; diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp index 7423149..5d3c880 100644 --- a/src/system/runtime_loader/elf.cpp +++ b/src/system/runtime_loader/elf.cpp @@ -710,8 +710,8 @@ out: status_t -get_symbol_at_address(void* address, image_id* _imageID, char* nameBuffer, - int32* _nameLength, int32* _type, void** _location) +get_nearest_symbol_at_address(void* address, image_id* _imageID, + char** _imagePath, char** _symbolName, int32* _type, void** _location) { rld_lock(); @@ -721,42 +721,57 @@ get_symbol_at_address(void* address, image_id* _imageID, char* nameBuffer, return B_BAD_VALUE; } - for (uint32 i = 0; i < HASHTABSIZE(image); i++) { + struct Elf32_Sym* foundSymbol = NULL; + addr_t foundLocation = (addr_t)NULL; + + bool found = false; + for (uint32 i = 0; i < HASHTABSIZE(image) && !found; i++) { for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { struct Elf32_Sym *symbol = &image->syms[j]; addr_t location = symbol->st_value + image->regions[0].delta; - if (location <= (addr_t)address - && location - 1 + symbol->st_size >= (addr_t)address) { - const char* symbolName = SYMNAME(image, symbol); - strlcpy(nameBuffer, symbolName, *_nameLength); - *_nameLength = strlen(symbolName); - - int32 type; - if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC) - type = B_SYMBOL_TYPE_TEXT; - else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT) - type = B_SYMBOL_TYPE_DATA; - else - type = B_SYMBOL_TYPE_ANY; - // TODO: check with the return types of that BeOS function - - if (_imageID != NULL) - *_imageID = image->id; - if (_type != NULL) - *_type = type; - if (_location != NULL) - *_location = (void*)location; + if (location <= (addr_t)address && location >= foundLocation) { + foundSymbol = symbol; + foundLocation = location; - rld_unlock(); - return B_OK; + // jump out if we have an exact match + if (foundLocation == (addr_t)address) { + found = true; + break; + } } } } + if (_imageID != NULL) + *_imageID = image->id; + if (_imagePath != NULL) + *_imagePath = image->path; + + if (foundSymbol != NULL) { + *_symbolName = SYMNAME(image, foundSymbol); + + if (_type != NULL) { + if (ELF32_ST_TYPE(foundSymbol->st_info) == STT_FUNC) + *_type = B_SYMBOL_TYPE_TEXT; + else if (ELF32_ST_TYPE(foundSymbol->st_info) == STT_OBJECT) + *_type = B_SYMBOL_TYPE_DATA; + else + *_type = B_SYMBOL_TYPE_ANY; + // TODO: check with the return types of that BeOS function + } + + if (_location != NULL) + *_location = (void*)foundLocation; + } else { + *_symbolName = NULL; + if (_location != NULL) + *_location = NULL; + } + rld_unlock(); - return B_BAD_VALUE; + return B_OK; } diff --git a/src/system/runtime_loader/export.cpp b/src/system/runtime_loader/export.cpp index 00d44ac..62275c5 100644 --- a/src/system/runtime_loader/export.cpp +++ b/src/system/runtime_loader/export.cpp @@ -51,7 +51,7 @@ struct rld_export gRuntimeLoader = { get_symbol, get_library_symbol, get_nth_symbol, - get_symbol_at_address, + get_nearest_symbol_at_address, test_executable, get_next_image_dependency, diff --git a/src/system/runtime_loader/runtime_loader_private.h b/src/system/runtime_loader/runtime_loader_private.h index 76a1de7..3ac2d0d 100644 --- a/src/system/runtime_loader/runtime_loader_private.h +++ b/src/system/runtime_loader/runtime_loader_private.h @@ -65,8 +65,8 @@ image_id load_library(char const* path, uint32 flags, bool addOn, status_t unload_library(void* handle, image_id imageID, bool addOn); status_t get_nth_symbol(image_id imageID, int32 num, char* nameBuffer, int32* _nameLength, int32* _type, void** _location); -status_t get_symbol_at_address(void* address, image_id* _imageID, - char* nameBuffer, int32* _nameLength, int32* _type, void** _location); +status_t get_nearest_symbol_at_address(void* address, image_id* _imageID, + char** _imagePath, char** _symbolName, int32* _type, void** _location); status_t get_symbol(image_id imageID, char const* symbolName, int32 symbolType, bool recursive, image_id* _inImage, void** _location); status_t get_library_symbol(void* handle, void* caller, const char* symbolName,