Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
SCingolani opened this issue Jan 17, 2025 · 1 comment
Open

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

SCingolani opened this issue Jan 17, 2025 · 1 comment

Comments

@SCingolani
Copy link

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() {
...
@adamgreig
Copy link
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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants