Skip to content

#[naked]: report incompatible attributes #127853

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

Merged
merged 7 commits into from
Jul 28, 2024

Conversation

folkertdev
Copy link
Contributor

@folkertdev folkertdev commented Jul 17, 2024

tracking issue: #90957

this is a re-implementation of #93809 by @bstrie which was closed 2 years ago due to inactivity.

This PR takes some of the final comments into account, specifically providing a little more context in error messages, and using an allow list to determine which attributes are compatible with #[naked].

Notable attributes that are incompatible with #[naked] are:

  • #[inline]
  • #[track_caller]
  • #[target_feature] (this is now allowed, see PR discussion)
  • #[test], #[ignore], #[should_panic]

These attributes just directly conflict with what #[naked] should do.

Naked functions are still important for systems programming, embedded, and operating systems, so I'd like to move them forward.

@rustbot
Copy link
Collaborator

rustbot commented Jul 17, 2024

r? @compiler-errors

rustbot has assigned @compiler-errors.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 17, 2024
//
// * `#[inline]`
// * `#[track_caller]`
// * `#[target_feature]`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[target_feature] affects the set of instructions allowed inside inline assembly as well as the exact encoding of certain instructions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I'm going off of #90957 (comment) where @joshtriplett suggests to exclude #[target_feature] initially.

that was 2 years ago though so maybe that should be re-evaluated. Do you have concerns with allowing #[target_feature] now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what a reason for forbidding it would be, and why @joshtriplett thought it would be hard to get right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well a reason to be cautious is that I think to most (me included) it's not 100% clear what #[target_feature] could do. Are we absolutely sure that on no platform, present or future, a target feature would insert additional instructions that violate the assumptions of #[naked]?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I said at the time was that it might take some care to get right. If we take that care, and commit to avoiding any potential issues that might arise (e.g. locking down what a given target_feature means for a naked function and never inserting any instructions for it), then supporting the combination seems fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the implementation strategy in #128004 I don't think there is any risk of #[target_feature] inserting instructions. The user's inline assembly block is hoisted to a top-level global asm block, and the function itself becomes effectively an extern fn.

So I've now added target_feature to the allow list in a separate commit that can be reverted if there are any concerns.

@compiler-errors
Copy link
Member

r? bjorn3

@rustbot rustbot assigned bjorn3 and unassigned compiler-errors Jul 25, 2024
@bjorn3
Copy link
Member

bjorn3 commented Jul 26, 2024

@bors r+

@bors
Copy link
Collaborator

bors commented Jul 26, 2024

📌 Commit 45e943f has been approved by bjorn3

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 26, 2024
tgross35 added a commit to tgross35/rust that referenced this pull request Jul 26, 2024
…ssages, r=bjorn3

`#[naked]`: report incompatible attributes

tracking issue: rust-lang#90957

this is a re-implementation of rust-lang#93809 by `@bstrie` which was closed 2 years ago due to inactivity.

This PR takes some of the final comments into account, specifically providing a little more context in error messages, and using an allow list to determine which attributes are compatible with `#[naked]`.

Notable attributes that are incompatible with `#[naked]` are:

  * `#[inline]`
  * `#[track_caller]`
  * ~~`#[target_feature]`~~ (this is now allowed, see discussion below)
  * `#[test]`, `#[ignore]`, `#[should_panic]`

There may be valid use cases for `#[target_feature]` but for now it is disallowed. The others just directly conflict with what `#[naked]` should do.

Naked functions are still important for systems programming, embedded and operating systems, so I'd like to move them forward.
bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 26, 2024
Rollup of 9 pull requests

Successful merges:

 - rust-lang#124941 (Stabilize const `{integer}::from_str_radix` i.e. `const_int_from_str`)
 - rust-lang#127853 (`#[naked]`: report incompatible attributes)
 - rust-lang#128210 (rustdoc: change title of search results)
 - rust-lang#128223 (Refactor complex conditions in `collect_tokens_trailing_token`)
 - rust-lang#128224 (Remove unnecessary range replacements)
 - rust-lang#128226 (Remove redundant option that was just encoding that a slice was empty)
 - rust-lang#128227 (CI: do not respect custom try jobs for unrolled perf builds)
 - rust-lang#128229 (Improve `extern "<abi>" unsafe fn()` error message)
 - rust-lang#128235 (Fix `Iterator::filter` docs)

r? `@ghost`
`@rustbot` modify labels: rollup
@tgross35
Copy link
Contributor

@bors r-

It looks like the changes here are breaking the compiler_builtins build #128248 (comment). It seems like link-related attributes (linkage here) shouldn't be incompatible?

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jul 26, 2024
@folkertdev
Copy link
Contributor Author

folkertdev commented Jul 26, 2024

