crash.rs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. //! Debugging a crash (exception)
  2. //!
  3. //! Most crash conditions trigger a hard fault exception, whose handler is defined via
  4. //! `exception!(HardFault, ..)`. The `HardFault` handler has access to the exception frame, a
  5. //! snapshot of the CPU registers at the moment of the exception.
  6. //!
  7. //! This program crashes and the `HardFault` handler prints to the console the contents of the
  8. //! `ExceptionFrame` and then triggers a breakpoint. From that breakpoint one can see the backtrace
  9. //! that led to the exception.
  10. //!
  11. //! ``` text
  12. //! (gdb) continue
  13. //! Program received signal SIGTRAP, Trace/breakpoint trap.
  14. //! __bkpt () at asm/bkpt.s:3
  15. //! 3 bkpt
  16. //!
  17. //! (gdb) backtrace
  18. //! #0 __bkpt () at asm/bkpt.s:3
  19. //! #1 0x080030b4 in cortex_m::asm::bkpt () at $$/cortex-m-0.5.0/src/asm.rs:19
  20. //! #2 rust_begin_unwind (args=..., file=..., line=99, col=5) at $$/panic-semihosting-0.2.0/src/lib.rs:87
  21. //! #3 0x08001d06 in core::panicking::panic_fmt () at libcore/panicking.rs:71
  22. //! #4 0x080004a6 in crash::hard_fault (ef=0x20004fa0) at examples/crash.rs:99
  23. //! #5 0x08000548 in UserHardFault (ef=0x20004fa0) at <exception macros>:10
  24. //! #6 0x0800093a in HardFault () at asm.s:5
  25. //! Backtrace stopped: previous frame identical to this frame (corrupt stack?)
  26. //! ```
  27. //!
  28. //! In the console output one will find the state of the Program Counter (PC) register at the time
  29. //! of the exception.
  30. //!
  31. //! ``` text
  32. //! panicked at 'HardFault at ExceptionFrame {
  33. //! r0: 0x2fffffff,
  34. //! r1: 0x2fffffff,
  35. //! r2: 0x080051d4,
  36. //! r3: 0x080051d4,
  37. //! r12: 0x20000000,
  38. //! lr: 0x08000435,
  39. //! pc: 0x08000ab6,
  40. //! xpsr: 0x61000000
  41. //! }', examples/crash.rs:106:5
  42. //! ```
  43. //!
  44. //! This register contains the address of the instruction that caused the exception. In GDB one can
  45. //! disassemble the program around this address to observe the instruction that caused the
  46. //! exception.
  47. //!
  48. //! ``` text
  49. //! (gdb) disassemble/m 0x08000ab6
  50. //! Dump of assembler code for function core::ptr::read_volatile:
  51. //! 451 pub unsafe fn read_volatile<T>(src: *const T) -> T {
  52. //! 0x08000aae <+0>: sub sp, #16
  53. //! 0x08000ab0 <+2>: mov r1, r0
  54. //! 0x08000ab2 <+4>: str r0, [sp, #8]
  55. //!
  56. //! 452 intrinsics::volatile_load(src)
  57. //! 0x08000ab4 <+6>: ldr r0, [sp, #8]
  58. //! -> 0x08000ab6 <+8>: ldr r0, [r0, #0]
  59. //! 0x08000ab8 <+10>: str r0, [sp, #12]
  60. //! 0x08000aba <+12>: ldr r0, [sp, #12]
  61. //! 0x08000abc <+14>: str r1, [sp, #4]
  62. //! 0x08000abe <+16>: str r0, [sp, #0]
  63. //! 0x08000ac0 <+18>: b.n 0x8000ac2 <core::ptr::read_volatile+20>
  64. //!
  65. //! 453 }
  66. //! 0x08000ac2 <+20>: ldr r0, [sp, #0]
  67. //! 0x08000ac4 <+22>: add sp, #16
  68. //! 0x08000ac6 <+24>: bx lr
  69. //!
  70. //! End of assembler dump.
  71. //! ```
  72. //!
  73. //! `ldr r0, [r0, #0]` caused the exception. This instruction tried to load (read) a 32-bit word
  74. //! from the address stored in the register `r0`. Looking again at the contents of `ExceptionFrame`
  75. //! we see that the `r0` contained the address `0x2FFF_FFFF` when this instruction was executed.
  76. //!
  77. //! ---
  78. #![no_main]
  79. #![no_std]
  80. use panic_halt as _;
  81. use core::ptr;
  82. use cortex_m_rt::entry;
  83. #[entry]
  84. fn main() -> ! {
  85. unsafe {
  86. // read an address outside of the RAM region; this causes a HardFault exception
  87. ptr::read_volatile(0x2FFF_FFFF as *const u32);
  88. }
  89. loop {}
  90. }