Weird ROPI relocation model crashes - a hypothesis

I've been hacking on bolos-rs which is a Rust based SDK for Ledger security devices (thumbv6m-none-eabi target). Sadly there are no debug options available to me, other than seeing the app crash the device and trying to narrow down the issues by commenting out code and seeing when it crashes and when it stops crashing.

Anyway, I've had some weird crashes that I have a gut feeling is due to the ROPI relocation model. For instance, this works:

pub fn event() -> Response {
    let params = [
        UxType::Event as u8,
        0,
    ];
    invoke_ux(&params)
}

But this crashes:

pub fn event() -> Response {
    invoke_ux(&[
        UxType::Event as u8,
        0,
    ])
}

And at some point, I started getting crashes that went away after #[inline(never)] hint was added to the function above.

I know that clang ROPI support doesn't support C globals too well. But I haven't really deep-dived into the Rust compiler nor the clang codebase, but I have come to a hypothesis based on what I've observed. A hypothesis that I would like to bounce off of someone more knowledgeable regarding the inner workings of the compiler.

I'm thinking there might be some optimization somewhere in the compilation pipeline, that optimizes certain variables into globals, which end up not playing too well with ROPI relocation model. Does anyone know if such a thing exists somewhere in rustc or clang? Or maybe I'm barking up the wrong tree completely?

I haven't yet been able to make a bare-bones test case where the generated assembly could easily be analysed.

(Not a compiler dev.)
More than likely. Constants get optimised best the compiler can, taking a reference to one will result in a &'static to some global memory.
From what I have read write_volatile is way to avoid any such optimisation.

1 Like

There’s rvalue static promotion but I wouldn’t expect it to kick in in the example given because it’s not a 'static context; instead, I’d expect a “hidden” local to be created and passed to the invoke_ux(). But maybe there’s a bug/issue in how the latter optimizes on that platform.

I wouldn’t expect a 'static promotion here (if nothing else, it would lead to bloat if this happened consistently for cold functions).