This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: impossible to resolve symbols in same binary loaded twice with dlmopen


On Thu, Jul 8, 2010 at 10:31 PM, Tom Tromey <tromey@redhat.com> wrote:

> First, I'm curious: does gdb detect dlmopen calls automatically? ÂI

Not with the libc implementation of dlmopen.

> thought there was some missing glibc feature here. ÂI haven't looked

The proper way to handle multiple namespaces in the dynamic loader
would be to use an implementation of the librtld_db.so solaris library
and modify gdb to use it. However, glibc does not provide such an
implementation to encapsulate the details of the loader data
structures.

> into it too much since I wasn't aware of anybody really using dlmopen.
> If gdb cannot do this, please file a bug report.

I do not believe that gdb can do this and I could file a bug but it's
probably going to be hard to fix (beyond my own abilities).

> I am not completely sure that this patch is sufficient.

It's sufficient for me because I use a dynamic loader that has a
different implementation of dlmopen:
  i. there is no compile-time bound on the number of namespaces which
can be created (i.e., the glibc has a 16 or 32 static upper bound)
  ii. there is extra API to be able to create a namespace
independently from loading a binary and extra API to specify some
redirections (say, map libc.so.6 to libc-ns3.so): it's an easy-to-use
API compared to using an audit library
  iii. there is extra API to shutdown a namespace without having to
invoke the destructors of the binaries loaded in it (important to
allow the main process to be shielded from the namespaces)
  iv. the linkmap exported to the debugger contains the binaries of
_all_ the binaries loaded in all namespaces. The loader is careful to
still resolve symbols correctly within each namespace but the linkmap
exported to the debugger contains all binaries to allow gdb to find
all binaries and put breakpoints in them without having to know about
the namespaces.

However, as a disclaimer, the patch I posted and the associated bug
report have been tested on a libc-based system.

> It doesn't seem like it would handle PIE properly. ÂI think you would
> have to modify objfile_relocate as well.

I am not sure I follow you. I have been using this code with PIEs
(with my other loader, arguably) and have been able to debug stuff.
What symptom do you have in mind ?

> I was wondering if there is a possible bug with a program dlmopen()ing
> itself, but after thinking about it my guess is no.

I don't see any problem with this but I did not test it. Will do so.

> Once you have this patch, does it really work? ÂIt seems like it would
> work ok for some things, like backtraces, but not other things. ÂE.g.,
> does symbol lookup work properly in the dlmopen case? ÂI would imagine
> that it does or does not depending on the ordering of objfiles in gdb's
> internal list.

If you use the libc loader and run the test program I attached to the
bug report, you will see that it's indeed impossible to put a
breakpoint or print the address of a function located in a binary
loaded with dlmopen (LD_ID_NEWLM) because gdb is not notified of the
existence of the binaries loaded with dlmopen (and if you inspect the
inferior's linkmap through the _r_debug variable by hand as show
below, you can see that it really does not contain them). It works
fine with my loader though (for the reasons I outlined above).

I would be happy to do more work if needed to satisfy the needs of gdb
on top of the libc dlmopen (even though I am not going to use it): do
you have a specific idea of how you would like this to be done ?

Mathieu

[sample gdb session]
Breakpoint 1, main (argc=2, argv=0x7fffffffe158) at test.c:14
14	  bool doA = true;
(gdb) n
15	  if (strcmp (argv[1], "a") == 0)
(gdb)
17	      doA = true;
(gdb)
23	  void *a = dlmopen (LM_ID_NEWLM, "./libtest.so", RTLD_LAZY);
(gdb)
24	  void *b = dlmopen (LM_ID_NEWLM, "./libtest.so", RTLD_LAZY);
(gdb)
26	  if (doA)
(gdb) p _r_debug.r_map
$6 = (struct link_map_public *) 0x37fa61f0e8
(gdb) p *_r_debug.r_map
$7 = {l_addr = 0, l_name = 0x37fa419614 "", l_ld = 0x600948, l_next =
0x37fa61f678, l_prev = 0x0}
(gdb) p *_r_debug.r_map->l_next
$8 = {l_addr = 140737363566592, l_name = 0x37fa419614 "", l_ld =
0x7ffff7ffe580,
  l_next = 0x7ffff7ffd658, l_prev = 0x37fa61f0e8}
(gdb) p *_r_debug.r_map->l_next->l_next
$9 = {l_addr = 0, l_name = 0x7ffff7ffd640 "/lib64/libdl.so.2", l_ld =
0x37fb202da0,
  l_next = 0x7ffff7ffdb20, l_prev = 0x37fa61f678}
(gdb) p *_r_debug.r_map->l_next->l_next->l_next
$10 = {l_addr = 0, l_name = 0x7ffff7ffdb08 "/lib64/libc.so.6", l_ld =
0x37fab72b40,
  l_next = 0x37fa61e970, l_prev = 0x7ffff7ffd658}
(gdb) p *_r_debug.r_map->l_next->l_next->l_next->l_next
$11 = {l_addr = 0, l_name = 0x400200 "/lib64/ld-linux-x86-64.so.2",
l_ld = 0x37fa61ddf0, l_next = 0x0,
  l_prev = 0x7ffff7ffdb20}

-- 
Mathieu Lacage <mathieu.lacage@gmail.com>


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