1
votes

When I run into a fault handler on my ARM cortex-M4 (Thumb) I get a snapshot of the CPU register just before the fault occured. With this information I can find the stack pointer where it was. Now, what I want is to backtrace through all functions it passed. The only problem I see here is that I don't have a frame pointer, so I cannot really see where a certain subroutine has saved the LR, ad infinitum.

How would one tackle this problem if the frame pointer is not available in r7?

3
disassemble the code and see what is on the stack.old_timer
What debugger are you using? I know a call stack is available on Keil Uvision. Are you tripping a trap of some kind?Koorosh Hajiani
@KooroshHajiani I'm not using a debugger, my target is running free and has logging (printf-style) capability.Evert
Under some conditions, functions that can't return (because of while (1)'s, or otherwise), won't push the LR, as it'll never use it again. In these cases you can use a non-const object-global variable in the while (while (dummy == 0)), to trick the compiler, and make it think the function can return. Could this match the problem you have?dromtrund

3 Answers

1
votes

This blog post discusses this issue with reference to the MIPS architecture - the principles can be readily adapted to ARM architectures.

In short, it describes three possibilities for locating the stack frame for a given SP and PC:

  • Using compiler-generated debug information (not included in the executable image) to calculate it.
  • Using compiler-generated stack-unwinding (exception handling) information (included in the executable image) to calculate it.
  • Scanning the call site to locate the prologue or epilogue code that adjusts the stack pointer, and deducing the stack frame address from that.

Obviously it's very compiler- and compiler-option dependent, and not guaranteed to work in all cases.

0
votes

R7 is not the frame pointer on the M4, it's R11. R7 is the FP for Cortex-M0+/M1 where only the lower registers are generally available. In anycase, when Cortex-M makes a call to a function using BL and variants, it saves the return address into LR (link register). At function entry, the LR is saved onto the stack. So in theory, to get a call trace, you would "chase" the chain of the LRs.

Unfortunately, the saved location of LR on the stack is not defined by the calling convention, and its location must be deduced from the debug info for that function entry in the DWARF records (in the .elf file). I do not know if there is an utility that would extract the LR locations from an ELF file, but it should not be too difficult.

0
votes

Richard at ImageCraft is right.

More information can be found here

This works fine with C code. I had a harder applying it to C++ but it's not impossible.