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