In previous versions of GCC, the symbol offsets reported by objdump
matched the ones used during the actual execution of the code. For example:
$ cat example.c
#include <stdio.h>
int g_someGlobal = 0;
int main()
{
printf("%d\n", g_someGlobal);
return 0;
}
$ gcc-6 -v
...
gcc version 6.1.1 20160802 (Debian 6.1.1-11)
$ gcc-6 -O0 -g -o example example.c
$ objdump -x example | grep Global
...
080496f4 g O .bss 00000004 g_someGlobal
...
And indeed, when running the binary, the actual address of the symbol used during execution is the same one as that reported by objdump:
$ gdb ./example
...
(gdb) start
Temporary breakpoint 1, main () at example.c:10
10 printf("%d\n", g_someGlobal);
(gdb) p/x &g_someGlobal
$1 = 0x80496f4
Unfortunately, repeating the same sequence of commands in the recently released Debian Stretch, this happens instead:
$ gcc-6 -v
...
gcc version 6.3.0 20170415 (Debian 6.3.0-14)
$ gcc-6 -O0 -g -o example example.c
$ objdump -x example | grep Global
00002020 g O .bss 00000004 g_someGlobal
The symbol offset now seems to be a much smaller value - which...
$ gdb ./example
...
(gdb) start
...
Temporary breakpoint 1, main () at example.c:7
7 printf("%d\n", g_someGlobal);
(gdb) p/x &g_someGlobal
$1 = 0x80002020
...no longer matches with the one used at runtime.
Am I making a mistake here? Has the usage of the tools changed in the meantime? If not, what is the reasoning behind this change?
Regardless - in theory there must be a way to get the "expected run-time offset" of the .bss segment that hosts the variable (objdump
does report which section it will be placed in, so the final run-time position could be calculated by adding the .bss
offset). In my preliminary attempts to do so, I have not found a way to get this, though:
$ readelf --sections example | grep bss
[26] .bss NOBITS 0000201c 00101c 000008 00 WA 0 0 4
This doesn't seem to report the "shift" of 0x80000000 that seems to happen to .bss
-hosted variables in this example.
(Even if that is a "magic constant" for this new execution environment, does that apply to the .data
variables, too? And to be honest, I hate magic values - previously, whatever came out of objdump -x
was accurate, regardless of where the symbols resided...)
Any information to resolve this most welcome. Ideally, I'd like to reproduce the old behavior of objdump -x
- i.e. to statically (NOT at run-time) get the value of the run-time address of a symbol, from the ELF that hosts it.
UPDATE: I did a custom compile (from sources) of GCC7.1.0, and this is no longer reproducible. Perhaps this was a regression in GCC 6.3 (the version packaged in Debian Stretch)...