Conveniently, if the program was compiled with GCC there's a much
easier way. GCC has a builtin primitive that lets you get the
frame pointer or return pointer address of any function in the call stack (documentation
here.) Obviously, this is just the address, but you can then
use dladdr()
to extract the name of the function.
Put together, you've got a backtrace.
Note that this only gives you the function name and
(with some work) the offset into the function. You'd need to
grovel through the symbol table or something to actually
figure out what line of source you were on. Still, that's information
you didn't have before and is enough for a lot of purposes.
On FreeBSD, there's actually a library in ports called libexecinfo, which implements this trick. That's where I learned about it. Glibc also includes this as a native facility. I assume it works like this, but haven't bothered to examine the source.