[haiku-commits] haiku: hrev43953 - src/system/runtime_loader src/system/libroot/posix headers/private/runtime_loader

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 5 Apr 2012 12:32:56 +0200 (CEST)

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,


Other related posts:

  • » [haiku-commits] haiku: hrev43953 - src/system/runtime_loader src/system/libroot/posix headers/private/runtime_loader - ingo_weinhold