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

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

    From b952ec392c7b93c7448c6a943eca6bca76f2803e Mon Sep 17 00:00:00 2001
    From: Hamish Morrison <hamish@lavabit.com>
    Date: Sun, 25 Mar 2012 15:43:40 +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                   |   17 ++---
     src/system/runtime_loader/elf.cpp                  |   65 ++++++++++++--------
     src/system/runtime_loader/export.cpp               |    2 +-
     src/system/runtime_loader/runtime_loader_private.h |    4 +-
     5 files changed, 52 insertions(+), 41 deletions(-)
    
    diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h
    index 05a2d74..6b0b922 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** _symName, int32* _type,
     41        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..15d9ff7 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* symName;
    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, &symName, 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 = symName;
    9795    info->dli_saddr = location;
    98 
    9996    return 1;
    10097}
    10198
  • src/system/runtime_loader/elf.cpp

    diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp
    index 7423149..dff0bc1 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** _symName, 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    struct Elf32_Sym* foundSym = NULL;
     725    addr_t foundLocation = (addr_t)NULL;
     726
    724727    for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
    725728        for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
    726729                j = HASHCHAINS(image)[j]) {
    727730            struct Elf32_Sym *symbol = &image->syms[j];
    728731            addr_t location = symbol->st_value + image->regions[0].delta;
    729732
    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;
     733            if (location <= (addr_t)address && location >= foundLocation) {
     734                foundSym = symbol;
     735                foundLocation = location;
    751736
    752                 rld_unlock();
    753                 return B_OK;
     737                // jump out if we have an exact match
     738                if (foundLocation == (addr_t)address)
     739                    goto out;
    754740            }
    755741        }
    756742    }
    757743
     744out:
     745    if (_imageID != NULL)
     746        *_imageID = image->id;
     747    if (_imagePath != NULL)
     748        *_imagePath = image->path;
     749
     750    if (foundSym != NULL) {
     751        *_symName = SYMNAME(image, foundSym);
     752
     753        if (_type != NULL) {
     754            if (ELF32_ST_TYPE(foundSym->st_info) == STT_FUNC)
     755                *_type = B_SYMBOL_TYPE_TEXT;
     756            else if (ELF32_ST_TYPE(foundSym->st_info) == STT_OBJECT)
     757                *_type = B_SYMBOL_TYPE_DATA;
     758            else
     759                *_type = B_SYMBOL_TYPE_ANY;
     760            // TODO: check with the return types of that BeOS function
     761        }
     762
     763        if (_location != NULL)
     764            *_location = (void*)foundLocation;
     765    } else {
     766        *_symName = NULL;
     767        if (_location != NULL)
     768            *_location = NULL;
     769    }
     770
    758771    rld_unlock();
    759     return B_BAD_VALUE;
     772    return B_OK;
    760773}
    761774
    762775
  • 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..23b9de1 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** _symName, 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,