Copy-Relocate debug error

Michael Eager eager@eagerm.com
Mon Jan 30 20:08:00 GMT 2012


Here is a small test program which uses copy-relocate on X86_64.
Gdb-7.2 gives the wrong value when a global symbol is printed when
stopping in a function in the shared library.  gdb-7.3 (and later)
give the correct result.  I'm not sure that they get the correct
result because a problem in gdb-7.2 was fixed rather than by accident.

Here's the test program:

$ cat tmp.c
extern int tab[100];

int
main (void)
{
   tab[10] = 10;
   sub ();
   return 0;
}
$ cat libtmp.c
int tab[100] = {2,4,6};

void
sub (void)
{
   tab[20] = 20;
}
$ gcc -fpic --shared -g -o libtmp.so libtmp.c
$ gcc -g tmp.c libtmp.so -Wl,-R,`pwd`

Running gdb:

$ gdb a.out
(gdb) b sub
(gdb) run
(gdb) info addr tab
Symbol "tab" is static storage at address 0xxxxxx.

On gdb-7.2, the address given is for the copy of 'tab' in the
shared library.  This is not the one which sub() is using.  Sub()
references 'tab' indirectly through the GOT, which the run time
loader has set to point to the copy of 'tab' in the executable
which it created as a result of the R_X86_64_COPY for 'tab' in tmp.c.

The code to reference 'tab' in sub() is:
      mov    0x200285(%rip),%rax        # 200890 <_DYNAMIC+0x1d0>

When gdb-7.2 searches for 'tab', it finds the symbol in the
shared library symbol table with the address specified by this
DWARF location:
     DW_OP_addr  tab

This is incorrect.  The correct DWARF should describe the code:
     DW_OP_addr  tab@GOT
     DW_OP_deref

If I change the DWARF data for 'tab', gdb complains that this is
a "complex expression", which is not supported.

gdb-head gives the correct result because the symbols for a.out
are read as a side-effect of walking the frame chain and it finds
the global definition for 'tab' in a.out, never looking at the
symbols (or DWARF info) for 'tab' in libtmp.so.  This does not
happen in gdb-7.2 (I'm not sure why), so it finds the (incorrect)
definition in libtmp.so.  If I stop in main() before stopping in
sub(), then gdb-7.2 resolves the address correctly.

I'm looking for suggestions on how to correct this in gdb-7.2.
(I don't have the option of moving to a more recent version.)

I can modify gdb to recognize DW_OP_deref (I would guess in
locexpr_describe_location_piece()).  I can (somehow) force gdb
to always read the symbols from the executable.  (Anyone know
if this was an intentional change or a side effect of some other
patch?)

Any other suggestions?


-- 
Michael Eager	 eager@eagercon.com
1960 Park Blvd., Palo Alto, CA 94306  650-325-8077



More information about the Gdb mailing list