Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CL and CMD into to pdb debug info #113492

Merged
merged 1 commit into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this be CString's, so avoid playing with null bytes in rust and cpp side code? Didn't read all previous discussion, sorry, if it was suggested previously.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose this version because for me it had the right balance between readability and performance for passing of CStrings through a C API. While I don't think this code is pretty, other version create more allocations, while not being much better IMO. Other views might differ and if someone feels very strongly about this I will change this.

I previously tried a version with an Vec of CStrings and a Vec with pointers to those, passing the slice of the latter to llvm::LLVMRustCreateTargetMachine.

However, that target machine factory lambda requires Fn+send+sync. I can only move the Pointer Vec into it via some terrible casting and introducing other types, because ptrs are not send+sync. If create the pointer Vec inside the lambda I have an allocation every time the lambda gets called.

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;
Expand All @@ -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(),
)
};

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ fn mk_session(handler: &mut EarlyErrorHandler, matches: getopts::Matches) -> (Se
None,
"",
None,
Default::default(),
);
(sess, cfg)
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -113,6 +114,7 @@ pub fn create_session(
target_override,
rustc_version_str().unwrap_or("unknown"),
ice_file,
expanded_args,
);

codegen_backend.init(&sess);
Expand Down
39 changes: 38 additions & 1 deletion compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -744,6 +750,7 @@ impl Options {
json_unused_externs,
scrape_examples_options,
unstable_features,
expanded_args: args,
};
let render_options = RenderOptions {
output,
Expand Down
2 changes: 2 additions & 0 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ pub(crate) fn create_config(
describe_lints,
lint_cap,
scrape_examples_options,
expanded_args,
..
}: RustdocOptions,
RenderOptions { document_private, .. }: &RenderOptions,
Expand Down Expand Up @@ -291,6 +292,7 @@ pub(crate) fn create_config(
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),
ice_file: None,
expanded_args,
}
}

Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/doctest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions tests/run-make-fulldeps/issue-19371/foo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down
16 changes: 16 additions & 0 deletions tests/run-make/pdb-buildinfo-cl-cmd/Makefile
Original file line number Diff line number Diff line change
@@ -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'
2 changes: 2 additions & 0 deletions tests/run-make/pdb-buildinfo-cl-cmd/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fn main() {
}
1 change: 1 addition & 0 deletions tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"main.rs" "-g" "--crate-name" "my_crate_name" "--crate-type" "bin" "-C" "metadata=dc9ef878b0a48666" "--out-dir"
Loading