1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
// Auto-generated. Do not modify this file! Instead modify examples/exception.rs //! Exceptions handlers are smart! They help you find the source of crashes //! //! At the end there's a program that crashes. Run it with `(gdb) continue`: //! //! By the time you hit the exception, you'll see the following output in `itmdump`: //! //! ``` text //! $ itmdump /tmp/itm.fifo //! (..) //! EXCEPTION HardFault @ PC=0x080000a2 //! ``` //! //! which indicates that this is a "hard fault" exception. It also tells you were the crash //! originated! The PC (Program Counter) value is the address of the instruction that generated the //! crash. You can disassemble your program around that address using GDB: //! //! ``` text //! (gdb) disas /m 0x080000a2 //! Dump of assembler code for function exception::main: //! 32 pub extern "C" fn main() -> ! { //! 0x08000092 <+0>: sub sp, #8 //! 0x08000094 <+2>: b.n 0x8000096 <exception::main+4> //! //! 33 // This reads beyond the boundary of available RAM (40KiB starting at //! 34 // 0x4000_0000) and triggers a hard fault exception //! 35 let _hard_fault_exception = unsafe { //! 36 *((0x4000_0000 + 40 * 1024) as *const u32) //! 0x08000096 <+4>: b.n 0x8000098 <exception::main+6> //! 0x08000098 <+6>: b.n 0x800009a <exception::main+8> //! 0x0800009a <+8>: movw r0, #40960 ; 0xa000 //! 0x0800009e <+12>: movt r0, #16384 ; 0x4000 //! 0x080000a2 <+16>: ldr r0, [r0, #0] ; <-- //! 0x080000a4 <+18>: str r0, [sp, #4] //! //! 37 }; //! 38 //! 39 loop {} //! 0x080000a6 <+20>: b.n 0x80000a8 <exception::main+22> //! 0x080000a8 <+22>: b.n 0x80000a8 <exception::main+22> //! //! End of assembler dump. //! ``` //! //! `ldr r0, [r0, #0]` is the faulty instruction. It tries to load the word at the address that `r0` //! indicates. From the two previous instructions, you can tell that `r0` holds the value //! `0x4000a000`. //! //! Wait! That's not everything. There's also a local `sf` variable that points to the stack frame //! where the exception occurred. If you print it under GDB, you'll see the state of several //! registers at the moment of the crash: //! //! ``` text //! (gdb) p/x *sf //! $1 = {r0 = 0x4000a000, r1 = 0x48001000, r2 = 0x55550000, r3 = 0x48001000, //! r12 = 0x8003950, lr = 0x8000085, pc = 0x80000a2, xpsr = 0x1000000} //! ``` //! //! See? `r0 = 0x4000a000` that matches our expectations from reading the disassembly. //! //! ``` rust,no_run //! #![no_main] //! #![no_std] //! //! extern crate f3; //! //! #[export_name = "main"] //! pub extern "C" fn main() -> ! { //! // This reads beyond the boundary of available RAM (40KiB starting at //! // 0x4000_0000) and triggers an exception //! let _hard_fault_exception = //! unsafe { *((0x4000_0000 + 40 * 1024) as *const u32) }; //! //! loop {} //! } //! ```