Skip to content

Any reason why the #[exception] macro disallows extern "C" fns? #575

Open
@SCingolani

Description

@SCingolani

I have the following signature for my HardFault handler:

#[exception(trampoline = false)]
#[naked]
unsafe fn HardFault() -> ! {
...

This triggers the compiler warning

warning: Rust ABI is unsupported in naked functions
note: #[warn(undefined_naked_function_abi)] on by default

Which could be avoided by modifying the signature to be:

#[exception(trampoline = false)]
#[naked]
unsafe extern "C" fn HardFault() -> ! {
...

But this is not accepted by the macro:

HardFault handler must have signature unsafe fn() -> !

Is there any reason for the macro to not allow specifying the ABI?

Also, could someone point me as to why does the following not produce the same warning?

#[pre_init]
#[naked]
unsafe fn pre_init() {
...

Activity

adamgreig

adamgreig commented on Jan 22, 2025

@adamgreig
Member

Do you still get this error on the latest nightly? I can compile the following OK:

#![no_std]
#![no_main]
#![feature(naked_functions)]

#[naked]
#[cortex_m_rt::pre_init]
unsafe fn pre_init() {
    core::arch::naked_asm!("nop");
}

#[naked]
#[cortex_m_rt::exception(trampoline=false)]
unsafe fn HardFault() -> ! {
    core::arch::naked_asm!("nop");
}

I don't think there's any reason to prohibit extern "C" functions here, but because the macro already generates the actual ISR and makes it extern "C" as appropriate, I don't think we should need to change the user interface. We added naked to the list of allowed attributes a while ago and what it means has changed as it moves towards stabilisation, so we should probably just make sure that the attribute does what's expected in this context.

You might find using cargo expand illuminating, for example the above expands to:

#[export_name = "__pre_init"]
#[allow(missing_docs)]
#[naked]
pub unsafe fn pre_init() {
    asm!("nop");
}
#[doc(hidden)]
#[export_name = "_HardFault"]
unsafe extern "C" fn __cortex_m_rt_HardFault_trampoline() {}
#[export_name = "HardFault"]
#[link_section = ".HardFault.user"]
#[naked]
unsafe fn __cortex_m_rt_HardFault() -> ! {
    asm!("nop");
}

in cortex-m-rt, there's a bl __pre_init which is how the pre-init function gets called, while HardFault is referred to from as extern "C" fn HardFault(); and placed into the vector table so will be called directly by hardware. The _HardFault is empty and just for diagnostics. It looks like this should all work as expected with naked functions.

SCingolani

SCingolani commented on Feb 6, 2025

@SCingolani
Author

Strange, with an empty project containing just the code from your test and rustc 1.86.0-nightly (a9730c3b5 2025-02-05) I still get:

error: #[panic_handler] function required, but not found

warning: Rust ABI is unsupported in naked functions
--> src/main.rs:13:1
|
13 | unsafe fn HardFault() -> ! {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(undefined_naked_function_abi)] on by default

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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

        Participants

        @adamgreig@SCingolani

        Issue actions

          Any reason why the `#[exception]` macro disallows `extern "C" fn`s? · Issue #575 · rust-embedded/cortex-m