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 <[email protected]>
This commit is contained in:
committed by
Ingo Weinhold
parent
71cfb0c8d0
commit
43e7b1c2b0
@@ -36,8 +36,9 @@ struct rld_export {
|
|||||||
status_t (*get_nth_image_symbol)(image_id imageID, int32 num,
|
status_t (*get_nth_image_symbol)(image_id imageID, int32 num,
|
||||||
char *symbolName, int32 *nameLength, int32 *symbolType,
|
char *symbolName, int32 *nameLength, int32 *symbolType,
|
||||||
void **_location);
|
void **_location);
|
||||||
status_t (*get_symbol_at_address)(void* address, image_id* _imageID,
|
status_t (*get_nearest_symbol_at_address)(void* address,
|
||||||
char* nameBuffer, int32* _nameLength, int32* _type, void** _location);
|
image_id* _imageID, char** _imagePath, char** _symbolName,
|
||||||
|
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);
|
||||||
|
|||||||
@@ -74,15 +74,14 @@ dlerror(void)
|
|||||||
int
|
int
|
||||||
dladdr(void *address, Dl_info *info)
|
dladdr(void *address, Dl_info *info)
|
||||||
{
|
{
|
||||||
static char sImageName[MAXPATHLEN];
|
|
||||||
static char sSymbolName[NAME_MAX];
|
|
||||||
|
|
||||||
image_id image;
|
image_id image;
|
||||||
int32 nameLength = sizeof(sSymbolName);
|
char* imagePath;
|
||||||
|
char* symbolName;
|
||||||
void* location;
|
void* location;
|
||||||
image_info imageInfo;
|
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)
|
if (sStatus != B_OK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -90,10 +89,9 @@ dladdr(void *address, Dl_info *info)
|
|||||||
if (sStatus != B_OK)
|
if (sStatus != B_OK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
strlcpy(sImageName, imageInfo.name, MAXPATHLEN);
|
info->dli_fname = imagePath;
|
||||||
info->dli_fname = sImageName;
|
|
||||||
info->dli_fbase = imageInfo.text;
|
info->dli_fbase = imageInfo.text;
|
||||||
info->dli_sname = sSymbolName;
|
info->dli_sname = symbolName;
|
||||||
info->dli_saddr = location;
|
info->dli_saddr = location;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -710,8 +710,8 @@ out:
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
get_symbol_at_address(void* address, image_id* _imageID, char* nameBuffer,
|
get_nearest_symbol_at_address(void* address, image_id* _imageID,
|
||||||
int32* _nameLength, int32* _type, void** _location)
|
char** _imagePath, char** _symbolName, int32* _type, void** _location)
|
||||||
{
|
{
|
||||||
rld_lock();
|
rld_lock();
|
||||||
|
|
||||||
@@ -721,42 +721,57 @@ get_symbol_at_address(void* address, image_id* _imageID, char* nameBuffer,
|
|||||||
return B_BAD_VALUE;
|
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;
|
for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
|
||||||
j = HASHCHAINS(image)[j]) {
|
j = HASHCHAINS(image)[j]) {
|
||||||
struct Elf32_Sym *symbol = &image->syms[j];
|
struct Elf32_Sym *symbol = &image->syms[j];
|
||||||
addr_t location = symbol->st_value + image->regions[0].delta;
|
addr_t location = symbol->st_value + image->regions[0].delta;
|
||||||
|
|
||||||
if (location <= (addr_t)address
|
if (location <= (addr_t)address && location >= foundLocation) {
|
||||||
&& location - 1 + symbol->st_size >= (addr_t)address) {
|
foundSymbol = symbol;
|
||||||
const char* symbolName = SYMNAME(image, symbol);
|
foundLocation = location;
|
||||||
strlcpy(nameBuffer, symbolName, *_nameLength);
|
|
||||||
*_nameLength = strlen(symbolName);
|
|
||||||
|
|
||||||
int32 type;
|
// jump out if we have an exact match
|
||||||
if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC)
|
if (foundLocation == (addr_t)address) {
|
||||||
type = B_SYMBOL_TYPE_TEXT;
|
found = true;
|
||||||
else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT)
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
rld_unlock();
|
||||||
return B_BAD_VALUE;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +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,
|
get_nearest_symbol_at_address,
|
||||||
test_executable,
|
test_executable,
|
||||||
get_next_image_dependency,
|
get_next_image_dependency,
|
||||||
|
|
||||||
|
|||||||
@@ -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 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,
|
status_t get_nearest_symbol_at_address(void* address, image_id* _imageID,
|
||||||
char* nameBuffer, int32* _nameLength, int32* _type, void** _location);
|
char** _imagePath, char** _symbolName, 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,
|
||||||
|
|||||||
Reference in New Issue
Block a user