This is the mail archive of the gdb@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: baffling assembly-level weirdness


On Mon, Jan 26, 2009 at 5:51 PM, Paul Pluzhnikov <ppluzhnikov@google.com> wrote:

>>> The following gdb session baffles me completely: %edx is reset to zero
>>> by the mov at address 0x0804ad62 instead of being set to the constant
>>> 0x804ad62. Of course, this code segfaults at $pc = 0x804ad68 when zero
>>> is dereferenced...
>>>
>>> Version: GNU gdb 6.8
>>>
>>> (gdb) disas $pc $pc+10
>>> Dump of assembler code from 0x804ad62 to 0x804ad6c:
>>> 0x0804ad62 <indent+50>:       mov    0x805e3c0,%edx
>>
>> This is a load from memory at address 0x805e3c0, in x86 syntax.
>
> Additional clues:
>
>  (gdb) p/a 0x805e3c0
>
> will likely print "stdout". If you break in main, and do
>
>  (gbd) x/a 0x805e3c0
>
> it will likely print something like:
>
>  0x8053ac0 <stdout>:   0x4dcdb5e0 <_IO_2_1_stdout_>
>
> It sounds like your program is corrupting stdout somewhere.
> The fastest way to find out where that happens:
>
>  (gdb) watch *(int **)0x8053ac0

You did put me on the right track so, in case this might be useful to
someone else, here is what was going on:

1) I am writing an ELF loader so, the bug was not in my program
corrupting the variable but in the variable not being initialized
correctly by the loader during relocation

2) the libc has a global stdout variable which is initialized with a
R_386_GLOB_DAT relocation by the loader:
mathieu@mathieu-boulot:~/code/elf-loader$ readelf -s
/lib/libc.so.6|grep stdout@@
  1063: 00135860     4 OBJECT  GLOBAL DEFAULT   32 stdout@@GLIBC_2.0
mathieu@mathieu-boulot:~/code/elf-loader$ readelf -r
/lib/libc.so.6|grep 00135860
00134f34  00042706 R_386_GLOB_DAT    00135860   stdout
00135860  00032d01 R_386_32          001354e0   _IO_2_1_stdout_

3) the main executable has a global stdout variable which is
referenced by the code in the main binary and initialized by a
R_386_COPY relocation:
mathieu@mathieu-boulot:~/code/elf-loader$ readelf -s /bin/ls|grep stdout@
    93: 0805e3c0     4 OBJECT  GLOBAL DEFAULT   25 stdout@GLIBC_2.0 (2)
mathieu@mathieu-boulot:~/code/elf-loader$ readelf -r /bin/ls|grep 0805e3c0
0805e3c0  00005d05 R_386_COPY        0805e3c0   stdout
which is expected to copy the value of the stdout symbol from the libc.so.6

4) it turns out that the symbol lookup associated to a R_*_COPY
relocation is supposed to ignore the main executable which is
something I had no idea about and adding an extra if statement to
ignore the main executable during symbol resolution for a R_*_COPY
reloc fixed the problem.

As a side-note, I really wonder why (3): none of the executables I
link myself contain an stdout variable so, I am somewhat curious as to
where this is coming from (I would expect each access to stdout from
the main binary to directly reference the symbol from the libc through
the GOT). But, well, next time.

anyway, thanks a lot to the very helpful souls here,
Mathieu
-- 
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]