about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-08 10:06:40 +0000
committerbors <bors@rust-lang.org>2023-09-08 10:06:40 +0000
commit9be4eac2647432aa863f65da8a116f2eafd90ee9 (patch)
treee3e314564294f95fa70e26dff6a5f68f4386be09
parentde4cba3a98a15a891ad708a049c7fb5682083d97 (diff)
parent4cdc633301e3c760fb36470afc216a9e09351fa3 (diff)
downloadrust-9be4eac2647432aa863f65da8a116f2eafd90ee9.tar.gz
rust-9be4eac2647432aa863f65da8a116f2eafd90ee9.zip
Auto merge of #113492 - nebulark:pr_96475, r=petrochenkov
Add CL and CMD into to pdb debug info

Partial fix for https://github.com/rust-lang/rust/issues/96475

The Arg0 and CommandLineArgs of the MCTargetOptions cpp class are not set within https://github.com/rust-lang/rust/blob/bb548f964572f7fe652716f5897d9050a31c936e/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp#L378

This causes LLVM to not  neither output any compiler path (cl) nor the arguments that were used when invoking it (cmd) in the PDB file.

This fix adds the missing information to the target machine so LLVM can use it.
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs20
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs7
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs1
-rw-r--r--compiler/rustc_interface/src/interface.rs7
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_interface/src/util.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp39
-rw-r--r--compiler/rustc_session/src/session.rs8
-rw-r--r--src/librustdoc/config.rs7
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/doctest.rs1
-rw-r--r--tests/run-make-fulldeps/issue-19371/foo.rs1
-rw-r--r--tests/run-make/pdb-buildinfo-cl-cmd/Makefile16
-rw-r--r--tests/run-make/pdb-buildinfo-cl-cmd/main.rs2
-rw-r--r--tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt1
16 files changed, 117 insertions, 1 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 47cc5bd52e2..c49d322fc00 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -216,6 +216,24 @@ pub fn target_machine_factory(
 
     let force_emulated_tls = sess.target.force_emulated_tls;
 
+    // copy the exe path, followed by path all into one buffer
+    // null terminating them so we can use them as null terminated strings
+    let args_cstr_buff = {
+        let mut args_cstr_buff: Vec<u8> = Vec::new();
+        let exe_path = std::env::current_exe().unwrap_or_default();
+        let exe_path_str = exe_path.into_os_string().into_string().unwrap_or_default();
+
+        args_cstr_buff.extend_from_slice(exe_path_str.as_bytes());
+        args_cstr_buff.push(0);
+
+        for arg in sess.expanded_args.iter() {
+            args_cstr_buff.extend_from_slice(arg.as_bytes());
+            args_cstr_buff.push(0);
+        }
+
+        args_cstr_buff
+    };
+
     Arc::new(move |config: TargetMachineFactoryConfig| {
         let split_dwarf_file =
             path_mapping.map_prefix(config.split_dwarf_file.unwrap_or_default()).0;
@@ -242,6 +260,8 @@ pub fn target_machine_factory(
                 use_init_array,
                 split_dwarf_file.as_ptr(),
                 force_emulated_tls,
+                args_cstr_buff.as_ptr() as *const c_char,
+                args_cstr_buff.len(),
             )
         };
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 01cbf7d3b11..1f03c932cfd 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2132,7 +2132,10 @@ extern "C" {
         UseInitArray: bool,
         SplitDwarfFile: *const c_char,
         ForceEmulatedTls: bool,
+        ArgsCstrBuff: *const c_char,
+        ArgsCstrBuffLen: usize,
     ) -> Option<&'static mut TargetMachine>;
+
     pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
     pub fn LLVMRustAddLibraryInfo<'a>(
         PM: &PassManager<'a>,
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index f485af00bca..3bf98c46dea 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -343,6 +343,12 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
     pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
 
+    /// All commandline args used to invoke the compiler, with @file args fully expanded.
+    /// This will only be used within debug info, e.g. in the pdb file on windows
+    /// This is mainly useful for other tools that reads that debuginfo to figure out
+    /// how to call the compiler with the same arguments.
+    pub expanded_args: Vec<String>,
+
     /// Handler to use for diagnostics produced during codegen.
     pub diag_emitter: SharedEmitter,
     /// LLVM optimizations for which we want to print remarks.
@@ -1108,6 +1114,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
         cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(),
         coordinator_send,
+        expanded_args: tcx.sess.expanded_args.clone(),
         diag_emitter: shared_emitter.clone(),
         output_filenames: tcx.output_filenames(()).clone(),
         regular_module_config: regular_config,
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 1a16759d7f9..e56347ab38e 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -313,6 +313,7 @@ fn run_compiler(
         override_queries: None,
         make_codegen_backend,
         registry: diagnostics_registry(),
+        expanded_args: args,
     };
 
     match make_input(&early_error_handler, &matches.free) {
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 5b417e008cf..a0f0b530bae 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -279,6 +279,12 @@ pub struct Config {
 
     /// Registry of diagnostics codes.
     pub registry: Registry,
+
+    /// All commandline args used to invoke the compiler, with @file args fully expanded.
+    /// This will only be used within debug info, e.g. in the pdb file on windows
+    /// This is mainly useful for other tools that reads that debuginfo to figure out
+    /// how to call the compiler with the same arguments.
+    pub expanded_args: Vec<String>,
 }
 
 // JUSTIFICATION: before session exists, only config
@@ -317,6 +323,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 config.make_codegen_backend,
                 registry.clone(),
                 config.ice_file,
+                config.expanded_args,
             );
 
             if let Some(parse_sess_created) = config.parse_sess_created {
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index b53ba251bcd..ccf8b5630d4 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -68,6 +68,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se
         None,
         "",
         None,
+        Default::default(),
     );
     (sess, cfg)
 }
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 5c9b39cdbe3..37e242c6e40 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -71,6 +71,7 @@ pub fn create_session(
     >,
     descriptions: Registry,
     ice_file: Option<PathBuf>,
+    expanded_args: Vec<String>,
 ) -> (Session, Box<dyn CodegenBackend>) {
     let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
         make_codegen_backend(&sopts)
@@ -113,6 +114,7 @@ pub fn create_session(
         target_override,
         rustc_version_str().unwrap_or("unknown"),
         ice_file,
+        expanded_args,
     );
 
     codegen_backend.init(&sess);
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 4ac739326d2..4ed086ff42f 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -406,7 +406,8 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     bool RelaxELFRelocations,
     bool UseInitArray,
     const char *SplitDwarfFile,
-    bool ForceEmulatedTls) {
+    bool ForceEmulatedTls,
+    const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) {
 
   auto OptLevel = fromRust(RustOptLevel);
   auto RM = fromRust(RustReloc);
@@ -462,12 +463,48 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
 
   Options.EmitStackSizeSection = EmitStackSizeSection;
 
+
+  if (ArgsCstrBuff != nullptr)
+  {
+    int buffer_offset = 0;
+    assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0');
+
+    const size_t arg0_len = std::strlen(ArgsCstrBuff);
+    char* arg0 = new char[arg0_len + 1];
+    memcpy(arg0, ArgsCstrBuff, arg0_len);
+    arg0[arg0_len] = '\0';
+    buffer_offset += arg0_len + 1;
+
+    const int num_cmd_arg_strings =
+      std::count(&ArgsCstrBuff[buffer_offset], &ArgsCstrBuff[ArgsCstrBuffLen], '\0');
+
+    std::string* cmd_arg_strings = new std::string[num_cmd_arg_strings];
+    for (int i = 0; i < num_cmd_arg_strings; ++i)
+    {
+      assert(buffer_offset < ArgsCstrBuffLen);
+      const int len = std::strlen(ArgsCstrBuff + buffer_offset);
+      cmd_arg_strings[i] = std::string(&ArgsCstrBuff[buffer_offset], len);
+      buffer_offset += len + 1;
+    }
+
+    assert(buffer_offset == ArgsCstrBuffLen);
+
+    Options.MCOptions.Argv0 = arg0;
+    Options.MCOptions.CommandLineArgs =
+      llvm::ArrayRef<std::string>(cmd_arg_strings, num_cmd_arg_strings);
+  }
+
   TargetMachine *TM = TheTarget->createTargetMachine(
       Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
   return wrap(TM);
 }
 
 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
+
+  MCTargetOptions& MCOptions = unwrap(TM)->Options.MCOptions;
+  delete[] MCOptions.Argv0;
+  delete[] MCOptions.CommandLineArgs.data();
+
   delete unwrap(TM);
 }
 
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 86db2edab7b..9bff9017881 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -204,6 +204,12 @@ pub struct Session {
 
     /// The version of the rustc process, possibly including a commit hash and description.
     pub cfg_version: &'static str,
+
+    /// All commandline args used to invoke the compiler, with @file args fully expanded.
+    /// This will only be used within debug info, e.g. in the pdb file on windows
+    /// This is mainly useful for other tools that reads that debuginfo to figure out
+    /// how to call the compiler with the same arguments.
+    pub expanded_args: Vec<String>,
 }
 
 pub struct PerfStats {
@@ -1325,6 +1331,7 @@ pub fn build_session(
     target_override: Option<Target>,
     cfg_version: &'static str,
     ice_file: Option<PathBuf>,
+    expanded_args: Vec<String>,
 ) -> Session {
     // FIXME: This is not general enough to make the warning lint completely override
     // normal diagnostic warnings, since the warning lint can also be denied and changed
@@ -1467,6 +1474,7 @@ pub fn build_session(
         target_features: Default::default(),
         unstable_target_features: Default::default(),
         cfg_version,
+        expanded_args,
     };
 
     validate_commandline_args_with_session_available(&sess);
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 1ce7efdfc20..974dc1c5135 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -157,6 +157,12 @@ pub(crate) struct Options {
     /// Note: this field is duplicated in `RenderOptions` because it's useful
     /// to have it in both places.
     pub(crate) unstable_features: rustc_feature::UnstableFeatures,
+
+    /// All commandline args used to invoke the compiler, with @file args fully expanded.
+    /// This will only be used within debug info, e.g. in the pdb file on windows
+    /// This is mainly useful for other tools that reads that debuginfo to figure out
+    /// how to call the compiler with the same arguments.
+    pub(crate) expanded_args: Vec<String>,
 }
 
 impl fmt::Debug for Options {
@@ -744,6 +750,7 @@ impl Options {
             json_unused_externs,
             scrape_examples_options,
             unstable_features,
+            expanded_args: args,
         };
         let render_options = RenderOptions {
             output,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index eadff37b592..7cd25ef444b 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -194,6 +194,7 @@ pub(crate) fn create_config(
         describe_lints,
         lint_cap,
         scrape_examples_options,
+        expanded_args,
         ..
     }: RustdocOptions,
     RenderOptions { document_private, .. }: &RenderOptions,
@@ -291,6 +292,7 @@ pub(crate) fn create_config(
         make_codegen_backend: None,
         registry: rustc_driver::diagnostics_registry(),
         ice_file: None,
+        expanded_args,
     }
 }
 
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 36d5adb6304..bb7d26c541b 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -109,6 +109,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
         make_codegen_backend: None,
         registry: rustc_driver::diagnostics_registry(),
         ice_file: None,
+        expanded_args: options.expanded_args.clone(),
     };
 
     let test_args = options.test_args.clone();
diff --git a/tests/run-make-fulldeps/issue-19371/foo.rs b/tests/run-make-fulldeps/issue-19371/foo.rs
index 68132638759..1c9d33dcc8e 100644
--- a/tests/run-make-fulldeps/issue-19371/foo.rs
+++ b/tests/run-make-fulldeps/issue-19371/foo.rs
@@ -61,6 +61,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
         override_queries: None,
         make_codegen_backend: None,
         registry: rustc_driver::diagnostics_registry(),
+        expanded_args: Default::default(),
     };
 
     interface::run_compiler(config, |compiler| {
diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/Makefile b/tests/run-make/pdb-buildinfo-cl-cmd/Makefile
new file mode 100644
index 00000000000..a7be301a5b0
--- /dev/null
+++ b/tests/run-make/pdb-buildinfo-cl-cmd/Makefile
@@ -0,0 +1,16 @@
+include ../tools.mk
+
+# only-windows-msvc
+
+# tests if the pdb contains the following information in the LF_BUILDINFO:
+# 1. the commandline args to compile it (cmd)
+# 2. full path to the compiler (cl)
+
+# we just do a stringsearch on the pdb, as these need to show up at least once, as the LF_BUILDINFO is created for each cgu
+# actual parsing would be better, but this is a simple and good enough solution for now
+
+all:
+	$(RUSTC_ORIGINAL) main.rs -g --crate-name my_crate_name --crate-type bin -C metadata=dc9ef878b0a48666 --out-dir $(TMPDIR)
+	cat '$(TMPDIR)/my_crate_name.pdb' | grep -F '$(RUSTC_ORIGINAL)'
+# using a file containing the string so I don't have problems with escaping quotes and spaces 
+	cat '$(TMPDIR)/my_crate_name.pdb' | grep -f 'stringlist.txt'
diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/main.rs b/tests/run-make/pdb-buildinfo-cl-cmd/main.rs
new file mode 100644
index 00000000000..f79c691f085
--- /dev/null
+++ b/tests/run-make/pdb-buildinfo-cl-cmd/main.rs
@@ -0,0 +1,2 @@
+fn main() {
+}
diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt b/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt
new file mode 100644
index 00000000000..634e9f19e89
--- /dev/null
+++ b/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt
@@ -0,0 +1 @@
+"main.rs" "-g" "--crate-name" "my_crate_name" "--crate-type" "bin" "-C" "metadata=dc9ef878b0a48666" "--out-dir"
\ No newline at end of file