When developing a Rust no_std
bootloader for my micro:bit v2.21 (Cortex-M4, nRF52833), I have encountered a weird error.
The bootloader jumps to the main application using cortex_m::asm::bootstrap(sp, pc);
call.
Out of curiosity, I wanted to see:
- What the beginning of the Vector Table looks like on flash (addresses
0x0
and0x4
). - What addresses in RAM the Stack Pointer and Program Counter point to.
I know I can peek into the vector table using objdump
, but I wanted to see it right from the code to ensure I am handing over the bootloader's control to the right place.
What an interesting journey this was :)
Anyway, I ran into a weird issue happening only in the debug
profile.
Using the rtt_target
and log
crates, I wanted to see the SP and PC values on flash and the values they point to in RAM.
When logging the content of the SP (dereferencing the value of the 0x0
address in flash), I got:
ERROR [cortex_sp_null] The panic handler was called with PanicInfo: panicked at src/main.rs:43:9:
null pointer dereference occurred
This is a simplified main fn
I used.
#[entry]
fn main() -> ! {
let flash_origin = 0x0u32;
// Load memory addresses from the Vector Table in Flash
let sp_ptr = flash_origin as *const u32; // Stack Pointer
let pc_ptr = (flash_origin + 4) as *const u32; // Program Counter pointer
unsafe {
info!("SP FLASH ADDRESS: {:#010X}", sp_ptr as usize);
info!("PC FLASH ADDRESS: {:#010X}", pc_ptr as usize);
info!("SP RAM ADDRESS: {:#010X}", *sp_ptr);
info!("PC RAM ADDRESS: {:#010X}", *pc_ptr);
}
loop { /* print the counter */ }
}
And this line caused the panic: info!("SP RAM ADDRESS: {:#010X}", *sp_ptr);
When building and flashing the code with the --release
parameter, the code runs fine and prints out:
INFO [cortex_sp_null] Started the application
INFO [cortex_sp_null] SP FLASH ADDRESS: 0x00000000
INFO [cortex_sp_null] PC FLASH ADDRESS: 0x00000004
INFO [cortex_sp_null] SP RAM ADDRESS: 0x20020000
INFO [cortex_sp_null] PC RAM ADDRESS: 0x00000401
INFO [cortex_sp_null] Counter: 0
INFO [cortex_sp_null] Counter: 1
Without the --release
parameter, though, I get:
INFO [cortex_sp_null] Started the application
INFO [cortex_sp_null] SP FLASH ADDRESS: 0x00000000
INFO [cortex_sp_null] PC FLASH ADDRESS: 0x00000004
ERROR [cortex_sp_null] The panic handler was called with PanicInfo: panicked at src/main.rs:43:9:
null pointer dereference occurred
Do you have any idea why this could be happening? I would have assumed that the behaviour should be the same regardless of the profile.
The simplified replication application is available on GitHub, including full replication steps in the README. https://github.com/lobodpav/cortex-sp-null
sp_ptr
is equal to 0x0, and you get a crash as above when dereferencing via*sp_ptr
?! If so, the answer is quite simple: It is always invalid to dereference the null pointer. Without--release
, the compiler will helpfully inject safety checks. Yet in (default)--release
, you simply get Undefined Behavior. The fact that it seems to work is irrelevant.null
are not the same thing @user2722968 That being said the check inserted by the compiler is probably the culprit here.sp_ptr
is a pointer to flash address0x0
. I can disassemble the binary to confirm that there is a check inserted in thedebug
profile. Thanks for the hint!0x0
memory address prohibited to have? If so, how am I able to read memory from the start? :)