Stack tracing for calling stack
Stack tracing for calling stack
If something goes horribly wrong and your OS gets an exception you cannot handle, it's nice to display the good old register dump and the like. What may also be very useful is printing somewhere the function that caused the exception. I've created a simple look-up from the ELF symbol table that does that (it works; and yes, it would also be great to be able to print e.g. the line number, but I'm not fancying to make a DWARF interpreter anytime soon).
However, what could also be rather useful is displaying a calling stack, showing which function called my function, which function called that one, etc. My question is how to do that. Just scan down the stack and try to interpret every dword as an address, and see whether that's somewhere in the symbol table? Seems rather crude and error prone, but it's the only thing I can think of right now.
JAL
However, what could also be rather useful is displaying a calling stack, showing which function called my function, which function called that one, etc. My question is how to do that. Just scan down the stack and try to interpret every dword as an address, and see whether that's somewhere in the symbol table? Seems rather crude and error prone, but it's the only thing I can think of right now.
JAL
Hi.
You can do it by unwinding stack frames. In most cases (and with GCC, pretty much all cases) a function starts by pushing the base pointer (ebp). So you end up with something like this as a stack:
And, in fact, the *current* value of EBP will point to where the old one was pushed. So if you take EBP and keep dereferencing it, you will end up unwinding the stack, one frame at a time.
then note, that if you take any of those EBPs you just found, and add 4 to it and dereference it (go one place up the stack from it), you get the return address from that stack frame.
So all you have to do is follow the trail of EBPs, find the return addresses for each stack frame, and lookup the symbol for each. Sorted.
You can do it by unwinding stack frames. In most cases (and with GCC, pretty much all cases) a function starts by pushing the base pointer (ebp). So you end up with something like this as a stack:
Code: Select all
20 <-- ESP
24
28 <-- Pushed EBP
32 <-- Pushed Return address
34
then note, that if you take any of those EBPs you just found, and add 4 to it and dereference it (go one place up the stack from it), you get the return address from that stack frame.
So all you have to do is follow the trail of EBPs, find the return addresses for each stack frame, and lookup the symbol for each. Sorted.
I figured that much, however that only works with the same calling convention. If one has certain functions that take register parameters, or one uses assembly functions, then one is stuck (well, I am stuck, since I use these :))?JamesM wrote:So all you have to do is follow the trail of EBPs, find the return addresses for each stack frame, and lookup the symbol for each. Sorted.
JAL
Ok, then I should use the PUSH EBP trick in my asm routines as well. Thanks for this very helpful information!JamesM wrote:This depends. Functions using register-passing will still work as long as the base pointer is pushed at the start of the function, which is the case for pretty much any function requiring stack-local storage. Assembler functions work for me as well (because I push EBP).
JAL
- zaleschiemilgabriel
- Member
- Posts: 232
- Joined: Mon Feb 04, 2008 3:58 am
Re:
Hi JAL,jal wrote: Ok, then I should use the PUSH EBP trick in my asm routines as well. Thanks for this very helpful information!
JAL
Did you have luck implementing this one? I too have a similar requirement and your input will be very helpful to me.
Thx