From e2040be89367877a41947757787c3e24b2c7baff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 24 Oct 2008 09:53:48 +0000 Subject: [PATCH] * Applied patch by Romain Picard: added support for the GNU extension dladdr(), thanks! * This closes ticket #2818. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28308 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/posix/dlfcn.h | 17 +++++++-- src/system/libroot/posix/dlfcn.c | 64 ++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 6 deletions(-) diff --git a/headers/posix/dlfcn.h b/headers/posix/dlfcn.h index f671bd2430..ff673e2a76 100644 --- a/headers/posix/dlfcn.h +++ b/headers/posix/dlfcn.h @@ -1,8 +1,10 @@ +/* + * Copyright 2003-2008, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ #ifndef _DLFCN_H #define _DLFCN_H -/* -** Distributed under the terms of the OpenBeOS License. -*/ + #include @@ -17,10 +19,19 @@ extern "C" { #endif +/* This is a gnu extension for the dladdr function */ +typedef struct { + const char *dli_fname; /* Filename of defining object */ + void *dli_fbase; /* Load address of that object */ + const char *dli_sname; /* Name of nearest lower symbol */ + void *dli_saddr; /* Exact value of nearest symbol */ +} Dl_info; + extern int dlclose(void *image); extern char *dlerror(void); extern void *dlopen(const char *path, int mode); extern void *dlsym(void *image, const char *symbolName); +extern int dladdr(void *addr, Dl_info *info); #ifdef __cplusplus } diff --git a/src/system/libroot/posix/dlfcn.c b/src/system/libroot/posix/dlfcn.c index 3c9c69d21f..c28fbf91cc 100644 --- a/src/system/libroot/posix/dlfcn.c +++ b/src/system/libroot/posix/dlfcn.c @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2002, Manuel J. Petit. All rights reserved. @@ -72,6 +72,64 @@ dlerror(void) } +int +dladdr(void *addr, Dl_info *info) +{ + char curSymName[NAME_MAX]; + static char symName[NAME_MAX]; + static char imageName[MAXPATHLEN]; + void *symLocation; + int32 cookie; + int32 symType, symNameLength; + uint32 symIndex; + image_info imageInfo; + + if (info == NULL) + return 0; + + imageName[0] = '\0'; + symName[0] = '\0'; + info->dli_fname = imageName; + info->dli_saddr = NULL; + info->dli_sname = symName; + + cookie = 0; + while (get_next_image_info(0, &cookie, &imageInfo) == B_OK) { + // 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; + symIndex = 0; + symNameLength = NAME_MAX; + + while (get_nth_image_symbol(imageInfo.id, symIndex, curSymName, + &symNameLength, &symType, &symLocation) == B_OK) { + // check if symbol is the nearest until now + if (symType == B_SYMBOL_TYPE_TEXT + && 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; + } + symIndex++; + symNameLength = NAME_MAX; + } + break; + } + } + + if (info->dli_saddr != NULL) + return 1; + + return 0; +} + + // __libc_dl*** wrappers // We use a mixed glibc / bsd libc, and glibc wants these void *__libc_dlopen(const char *name); @@ -83,8 +141,8 @@ __libc_dlopen(const char *name) { return dlopen(name, 0); } - - + + void * __libc_dlsym(void *handle, const char *name) {