Symbol offsets reported by objdump no longer match run-time offsets

Viewed 725

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)...

1 Answers
Related