right, that's a (perma-unstable, apparently) unstable attribute and only external linkage makes sense, but it makes sense to add to the allowlist I think. I'll add it

@folkertdev
Copy link
Contributor Author

@rustbot ready

though are there other unstable attributes that may be missing from that list? is there a comprehensive list of such attributes?

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 26, 2024
@tgross35
Copy link
Contributor

I don't know of any list specific for attributes unfortunately, just the huge list in compiler/rustc_span/src/symbol.rs. link_ordinal seems to make sense too, maybe worth double checking the other link_* symbols to see if they are applicable.

Does this correctly flag on #[cfg_attr(foo, invalid_attribute)] when foo is true? Could probably use a test if so. (Also probably a squash).

github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Aug 2, 2024
…bjorn3

make `///` doc comments compatible with naked functions

tracking issue: rust-lang/rust#90957

reported in rust-lang/rust#127853 (comment)

it turns out `/// doc comment` and `#[doc = "doc comment"]` are represented differently, at least at the point where we perform the check for what should be allowed. The `///` style doc comment is now also allowed.

r? ``@bjorn3``

cc ``@hsanzg``
@Freax13
Copy link
Contributor

Freax13 commented Aug 17, 2024

unclear. Whether these make sense really depends on the outcome of #128004

  • sym::repr

  • sym::patchable_function_entry

  • sym::no_sanitize

Before this PR was merged, I was able to use #[no_sanitize(address)] on a #[naked] function with the calling convention "x86-interrupt". Omitting #[no_sanitize(address)] leads to a compiler crash. I tried looking at the generated LLVM IR and the function prologue contains a bunch of other KASAN-related stuff which I wouldn't expect for naked function. I'm not sure whether the right solution here is to stop sanitizing naked functions in the first place or to allow #[no_sanitize(...)] on them.

@folkertdev
Copy link
Contributor Author

The idea of the linked PR is to implement naked functions like this

core::arch::global_asm!(".globl page_fault_handler","page_fault_handler:", "ud2");

extern "x86-interrupt" { 
    fn page_fault_handler(_: u64, _: u64);
}

but with support for (const) generics and with being able to export the symbol (which is tricky with extern function declarations in user space). I think in that world, the no_sanitize is no longer needed? At least on godbolt the above codegens fine.

However, in the meantime, we probably should not break anyone? @bjorn3 do you have thoughts on what to do?

@tgross35
Copy link
Contributor

Before this PR was merged, I was able to use #[no_sanitize(address)] on a #[naked] function with the calling convention "x86-interrupt". Omitting #[no_sanitize(address)] leads to a compiler crash. I tried looking at the generated LLVM IR and the function prologue contains a bunch of other KASAN-related stuff which I wouldn't expect for naked function. I'm not sure whether the right solution here is to stop sanitizing naked functions in the first place or to allow #[no_sanitize(...)] on them.

@Freax13 could you open a new bug for this crash? It seems like that very specific combination of extern "x86-interrupt", sanitizers, and naked functions is required to reproduce. And it's been around since before this PR, https://godbolt.org/z/EnhsWxejT (using RUSTC_BOOTSTRAP for the demo). Naked functions should probably just never get sanitizer annotations, but we can ping project-exploit-mitigations on the issue to confirm.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Dec 1, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`
fmease added a commit to fmease/rust that referenced this pull request Dec 4, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`
fmease added a commit to fmease/rust that referenced this pull request Dec 5, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with ``@Amanieu`` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? ``@Amanieu``
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 8, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 8, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`

try-job: x86_64-gnu-nopt
jieyouxu added a commit to jieyouxu/rust that referenced this pull request Dec 9, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`

try-job: x86_64-gnu-nopt
jieyouxu added a commit to jieyouxu/rust that referenced this pull request Dec 9, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with ``@Amanieu`` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? ``@Amanieu``

try-job: x86_64-gnu-nopt
fmease added a commit to fmease/rust that referenced this pull request Dec 9, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`

try-job: x86_64-gnu-nopt
try-job: x86_64-apple-1
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 9, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`

try-job: x86_64-gnu-nopt
try-job: x86_64-apple-1
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 10, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`

try-job: x86_64-gnu-nopt
try-job: x86_64-apple-1
try-job: x86-64-msvc
try-job: i686-mingw
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 10, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`

try-job: x86_64-gnu-nopt
try-job: x86_64-apple-1
try-job: x86_64-msvc
try-job: i686-mingw
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 10, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`

try-job: x86_64-gnu-nopt
try-job: x86_64-apple-1
try-job: x86_64-msvc
try-job: i686-mingw
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 11, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 11, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 11, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang#90957

Fixes rust-lang#124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Dec 12, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang/rust#90957

