diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 56dca6c8b9021..29ae1548b7439 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2767,6 +2767,10 @@ fn add_order_independent_options( cmd.pgo_gen(); } + if sess.opts.unstable_opts.instrument_mcount { + cmd.enable_profiling(); + } + if sess.opts.cg.control_flow_guard != CFGuard::Disabled { cmd.control_flow_guard(); } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 3ace1a8c266cf..89cd1528ced9f 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -352,6 +352,7 @@ pub(crate) trait Linker { fn add_no_exec(&mut self) {} fn add_as_needed(&mut self) {} fn reset_per_library_state(&mut self) {} + fn enable_profiling(&mut self) {} } impl dyn Linker + '_ { @@ -732,6 +733,19 @@ impl<'a> Linker for GccLinker<'a> { self.link_or_cc_args(&["-u", "__llvm_profile_runtime"]); } + fn enable_profiling(&mut self) { + // This flag is also used when linking to choose target specific + // libraries needed to enable profiling. + self.cc_arg("-pg"); + // On windows-gnu targets, libgmon also needs to be linked, and this + // requires readding libraries to satisfy its dependencies. + if self.sess.target.is_like_windows { + self.cc_arg("-lgmon"); + self.cc_arg("-lkernel32"); + self.cc_arg("-lmsvcrt"); + } + } + fn control_flow_guard(&mut self) {} fn ehcont_guard(&mut self) {} diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs index d2fe42b903062..cee3f91226998 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnu.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs @@ -106,6 +106,7 @@ pub(crate) fn opts() -> TargetOptions { // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to // output DWO, despite using DWARF, doesn't use ELF.. supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + mcount: "_mcount".into(), ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs index 3bd8ebd0ed3d5..8e26852d03711 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs @@ -53,6 +53,7 @@ pub(crate) fn opts() -> TargetOptions { // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to // output DWO, despite using DWARF, doesn't use ELF.. supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + mcount: "_mcount".into(), ..Default::default() } } diff --git a/tests/run-make/instrument-mcount-link-pg/main.rs b/tests/run-make/instrument-mcount-link-pg/main.rs new file mode 100644 index 0000000000000..47ad8c634112b --- /dev/null +++ b/tests/run-make/instrument-mcount-link-pg/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World!"); +} diff --git a/tests/run-make/instrument-mcount-link-pg/rmake.rs b/tests/run-make/instrument-mcount-link-pg/rmake.rs new file mode 100644 index 0000000000000..184bd9429bfd8 --- /dev/null +++ b/tests/run-make/instrument-mcount-link-pg/rmake.rs @@ -0,0 +1,19 @@ +// When building a binary instrumented with mcount, verify the +// binary is linked with the correct crt to enable profiling. +// +//@ only-gnu +//@ ignore-cross-compile + +use run_make_support::{path, run, rustc}; + +fn main() { + // Compile instrumentation enabled binary, and verify -pg is passed + let link_args = + rustc().input("main.rs").arg("-Zinstrument-mcount").print("link-args").run().stdout_utf8(); + assert!(link_args.contains("\"-pg\"")); + + // Run it, and verify gmon.out is created + assert!(!path("gmon.out").exists()); + run("main"); + assert!(path("gmon.out").exists()); +}