为什么我的汇编转储中的地址与寄存器的地址不同? [英] Why do the addresses in my assembler dump differ from the addresses of registers?

查看:14
本文介绍了为什么我的汇编转储中的地址与寄存器的地址不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

编译

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

当我在 gdb 中运行 disassemble main 时,我得到以下输出:

0x0000051d <+0>: lea ecx,[esp+0x4]0x00000521 <+4>: 和 esp,0xfffffff00x00000524 <+7>: 推送 DWORD PTR [ecx-0x4]0x00000527 <+10>:推送ebp0x00000528 <+11>: mov ebp,esp0x0000052a <+13>: 推 ebx0x0000052b <+14>: 推送 ecx0x0000052c <+15>: sub esp,0x100x0000052f<+18>:调用0x420<__x86.get_pc_thunk.bx>0x00000534<+23>:添加ebx,0x1aa40x0000053a <+29>: mov DWORD PTR [ebp-0xc],0x0... [为简洁起见截断]

但是,当我跑步时

(gdb) 中断主要(gdb) 运行(gdb) 信息寄存器 eip

我明白了

eip 0x5655553a 0x5655553a <main+29>

为什么main+29在汇编转储中显示为0x0000053a,但在给出eip地址时显示为0x5655553a?

解决方案

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

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

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


相关:x86-64 Linux 中不再允许 32 位绝对地址?了解有关 PIE 的更多信息(均为 32 位和 64 位 x86,一般来说.)

GDB - 断点地址与此类似,但不完全相同.p>

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?

解决方案

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. (e.g. starti to start it running, then disas my_func to get a valid address within that process; GDB disables ASLR so it will be the same every time only if running under GDB, or with other ways of disabling ASLR for a specific run of a process or system-wide.)

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.

这篇关于为什么我的汇编转储中的地址与寄存器的地址不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