diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h index 86e33ee53d..05a2d74f6d 100644 --- a/headers/private/runtime_loader/runtime_loader.h +++ b/headers/private/runtime_loader/runtime_loader.h @@ -1,6 +1,6 @@ /* * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2011, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -33,8 +33,11 @@ struct rld_export { int32 symbolType, bool recursive, image_id *_inImage, void **_location); status_t (*get_library_symbol)(void* handle, void* caller, const char* symbolName, void **_location); - status_t (*get_nth_image_symbol)(image_id imageID, int32 num, char *symbolName, - int32 *nameLength, int32 *symbolType, void **_location); + 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 (*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 7d34f20f2a..837eb3ae8e 100644 --- a/src/system/libroot/posix/dlfcn.c +++ b/src/system/libroot/posix/dlfcn.c @@ -72,60 +72,31 @@ dlerror(void) int -dladdr(void *addr, Dl_info *info) +dladdr(void *address, Dl_info *info) { -// TODO: This can be implemented more efficiently in the runtime loader. -// get_library_symbol() already has the code doing that. - char curSymName[NAME_MAX]; - static char symName[NAME_MAX]; - static char imageName[MAXPATHLEN]; - void *symLocation; - int32 cookie; - int32 symType, symNameLength; - uint32 symIndex; - image_info imageInfo; + static char sImageName[MAXPATHLEN]; + static char sSymbolName[NAME_MAX]; - if (info == NULL) + image_id image; + int32 nameLength = sizeof(sSymbolName); + void* location; + image_info imageInfo; + sStatus = __gRuntimeLoader->get_symbol_at_address(address, &image, + sSymbolName, &nameLength, NULL, &location); + if (sStatus != B_OK) return 0; - imageName[0] = '\0'; - symName[0] = '\0'; - info->dli_fname = imageName; - info->dli_saddr = NULL; - info->dli_sname = symName; + sStatus = get_image_info(image, &imageInfo); + if (sStatus != B_OK) + return 0; - cookie = 0; - while (get_next_image_info(0, &cookie, &imageInfo) == B_OK) { - // check if the image holds the symbol - if ((addr_t)addr >= (addr_t)imageInfo.text - && (addr_t)addr < (addr_t)imageInfo.text + imageInfo.text_size) { - strlcpy(imageName, imageInfo.name, MAXPATHLEN); - info->dli_fbase = imageInfo.text; - symIndex = 0; - symNameLength = NAME_MAX; + strlcpy(sImageName, imageInfo.name, MAXPATHLEN); + info->dli_fname = sImageName; + info->dli_fbase = imageInfo.text; + info->dli_sname = sSymbolName; + info->dli_saddr = location; - while (get_nth_image_symbol(imageInfo.id, symIndex, curSymName, - &symNameLength, &symType, &symLocation) == B_OK) { - // check if symbol is the nearest until now - if (symLocation <= addr && symLocation >= info->dli_saddr) { - strlcpy(symName, curSymName, NAME_MAX); - info->dli_saddr = symLocation; - - // stop here if exact match - if (info->dli_saddr == addr) - return 1; - } - symIndex++; - symNameLength = NAME_MAX; - } - break; - } - } - - if (info->dli_saddr != NULL) - return 1; - - return 0; + return 1; } diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp index fd7f9b0225..7423149f06 100644 --- a/src/system/runtime_loader/elf.cpp +++ b/src/system/runtime_loader/elf.cpp @@ -1,6 +1,6 @@ /* * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2011, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -709,6 +709,57 @@ out: } +status_t +get_symbol_at_address(void* address, image_id* _imageID, char* nameBuffer, + int32* _nameLength, int32* _type, void** _location) +{ + rld_lock(); + + image_t* image = find_loaded_image_by_address((addr_t)address); + if (image == NULL) { + rld_unlock(); + return B_BAD_VALUE; + } + + for (uint32 i = 0; i < HASHTABSIZE(image); 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; + + rld_unlock(); + return B_OK; + } + } + } + + rld_unlock(); + return B_BAD_VALUE; +} + + status_t get_symbol(image_id imageID, char const *symbolName, int32 symbolType, bool recursive, image_id *_inImage, void **_location) diff --git a/src/system/runtime_loader/export.cpp b/src/system/runtime_loader/export.cpp index 03b72152f1..00d44ac5b3 100644 --- a/src/system/runtime_loader/export.cpp +++ b/src/system/runtime_loader/export.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2011, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -51,6 +51,7 @@ struct rld_export gRuntimeLoader = { get_symbol, get_library_symbol, get_nth_symbol, + get_symbol_at_address, test_executable, get_next_image_dependency, diff --git a/src/system/runtime_loader/images.cpp b/src/system/runtime_loader/images.cpp index a35bdd5cbb..0446b6d286 100644 --- a/src/system/runtime_loader/images.cpp +++ b/src/system/runtime_loader/images.cpp @@ -1,6 +1,6 @@ /* * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2003-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2011, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -597,6 +597,22 @@ find_loaded_image_by_id(image_id id, bool ignoreDisposable) } +image_t* +find_loaded_image_by_address(addr_t address) +{ + for (image_t* image = sLoadedImages.head; image; image = image->next) { + for (uint32 i = 0; i < image->num_regions; i++) { + elf_region_t& region = image->regions[i]; + if (region.vmstart <= address + && region.vmstart - 1 + region.vmsize >= address) + return image; + } + } + + return NULL; +} + + void set_image_flags_recursively(image_t* image, uint32 flags) { diff --git a/src/system/runtime_loader/images.h b/src/system/runtime_loader/images.h index a9fa9afdf7..a929040b42 100644 --- a/src/system/runtime_loader/images.h +++ b/src/system/runtime_loader/images.h @@ -1,6 +1,6 @@ /* * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2011, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -66,6 +66,7 @@ void dequeue_disposable_image(image_t* image); image_t* find_loaded_image_by_name(char const* name, uint32 typeMask); image_t* find_loaded_image_by_id(image_id id, bool ignoreDisposable); +image_t* find_loaded_image_by_address(addr_t address); void set_image_flags_recursively(image_t* image, uint32 flags); void clear_image_flags_recursively(image_t* image, uint32 flags); diff --git a/src/system/runtime_loader/runtime_loader_private.h b/src/system/runtime_loader/runtime_loader_private.h index 1ff95cd41e..76a1de7ac9 100644 --- a/src/system/runtime_loader/runtime_loader_private.h +++ b/src/system/runtime_loader/runtime_loader_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2003-2011, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -65,6 +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_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,