This is the mail archive of the libc-alpha@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[qfp@netserv.net.au (David Seymour)] libc/1633: dladdr cannot find symbols in the main executable



Hi glibc folks,

can somebody evaluate the appended patch, please?

Thanks,
Andreas



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
***************************



-- 
 Andreas Jaeger
  SuSE Labs aj@suse.de
   private aj@arthur.rhein-neckar.de

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]