[英]How to get relative offset of assembly instruction from `push %ebp`
当我在gdb
使用disas
时。 我可能会得到这样的东西。
(gdb) disas bar
Dump of assembler code for function bar:
0x08048e84 <+0>: push %ebp
0x08048e85 <+1>: mov %esp,%ebp
0x08048e87 <+3>: sub $0x8,%esp
0x08048e8a <+6>: mov 0xc(%ebp),%eax
0x08048e8d <+9>: mov 0x8(%ebp),%edx
0x08048e90 <+12>: add %edx,%eax
0x08048e92 <+14>: mov %eax,-0x4(%ebp)
0x08048e95 <+17>: mov 0x81f4074,%eax
0x08048e9a <+22>: mov %eax,(%esp)
0x08048e9d <+25>: call 0x8048ed8 <traceback>
0x08048ea2 <+30>: mov -0x4(%ebp),%eax
0x08048ea5 <+33>: mov %eax,0x8(%ebp)
0x08048ea8 <+36>: leave
0x08048ea9 <+37>: ret
End of assembler dump.
假设我的C程序中有0x08048ea2
。 我如何获得偏移量<+30>
并获得0x08048e84
。
很难说出到底要做什么,但是回溯功能通常会查看“堆栈帧”并从那里找到返回地址。 然后,他们解析函数列表,以查找每个返回地址的前一个函数。 如果您在调试器中,那么大概也可以说出返回地址代表的代码行。
从这里,我不确定问题是“如何评估堆栈框架”还是“如何找到'紧邻的函数'”。
堆栈帧的生成是特定于平台的,但通常使用特定的寄存器来保存一个地址,该地址是在函数输入时建立的堆栈上的固定位置。 堆栈框架通常指向堆栈中先前堆栈框架指针处(或旁边)的位置。 这允许使用帧指针遍历堆栈并评估返回地址(返回地址通常位于相对于堆栈帧信息的固定位置。
请注意,编译器可以进行多种优化,这些优化会影响堆栈帧(具体来说有两个:禁用堆栈帧生成和返回值优化)。
确定功能的地址也取决于平台。 如果需要,编译器和链接器将创建和管理调试符号。 这实际上嵌入了一个函数名和起始地址的查找表,该表已加载到内存中供调试器访问。 更好的系统还将提供在发行版本中查找符号名称的功能。 他们通常通过让IDE提供功能基地址(一个映射文件),然后找出代码段被加载到内存中的位置来实现此目的。 我怀疑此信息是由OS调用提供的,但也许还有其他机制。
我有一个愚蠢的方法。 添加这样的标签:
/* ommit some code */
label:
mov -0x4(%ebp),%eax
mov %eax,0x8(%ebp)
leave
ret
然后:
lea eax, label /* eax will be 0x08048ea2 */
lea ebx, bar /* ebx will be 0x08048e84 */
sub eax, ebx /* get the offset */
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.