Module f3::examples::exception
[−]
[src]
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
:
$ 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:
(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:
(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.
#![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 {} }Run