Fixes #124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang/rust#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`
lnicola pushed a commit to lnicola/rust-analyzer that referenced this pull request Dec 23, 2024
codegen `#[naked]` functions using global asm

tracking issue: rust-lang/rust#90957

Fixes #124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang/rust#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`
antoyo pushed a commit to rust-lang/rustc_codegen_gcc that referenced this pull request Jan 13, 2025
codegen `#[naked]` functions using global asm

tracking issue: rust-lang/rust#90957

Fixes #124375

This implements the approach suggested in the tracking issue: use the existing global assembly infrastructure to emit the body of `#[naked]` functions. The main advantage is that we now have full control over what gets generated, and are no longer dependent on LLVM not sneakily messing with our output (inlining, adding extra instructions, etc).

I discussed this approach with `@Amanieu` and while I think the general direction is correct, there is probably a bunch of stuff that needs to change or move around here. I'll leave some inline comments on things that I'm not sure about.

Combined with rust-lang/rust#127853, if both accepted, I think that resolves all steps from the tracking issue.

r? `@Amanieu`
jieyouxu added a commit to jieyouxu/rust that referenced this pull request Apr 21, 2025
…ns, r=tgross35,Amanieu,traviscross

Stabilize `naked_functions`

tracking issue: rust-lang#90957
request for stabilization on tracking issue: rust-lang#90957 (comment)
reference PR: rust-lang/reference#1689

# Request for Stabilization

Two years later, we're ready to try this again. Even though this issue is already marked as having passed FCP, given the amount of time that has passed and the changes in implementation strategy, we should follow the process again.

## Summary

The `naked_functions` feature has two main parts: the `#[naked]` function attribute, and the `naked_asm!` macro.

An example of a naked function:

```rust
const THREE: usize = 3;

#[naked]
pub extern "sysv64" fn add_n(number: usize) -> usize {
    // SAFETY: the validity of the used registers
    // is guaranteed according to the "sysv64" ABI
    unsafe {
        core::arch::naked_asm!(
            "add rdi, {}",
            "mov rax, rdi",
            "ret",
            const THREE,
        )
    }
}
```

When the `#[naked]` attribute is applied to a function, the compiler won't emit a [function prologue](https://en.wikipedia.org/wiki/Function_prologue_and_epilogue) or epilogue when generating code for this function. This attribute is analogous to [`__attribute__((naked))`](https://developer.arm.com/documentation/100067/0608/Compiler-specific-Function--Variable--and-Type-Attributes/--attribute----naked---function-attribute) in C. The use of this feature allows the programmer to have precise control over the assembly that is generated for a given function.

The body of a naked function must consist of a single `naked_asm!` invocation, a heavily restricted variant of the `asm!` macro: the only legal operands are `const` and `sym`, and the only legal options are `raw` and `att_syntax`. In lieu of specifying operands, the `naked_asm!` within a naked function relies on the function's calling convention to determine the validity of registers.

## Documentation

