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
This commit is contained in:
parent
a35cf79fcb
commit
31a5066e0b
@ -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],
|
||||
|
@ -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
|
||||
}
|
||||
@ -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
|
||||
|
@ -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
|
||||
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user