diff options
author | nate <nate@FreeBSD.org> | 1999-03-24 23:37:35 +0000 |
---|---|---|
committer | nate <nate@FreeBSD.org> | 1999-03-24 23:37:35 +0000 |
commit | 49744ae917b1d49bd77a6009a2afa719abc35c55 (patch) | |
tree | 01e42078cb287500f5592cf8cbfe187e52a8677a /libexec | |
parent | c42abfb1fe46d89d8c6bffc17aa69c778f17e2b4 (diff) | |
download | FreeBSD-src-49744ae917b1d49bd77a6009a2afa719abc35c55.zip FreeBSD-src-49744ae917b1d49bd77a6009a2afa719abc35c55.tar.gz |
- Added dladdr(3) support.
Reviewed by: jdp@FreeBSD.org
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/rtld-elf/rtld.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 9b4a9cf..02f9c20 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: rtld.c,v 1.12 1998/10/13 03:31:59 jdp Exp $ + * $Id: rtld.c,v 1.13 1998/11/27 21:19:52 dfr Exp $ */ /* @@ -148,6 +148,7 @@ static func_ptr_type exports[] = { (func_ptr_type) &dlerror, (func_ptr_type) &dlopen, (func_ptr_type) &dlsym, + (func_ptr_type) &dladdr, NULL }; @@ -1259,6 +1260,51 @@ dlsym(void *handle, const char *name) return NULL; } +int +dladdr(const void *addr, Dl_info *info) +{ + const Obj_Entry *obj; + const Elf_Sym *def; + void *symbol_addr; + unsigned long symoffset; + + obj = obj_from_addr(addr); + if (obj == NULL) { + _rtld_error("No shared object contains address"); + return 0; + } + info->dli_fname = obj->path; + info->dli_fbase = obj->relocbase; + info->dli_saddr = (void *)0; + info->dli_sname = NULL; + + /* + * Walk the symbol list looking for the symbol whosse address is + * closest to the address sent in. + */ + for (symoffset = 0; symoffset < obj->nchains; symoffset++) { + def = obj->symtab + symoffset; + symbol_addr = obj->relocbase + def->st_value; + /* + *If the symbol is greater than the specified address, or if it + * is further away from addr than the current nearest symbol, + * then reject it. + */ + if (symbol_addr > addr || + symbol_addr < info->dli_saddr) + continue; + + /* Update our idea of the nearest symbol. */ + info->dli_sname = obj->strtab + def->st_name; + info->dli_saddr = symbol_addr; + + /* Exact match? */ + if (info->dli_saddr == addr) + break; + } + return 1; +} + static void linkmap_add(Obj_Entry *obj) { |