Skip to content

Commit 6efaef6

Browse files
committed
Auto merge of #57220 - quark-zju:mcount, r=estebank
Add `-Z instrument-mcount` This flag inserts `mcount` function call to the beginning of every function after inline processing. So tracing tools like uftrace [1] (or ftrace for Linux kernel modules) have a chance to examine function calls. It is similar to the `-pg` flag provided by gcc or clang, but without generating a `__gmon_start__` function for executables. If a program runs without being traced, no `gmon.out` will be written to disk. Under the hood, it simply adds `"instrument-function-entry-inlined"="mcount"` attribute to every function. The `post-inline-ee-instrument` LLVM pass does the actual job. [1]: https://github.com/namhyung/uftrace
2 parents 433ef82 + 31a5066 commit 6efaef6

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

src/librustc/session/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
12271227
"verify incr. comp. hashes of green query instances"),
12281228
incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED],
12291229
"ignore spans during ICH computation -- used for testing"),
1230+
instrument_mcount: bool = (false, parse_bool, [TRACKED],
1231+
"insert function instrument code for mcount-based tracing"),
12301232
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
12311233
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
12321234
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],

src/librustc/session/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,9 @@ impl Session {
503503
pub fn profile_queries_and_keys(&self) -> bool {
504504
self.opts.debugging_opts.profile_queries_and_keys
505505
}
506+
pub fn instrument_mcount(&self) -> bool {
507+
self.opts.debugging_opts.instrument_mcount
508+
}
506509
pub fn count_llvm_insns(&self) -> bool {
507510
self.opts.debugging_opts.count_llvm_insns
508511
}
@@ -667,7 +670,11 @@ impl Session {
667670
}
668671

669672
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
670-
if let Some(x) = self.opts.cg.force_frame_pointers {
673+
// "mcount" function relies on stack pointer.
674+
// See https://sourceware.org/binutils/docs/gprof/Implementation.html
675+
if self.instrument_mcount() {
676+
true
677+
} else if let Some(x) = self.opts.cg.force_frame_pointers {
671678
x
672679
} else {
673680
!self.target.target.options.eliminate_frame_pointer

src/librustc_codegen_llvm/attributes.rs

+13
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value)
7878
}
7979
}
8080

81+
/// Tell LLVM what instrument function to insert.
82+
#[inline]
83+
pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
84+
if cx.sess().instrument_mcount() {
85+
// Similar to `clang -pg` behavior. Handled by the
86+
// `post-inline-ee-instrument` LLVM pass.
87+
llvm::AddFunctionAttrStringValue(
88+
llfn, llvm::AttributePlace::Function,
89+
const_cstr!("instrument-function-entry-inlined"), const_cstr!("mcount"));
90+
}
91+
}
92+
8193
pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
8294
// Only use stack probes if the target specification indicates that we
8395
// should be using stack probes
@@ -174,6 +186,7 @@ pub fn from_fn_attrs(
174186
}
175187

176188
set_frame_pointer_elimination(cx, llfn);
189+
set_instrument_function(cx, llfn);
177190
set_probestack(cx, llfn);
178191

179192
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {

0 commit comments

Comments
 (0)