Skip to content

Commit

Permalink
Add -Z instrument-mcount
Browse files Browse the repository at this point in the history
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
  • Loading branch information
quark-zju committed Dec 30, 2018
1 parent a35cf79 commit 31a5066
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"verify incr. comp. hashes of green query instances"),
incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED],
"ignore spans during ICH computation -- used for testing"),
instrument_mcount: bool = (false, parse_bool, [TRACKED],
"insert function instrument code for mcount-based tracing"),
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
Expand Down
9 changes: 8 additions & 1 deletion src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,9 @@ impl Session {
pub fn profile_queries_and_keys(&self) -> bool {
self.opts.debugging_opts.profile_queries_and_keys
}
pub fn instrument_mcount(&self) -> bool {
self.opts.debugging_opts.instrument_mcount
}
pub fn count_llvm_insns(&self) -> bool {
self.opts.debugging_opts.count_llvm_insns
}
Expand Down Expand Up @@ -667,7 +670,11 @@ impl Session {
}

pub fn must_not_eliminate_frame_pointers(&self) -> bool {
if let Some(x) = self.opts.cg.force_frame_pointers {
// "mcount" function relies on stack pointer.
// See https://sourceware.org/binutils/docs/gprof/Implementation.html
if self.instrument_mcount() {
true
} else if let Some(x) = self.opts.cg.force_frame_pointers {
x
} else {
!self.target.target.options.eliminate_frame_pointer
Expand Down
13 changes: 13 additions & 0 deletions src/librustc_codegen_llvm/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value)
}
}

/// Tell LLVM what instrument function to insert.
#[inline]
pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
if cx.sess().instrument_mcount() {
// Similar to `clang -pg` behavior. Handled by the
// `post-inline-ee-instrument` LLVM pass.
llvm::AddFunctionAttrStringValue(
llfn, llvm::AttributePlace::Function,
const_cstr!("instrument-function-entry-inlined"), const_cstr!("mcount"));
}
}

pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
// Only use stack probes if the target specification indicates that we
// should be using stack probes
Expand Down Expand Up @@ -174,6 +186,7 @@ pub fn from_fn_attrs(
}

set_frame_pointer_elimination(cx, llfn);
set_instrument_function(cx, llfn);
set_probestack(cx, llfn);

if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
Expand Down

0 comments on commit 31a5066

Please sign in to comment.