Ticket #8064: 0001-Fix-dladdr-behaviour2.patch

File 0001-Fix-dladdr-behaviour2.patch, 7.0 KB (added by hamish, 12 years ago)
  • headers/private/runtime_loader/runtime_loader.h

    From f61f8fb2675e29c221a470ed7212826581681dea Mon Sep 17 00:00:00 2001
    From: Hamish Morrison <hamish@lavabit.com>
    Date: Sat, 31 Mar 2012 17:47:08 +0000
    Subject: [PATCH] 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.
    ---
     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 +-
     5 files changed, 55 insertions(+), 41 deletions(-)
    
    diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h
    index 05a2d74..132a674 100644
    a b struct rld_export {  
    3636    status_t (*get_nth_image_symbol)(image_id imageID, int32 num,
    3737        char *symbolName, int32 *nameLength, int32 *symbolType,
    3838        void **_location);
    39     status_t (*get_symbol_at_address)(void* address, image_id* _imageID,
    40         char* nameBuffer, int32* _nameLength, int32* _type, void** _location);
     39    status_t (*get_nearest_symbol_at_address)(void* address,
     40        image_id* _imageID, char** _imagePath, char** _symbolName,
     41        int32* _type, void** _location);
    4142    status_t (*test_executable)(const char *path, char *interpreter);
    4243    status_t (*get_next_image_dependency)(image_id id, uint32 *cookie,
    4344        const char **_name);
  • src/system/libroot/posix/dlfcn.c

    diff --git a/src/system/libroot/posix/dlfcn.c b/src/system/libroot/posix/dlfcn.c
    index 837eb3a..d85c649 100644
    a b dlerror(void)  
    7474int
    7575dladdr(void *address, Dl_info *info)
    7676{
    77     static char sImageName[MAXPATHLEN];
    78     static char sSymbolName[NAME_MAX];
    79 
    8077    image_id image;
    81     int32 nameLength = sizeof(sSymbolName);
     78    char* imagePath;
     79    char* symbolName;
    8280    void* location;
    8381    image_info imageInfo;
    84     sStatus = __gRuntimeLoader->get_symbol_at_address(address, &image,
    85         sSymbolName, &nameLength, NULL, &location);
     82
     83    sStatus = __gRuntimeLoader->get_nearest_symbol_at_address(address, &image,
     84        &imagePath, &symbolName, NULL, &location);
    8685    if (sStatus != B_OK)
    8786        return 0;
    8887
    dladdr(void *address, Dl_info *info)  
    9089    if (sStatus != B_OK)
    9190        return 0;
    9291
    93     strlcpy(sImageName, imageInfo.name, MAXPATHLEN);
    94     info->dli_fname = sImageName;
     92    info->dli_fname = imagePath;
    9593    info->dli_fbase = imageInfo.text;
    96     info->dli_sname = sSymbolName;
     94    info->dli_sname = symbolName;
    9795    info->dli_saddr = location;
    9896
    9997    return 1;
  • src/system/runtime_loader/elf.cpp

    diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp
    index 7423149..ed8822d 100644
    a b out:  
    710710
    711711
    712712status_t
    713 get_symbol_at_address(void* address, image_id* _imageID, char* nameBuffer,
    714     int32* _nameLength, int32* _type, void** _location)
     713get_nearest_symbol_at_address(void* address, image_id* _imageID,
     714    char** _imagePath, char** _symbolName, int32* _type, void** _location)
    715715{
    716716    rld_lock();
    717717
    get_symbol_at_address(void* address, image_id* _imageID, char* nameBuffer,  
    721721        return B_BAD_VALUE;
    722722    }
    723723
    724     for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
     724    struct Elf32_Sym* foundSymbol = NULL;
     725    addr_t foundLocation = (addr_t)NULL;
     726
     727    bool found = false;
     728    for (uint32 i = 0; i < HASHTABSIZE(image) && found == false; i++) {
    725729        for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
    726730                j = HASHCHAINS(image)[j]) {
    727731            struct Elf32_Sym *symbol = &image->syms[j];
    728732            addr_t location = symbol->st_value + image->regions[0].delta;
    729733
    730             if (location <= (addr_t)address
    731                 && location - 1 + symbol->st_size >= (addr_t)address) {
    732                 const char* symbolName = SYMNAME(image, symbol);
    733                 strlcpy(nameBuffer, symbolName, *_nameLength);
    734                 *_nameLength = strlen(symbolName);
    735 
    736                 int32 type;
    737                 if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC)
    738                     type = B_SYMBOL_TYPE_TEXT;
    739                 else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT)
    740                     type = B_SYMBOL_TYPE_DATA;
    741                 else
    742                     type = B_SYMBOL_TYPE_ANY;
    743                     // TODO: check with the return types of that BeOS function
    744 
    745                 if (_imageID != NULL)
    746                     *_imageID = image->id;
    747                 if (_type != NULL)
    748                     *_type = type;
    749                 if (_location != NULL)
    750                     *_location = (void*)location;
     734            if (location <= (addr_t)address && location >= foundLocation) {
     735                foundSymbol = symbol;
     736                foundLocation = location;
    751737
    752                 rld_unlock();
    753                 return B_OK;
     738                // jump out if we have an exact match
     739                if (foundLocation == (addr_t)address) {
     740                    found = true;
     741                    break;
     742                }
    754743            }
    755744        }
    756745    }
    757746
     747    if (_imageID != NULL)
     748        *_imageID = image->id;
     749    if (_imagePath != NULL)
     750        *_imagePath = image->path;
     751
     752    if (foundSymbol != NULL) {
     753        *_symbolName = SYMNAME(image, foundSymbol);
     754
     755        if (_type != NULL) {
     756            if (ELF32_ST_TYPE(foundSymbol->st_info) == STT_FUNC)
     757                *_type = B_SYMBOL_TYPE_TEXT;
     758            else if (ELF32_ST_TYPE(foundSymbol->st_info) == STT_OBJECT)
     759                *_type = B_SYMBOL_TYPE_DATA;
     760            else
     761                *_type = B_SYMBOL_TYPE_ANY;
     762            // TODO: check with the return types of that BeOS function
     763        }
     764
     765        if (_location != NULL)
     766            *_location = (void*)foundLocation;
     767    } else {
     768        *_symbolName = NULL;
     769        if (_location != NULL)
     770            *_location = NULL;
     771    }
     772
    758773    rld_unlock();
    759     return B_BAD_VALUE;
     774    return B_OK;
    760775}
    761776
    762777
  • src/system/runtime_loader/export.cpp

    diff --git a/src/system/runtime_loader/export.cpp b/src/system/runtime_loader/export.cpp
    index 00d44ac..62275c5 100644
    a b struct rld_export gRuntimeLoader = {  
    5151    get_symbol,
    5252    get_library_symbol,
    5353    get_nth_symbol,
    54     get_symbol_at_address,
     54    get_nearest_symbol_at_address,
    5555    test_executable,
    5656    get_next_image_dependency,
    5757
  • src/system/runtime_loader/runtime_loader_private.h

    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 b image_id load_library(char const* path, uint32 flags, bool addOn,  
    6565status_t unload_library(void* handle, image_id imageID, bool addOn);
    6666status_t get_nth_symbol(image_id imageID, int32 num, char* nameBuffer,
    6767    int32* _nameLength, int32* _type, void** _location);
    68 status_t get_symbol_at_address(void* address, image_id* _imageID,
    69     char* nameBuffer, int32* _nameLength, int32* _type, void** _location);
     68status_t get_nearest_symbol_at_address(void* address, image_id* _imageID,
     69    char** _imagePath, char** _symbolName, int32* _type, void** _location);
    7070status_t get_symbol(image_id imageID, char const* symbolName, int32 symbolType,
    7171    bool recursive, image_id* _inImage, void** _location);
    7272status_t get_library_symbol(void* handle, void* caller, const char* symbolName,