【问题标题】:Why do the addresses in my assembler dump differ from the addresses of registers?为什么我的汇编转储中的地址与寄存器的地址不同?
【发布时间】:2018-11-15 00:41:37
【问题描述】:

我有一个非常基本的程序,我用

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

当我在 gdb 中运行 disassemble 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?

【问题讨论】:

    标签: gcc assembly x86 gdb


    【解决方案1】:

    您的 GCC 默认会生成 PIE 可执行文件,因此文件中没有固定的基地址(反汇编显示它相对于 0,即偏移量而不是绝对地址)。

    一旦内核的 ELF 程序加载器从可执行文件创建了一个正在运行的进程(并选择了一个虚拟地址作为基地址),GDB 就可以向您显示实际的运行时虚拟地址。 (例如starti 开始运行,然后 disas my_func 在该进程中获取有效地址;GDB 禁用 ASLR,因此只有在 GDB 下运行或与其他为进程或系统范围的特定运行禁用 ASLR 的方法。)

    使用 -fno-pie -no-pie 构建以获取位置-相关可执行文件,其中运行时地址可从可执行元数据中获知。 (对于 i386 代码,您绝对应该更喜欢 -fno-pie:如果没有 RIP-relative 寻址,位置无关代码的额外性能/代码大小成本明显低于 x86-64。)


    相关:32-bit absolute addresses no longer allowed in x86-64 Linux? 了解有关 PIE 的更多信息(包括 32 位和 64 位 x86,以及一般情况。)

    GDB - Address of breakpoint 与此类似,但不完全相同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-19
      • 2014-09-11
      • 1970-01-01
      相关资源
      最近更新 更多