Making Stack Walker Works in Application with Optimization Enable
I am refering to article at http://www.wintoolzone.com/articles/AuthoringStackWalkerForX86.pdf
I am using VC++ 2008. I realize that when I turn the optimization to "Maximum Speed (/O2)", even I set the "Omit Frame Pointer" explicitly to No, getting function returned address will not work correctly through stack frame pointer.
In the article, it mentions :
"Requires stack frame pointer to be present in the produced code. Optimized code where stack frame pointer is absent will not be walked by this code. Its left as an exercise for the reader to implement it over this codebase."
I was wondering, anyone of you have an portable way, to walk through both optimized 开发者_Python百科and unoptimized code, without making assumption on the availability of stack frame pointer?
Currently, the above stack walker example is making assumption every function is having
push ebp
mov ebp,esp
as the first line of function's code.
I had once tried RtlCaptureStackBackTrace
, but its limitation up to 62 frames doesn't serve my purpose.
I suppose its main assumption isn't the pattern
push ebp
mov ebp,esp
but rather the assumption that ebp
is always used as frame pointer. This allows simple stack unwinding: ebp
points to last saved stack frame, all data above it are locals, the next value on the stack is the return address of the caller. Simple.
For a complex one you should literaly "dump" the stack, trying to tell as much as possible about each value. Is it just a value? A return address? Parameter for the function? or maybe a string?
To check if a dword is a return address, you can enumarate all loaded modules and obtain the address range of their sections with execute rights. (maybe VirtualQuery
will be able to do it too).
By performing an "inventory" on each module, you can obtain the list of all exported symbols. This will give you at least some names.
Stack walking should work just fine, however some function calls may have been completely eliminated by optimizations such as inlining and tail calls, so of course they won't show up in the call stack.
精彩评论