From 349a66214f36f72b1e78414f3f5aaf0f3a849715 Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Tue, 10 Feb 2026 09:41:54 -0600 Subject: [PATCH 1/4] Add compiler support for instrumenting functions --- text/0000-instrumented-functions.md | 175 ++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 text/0000-instrumented-functions.md diff --git a/text/0000-instrumented-functions.md b/text/0000-instrumented-functions.md new file mode 100644 index 00000000000..0cac5ee0145 --- /dev/null +++ b/text/0000-instrumented-functions.md @@ -0,0 +1,175 @@ +- Feature Name: instrument-functions +- Start Date: 2026-02-05 +- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) +- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) + +## Summary +[summary]: #summary + +This feature provides a means to insert a function call into the prologue or epilogue of each function. +This RFC presents an option to consolidate the various similar, yet mutually exclusive mechanisms to +instrument functions. + +## Motivation +[motivation]: #motivation + +There are at least three different ways to instrument functions with gcc and clang, and some have +partial support in Rust today: + +* mcount, a counting function inserted into the prologue of each function which takes the caller and callee +addresses, and performs interesting things with them. This is historically used with the prof or gprof +utilities available on GNU/linux or BSD. +* fentry, a derivative of mcount with a slightly different ABI. It is meant to intercept function entry +to inspect or manipulate arguments as well as the traditional mcount features +* [XRay](https://llvm.org/docs/XRay.html), an LLVM project to instrument both entry and exit of functions, +with dynamic enablement. + +These features are all very similar, are effectively mutually exclusive (e.g., mcount and fentry). + +mcount deserves a little extra background. This feature has existed on many C toolchains for decades, and +gcc/clang have developed extensions to support novel features like linux's [ftrace](https://docs.kernel.org/trace/ftrace.html). +Those features include tracking the location of instrumentation insertion (`-mrecord-mcount`), and the +ability to generate nop's in place of the call (`-mnop-mcount`). + +Linux's ftrace supports using patchable functions or mcount instrumentation. Kernel maintainers may choose one +over the other, and may make different choices depending on the architecture. Rust should implement +function instrumentation which supports mcount. + + +## Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +Today, Rust supports experimental disparate options to enable function instrumentation using XRay and mcount, +possibly simultaneously. + +This RFC proposes a unified set of options to enable one instrumentation framework, and provide sufficient +language integration to control individual function instrumentation. + +Function instrumentation is generally limited to inserting a counting function into the entry and exit +of each function. A counting function is one which takes the caller's and callee's address as arguments, +but may have sufficient visibility to inspect and modify callee arguments, or reroute to an entirely +different function call. + +For each target, a counting function is inserted into a specific part of a function's entry or exit. For +targets which support gprof, a specific target defined counting function is expected to be called. For +example, on x86_64-linux `__fentry__` or `mcount` is the expected counting function. The ABI of these +functions is expected to be stable despite their lack of documentation (e.g., glibc provides these symbols). + +gcc and clang provide the following options which are used to instrument functions for common usages: +* ftrace: linux only, `-pg` or `-pg -fentry` with `-mrecord-mcount` and optionally `-mnop-mcount`. +* gprof: `-pg` or `-pg -fentry` with an altered set of crt libraries (see `gcrt1.o` vs `crt1.o` on glibc). +* XRay: clang/llvm only, `-fxray-instrument` which links a special compiler-rt runtime. + +The Rust compiler should support flags which offer interoperability with these gcc and clang options as +Rust compiled code will need to link with gcc and clang compiled code which uses these options and +work as expected. + +## Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +As of the creation of the RFC, the unstable options `-Zinstrument-mcount` and `-Zinstrument-xray` exist, and no +options exist to enable `fentry` instrumentation. + +### Additional options to rustc + +`-Zinstrument-function` shall be added. It will take the instrumentation framework as a string argument: + * `never`: Do not instrument anything. This is the default option. + * `mcount`: Instrument function entry with the target's mcount function (if supported). + * `fentry`: Instrument function entry with the target's fentry function (if supported). + * `xray`: Instrument function entry and exit with XRay (if supported). + +The options `-Zinstrument-mcount` and `-Zinstrument-xray` will be removed in favor of +framework specific configuration options described below. + +`-Zinstrument-mcount-opts`, `-Zinstrument-fentry-opts`: + * `record`, `no-record`: Record each call to the counting function in a separate binary section, or not. + * `call`, `no-call`: Insert a call to the counting function or a nop of equal size. + +`-Zinstrument-xray-opts`: + * `ignore-loops`: Ignore presence of loops, instrument functions based only on instruction count. + * `instruction-threshold=10`: Set a different instruction threshold for instrumentation. + * `no-entry`: Do not instrument function entry. + * `no-exit`: Do not instrument function exit. + +Finally, a single builtin attribute will be added to control the insertion of the counting function. The +default options for each framework will be documented and stable. + +Each of these features is controlled by applying a set of function attributes to each LLVM generated +function. The implementation will apply the correct set of LLVM function attributes. + +Example usage might be: +```shell +$ RUSTFLAGS="-Zinstrument-function=mcount -Zinstrument-mcount-opts=record,call" cargo build + +$ RUSTFLAGS="-Zinstrument-function=fentry -Zinstrument-fentry-opts=record,no-call" cargo build + +$ RUSTFLAGS="-Zinstrument-function=xray -Zinstrument-xray-opts=ignore-loops" cargo build +``` + +### Language additions + +A single builtin attribute, `instrument_fn`, will be added. It will be applied to functions and methods +only. It will accept two options `entry="on|off"` and `exit="on|off"` which will control insertion of the +counting function in the respective function locations. + +Usage will look like the following: + +```rust +#[instrument_fn(entry = "off")] +fn no_entry_instrument() { +} + +#[instrument_fn(exit = "off")] +fn no_exit_instrument() { +} + +#[instrument_fn(entry = "off", exit = "off")] +fn no_instrument() { +} +``` + +Likewise, if no instrumentation is enabled, this attribute is quietly ignored. + +### Other changes + +Supporting gprof requires special linker support. Rust's integration with the linker will need to +facilitate linking the correct crt objects when creating binaries. On glibc targets, this requires +replacing `crt1.o` with `gcrt1.o`. + +## Drawbacks +[drawbacks]: #drawbacks + +The counting function ABI is not documented for most targets. Using this option could potentially generate +incompatible calls if the ABI requirements of the counting function change. + +Likewise, gprof is likely not a compelling argument today with substantially more advanced statistical +profilers like `perf`, and this is not meant to be a code coverage tool. + +## Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +Patchable function entries have many overlapping features. So much so that the Linux kernel can also use them +to implement instrumentation on many architectures. Though, some architectures still use mcount/fentry even +if patchable entries are available. + +Likewise, there may not be reason to bundle all function instrumentation into a single set of options. + +## Prior art +[prior-art]: #prior-art + +Similar features exist in gcc and clang as noted above. This extends those features into Rust. + +## Unresolved questions +[unresolved-questions]: #unresolved-questions + +- Can we stabilize the mcount portions of this RFC? The underlying counting functions have target specific + ABI which is mostly undocumented, but has historically been stable. + +## Future possibilities +[future-possibilities]: #future-possibilities + +This RFC assumes only one form of instrumentation would ever be needed at any time. It is conceivable +different parts of a binary could be compiled to use different instrumentation frameworks. + +It is possible new frameworks will be added to support instrumenting functions. The command line and +attribute syntax should be expandable to meet those needs. From ed02f6785ddfa87b764a3e3362a7fe731bc613ac Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Wed, 11 Feb 2026 16:46:33 -0600 Subject: [PATCH 2/4] Update based on initial feedback * Add `#[instrument_fn = "off"]` form. * s/linux/Linux/ when used as a proper noun. * Add prior art paragraph about patachable-function-entries rfc. * Clarify `ignore-loops` xray option. --- text/0000-instrumented-functions.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/text/0000-instrumented-functions.md b/text/0000-instrumented-functions.md index 0cac5ee0145..0fd9b1fe7fa 100644 --- a/text/0000-instrumented-functions.md +++ b/text/0000-instrumented-functions.md @@ -18,16 +18,16 @@ partial support in Rust today: * mcount, a counting function inserted into the prologue of each function which takes the caller and callee addresses, and performs interesting things with them. This is historically used with the prof or gprof -utilities available on GNU/linux or BSD. +utilities available on GNU/Linux or BSD. * fentry, a derivative of mcount with a slightly different ABI. It is meant to intercept function entry to inspect or manipulate arguments as well as the traditional mcount features * [XRay](https://llvm.org/docs/XRay.html), an LLVM project to instrument both entry and exit of functions, with dynamic enablement. -These features are all very similar, are effectively mutually exclusive (e.g., mcount and fentry). +These features are very similar, and are effectively mutually exclusive (e.g., mcount and fentry). mcount deserves a little extra background. This feature has existed on many C toolchains for decades, and -gcc/clang have developed extensions to support novel features like linux's [ftrace](https://docs.kernel.org/trace/ftrace.html). +gcc/clang have developed extensions to support novel features like Linux's [ftrace](https://docs.kernel.org/trace/ftrace.html). Those features include tracking the location of instrumentation insertion (`-mrecord-mcount`), and the ability to generate nop's in place of the call (`-mnop-mcount`). @@ -56,7 +56,7 @@ example, on x86_64-linux `__fentry__` or `mcount` is the expected counting funct functions is expected to be stable despite their lack of documentation (e.g., glibc provides these symbols). gcc and clang provide the following options which are used to instrument functions for common usages: -* ftrace: linux only, `-pg` or `-pg -fentry` with `-mrecord-mcount` and optionally `-mnop-mcount`. +* ftrace: Linux only, `-pg` or `-pg -fentry` with `-mrecord-mcount` and optionally `-mnop-mcount`. * gprof: `-pg` or `-pg -fentry` with an altered set of crt libraries (see `gcrt1.o` vs `crt1.o` on glibc). * XRay: clang/llvm only, `-fxray-instrument` which links a special compiler-rt runtime. @@ -86,7 +86,7 @@ framework specific configuration options described below. * `call`, `no-call`: Insert a call to the counting function or a nop of equal size. `-Zinstrument-xray-opts`: - * `ignore-loops`: Ignore presence of loops, instrument functions based only on instruction count. + * `ignore-loops`: Ignore loop behavior when deciding to instrument a function. * `instruction-threshold=10`: Set a different instruction threshold for instrumentation. * `no-entry`: Do not instrument function entry. * `no-exit`: Do not instrument function exit. @@ -109,8 +109,8 @@ $ RUSTFLAGS="-Zinstrument-function=xray -Zinstrument-xray-opts=ignore-loops" car ### Language additions A single builtin attribute, `instrument_fn`, will be added. It will be applied to functions and methods -only. It will accept two options `entry="on|off"` and `exit="on|off"` which will control insertion of the -counting function in the respective function locations. +only. It will accept two list entries `entry="on|off"` and `exit="on|off"`. Additionally, a simpler form +`#[instrument_fn = "off"]` will disable all instrumentation. Usage will look like the following: @@ -124,7 +124,11 @@ fn no_exit_instrument() { } #[instrument_fn(entry = "off", exit = "off")] -fn no_instrument() { +fn no_instrument_verbose() { +} + +#[instrument_fn = "off"] +fn no_instrument_terse() { } ``` @@ -159,6 +163,11 @@ Likewise, there may not be reason to bundle all function instrumentation into a Similar features exist in gcc and clang as noted above. This extends those features into Rust. +When using mcount or fentry with recording and nop insertion, this feature can behave similarly +to patchable-function-entries presented in rfc#3543. There are some minor differences in the details +of how nops are recorded. However, both can be used simultaneously without issue. This is the case +for some Linux kernel configurations (e.g., x86-64 on fedora at the time of writing). + ## Unresolved questions [unresolved-questions]: #unresolved-questions From c6208ef8f0518d87b97a922d46cdcf370c975c4a Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Tue, 24 Feb 2026 13:55:23 -0600 Subject: [PATCH 3/4] Update RFC number --- ...instrumented-functions.md => 3917-instrumented-functions.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename text/{0000-instrumented-functions.md => 3917-instrumented-functions.md} (99%) diff --git a/text/0000-instrumented-functions.md b/text/3917-instrumented-functions.md similarity index 99% rename from text/0000-instrumented-functions.md rename to text/3917-instrumented-functions.md index 0fd9b1fe7fa..2ac2d1ce180 100644 --- a/text/0000-instrumented-functions.md +++ b/text/3917-instrumented-functions.md @@ -1,6 +1,6 @@ - Feature Name: instrument-functions - Start Date: 2026-02-05 -- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) +- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/3917) - Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) ## Summary From 7dee89e4ceef91f6b919411bd2b07b8d40b4d936 Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Tue, 24 Feb 2026 14:44:05 -0600 Subject: [PATCH 4/4] Simplify instrument_fn attribute With the current instrumentation frameworks, I don't think there is benefit to fine grain controls. I have simplified the attribute to "on" and "off". XRay has some creative options, but fine grain control of entry and exit instrumentation insertion probably isn't useful. --- text/3917-instrumented-functions.md | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/text/3917-instrumented-functions.md b/text/3917-instrumented-functions.md index 2ac2d1ce180..1f19a33dab6 100644 --- a/text/3917-instrumented-functions.md +++ b/text/3917-instrumented-functions.md @@ -109,29 +109,21 @@ $ RUSTFLAGS="-Zinstrument-function=xray -Zinstrument-xray-opts=ignore-loops" car ### Language additions A single builtin attribute, `instrument_fn`, will be added. It will be applied to functions and methods -only. It will accept two list entries `entry="on|off"` and `exit="on|off"`. Additionally, a simpler form -`#[instrument_fn = "off"]` will disable all instrumentation. - -Usage will look like the following: +only. The attribute will accept an "on" or "off" option as `#[instrument_fn = "on|off"]`. ```rust -#[instrument_fn(entry = "off")] -fn no_entry_instrument() { -} - -#[instrument_fn(exit = "off")] -fn no_exit_instrument() { -} - -#[instrument_fn(entry = "off", exit = "off")] -fn no_instrument_verbose() { +#[instrument_fn = "on"] +fn always_instrument() { } #[instrument_fn = "off"] -fn no_instrument_terse() { +fn never_instrument() { } ``` +For XRay, "on" and "off" are equivalent to always and never instrumenting. For mcount and fentry, +"on" has no effect. + Likewise, if no instrumentation is enabled, this attribute is quietly ignored. ### Other changes @@ -180,5 +172,6 @@ for some Linux kernel configurations (e.g., x86-64 on fedora at the time of writ This RFC assumes only one form of instrumentation would ever be needed at any time. It is conceivable different parts of a binary could be compiled to use different instrumentation frameworks. -It is possible new frameworks will be added to support instrumenting functions. The command line and -attribute syntax should be expandable to meet those needs. +It might be desirable to provide finer control over instrumentation. This could be done by extending the +attribute with options, e.g.: `#[instrument_fn(xray="off", mcount="on")]`. Similarly, this extension could +be used to supply individual instrumentation options to a function.