Course contentsShow
← Rust
Lesson 1857 of 1,91016. Specialized Runtime TargetsFree lesson

Debugging Hard Faults

Analyze CPU core dumps to trace the origin of runtime crashes in bare-metal environments.

In this lesson, you will learn how to analyze CPU core dumps to pinpoint the exact location and cause of runtime crashes in bare-metal Rust environments.

When a bare-metal Rust program hits an irrecoverable state—such as an invalid memory access or an illegal instruction—the CPU triggers a "Hard Fault." In standard environments, the OS handles this, but in embedded, the CPU simply stops or resets. To debug this, we must capture a "core dump" (the state of CPU registers and stack memory) at the moment of failure.

The Anatomy of a Fault

When a fault occurs, the CPU pushes critical diagnostic information onto the stack, including the Program Counter (PC), Link Register (LR), and status registers. By defining a custom #[panic_handler] or a hardware fault exception handler, you can extract these values.

The most critical register is the Program Counter (PC), which holds the address of the instruction that caused the crash. If your build includes debug symbols, you can map this hex address back to a specific line of code using addr2line or by inspecting the generated ELF file.

Analyzing the Dump

Suppose your handler captures a PC value of 0x0800_12a4. You would use the following command in your terminal:

# Point to your compiled ELF binary and the offending address
rust-objdump -d my_embedded_app.elf | grep -A 5 "080012a4"

This reveals the assembly instruction that failed. Often, this reveals a NULL pointer dereference or an out-of-bounds access that the compiler's safety checks couldn't catch at compile-time—perhaps due to unsafe blocks or direct peripheral register manipulation.

Walking the Stack

Beyond the PC, you should inspect the Stack Pointer (SP). By tracing the stack backwards (the "backtrace"), you can see which functions called the crashing code. In resource-constrained systems, verify if the stack pointer has drifted into illegal memory, which is a common cause of hard faults in recursive or deep function call chains.

Key Takeaway: Hard faults are not opaque crashes; by capturing the Program Counter and mapping it against your ELF binary's debug symbols, you can translate hardware-level failures into precise source-code locations.