我有一个非常基本的程序,可以使用
进行编译gcc -m32 -g -o hello32.out hello.c
当我在gdb中运行反汇编main时,得到以下输出:
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]
但是,当我跑步时
(gdb) break main
(gdb) run
(gdb) info register eip
我知道
eip 0x5655553a 0x5655553a <main+29>
为什么main + 29在汇编器转储中显示为0x0000053a,而在给定eip地址时却显示为0x5655553a?
答案 0 :(得分:2)
您的GCC默认情况下使PIE可执行,因此文件中没有固定的基地址(反汇编显示它相对于0,即偏移量而不是绝对地址)。
一旦内核的ELF程序加载器从可执行文件创建了一个正在运行的进程(并选择了一个虚拟地址作为基础),GDB就会向您显示实际的运行时虚拟地址。
使用-fno-pie -no-pie
构建以获取与位置相关的可执行文件,其中从可执行文件元数据中可以获知运行时地址。 (对于i386代码,您绝对应该使用-fno-pie
:如果没有RIP相对地址,则位置无关代码的额外性能/代码大小成本要比x86-64差得多。)
相关:32-bit absolute addresses no longer allowed in x86-64 Linux?进一步了解PIE(32位和64位x86,以及一般情况)。
GDB - Address of breakpoint与此相似,但不完全相同。