Add -Zinstrument-mcount=fentry to -Zinstrument-mcount#158036
Conversation
|
These commits modify compiler targets. |
|
r? @jackh726 rustbot has assigned @jackh726. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
fentry is essentially a simpler version of mcount where the counting function is called before any other function prologue actions happen. fentry is still used by the linux x86-64 kernel. It's unclear if or when patchable-function-entry will replace it. It is also used by clang for some x86-64 mingw toolchains. This is only supported on some x86, x86-64, and s390x targets.
|
@rustbot reroll |
|
@rustbot reroll |
|
What's the context/impetus for adding this? Is it for RfL? |
|
RfL. It is still used by x86, and likely not going away anytime soon. x86 is using patchable function entries exclusively for security mitigation techniques. |
| /// The different settings that the `-Z Instrument-mcount` flag can have. | ||
| #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | ||
| pub enum InstrumentMcount { | ||
| /// `-Z instrument-mcount=no` | ||
| Disabled, | ||
| /// `-Z instrument-mcount=yes` | ||
| Mcount, | ||
| /// `-Z instrument-mcount=fentry` | ||
| Fentry, | ||
| } |
There was a problem hiding this comment.
The whole -Z instrument-mcount is missing an entry in the unstable book, can you add one in src/doc/unstable-book/src/compiler-flags/?
We at least try to document things from first principles, rather than just deferring to clang/LLVM.
There was a problem hiding this comment.
Agreed. I have been working on that. Making a simple example of a Rust mcount function has been a little a bit trickier than I'd expected. I'll add it.
| // Define a custom mcount function. This may partially or fully override the glibc | ||
| // implementation depending on linker options. | ||
| #[unsafe(naked)] | ||
| #[no_mangle] | ||
| #[cfg(all(target_os = "linux", target_arch = "x86_64"))] | ||
| pub extern "C" fn mcount() { | ||
| core::arch::naked_asm!( | ||
| // A simplified version based on the glibc x86-64 mcount wrapper. | ||
| // Save register arguments to the stack, and call the mcount above. | ||
| "push rax", | ||
| "push rcx", | ||
| "push rdx", | ||
| "push rsi", | ||
| "push rdi", | ||
| "push r8", | ||
| "push r9", | ||
| "mov rsi, 56[rsp]", | ||
| "mov rdi, 8[rbp]", | ||
| "call __count_fn", | ||
| "pop r9", | ||
| "pop r8", | ||
| "pop rdi", | ||
| "pop rsi", | ||
| "pop rdx", | ||
| "pop rcx", | ||
| "pop rax", | ||
| "ret", | ||
| ) | ||
| } |
There was a problem hiding this comment.
Just linking this, mcount could use extern "custom" #140829 if the ABI is truly custom.
| #[unsafe(naked)] | ||
| #[no_mangle] | ||
| #[cfg(all(target_os = "linux", target_arch = "x86_64"))] | ||
| pub extern "C" fn mcount() { |
There was a problem hiding this comment.
| pub extern "C" fn mcount() { | |
| unsafe extern "C" fn mcount() { |
A bunch of things are pub here that really don't need to be. And if this function really has a custom ABI then it should be unsafe to call. Practically it seems fine though because all relevant registers are restored. It would help to write that down as a safety comment on the naked_asm! though.
|
|
||
| In essence, this is implementing the function `fn mcount(caller: *const std::ffi::c_void, callee: *const std::ffi::c_void)`. The calling convention for mcount follows its own ABI, which isn't usually the standard ABI for the target, but is enforced by preexisting convention. | ||
|
|
||
| A trivial example on x86_64-unknown-linux-gnu looks something like the following. The `#[instrument_fn]` attribute can be used to disable profiling to simplify writing counting functions, but implementors must be very careful when calling other functions (or closures which fail to inline) as they may also call mcount. |
There was a problem hiding this comment.
Can you elaborate a bit more on what this example should do? I get
> RUSTFLAG="-Z instrument-mcount=yes" cargo +nightly run
main() called
> rustc +nightly -vV
rustc 1.98.0-nightly (4429659e4 2026-06-22)
binary: rustc
commit-hash: 4429659e4745016bd3f26a4a421843edc7fbc422
commit-date: 2026-06-22
host: x86_64-unknown-linux-gnu
release: 1.98.0-nightly
LLVM version: 22.1.7
So __count_fn is not actually called?
fentry is essentially a simpler version of mcount where the counting function is called before any other function prologue actions happen.
fentry is still used by the linux x86-64 kernel. It's unclear if or when patchable-function-entry will replace it. It is also used by clang for some x86-64 mingw toolchains.
This is only supported on some x86, x86-64, and s390x targets.