I'm using breakpad in my project to handle crashes and generate stack trace. In stack trace, there are different ways how function calls info found by stackwalker. Process described here Finding_the_caller_frame:
What`s the difference between them? And more importantly how they could help in terms of debugging?
Thread 0 (crashed)
0 test_google_breakpad!crash [test_breakpad.cpp : 17 + 0x4]
r4 = 0x00015530 r5 = 0xbea2cbe4 r6 = 0xffffff38 r7 = 0xbea2cb5c
r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 fp = 0x00000000
sp = 0xbea2cb50 lr = 0x00009025 pc = 0x00008f84
Found by: given as instruction pointer in context
1 test_google_breakpad!main [test_breakpad.cpp : 25 + 0x3]
r4 = 0x00015530 r5 = 0xbea2cbe4 r6 = 0xffffff38 r7 = 0xbea2cb5c
r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 fp = 0x00000000
sp = 0xbea2cb50 pc = 0x00009025
Found by: call frame info
2 libc.so + 0x164e5
r4 = 0x00008f64 r5 = 0xbea2cc34 r6 = 0x00000001 r7 = 0xbea2cc3c
r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 fp = 0x00000000
sp = 0xbea2cc18 pc = 0x400c34e7
Found by: call frame info
The instruction pointer method means that there's a CPU register already pointing at the function's memory location so there was no need to search for the function. This is the easiest and most reliable way to find the current stack frame.
Next using the call frame technique you can find the caller of the current function by looking at the place in stack memory where the return address is stored. This is the exact technique that a "return" would use to find its return destination. This technique can be chained because each previous call also put its return value on the stack. This is pretty reliable, but can fail if some stack memory got corrupted (maybe stack overflow, maybe buggy pointer write) and one or more return addresses were obliterated.
Finally the least reliable technique is to just search the stack memory for anything that looks like a function address. This can help you recover from a corrupted stack but it can be hard to tell data (including function pointers!) apart from function addresses so it's guesswork. If you find one, though, you can often then chain back to the call frame technique if you find some stack that wasn't trashed.