The Rust Reference: rust-lang/reference#1689
(Previous PR: rust-lang/reference#1153)

## Tests

* [tests/run-make/naked-symbol-visiblity](https://github.com/rust-lang/rust/tree/master/tests/codegen/naked-fn) verifies that `pub`, `#[no_mangle]` and `#[linkage = "..."]` work correctly for naked functions
* [tests/codegen/naked-fn](https://github.com/rust-lang/rust/tree/master/tests/codegen/naked-fn) has tests for function alignment, use of generics, and validates the exact assembly output on linux, macos, windows and thumb
* [tests/ui/asm/naked-*](https://github.com/rust-lang/rust/tree/master/tests/ui/asm) tests for incompatible attributes, generating errors around incorrect use of `naked_asm!`, etc

## Interaction with other (unstable) features

### [fn_align](rust-lang#82232)

Combining `#[naked]` with `#[repr(align(N))]` works well, and is tested e.g. here

- https://github.com/rust-lang/rust/blob/master/tests/codegen/naked-fn/aligned.rs
- https://github.com/rust-lang/rust/blob/master/tests/codegen/naked-fn/min-function-alignment.rs

It's tested extensively because we do need to explicitly support the `repr(align)` attribute (and make sure we e.g. don't mistake powers of two for number of bytes).

## History

This feature was originally proposed in [RFC 1201](rust-lang/rfcs#1201), filed on 2015-07-10 and accepted on 2016-03-21. Support for this feature was added in [rust-lang#32410](rust-lang#32410), landing on 2016-03-23. Development languished for several years as it was realized that the semantics given in RFC 1201 were insufficiently specific. To address this, a minimal subset of naked functions was specified by [RFC 2972](rust-lang/rfcs#2972), filed on 2020-08-07 and accepted on 2021-11-16. Prior to the acceptance of RFC 2972, all of the stricter behavior specified by RFC 2972 was implemented as a series of warn-by-default lints that would trigger on existing uses of the `naked` attribute; these lints became hard errors in [rust-lang#93153](rust-lang#93153) on 2022-01-22. As a result, today RFC 2972 has completely superseded RFC 1201 in describing the semantics of the `naked` attribute.

More recently, the `naked_asm!` macro was added to replace the earlier use of a heavily restricted `asm!` invocation. The `naked_asm!` name is clearer in error messages, and provides a place for documenting the specific requirements of inline assembly in naked functions.

The implementation strategy was changed to emitting a global assembly block. In effect, an extern function

```rust
extern "C" fn foo() {
    core::arch::naked_asm!("ret")
}
```

is emitted as something similar to

```rust
core::arch::global_asm!(
    "foo:",
    "ret"
);

extern "C" {
    fn foo();
}
```

The codegen approach was chosen over the llvm naked function attribute because:

- the rust compiler can guarantee the behavior (no sneaky additional instructions, no inlining, etc.)
- behavior is the same on all backends (llvm, cranelift, gcc, etc)

Finally, there is now an allow list of compatible attributes on naked functions, so that e.g. `#[inline]` is rejected with an error. The `#[target_feature]` attribute on naked functions was later made separately unstable, because implementing it is complex and we did not want to block naked functions themselves on how target features work on them. See also rust-lang#138568.

relevant PRs for these recent changes

- rust-lang#127853
- rust-lang#128651
- rust-lang#128004
- rust-lang#138570
-
### Various historical notes

#### `noreturn`
[RFC 2972](https://github.com/rust-lang/rfcs/blob/master/text/2972-constrained-naked.md) mentions that naked functions

> must have a body which contains only a single asm!() statement which:
> iii. must contain the noreturn option.

Instead of `asm!`, the current implementation mandates that the body contain a single `naked_asm!` statement. The `naked_asm!` macro is a heavily restricted version of the `asm!` macro, making it easier to talk about and document the rules of assembly in naked functions and give dedicated error messages.

For `naked_asm!`, the behavior of the `asm!`'s `noreturn` option is implicit. The `noreturn` option means that it is UB for control flow to fall through the end of the assembly block. With `asm!`, this option is usually used for blocks that diverge (and thus have no return and can be typed as `!`). With `naked_asm!`, the intent is different: usually naked funtions do return, but they must do so from within the assembly block. The `noreturn` option was used so that the compiler would not itself also insert a `ret` instruction at the very end.

#### padding / `ud2`

A `naked_asm!` block that violates the safety assumption that control flow must not fall through the end of the assembly block is UB. Because no return instruction is emitted, whatever bytes follow the naked function will be executed, resulting in truly undefined behavior. There has been discussion whether rustc should emit an invalid instruction (e.g. `ud2`  on x86) after the `naked_asm!` block to at least fail early in the case of an invalid `naked_asm!`. It was however decided that it is more useful to guarantee that `#[naked]` functions NEVER contain any instructions besides those in the `naked_asm!` block.

# unresolved questions

None

r? `@Amanieu`

I've validated the tests on x86_64 and aarch64
ChrisDenton added a commit to ChrisDenton/rust that referenced this pull request Apr 21, 2025
…ns, r=tgross35,Amanieu,traviscross

Stabilize `naked_functions`

tracking issue: rust-lang#90957
request for stabilization on tracking issue: rust-lang#90957 (comment)
reference PR: rust-lang/reference#1689

# Request for Stabilization

Two years later, we're ready to try this again. Even though this issue is already marked as having passed FCP, given the amount of time that has passed and the changes in implementation strategy, we should follow the process again.

## Summary

The `naked_functions` feature has two main parts: the `#[naked]` function attribute, and the `naked_asm!` macro.

An example of a naked function:

```rust
const THREE: usize = 3;

#[naked]
pub extern "sysv64" fn add_n(number: usize) -> usize {
    // SAFETY: the validity of the used registers
    // is guaranteed according to the "sysv64" ABI
    unsafe {
        core::arch::naked_asm!(
            "add rdi, {}",
            "mov rax, rdi",
            "ret",
            const THREE,
        )
    }
}
```

When the `#[naked]` attribute is applied to a function, the compiler won't emit a [function prologue](https://en.wikipedia.org/wiki/Function_prologue_and_epilogue) or epilogue when generating code for this function. This attribute is analogous to [`__attribute__((naked))`](https://developer.arm.com/documentation/100067/0608/Compiler-specific-Function--Variable--and-Type-Attributes/--attribute----naked---function-attribute) in C. The use of this feature allows the programmer to have precise control over the assembly that is generated for a given function.

The body of a naked function must consist of a single `naked_asm!` invocation, a heavily restricted variant of the `asm!` macro: the only legal operands are `const` and `sym`, and the only legal options are `raw` and `att_syntax`. In lieu of specifying operands, the `naked_asm!` within a naked function relies on the function's calling convention to determine the validity of registers.

## Documentation

The Rust Reference: rust-lang/reference#1689
(Previous PR: rust-lang/reference#1153)

## Tests

* [tests/run-make/naked-symbol-visiblity](https://github.com/rust-lang/rust/tree/master/tests/codegen/naked-fn) verifies that `pub`, `#[no_mangle]` and `#[linkage = "..."]` work correctly for naked functions
* [tests/codegen/naked-fn](https://github.com/rust-lang/rust/tree/master/tests/codegen/naked-fn) has tests for function alignment, use of generics, and validates the exact assembly output on linux, macos, windows and thumb
* [tests/ui/asm/naked-*](https://github.com/rust-lang/rust/tree/master/tests/ui/asm) tests for incompatible attributes, generating errors around incorrect use of `naked_asm!`, etc

## Interaction with other (unstable) features

### [fn_align](rust-lang#82232)

Combining `#[naked]` with `#[repr(align(N))]` works well, and is tested e.g. here

- https://github.com/rust-lang/rust/blob/master/tests/codegen/naked-fn/aligned.rs
- https://github.com/rust-lang/rust/blob/master/tests/codegen/naked-fn/min-function-alignment.rs

It's tested extensively because we do need to explicitly support the `repr(align)` attribute (and make sure we e.g. don't mistake powers of two for number of bytes).

## History

This feature was originally proposed in [RFC 1201](rust-lang/rfcs#1201), filed on 2015-07-10 and accepted on 2016-03-21. Support for this feature was added in [rust-lang#32410](rust-lang#32410), landing on 2016-03-23. Development languished for several years as it was realized that the semantics given in RFC 1201 were insufficiently specific. To address this, a minimal subset of naked functions was specified by [RFC 2972](rust-lang/rfcs#2972), filed on 2020-08-07 and accepted on 2021-11-16. Prior to the acceptance of RFC 2972, all of the stricter behavior specified by RFC 2972 was implemented as a series of warn-by-default lints that would trigger on existing uses of the `naked` attribute; these lints became hard errors in [rust-lang#93153](rust-lang#93153) on 2022-01-22. As a result, today RFC 2972 has completely superseded RFC 1201 in describing the semantics of the `naked` attribute.

More recently, the `naked_asm!` macro was added to replace the earlier use of a heavily restricted `asm!` invocation. The `naked_asm!` name is clearer in error messages, and provides a place for documenting the specific requirements of inline assembly in naked functions.

The implementation strategy was changed to emitting a global assembly block. In effect, an extern function

```rust
extern "C" fn foo() {
    core::arch::naked_asm!("ret")
}
```

is emitted as something similar to

```rust
core::arch::global_asm!(
    "foo:",
    "ret"
);

extern "C" {
    fn foo();
}
```

The codegen approach was chosen over the llvm naked function attribute because:

- the rust compiler can guarantee the behavior (no sneaky additional instructions, no inlining, etc.)
- behavior is the same on all backends (llvm, cranelift, gcc, etc)

Finally, there is now an allow list of compatible attributes on naked functions, so that e.g. `#[inline]` is rejected with an error. The `#[target_feature]` attribute on naked functions was later made separately unstable, because implementing it is complex and we did not want to block naked functions themselves on how target features work on them. See also rust-lang#138568.

relevant PRs for these recent changes

- rust-lang#127853
- rust-lang#128651
- rust-lang#128004
- rust-lang#138570
-
### Various historical notes

#### `noreturn`
[RFC 2972](https://github.com/rust-lang/rfcs/blob/master/text/2972-constrained-naked.md) mentions that naked functions

> must have a body which contains only a single asm!() statement which:
> iii. must contain the noreturn option.

Instead of `asm!`, the current implementation mandates that the body contain a single `naked_asm!` statement. The `naked_asm!` macro is a heavily restricted version of the `asm!` macro, making it easier to talk about and document the rules of assembly in naked functions and give dedicated error messages.

For `naked_asm!`, the behavior of the `asm!`'s `noreturn` option is implicit. The `noreturn` option means that it is UB for control flow to fall through the end of the assembly block. With `asm!`, this option is usually used for blocks that diverge (and thus have no return and can be typed as `!`). With `naked_asm!`, the intent is different: usually naked funtions do return, but they must do so from within the assembly block. The `noreturn` option was used so that the compiler would not itself also insert a `ret` instruction at the very end.

#### padding / `ud2`

A `naked_asm!` block that violates the safety assumption that control flow must not fall through the end of the assembly block is UB. Because no return instruction is emitted, whatever bytes follow the naked function will be executed, resulting in truly undefined behavior. There has been discussion whether rustc should emit an invalid instruction (e.g. `ud2`  on x86) after the `naked_asm!` block to at least fail early in the case of an invalid `naked_asm!`. It was however decided that it is more useful to guarantee that `#[naked]` functions NEVER contain any instructions besides those in the `naked_asm!` block.

# unresolved questions

None

r? ``@Amanieu``

I've validated the tests on x86_64 and aarch64
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Apr 21, 2025
Rollup merge of rust-lang#134213 - folkertdev:stabilize-naked-functions, r=tgross35,Amanieu,traviscross

Stabilize `naked_functions`

tracking issue: rust-lang#90957
request for stabilization on tracking issue: rust-lang#90957 (comment)
reference PR: rust-lang/reference#1689

# Request for Stabilization

Two years later, we're ready to try this again. Even though this issue is already marked as having passed FCP, given the amount of time that has passed and the changes in implementation strategy, we should follow the process again.

## Summary

The `naked_functions` feature has two main parts: the `#[naked]` function attribute, and the `naked_asm!` macro.

An example of a naked function:

```rust
const THREE: usize = 3;

#[naked]
pub extern "sysv64" fn add_n(number: usize) -> usize {
    // SAFETY: the validity of the used registers
    // is guaranteed according to the "sysv64" ABI
    unsafe {
        core::arch::naked_asm!(
            "add rdi, {}",
            "mov rax, rdi",
            "ret",
            const THREE,
        )
    }
}
```

When the `#[naked]` attribute is applied to a function, the compiler won't emit a [function prologue](https://en.wikipedia.org/wiki/Function_prologue_and_epilogue) or epilogue when generating code for this function. This attribute is analogous to [`__attribute__((naked))`](https://developer.arm.com/documentation/100067/0608/Compiler-specific-Function--Variable--and-Type-Attributes/--attribute----naked---function-attribute) in C. The use of this feature allows the programmer to have precise control over the assembly that is generated for a given function.

The body of a naked function must consist of a single `naked_asm!` invocation, a heavily restricted variant of the `asm!` macro: the only legal operands are `const` and `sym`, and the only legal options are `raw` and `att_syntax`. In lieu of specifying operands, the `naked_asm!` within a naked function relies on the function's calling convention to determine the validity of registers.

## Documentation

The Rust Reference: rust-lang/reference#1689
(Previous PR: rust-lang/reference#1153)

## Tests

* [tests/run-make/naked-symbol-visiblity](https://github.com/rust-lang/rust/tree/master/tests/codegen/naked-fn) verifies that `pub`, `#[no_mangle]` and `#[linkage = "..."]` work correctly for naked functions
* [tests/codegen/naked-fn](https://github.com/rust-lang/rust/tree/master/tests/codegen/naked-fn) has tests for function alignment, use of generics, and validates the exact assembly output on linux, macos, windows and thumb
* [tests/ui/asm/naked-*](https://github.com/rust-lang/rust/tree/master/tests/ui/asm) tests for incompatible attributes, generating errors around incorrect use of `naked_asm!`, etc

## Interaction with other (unstable) features

### [fn_align](rust-lang#82232)

Combining `#[naked]` with `#[repr(align(N))]` works well, and is tested e.g. here

- https://github.com/rust-lang/rust/blob/master/tests/codegen/naked-fn/aligned.rs
- https://github.com/rust-lang/rust/blob/master/tests/codegen/naked-fn/min-function-alignment.rs

It's tested extensively because we do need to explicitly support the `repr(align)` attribute (and make sure we e.g. don't mistake powers of two for number of bytes).

## History

This feature was originally proposed in [RFC 1201](rust-lang/rfcs#1201), filed on 2015-07-10 and accepted on 2016-03-21. Support for this feature was added in [rust-lang#32410](rust-lang#32410), landing on 2016-03-23. Development languished for several years as it was realized that the semantics given in RFC 1201 were insufficiently specific. To address this, a minimal subset of naked functions was specified by [RFC 2972](rust-lang/rfcs#2972), filed on 2020-08-07 and accepted on 2021-11-16. Prior to the acceptance of RFC 2972, all of the stricter behavior specified by RFC 2972 was implemented as a series of warn-by-default lints that would trigger on existing uses of the `naked` attribute; these lints became hard errors in [rust-lang#93153](rust-lang#93153) on 2022-01-22. As a result, today RFC 2972 has completely superseded RFC 1201 in describing the semantics of the `naked` attribute.

More recently, the `naked_asm!` macro was added to replace the earlier use of a heavily restricted `asm!` invocation. The `naked_asm!` name is clearer in error messages, and provides a place for documenting the specific requirements of inline assembly in naked functions.

The implementation strategy was changed to emitting a global assembly block. In effect, an extern function

```rust
extern "C" fn foo() {
    core::arch::naked_asm!("ret")
}
```

is emitted as something similar to

```rust
core::arch::global_asm!(
    "foo:",
    "ret"
);

extern "C" {
    fn foo();
}
```

The codegen approach was chosen over the llvm naked function attribute because:

- the rust compiler can guarantee the behavior (no sneaky additional instructions, no inlining, etc.)
- behavior is the same on all backends (llvm, cranelift, gcc, etc)

Finally, there is now an allow list of compatible attributes on naked functions, so that e.g. `#[inline]` is rejected with an error. The `#[target_feature]` attribute on naked functions was later made separately unstable, because implementing it is complex and we did not want to block naked functions themselves on how target features work on them. See also rust-lang#138568.

relevant PRs for these recent changes

- rust-lang#127853
- rust-lang#128651
- rust-lang#128004
- rust-lang#138570
-
### Various historical notes

#### `noreturn`
[RFC 2972](https://github.com/rust-lang/rfcs/blob/master/text/2972-constrained-naked.md) mentions that naked functions

> must have a body which contains only a single asm!() statement which:
> iii. must contain the noreturn option.

Instead of `asm!`, the current implementation mandates that the body contain a single `naked_asm!` statement. The `naked_asm!` macro is a heavily restricted version of the `asm!` macro, making it easier to talk about and document the rules of assembly in naked functions and give dedicated error messages.

For `naked_asm!`, the behavior of the `asm!`'s `noreturn` option is implicit. The `noreturn` option means that it is UB for control flow to fall through the end of the assembly block. With `asm!`, this option is usually used for blocks that diverge (and thus have no return and can be typed as `!`). With `naked_asm!`, the intent is different: usually naked funtions do return, but they must do so from within the assembly block. The `noreturn` option was used so that the compiler would not itself also insert a `ret` instruction at the very end.

#### padding / `ud2`

A `naked_asm!` block that violates the safety assumption that control flow must not fall through the end of the assembly block is UB. Because no return instruction is emitted, whatever bytes follow the naked function will be executed, resulting in truly undefined behavior. There has been discussion whether rustc should emit an invalid instruction (e.g. `ud2`  on x86) after the `naked_asm!` block to at least fail early in the case of an invalid `naked_asm!`. It was however decided that it is more useful to guarantee that `#[naked]` functions NEVER contain any instructions besides those in the `naked_asm!` block.

# unresolved questions

None

r? ``@Amanieu``

I've validated the tests on x86_64 and aarch64
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Apr 22, 2025
…oss35,Amanieu,traviscross

Stabilize `naked_functions`

tracking issue: rust-lang/rust#90957
request for stabilization on tracking issue: rust-lang/rust#90957 (comment)
reference PR: rust-lang/reference#1689

# Request for Stabilization

Two years later, we're ready to try this again. Even though this issue is already marked as having passed FCP, given the amount of time that has passed and the changes in implementation strategy, we should follow the process again.

## Summary

The `naked_functions` feature has two main parts: the `#[naked]` function attribute, and the `naked_asm!` macro.

An example of a naked function:

```rust
const THREE: usize = 3;

#[naked]
pub extern "sysv64" fn add_n(number: usize) -> usize {
    // SAFETY: the validity of the used registers
    // is guaranteed according to the "sysv64" ABI
    unsafe {
        core::arch::naked_asm!(
            "add rdi, {}",
            "mov rax, rdi",
            "ret",
            const THREE,
        )
    }
}
```

When the `#[naked]` attribute is applied to a function, the compiler won't emit a [function prologue](https://en.wikipedia.org/wiki/Function_prologue_and_epilogue) or epilogue when generating code for this function. This attribute is analogous to [`__attribute__((naked))`](https://developer.arm.com/documentation/100067/0608/Compiler-specific-Function--Variable--and-Type-Attributes/--attribute----naked---function-attribute) in C. The use of this feature allows the programmer to have precise control over the assembly that is generated for a given function.

The body of a naked function must consist of a single `naked_asm!` invocation, a heavily restricted variant of the `asm!` macro: the only legal operands are `const` and `sym`, and the only legal options are `raw` and `att_syntax`. In lieu of specifying operands, the `naked_asm!` within a naked function relies on the function's calling convention to determine the validity of registers.

## Documentation

The Rust Reference: rust-lang/reference#1689
(Previous PR: rust-lang/reference#1153)

## Tests

* [tests/run-make/naked-symbol-visiblity](https://github.com/rust-lang/rust/tree/master/tests/codegen/naked-fn) verifies that `pub`, `#[no_mangle]` and `#[linkage = "..."]` work correctly for naked functions
* [tests/codegen/naked-fn](https://github.com/rust-lang/rust/tree/master/tests/codegen/naked-fn) has tests for function alignment, use of generics, and validates the exact assembly output on linux, macos, windows and thumb
* [tests/ui/asm/naked-*](https://github.com/rust-lang/rust/tree/master/tests/ui/asm) tests for incompatible attributes, generating errors around incorrect use of `naked_asm!`, etc

## Interaction with other (unstable) features

### [fn_align](rust-lang/rust#82232)

Combining `#[naked]` with `#[repr(align(N))]` works well, and is tested e.g. here

- https://github.com/rust-lang/rust/blob/master/tests/codegen/naked-fn/aligned.rs
- https://github.com/rust-lang/rust/blob/master/tests/codegen/naked-fn/min-function-alignment.rs

It's tested extensively because we do need to explicitly support the `repr(align)` attribute (and make sure we e.g. don't mistake powers of two for number of bytes).

## History

This feature was originally proposed in [RFC 1201](rust-lang/rfcs#1201), filed on 2015-07-10 and accepted on 2016-03-21. Support for this feature was added in [#32410](rust-lang/rust#32410), landing on 2016-03-23. Development languished for several years as it was realized that the semantics given in RFC 1201 were insufficiently specific. To address this, a minimal subset of naked functions was specified by [RFC 2972](rust-lang/rfcs#2972), filed on 2020-08-07 and accepted on 2021-11-16. Prior to the acceptance of RFC 2972, all of the stricter behavior specified by RFC 2972 was implemented as a series of warn-by-default lints that would trigger on existing uses of the `naked` attribute; these lints became hard errors in [#93153](rust-lang/rust#93153) on 2022-01-22. As a result, today RFC 2972 has completely superseded RFC 1201 in describing the semantics of the `naked` attribute.

More recently, the `naked_asm!` macro was added to replace the earlier use of a heavily restricted `asm!` invocation. The `naked_asm!` name is clearer in error messages, and provides a place for documenting the specific requirements of inline assembly in naked functions.

The implementation strategy was changed to emitting a global assembly block. In effect, an extern function

```rust
extern "C" fn foo() {
    core::arch::naked_asm!("ret")
}
```

is emitted as something similar to

```rust
core::arch::global_asm!(
    "foo:",
    "ret"
);

extern "C" {
    fn foo();
}
```

The codegen approach was chosen over the llvm naked function attribute because:

- the rust compiler can guarantee the behavior (no sneaky additional instructions, no inlining, etc.)
- behavior is the same on all backends (llvm, cranelift, gcc, etc)

Finally, there is now an allow list of compatible attributes on naked functions, so that e.g. `#[inline]` is rejected with an error. The `#[target_feature]` attribute on naked functions was later made separately unstable, because implementing it is complex and we did not want to block naked functions themselves on how target features work on them. See also rust-lang/rust#138568.

relevant PRs for these recent changes

- rust-lang/rust#127853
- rust-lang/rust#128651
- rust-lang/rust#128004
- rust-lang/rust#138570
-
### Various historical notes

#### `noreturn`
[RFC 2972](https://github.com/rust-lang/rfcs/blob/master/text/2972-constrained-naked.md) mentions that naked functions

> must have a body which contains only a single asm!() statement which:
> iii. must contain the noreturn option.

Instead of `asm!`, the current implementation mandates that the body contain a single `naked_asm!` statement. The `naked_asm!` macro is a heavily restricted version of the `asm!` macro, making it easier to talk about and document the rules of assembly in naked functions and give dedicated error messages.

For `naked_asm!`, the behavior of the `asm!`'s `noreturn` option is implicit. The `noreturn` option means that it is UB for control flow to fall through the end of the assembly block. With `asm!`, this option is usually used for blocks that diverge (and thus have no return and can be typed as `!`). With `naked_asm!`, the intent is different: usually naked funtions do return, but they must do so from within the assembly block. The `noreturn` option was used so that the compiler would not itself also insert a `ret` instruction at the very end.

#### padding / `ud2`

A `naked_asm!` block that violates the safety assumption that control flow must not fall through the end of the assembly block is UB. Because no return instruction is emitted, whatever bytes follow the naked function will be executed, resulting in truly undefined behavior. There has been discussion whether rustc should emit an invalid instruction (e.g. `ud2`  on x86) after the `naked_asm!` block to at least fail early in the case of an invalid `naked_asm!`. It was however decided that it is more useful to guarantee that `#[naked]` functions NEVER contain any instructions besides those in the `naked_asm!` block.

# unresolved questions

None

r? ``@Amanieu``

I've validated the tests on x86_64 and aarch64
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.