* 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
This commit is contained in:
Axel Dörfler 2008-10-24 09:53:48 +00:00
parent 2d265d2a5b
commit e2040be893
2 changed files with 75 additions and 6 deletions

View File

@ -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 <sys/types.h>
@ -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
}

View File

@ -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)
{