- Subject: libc/1633: dladdr cannot find symbols in the main executable
- From: qfp at netserv dot net dot au (David Seymour)
- Date: Mon Mar 6 15:50:00 2000
Topics:
libc/1633: dladdr cannot find symbols in the main executable
----------------------------------------------------------------------
Date: 6 Mar 2000 13:45:56 -0000
From: qfp@netserv.net.au (David Seymour)
To: bugs@gnu.org
Subject: libc/1633: dladdr cannot find symbols in the main executable
Message-Id: <20000306134556.19222.qmail@quokka.home.bogonet>
>Number: 1633
>Category: libc
>Synopsis: dladdr cannot find symbols in the main executable
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: libc-gnats
>State: open
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Mon Mar 06 09:00:01 EST 2000
>Last-Modified:
>Originator: David Seymour
>Organization:
David Seymour
qfp@netserv.net.au
>
>Release: libc-2.1.3
>Environment:
Host type: i386-redhat-linux-gnu
System: Linux quokka.home.bogonet 2.2.14 #2 Sat Mar 4 10:22:44 WST 2000 i686 unknown
Architecture: i686
Addons: crypt glibc-compat linuxthreads
Build CFLAGS: -g -O3
Build CC: gcc
Compiler version: 2.95.2 19991024 (release)
Kernel headers: 2.2.14
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: yes
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio
>Description:
In a executable compiled (linked) with -rdynamic (-export-dynamic)
you can find the address from the symbol name with dlsym, but
can find the symbol name from the address using dladdr. Symbols in
dynamic libraries (i.e. compiled with -lfoo) and libraries opened with
dlopen() work fine.
>How-To-Repeat:
Little example progy:
file dlbug_main.cc:
- ---------------------------------------------------------------------
#define _GNU_SOURCE
#include <iostream>
#include <dlfcn.h>
extern "C" {
const char* static_string = "Got the static sting here";
}
void FindSymbol(const char** addr)
{
Dl_info dl_info;
if (dladdr(addr, &dl_info)) {
cout << "Found object at address " << addr << endl;
cout << "dl_info.dli_fname = " << dl_info.dli_fname << endl;
cout << "dl_info.dli_fbase = " << dl_info.dli_fbase << endl;
cout << "dl_info.dli_sname = " << dl_info.dli_sname << endl;
cout << "dl_info.dli_saddr = " << dl_info.dli_saddr << endl;
}
else {
cout << "No shared object's segments contain the address "
<< addr << endl;
}
}
const char** FindAddress(void* dlh, const char* name)
{
const char** addr = (const char**) dlsym(dlh, name);
if (addr) {
cout << "Found address of symbol " << name << endl;
cout << "Containes string \"" << *addr << "\"" << endl;
return addr;
}
else {
cout << "Could not find address of symbol " << name << endl;
cout << dlerror() << endl;
return 0;
}
}
int main(int argc, char** argv)
{
void* gdl = dlopen(0, RTLD_LAZY);
if (!gdl) exit(1);
void* dlh = dlopen("libdlbug_dlopen.so", RTLD_LAZY);
if (!dlh) exit(1);
const char** addr;
cout << "Static" << endl;
addr = FindAddress(gdl, "static_string");
if (addr) FindSymbol(addr);
cout << "Dynamic" << endl;
addr = FindAddress(gdl, "dynamic_string");
if (addr) FindSymbol(addr);
cout << "Dlopen" << endl;
addr = FindAddress(dlh, "dlopen_string");
if (addr) FindSymbol(addr);
}
- ---------------------------------------------------------------------
file dlbug_dyn.cc:
- ---------------------------------------------------------------------
extern "C" {
const char* dynamic_string = "Got the dynamic string here";
}
- ---------------------------------------------------------------------
file dlbug_dlopen.cc:
- ---------------------------------------------------------------------
extern "C" {
const char* dlopen_string = "Got the dlopen string here";
}
- ---------------------------------------------------------------------
file Makefile:
- ---------------------------------------------------------------------
dlbug: dlbug_main.cc libdlbug_dyn.so libdlbug_dlopen.so
g++ -rdynamic -g -o dlbug dlbug_main.cc -L. -ldlbug_dyn -ldl
libdlbug_dyn.so: dlbug_dyn.o
g++ -shared -o libdlbug_dyn.so dlbug_dyn.o
libdlbug_dlopen.so: dlbug_dlopen.o
g++ -shared -o libdlbug_dlopen.so dlbug_dlopen.o
dlbug_dyn.o: dlbug_dyn.cc
g++ -g -fpic -c dlbug_dyn.cc
dlbug_dlopen.o: dlbug_dlopen.cc
g++ -g -fpic -c dlbug_dlopen.cc
.PHONY: test
test: dlbug
env LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ./dlbug
- ---------------------------------------------------------------------
make test gives:
- ---------------------------------------------------------------------
Static
Found address of symbol static_string
Containes string "Got the static sting here"
No shared object's segments contain the address 0x8059e0c
Dynamic
Found address of symbol dynamic_string
Containes string "Got the dynamic string here"
Found object at address 0x40016648
dl_info.dli_fname = ./libdlbug_dyn.so
dl_info.dli_fbase = 0x40015000
dl_info.dli_sname = dynamic_string
dl_info.dli_saddr = 0x40016648
Dlopen
Found address of symbol dlopen_string
Containes string "Got the dlopen string here"
Found object at address 0x40018648
dl_info.dli_fname = ./libdlbug_dlopen.so
dl_info.dli_fbase = 0x40017000
dl_info.dli_sname = dlopen_string
dl_info.dli_saddr = 0x40018648
- ---------------------------------------------------------------------
>Fix:
I made the following change in elf/dl-addr.c:
- -- dl-addr.c- Mon Mar 6 21:35:01 2000
+++ dl-addr.c Tue Feb 23 02:12:08 1999
@@ -34,8 +34,8 @@
/* Find the highest-addressed object that ADDRESS is not below. */
match = NULL;
for (l = _dl_loaded; l; l = l->l_next)
- if ((l->l_addr != 0 || l->l_type == lt_executable) /* Make sure we do
- not currently set this map up in this moment. */
+ if (l->l_addr != 0 /* Make sure we do not currently set this map up
+ in this moment. */
&& addr >= l->l_addr && (!match || match->l_addr < l->l_addr))
match = l;
and all worked. Dont know if this is correct or safe, but will use a
local version so hacked within my program which requires it until something
better comes along.
Cheers Dave
>Audit-Trail:
>Unformatted:
------------------------------
End of forward1nCYnV Digest
***************************