Why do the addresses in my assembler dump differ from the addresses of registers?

2

I have a very basic program that I compiled with

gcc -m32 -g -o hello32.out hello.c

When I run disassemble main in gdb I get the following output:

0x0000051d <+0>:    lea    ecx,[esp+0x4]
0x00000521 <+4>:    and    esp,0xfffffff0
0x00000524 <+7>:    push   DWORD PTR [ecx-0x4]
0x00000527 <+10>:   push   ebp
0x00000528 <+11>:   mov    ebp,esp
0x0000052a <+13>:   push   ebx
0x0000052b <+14>:   push   ecx
0x0000052c <+15>:   sub    esp,0x10
0x0000052f <+18>:   call   0x420 <__x86.get_pc_thunk.bx>
0x00000534 <+23>:   add    ebx,0x1aa4
0x0000053a <+29>:   mov    DWORD PTR [ebp-0xc],0x0
... [truncated for brevity]

However, when I run

(gdb) break main
(gdb) run
(gdb) info register eip

I get

eip            0x5655553a   0x5655553a <main+29>

Why is main+29 shown as 0x0000053a in the assembler dump but 0x5655553a when the address of eip is given?

gcc
assembly
x86
gdb
asked on Stack Overflow Nov 15, 2018 by Bryan Coxwell

1 Answer

2

Your GCC makes PIE executables by default, so there is no fixed base address in the file (and disassembly shows it relative to 0, i.e. offsets rather than absolute addresses).

Once the kernel's ELF program loader has created a running process from the executable (and chosen a virtual address as the base), GDB can show you the actual runtime virtual addresses.

Build with -fno-pie -no-pie to get position-dependent executables where the runtime address is known from the executable metadata. (You should definitely prefer -fno-pie for i386 code: without RIP-relative addressing the extra performance / code-size cost of position-independent code is significantly worse than for x86-64.)


Related: 32-bit absolute addresses no longer allowed in x86-64 Linux? for more about PIE (both 32-bit and 64-bit x86, and in general.)

GDB - Address of breakpoint is similar to this but not exactly a duplicate.

answered on Stack Overflow Nov 15, 2018 by Peter Cordes

User contributions licensed under CC BY-SA 3.0