4

I'm on an ARM Cortex M0 (Nordic NRF51822) using the Segger JLink. When my code hard faults (say due to a dereferencing an invalid pointer), I see only the following stack trace:

(gdb) bt
#0  HardFault_HandlerC (hardfault_args=<optimized out>) at main_display.cpp:440
#1  0x00011290 in ?? ()

I have a hard fault handler installed and it can give me the lr and pc:

(gdb) p/x stacked_pc
$1 = 0x18ea6
(gdb) p/x stacked_lr
$2 = 0x18b35

And I know I can use addr-to-line to translate these to source code lines:

> arm-none-eabi-addr2line -e main_display.elf 0x18ea6
/Users/cmason/code/nrf/src/../libs/epaper/EPD_Display.cpp:33
> arm-none-eabi-addr2line -e main_display.elf 0x18b35
/Users/cmason/code/nrf/src/../libs/epaper/EPD.cpp:414

Can I get the rest of the backtrace somehow? If I stop at a normal breakpoint I can get a backtrace, so I know GDB can do the (somewhat complex) algorithm to unwind the stack on ARM. I understand that, in the general case, the stack may be screwed up by my code to the point where it's unreadable, but I don't think that's whats happening in this case.

I think this may be complicated by Nordic's memory protection scheme. Their bluetooth stack installs its own interrupt vector and prevents access to certain memory regions. Or maybe this is Segger's fault? On other examples of Cortex M0 do most people see regular back traces from hard faults?

Thanks!

-c

  • 1
    Possibly no; the *stack trace* is just reversing *frames* stored on the stack. If you have corrupted the stack, then the tracing will not work; the *link list* will be corrupt and at this point in time, it will be impossible to trace. See: [ARM link and frame pointer](http://stackoverflow.com/questions/15752188/arm-link-register-and-frame-pointer/) for more. Getting a register listing may be helpful. Look at the processor mode as well, if you are not is a *normal* user mode you can see the saved `pc`. – artless noise Sep 05 '13 at 15:58
  • 1
    Like I said, I don't believe the stack is corrupted in this case. I think 0x00011290 is Nordic's Hard Fault handler and that it's executing on an alternate non-user-mode stack. I'd guess my stack is still in memory, somewhere. I've also posted on [Nordic's forum](https://devzone.nordicsemi.com/index.php/back-trace-from-hard-fault-handler-with-s110-active). – Christopher Mason Sep 05 '13 at 16:47
  • You need to get `stacked_fp`, which doesn't exist in the [hard fault handler stuff](http://mcuoneclipse.com/2012/11/24/debugging-hard-faults-on-arm-cortex-m/). I don't think everyone knows about this stuff; you have installed a vector handler which records some status and then breaks to a debugger. The exception could over-write the user mode `fp` and then `gdb` is unable to trace; the same effect as if you corrupted the stack. – artless noise Sep 05 '13 at 17:20
  • Does this answer your question? [How to retain a stacktrace when Cortex-M3 gone in hardfault?](https://stackoverflow.com/questions/31255400/how-to-retain-a-stacktrace-when-cortex-m3-gone-in-hardfault) – L29Ah Dec 05 '19 at 15:14

1 Answers1

0

Cortex-M0 and Cortex-M3 is close enough that you can use the answer from this question: Stack Backtrace for ARM core using GCC compiler (when there is a MSP to PSP switch)

in short: GCC has a function _Unwind_Backtrace to generate a full call stack; this needs to be hacked up a bit to simulate doing a backtrace from before the exception entry happened. Details in the linked question.

user2501488
  • 141
  • 3