k = <rsp> <rip> <frame_count>
x64下manual stack walking与x86不同,x86一般情况下有ebp chain,x64没有ebp chain,类似x86的FPO
x64下,rsp在函数执行完prologue之后就不会变化(调用约定);
所以
0.如果函数内执行了call指令,call指令返回地址压栈后,rsp就会减8;
1.也就是说,在stack reconstruction时,识别到返回地址所在的栈地址,再加8,就是当前函数执行完prologue的rsp;
2.由于x64非叶子函数有function table entry,记录unwind info,包括prologue操作,所以根据unwind info,可以还原进入当前函数时rsp的值,这个值就是指向本函数执行完时的返回地址;
3.这时在回到步骤1,就是stack walking;
参考
http://blogs.msdn.com/b/ntdebugging/archive/2010/05/12/x64-manual-stack-reconstruction-and-stack-walking.aspx
调用约定
amd64规范,rdi,rsi,rdx,rcx,r8,r9,栈
ms规范,rcx,rdx,r8,r9,栈
func1(int a, int b, int c, int d, int e);
// a in RCX, b in RDX, c in R8, d in R9, e pushed on stack
注意,无论是amd还是ms,寄存器传送的参数在栈上都有home space,callee可选择是否把寄存器参数回写栈,debug下通常会,release下home space会作其他用途
函数参数识别
由于参数用寄存器传送,所以release下,参数查找会比较麻烦,通常做法是1.查看汇编代码,看参数传到那里才mov到栈;2.查看参数来源;