我在http://www.wintoolzone.com/articles/AuthoringStackWalkerForX86.pdf
指的是文章我正在使用VC ++ 2008.我意识到当我将优化转为“最大速度(/ O2)”时,即使我将“Omit Frame Pointer”显式设置为No,获取函数返回的地址也无法通过堆栈正常工作帧指针。
在文章中,它提到:
“需要堆栈帧指针 出现在生成的代码中。 堆栈帧优化的代码 指针不在将不会走 通过此代码。它作为练习留下了 供读者实施 这个代码库。“
我想知道,你们中的任何人都有一种可移植的方式,可以完成优化和未经优化的代码,而不必考虑堆栈帧指针的可用性吗?
目前,上面的堆栈遍历示例假设每个函数都有
push ebp
mov ebp,esp
作为函数代码的第一行。
我曾经尝试过RtlCaptureStackBackTrace
,但它的限制高达62帧不符合我的目的。
答案 0 :(得分:1)
我认为它的主要假设不是模式
push ebp
mov ebp,esp
而是假设ebp
始终用作帧指针。这允许简单的堆栈展开:ebp
指向上次保存的堆栈帧,其上方的所有数据都是本地数据,堆栈上的下一个值是调用者的返回地址。简单。
对于一个复杂的,你应该文明地“转储”堆栈,试图尽可能多地告诉每个值。这只是一个价值吗?退货地址?功能参数?或者是一个字符串?
要检查dword是否为返回地址,您可以设置所有已加载的模块并获取具有执行权限的部分的地址范围。 (也许VirtualQuery
也可以这样做。)
通过在每个模块上执行“库存”,您可以获取所有导出符号的列表。这将至少给你一些名字。
答案 1 :(得分:0)
堆栈遍历应该可以正常工作,但是某些函数调用可能已经通过内联和尾调用等优化完全消除,所以它们当然不会出现在调用堆栈中。