我在disas
中使用gdb
时。我可能会得到这样的东西。
(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
。
答案 0 :(得分:0)
很难说出你正在追求什么,但是回溯函数通常会查看“堆栈帧”并从那里找到返回地址。然后,他们解析函数列表,查找每个返回地址的前一个函数。如果您在调试器中,那么也可能会告诉返回地址代表的代码行。
从这里开始,我不确定问题是“如何评估堆栈帧”或“我如何找到'紧接在前的函数”。
堆栈帧生成是特定于平台的,但通常使用特定寄存器来保存在进入函数时建立的堆栈上的固定位置的地址。堆栈帧通常指向堆栈中位于前一堆栈帧指针处(或旁边)的位置。这允许使用帧指针遍历堆栈并评估返回地址(通常位于相对于堆栈帧信息的固定位置。
请注意,编译器可以进行各种优化,这些优化会影响堆栈帧(具体是两个:禁用堆栈帧生成和返回值优化)。
确定函数的地址也取决于平台。如果要求,编译器和链接器将创建和管理调试符号。这实际上嵌入了一个函数名和起始地址的查找表,该表被加载到内存中供调试器访问。更好的系统还将提供在发布版本中查找符号名称的功能。他们通常通过让IDE提供函数基地址(一个映射文件)来做到这一点,然后找出代码部分加载到内存的位置。我怀疑这些信息是由OS调用提供的,但也许还有其他一些机制。
答案 1 :(得分:0)
我有一个愚蠢的方法。 添加如下标签:
/* 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 */