Author: axeld Date: 2011-08-07 23:01:23 +0200 (Sun, 07 Aug 2011) New Revision: 42598 Changeset: https://dev.haiku-os.org/changeset/42598 Modified: haiku/trunk/headers/private/runtime_loader/runtime_loader.h haiku/trunk/src/system/libroot/posix/dlfcn.c haiku/trunk/src/system/runtime_loader/elf.cpp haiku/trunk/src/system/runtime_loader/export.cpp haiku/trunk/src/system/runtime_loader/images.cpp haiku/trunk/src/system/runtime_loader/images.h haiku/trunk/src/system/runtime_loader/runtime_loader_private.h Log: * Implemented dladdr() in the runtime loader. This is like a gazillion times faster than before. * This also solves a TODO in dladdr(), although I did not use get_library_symbol() as I didn't quite see how that could fit as the comment suggested; there is now a new function get_symbol_at_address() for this. Modified: haiku/trunk/headers/private/runtime_loader/runtime_loader.h =================================================================== --- haiku/trunk/headers/private/runtime_loader/runtime_loader.h 2011-08-07 20:24:34 UTC (rev 42597) +++ haiku/trunk/headers/private/runtime_loader/runtime_loader.h 2011-08-07 21:01:23 UTC (rev 42598) @@ -1,6 +1,6 @@ /* * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@xxxxxxx - * Copyright 2003-2006, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2003-2011, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -33,8 +33,11 @@ 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); Modified: haiku/trunk/src/system/libroot/posix/dlfcn.c =================================================================== --- haiku/trunk/src/system/libroot/posix/dlfcn.c 2011-08-07 20:24:34 UTC (rev 42597) +++ haiku/trunk/src/system/libroot/posix/dlfcn.c 2011-08-07 21:01:23 UTC (rev 42598) @@ -72,60 +72,31 @@ 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; + static char sImageName[MAXPATHLEN]; + static char sSymbolName[NAME_MAX]; + + 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; - if (info == NULL) + sStatus = get_image_info(image, &imageInfo); + if (sStatus != B_OK) return 0; - imageName[0] = '\0'; - symName[0] = '\0'; - info->dli_fname = imageName; - info->dli_saddr = NULL; - info->dli_sname = symName; + strlcpy(sImageName, imageInfo.name, MAXPATHLEN); + info->dli_fname = sImageName; + info->dli_fbase = imageInfo.text; + info->dli_sname = sSymbolName; + info->dli_saddr = location; - 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; - - 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; } Modified: haiku/trunk/src/system/runtime_loader/elf.cpp =================================================================== --- haiku/trunk/src/system/runtime_loader/elf.cpp 2011-08-07 20:24:34 UTC (rev 42597) +++ haiku/trunk/src/system/runtime_loader/elf.cpp 2011-08-07 21:01:23 UTC (rev 42598) @@ -1,6 +1,6 @@ /* * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@xxxxxxx - * Copyright 2003-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2003-2011, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -710,6 +710,57 @@ 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) { Modified: haiku/trunk/src/system/runtime_loader/export.cpp =================================================================== --- haiku/trunk/src/system/runtime_loader/export.cpp 2011-08-07 20:24:34 UTC (rev 42597) +++ haiku/trunk/src/system/runtime_loader/export.cpp 2011-08-07 21:01:23 UTC (rev 42598) @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2003-2011, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -51,6 +51,7 @@ get_symbol, get_library_symbol, get_nth_symbol, + get_symbol_at_address, test_executable, get_next_image_dependency, Modified: haiku/trunk/src/system/runtime_loader/images.cpp =================================================================== --- haiku/trunk/src/system/runtime_loader/images.cpp 2011-08-07 20:24:34 UTC (rev 42597) +++ haiku/trunk/src/system/runtime_loader/images.cpp 2011-08-07 21:01:23 UTC (rev 42598) @@ -1,6 +1,6 @@ /* * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@xxxxxxx - * Copyright 2003-2009, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2003-2011, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -597,6 +597,22 @@ } +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) { Modified: haiku/trunk/src/system/runtime_loader/images.h =================================================================== --- haiku/trunk/src/system/runtime_loader/images.h 2011-08-07 20:24:34 UTC (rev 42597) +++ haiku/trunk/src/system/runtime_loader/images.h 2011-08-07 21:01:23 UTC (rev 42598) @@ -1,6 +1,6 @@ /* * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@xxxxxxx - * Copyright 2003-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2003-2011, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -66,6 +66,7 @@ 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); Modified: haiku/trunk/src/system/runtime_loader/runtime_loader_private.h =================================================================== --- haiku/trunk/src/system/runtime_loader/runtime_loader_private.h 2011-08-07 20:24:34 UTC (rev 42597) +++ haiku/trunk/src/system/runtime_loader/runtime_loader_private.h 2011-08-07 21:01:23 UTC (rev 42598) @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2003-2011, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -65,6 +65,8 @@ 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,