Originally Posted by
matsp
You can quite easily write a function that dumps the stack in hex, and, if you can get a machine-readable form of the symbol table, can give you the function names from this.
The following should work on Intel-type architectures where the calling convention is "Push Args, Push Return, Push Base Pointer." The recur() and recur2() functions are just for demonstration. main() is proxied to trace(), in order to avoid any weirdness caused by main() not being a "normal" function. Calling backtrace(0) at any point will dump a raw trace, which you can fairly easily match up with function names by referring to a link map:
Code:
#include <stdio.h>
void recur(int n);
void recur2(int n);
unsigned int *base_top;
void backtrace(unsigned int dummy)
{
unsigned int *base = &dummy - 2;
unsigned int *ret = base + 1;
printf("0x%08x\n", *ret);
while(*base != (unsigned int)base_top)
{
base = (unsigned int *)*base;
ret = base + 1;
printf("0x%08x\n", *ret);
}
}
void recur(int n)
{
if(!n)
{
backtrace(0);
}
else
{
recur2(n);
}
}
void recur2(int n)
{
recur(n - 1);
}
int trace(int argc, char **argv)
{
base_top = (unsigned int *)&argc - 2;
recur(10);
}
int main(int argc, char **argv)
{
return trace(argc, argv);
}
Downside: Not portable, and liable to crash if the stack is not in pristine condition. Compiler optimizations may obscure your trace or cause it to explode. I provide no warranty