我想通过查看堆栈上的原始数据将堆栈划分为堆栈帧。我想通过找到保存的 EBP 指针的“链接列表”来做到这一点。
我可以假设(标准和常用的)C 编译器(例如 gcc)将始终在函数序言中的函数调用上更新和保存 EBP?
pushl %ebp
movl %esp, %ebp或者在某些情况下,某些编译器可能会为没有获取任何参数且没有局部变量的函数跳过该部分?
x86 调用约定和关于函数序言的Wiki 文章对此没有多大帮助。
仅通过查看原始数据,有没有更好的方法将堆栈划分为堆栈帧?
谢谢!
我想通过查看堆栈上的原始数据将堆栈划分为堆栈帧。我想通过找到保存的 EBP 指针的“链接列表”来做到这一点。
我可以假设(标准和常用的)C 编译器(例如 gcc)将始终在函数序言中的函数调用上更新和保存 EBP?
pushl %ebp
movl %esp, %ebp
或者在某些情况下,某些编译器可能会为没有获取任何参数且没有局部变量的函数跳过该部分?
x86 调用约定和关于函数序言的Wiki 文章对此没有多大帮助。
仅通过查看原始数据,有没有更好的方法将堆栈划分为堆栈帧?
谢谢!
某些版本的 gcc 有-fomit-frame-pointer
优化选项。如果有记忆,它甚至可以与参数/局部变量一起使用(它们直接从 ESP 索引而不是使用 EBP)。除非我弄错了,否则 MS VC++ 可以做的大致相同。
顺便说一句,我不确定一种接近普遍适用的方法。如果你有带有调试信息的代码,通常很容易——否则……
Even with the framepointer optimized out, stackframes are often distinguishable by looking through stack memory for saved return addresses instead. Remember that a function call sequence in x86 always consists of:
call someFunc ; pushes return address (instr. following `call`)
...
someFunc:
push EBP ; if framepointer is used
mov EBP, ESP ; if framepointer is used
push <nonvolatile regs>
...
so your stack will always - even if the framepointers are missing - have return addresses in there.
How do you recognize a return address ?
call
instructions on x86 have specific opcode formats; read a few bytes before the return address and check if you find a call
opcode there (99% most of the time, it's five bytes back for a direct call, and three bytes back for a call through a register). If so, you've found a return address.call
instructions.With that method, you can get candidates for the call sequence out of the stack even without having symbols, framesize debugging information or anything.
The details of how to piece the actual call sequence together from those candidates are less straightforward though, you need a disassembler and some heuristics to trace potential call flows from the lowest-found return address all the way up to the last known program location. Maybe one day I'll blog about it ;-) though at this point I'd rather say that the margin of a stackoverflow posting is too small to contain this ...