Skip to content

Unsoundness in LR register access. #570

Closed
@thomasw04

Description

@thomasw04

If I interpret this correctly, LR can basically contain an undefined value when reading it. (see https://doc.rust-lang.org/reference/inline-assembly.html#r-asm.rules.reg-not-input) In addition, the behavior is undefined when writing to LR without declaring it as out register. (see https://doc.rust-lang.org/reference/inline-assembly.html#r-asm.rules.reg-not-output)

Furthermore, specifically with the link register (LR) in the context of function calls, (see https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#subroutine-calls) this then completely relies on the compiler inlining this function, as otherwise, LR would contain the return address of the read/write function. (apart from that, by the rules above, LR does not even need to contain anything meaningful).

I am unsure how to solve this right now. If I am not mistaken, the inlining problem could be solved by using a macro.
However, regarding the undefined behavior in general, I am unsure if Rust currently has a way to make this reliably safe.

/// Reads the CPU register
#[cfg(cortex_m)]
#[inline]
pub fn read() -> u32 {
let r;
unsafe { asm!("mov {}, lr", out(reg) r, options(nomem, nostack, preserves_flags)) };
r
}
/// Writes `bits` to the CPU register
#[cfg(cortex_m)]
#[inline]
pub unsafe fn write(bits: u32) {
asm!("mov lr, {}", in(reg) bits, options(nomem, nostack, preserves_flags));
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions