* 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.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42598 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2011-08-07 21:01:23 +00:00
parent 5348fbe689
commit b6455c080b
7 changed files with 101 additions and 56 deletions
@@ -1,6 +1,6 @@
/* /*
* Copyright 2008-2009, Ingo Weinhold, [email protected]. * Copyright 2008-2009, Ingo Weinhold, [email protected].
* Copyright 2003-2006, Axel Dörfler, [email protected]. * Copyright 2003-2011, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2002, Manuel J. Petit. All rights reserved. * Copyright 2002, Manuel J. Petit. All rights reserved.
@@ -33,8 +33,11 @@ struct rld_export {
int32 symbolType, bool recursive, image_id *_inImage, void **_location); int32 symbolType, bool recursive, image_id *_inImage, void **_location);
status_t (*get_library_symbol)(void* handle, void* caller, status_t (*get_library_symbol)(void* handle, void* caller,
const char* symbolName, void **_location); const char* symbolName, void **_location);
status_t (*get_nth_image_symbol)(image_id imageID, int32 num, char *symbolName, status_t (*get_nth_image_symbol)(image_id imageID, int32 num,
int32 *nameLength, int32 *symbolType, void **_location); 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 (*test_executable)(const char *path, char *interpreter);
status_t (*get_next_image_dependency)(image_id id, uint32 *cookie, status_t (*get_next_image_dependency)(image_id id, uint32 *cookie,
const char **_name); const char **_name);
+17 -46
View File
@@ -72,61 +72,32 @@ dlerror(void)
int int
dladdr(void *addr, Dl_info *info) dladdr(void *address, Dl_info *info)
{ {
// TODO: This can be implemented more efficiently in the runtime loader. static char sImageName[MAXPATHLEN];
// get_library_symbol() already has the code doing that. static char sSymbolName[NAME_MAX];
char curSymName[NAME_MAX];
static char symName[NAME_MAX]; image_id image;
static char imageName[MAXPATHLEN]; int32 nameLength = sizeof(sSymbolName);
void *symLocation; void* location;
int32 cookie;
int32 symType, symNameLength;
uint32 symIndex;
image_info imageInfo; image_info imageInfo;
sStatus = __gRuntimeLoader->get_symbol_at_address(address, &image,
if (info == NULL) sSymbolName, &nameLength, NULL, &location);
if (sStatus != B_OK)
return 0; return 0;
imageName[0] = '\0'; sStatus = get_image_info(image, &imageInfo);
symName[0] = '\0'; if (sStatus != B_OK)
info->dli_fname = imageName; return 0;
info->dli_saddr = NULL;
info->dli_sname = symName;
cookie = 0; strlcpy(sImageName, imageInfo.name, MAXPATHLEN);
while (get_next_image_info(0, &cookie, &imageInfo) == B_OK) { info->dli_fname = sImageName;
// 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; info->dli_fbase = imageInfo.text;
symIndex = 0; info->dli_sname = sSymbolName;
symNameLength = NAME_MAX; 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; return 1;
} }
symIndex++;
symNameLength = NAME_MAX;
}
break;
}
}
if (info->dli_saddr != NULL)
return 1;
return 0;
}
// __libc_dl*** wrappers // __libc_dl*** wrappers
+52 -1
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2008-2010, Ingo Weinhold, [email protected]. * Copyright 2008-2010, Ingo Weinhold, [email protected].
* Copyright 2003-2008, Axel Dörfler, [email protected]. * Copyright 2003-2011, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2002, Manuel J. Petit. All rights reserved. * 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 status_t
get_symbol(image_id imageID, char const *symbolName, int32 symbolType, get_symbol(image_id imageID, char const *symbolName, int32 symbolType,
bool recursive, image_id *_inImage, void **_location) bool recursive, image_id *_inImage, void **_location)
+2 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2003-2006, Axel Dörfler, [email protected]. * Copyright 2003-2011, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2002, Manuel J. Petit. All rights reserved. * Copyright 2002, Manuel J. Petit. All rights reserved.
@@ -51,6 +51,7 @@ struct rld_export gRuntimeLoader = {
get_symbol, get_symbol,
get_library_symbol, get_library_symbol,
get_nth_symbol, get_nth_symbol,
get_symbol_at_address,
test_executable, test_executable,
get_next_image_dependency, get_next_image_dependency,
+17 -1
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2008-2010, Ingo Weinhold, [email protected]. * Copyright 2008-2010, Ingo Weinhold, [email protected].
* Copyright 2003-2009, Axel Dörfler, [email protected]. * Copyright 2003-2011, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2002, Manuel J. Petit. All rights reserved. * 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 void
set_image_flags_recursively(image_t* image, uint32 flags) set_image_flags_recursively(image_t* image, uint32 flags)
{ {
+2 -1
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. * 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. * Distributed under the terms of the MIT License.
* *
* Copyright 2002, Manuel J. Petit. All rights reserved. * 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_name(char const* name, uint32 typeMask);
image_t* find_loaded_image_by_id(image_id id, bool ignoreDisposable); 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 set_image_flags_recursively(image_t* image, uint32 flags);
void clear_image_flags_recursively(image_t* image, uint32 flags); void clear_image_flags_recursively(image_t* image, uint32 flags);
@@ -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. * Distributed under the terms of the MIT License.
* *
* Copyright 2002, Manuel J. Petit. All rights reserved. * 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 unload_library(void* handle, image_id imageID, bool addOn);
status_t get_nth_symbol(image_id imageID, int32 num, char* nameBuffer, status_t get_nth_symbol(image_id imageID, int32 num, char* nameBuffer,
int32* _nameLength, int32* _type, void** _location); 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, status_t get_symbol(image_id imageID, char const* symbolName, int32 symbolType,
bool recursive, image_id* _inImage, void** _location); bool recursive, image_id* _inImage, void** _location);
status_t get_library_symbol(void* handle, void* caller, const char* symbolName, status_t get_library_symbol(void* handle, void* caller, const char* symbolName,