sess/cg: re-introduce split dwarf kind
In #79570, `-Z split-dwarf-kind={none,single,split}` was replaced by `-C split-debuginfo={off,packed,unpacked}`. `-C split-debuginfo`'s packed and unpacked aren't exact parallels to single and split, respectively. On Unix, `-C split-debuginfo=packed` will put debuginfo into object files and package debuginfo into a DWARF package file (`.dwp`) and `-C split-debuginfo=unpacked` will put debuginfo into dwarf object files and won't package it. In the initial implementation of Split DWARF, split mode wrote sections which did not require relocation into a DWARF object (`.dwo`) file which was ignored by the linker and then packaged those DWARF objects into DWARF packages (`.dwp`). In single mode, sections which did not require relocation were written into object files but ignored by the linker and were not packaged. However, both split and single modes could be packaged or not, the primary difference in behaviour was where the debuginfo sections that did not require link-time relocation were written (in a DWARF object or the object file). This commit re-introduces a `-Z split-dwarf-kind` flag, which can be used to pick between split and single modes when `-C split-debuginfo` is used to enable Split DWARF (either packed or unpacked). Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
f1ce0e6a00
commit
08ed338f56
8 changed files with 184 additions and 61 deletions
|
@ -5,7 +5,7 @@ use rustc_fs_util::fix_windows_verbatim_for_gcc;
|
|||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
|
||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
|
||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
|
||||
use rustc_session::cstore::DllImport;
|
||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||
use rustc_session::search_paths::PathKind;
|
||||
|
@ -134,31 +134,47 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
|||
}
|
||||
}
|
||||
|
||||
// Remove the temporary object file and metadata if we aren't saving temps
|
||||
// Remove the temporary object file and metadata if we aren't saving temps.
|
||||
sess.time("link_binary_remove_temps", || {
|
||||
if !sess.opts.cg.save_temps {
|
||||
let remove_temps_from_module = |module: &CompiledModule| {
|
||||
if let Some(ref obj) = module.object {
|
||||
ensure_removed(sess.diagnostic(), obj);
|
||||
}
|
||||
// If the user requests that temporaries are saved, don't delete any.
|
||||
if sess.opts.cg.save_temps {
|
||||
return;
|
||||
}
|
||||
|
||||
let remove_temps_from_module = |module: &CompiledModule| {
|
||||
if let Some(ref obj) = module.object {
|
||||
ensure_removed(sess.diagnostic(), obj);
|
||||
}
|
||||
};
|
||||
|
||||
// Otherwise, always remove the metadata and allocator module temporaries.
|
||||
if let Some(ref metadata_module) = codegen_results.metadata_module {
|
||||
remove_temps_from_module(metadata_module);
|
||||
}
|
||||
|
||||
if let Some(ref allocator_module) = codegen_results.allocator_module {
|
||||
remove_temps_from_module(allocator_module);
|
||||
}
|
||||
|
||||
// If no requested outputs require linking, then the object temporaries should
|
||||
// be kept.
|
||||
if !sess.opts.output_types.should_link() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Potentially keep objects for their debuginfo.
|
||||
let (preserve_objects, preserve_dwarf_objects) = preserve_objects_for_their_debuginfo(sess);
|
||||
debug!(?preserve_objects, ?preserve_dwarf_objects);
|
||||
|
||||
for module in &codegen_results.modules {
|
||||
if !preserve_objects {
|
||||
remove_temps_from_module(module);
|
||||
}
|
||||
|
||||
if !preserve_dwarf_objects {
|
||||
if let Some(ref obj) = module.dwarf_object {
|
||||
ensure_removed(sess.diagnostic(), obj);
|
||||
}
|
||||
};
|
||||
|
||||
if sess.opts.output_types.should_link() && !preserve_objects_for_their_debuginfo(sess) {
|
||||
for module in &codegen_results.modules {
|
||||
remove_temps_from_module(module);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref metadata_module) = codegen_results.metadata_module {
|
||||
remove_temps_from_module(metadata_module);
|
||||
}
|
||||
|
||||
if let Some(ref allocator_module) = codegen_results.allocator_module {
|
||||
remove_temps_from_module(allocator_module);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1138,26 +1154,36 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
|||
bug!("Not enough information provided to determine how to invoke the linker");
|
||||
}
|
||||
|
||||
/// Returns a boolean indicating whether we should preserve the object files on
|
||||
/// the filesystem for their debug information. This is often useful with
|
||||
/// split-dwarf like schemes.
|
||||
fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
|
||||
/// Returns a pair of boolean indicating whether we should preserve the object and
|
||||
/// dwarf object files on the filesystem for their debug information. This is often
|
||||
/// useful with split-dwarf like schemes.
|
||||
fn preserve_objects_for_their_debuginfo(sess: &Session) -> (bool, bool) {
|
||||
// If the objects don't have debuginfo there's nothing to preserve.
|
||||
if sess.opts.debuginfo == config::DebugInfo::None {
|
||||
return false;
|
||||
return (false, false);
|
||||
}
|
||||
|
||||
// If we're only producing artifacts that are archives, no need to preserve
|
||||
// the objects as they're losslessly contained inside the archives.
|
||||
let output_linked =
|
||||
sess.crate_types().iter().any(|&x| x != CrateType::Rlib && x != CrateType::Staticlib);
|
||||
if !output_linked {
|
||||
return false;
|
||||
if sess.crate_types().iter().all(|&x| x.is_archive()) {
|
||||
return (false, false);
|
||||
}
|
||||
|
||||
// "unpacked" split debuginfo means that we leave object files as the
|
||||
// debuginfo is found in the original object files themselves
|
||||
sess.split_debuginfo() == SplitDebuginfo::Unpacked
|
||||
match (sess.split_debuginfo(), sess.opts.debugging_opts.split_dwarf_kind) {
|
||||
// If there is no split debuginfo then do not preserve objects.
|
||||
(SplitDebuginfo::Off, _) => (false, false),
|
||||
// If there is packed split debuginfo, then the debuginfo in the objects
|
||||
// has been packaged and the objects can be deleted.
|
||||
(SplitDebuginfo::Packed, _) => (false, false),
|
||||
// If there is unpacked split debuginfo and the current target can not use
|
||||
// split dwarf, then keep objects.
|
||||
(SplitDebuginfo::Unpacked, _) if !sess.target_can_use_split_dwarf() => (true, false),
|
||||
// If there is unpacked split debuginfo and the target can use split dwarf, then
|
||||
// keep the object containing that debuginfo (whether that is an object file or
|
||||
// dwarf object file depends on the split dwarf kind).
|
||||
(SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => (true, false),
|
||||
(SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => (false, true),
|
||||
}
|
||||
}
|
||||
|
||||
fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
|
||||
|
|
|
@ -286,7 +286,11 @@ impl TargetMachineFactoryConfig {
|
|||
module_name: &str,
|
||||
) -> TargetMachineFactoryConfig {
|
||||
let split_dwarf_file = if cgcx.target_can_use_split_dwarf {
|
||||
cgcx.output_filenames.split_dwarf_path(cgcx.split_debuginfo, Some(module_name))
|
||||
cgcx.output_filenames.split_dwarf_path(
|
||||
cgcx.split_debuginfo,
|
||||
cgcx.split_dwarf_kind,
|
||||
Some(module_name),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -329,6 +333,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
|
|||
pub target_arch: String,
|
||||
pub debuginfo: config::DebugInfo,
|
||||
pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
|
||||
pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
|
||||
|
||||
// Number of cgus excluding the allocator/metadata modules
|
||||
pub total_cgus: usize,
|
||||
|
@ -1060,6 +1065,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
target_arch: tcx.sess.target.arch.clone(),
|
||||
debuginfo: tcx.sess.opts.debuginfo,
|
||||
split_debuginfo: tcx.sess.split_debuginfo(),
|
||||
split_dwarf_kind: tcx.sess.opts.debugging_opts.split_dwarf_kind,
|
||||
};
|
||||
|
||||
// This is the "main loop" of parallel work happening for parallel codegen.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue