Skip to content

Commit

Permalink
session: stabilize split debuginfo on linux
Browse files Browse the repository at this point in the history
Stabilize the `-Csplit-debuginfo` flag...

- ...on Linux for all values of the flag. Split DWARF has been
  implemented for a few months, hasn't had any bug reports and has had
  some promising benchmarking for incremental debug build performance.
- ..on other platforms for the default value. It doesn't make any sense
  that `-Csplit-debuginfo=packed` is unstable on Windows MSVC when
  that's the default behaviour, but keep the other values unstable.

Signed-off-by: David Wood <[email protected]>
  • Loading branch information
davidtwco committed Aug 18, 2022
1 parent 8556e66 commit cf2c492
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 60 deletions.
7 changes: 0 additions & 7 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2423,13 +2423,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {

let pretty = parse_pretty(&unstable_opts, error_format);

if !unstable_opts.unstable_options
&& !target_triple.triple().contains("apple")
&& cg.split_debuginfo.is_some()
{
early_error(error_format, "`-Csplit-debuginfo` is unstable on this platform");
}

// Try to find a directory containing the Rust `src`, for more details see
// the doc comment on the `real_rust_source_base_dir` field.
let tmp_buf;
Expand Down
14 changes: 12 additions & 2 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
use rustc_target::asm::InlineAsmArch;
use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
use rustc_target::spec::{
SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel,
DebuginfoKind, SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel,
};

use std::cell::{self, RefCell};
Expand Down Expand Up @@ -661,8 +661,9 @@ impl Session {
)
}

/// Returns `true` if the target can use the current split debuginfo configuration.
pub fn target_can_use_split_dwarf(&self) -> bool {
!self.target.is_like_windows && !self.target.is_like_osx
self.target.debuginfo_kind == DebuginfoKind::Dwarf
}

pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
Expand Down Expand Up @@ -1543,6 +1544,15 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
sess.err(&format!("requested DWARF version {} is greater than 5", dwarf_version));
}
}

if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo())
&& !sess.opts.unstable_opts.unstable_options
{
sess.err(&format!(
"`-Csplit-debuginfo={}` is unstable on this platform",
sess.split_debuginfo()
));
}
}

/// Holds data on the current incremental compilation session, if there is one.
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_target/src/spec/apple_base.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{borrow::Cow, env};

use crate::spec::{cvs, FramePointer, SplitDebuginfo, TargetOptions};
use crate::spec::{cvs, DebuginfoKind, FramePointer, SplitDebuginfo, TargetOptions};
use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor};

fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs {
Expand Down Expand Up @@ -76,9 +76,15 @@ pub fn opts(os: &'static str, arch: &'static str, abi: &'static str) -> TargetOp
eh_frame_header: false,
lld_flavor: LldFlavor::Ld64,

debuginfo_kind: DebuginfoKind::DwarfDsym,
// The historical default for macOS targets is to run `dsymutil` which
// generates a packed version of debuginfo split from the main file.
split_debuginfo: SplitDebuginfo::Packed,
supported_split_debuginfo: Cow::Borrowed(&[
SplitDebuginfo::Packed,
SplitDebuginfo::Unpacked,
SplitDebuginfo::Off,
]),

// This environment variable is pretty magical but is intended for
// producing deterministic builds. This was first discovered to be used
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_target/src/spec/linux_base.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::spec::{cvs, RelroLevel, TargetOptions};
use crate::spec::{cvs, RelroLevel, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;

pub fn opts() -> TargetOptions {
TargetOptions {
Expand All @@ -10,6 +11,11 @@ pub fn opts() -> TargetOptions {
relro_level: RelroLevel::Full,
has_thread_local: true,
crt_static_respected: true,
supported_split_debuginfo: Cow::Borrowed(&[
SplitDebuginfo::Packed,
SplitDebuginfo::Unpacked,
SplitDebuginfo::Off,
]),
..Default::default()
}
}
104 changes: 99 additions & 5 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,23 +468,74 @@ impl fmt::Display for LinkOutputKind {

pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;

#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
/// Which kind of debuginfo does the target use?
///
/// Useful in determining whether a target supports Split DWARF (a target with
/// `DebuginfoKind::Dwarf` and supporting `SplitDebuginfo::Unpacked` for example).
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub enum DebuginfoKind {
/// DWARF debuginfo (such as that used on `x86_64_unknown_linux_gnu`).
#[default]
Dwarf,
/// DWARF debuginfo in dSYM files (such as on Apple platforms).
DwarfDsym,
/// Program database files (such as on Windows).
Pdb,
}

impl DebuginfoKind {
fn as_str(&self) -> &'static str {
match self {
DebuginfoKind::Dwarf => "dwarf",
DebuginfoKind::DwarfDsym => "dwarf-dsym",
DebuginfoKind::Pdb => "pdb",
}
}
}

impl FromStr for DebuginfoKind {
type Err = ();

fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"dwarf" => DebuginfoKind::Dwarf,
"dwarf-dsym" => DebuginfoKind::DwarfDsym,
"pdb" => DebuginfoKind::Pdb,
_ => return Err(()),
})
}
}

impl ToJson for DebuginfoKind {
fn to_json(&self) -> Json {
self.as_str().to_json()
}
}

impl fmt::Display for DebuginfoKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub enum SplitDebuginfo {
/// Split debug-information is disabled, meaning that on supported platforms
/// you can find all debug information in the executable itself. This is
/// only supported for ELF effectively.
///
/// * Windows - not supported
/// * macOS - don't run `dsymutil`
/// * ELF - `.dwarf_*` sections
/// * ELF - `.debug_*` sections
#[default]
Off,

/// Split debug-information can be found in a "packed" location separate
/// from the final artifact. This is supported on all platforms.
///
/// * Windows - `*.pdb`
/// * macOS - `*.dSYM` (run `dsymutil`)
/// * ELF - `*.dwp` (run `rust-llvm-dwp`)
/// * ELF - `*.dwp` (run `thorin`)
Packed,

/// Split debug-information can be found in individual object files on the
Expand All @@ -509,7 +560,7 @@ impl SplitDebuginfo {
impl FromStr for SplitDebuginfo {
type Err = ();

fn from_str(s: &str) -> Result<SplitDebuginfo, ()> {
fn from_str(s: &str) -> Result<Self, ()> {
Ok(match s {
"off" => SplitDebuginfo::Off,
"unpacked" => SplitDebuginfo::Unpacked,
Expand Down Expand Up @@ -1435,9 +1486,13 @@ pub struct TargetOptions {
/// thumb and arm interworking.
pub has_thumb_interworking: bool,

/// Which kind of debuginfo is used by this target?
pub debuginfo_kind: DebuginfoKind,
/// How to handle split debug information, if at all. Specifying `None` has
/// target-specific meaning.
pub split_debuginfo: SplitDebuginfo,
/// Which kinds of split debuginfo are supported by the target?
pub supported_split_debuginfo: StaticCow<[SplitDebuginfo]>,

/// The sanitizers supported by this target
///
Expand Down Expand Up @@ -1595,7 +1650,10 @@ impl Default for TargetOptions {
use_ctors_section: false,
eh_frame_header: true,
has_thumb_interworking: false,
split_debuginfo: SplitDebuginfo::Off,
debuginfo_kind: Default::default(),
split_debuginfo: Default::default(),
// `Off` is supported by default, but targets can remove this manually, e.g. Windows.
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
supported_sanitizers: SanitizerSet::empty(),
default_adjusted_cabi: None,
c_enum_min_bits: 32,
Expand Down Expand Up @@ -1868,6 +1926,19 @@ impl Target {
Some(Ok(()))
})).unwrap_or(Ok(()))
} );
($key_name:ident, DebuginfoKind) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
match s.parse::<DebuginfoKind>() {
Ok(level) => base.$key_name = level,
_ => return Some(Err(
format!("'{s}' is not a valid value for debuginfo-kind. Use 'dwarf', \
'dwarf-dsym' or 'pdb'.")
)),
}
Some(Ok(()))
})).unwrap_or(Ok(()))
} );
($key_name:ident, SplitDebuginfo) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
Expand Down Expand Up @@ -1904,6 +1975,25 @@ impl Target {
}
}
} );
($key_name:ident, falliable_list) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.remove(&name).and_then(|j| {
if let Some(v) = j.as_array() {
match v.iter().map(|a| FromStr::from_str(a.as_str().unwrap())).collect() {
Ok(l) => { base.$key_name = l },
// FIXME: `falliable_list` can't re-use the `key!` macro for list
// elements and the error messages from that macro, so it has a bad
// generic message instead
Err(_) => return Some(Err(
format!("`{:?}` is not a valid value for `{}`", j, name)
)),
}
} else {
incorrect_type.push(name)
}
Some(Ok(()))
}).unwrap_or(Ok(()))
} );
($key_name:ident, optional) => ( {
let name = (stringify!($key_name)).replace("_", "-");
if let Some(o) = obj.remove(&name) {
Expand Down Expand Up @@ -2190,7 +2280,9 @@ impl Target {
key!(use_ctors_section, bool);
key!(eh_frame_header, bool);
key!(has_thumb_interworking, bool);
key!(debuginfo_kind, DebuginfoKind)?;
key!(split_debuginfo, SplitDebuginfo)?;
key!(supported_split_debuginfo, falliable_list)?;
key!(supported_sanitizers, SanitizerSet)?;
key!(default_adjusted_cabi, Option<Abi>)?;
key!(c_enum_min_bits, u64);
Expand Down Expand Up @@ -2434,7 +2526,9 @@ impl ToJson for Target {
target_option_val!(use_ctors_section);
target_option_val!(eh_frame_header);
target_option_val!(has_thumb_interworking);
target_option_val!(debuginfo_kind);
target_option_val!(split_debuginfo);
target_option_val!(supported_split_debuginfo);
target_option_val!(supported_sanitizers);
target_option_val!(c_enum_min_bits);
target_option_val!(generate_arange_section);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/msvc_base.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::spec::{LinkerFlavor, LldFlavor, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;

pub fn opts() -> TargetOptions {
// Suppress the verbose logo and authorship debugging output, which would needlessly
Expand All @@ -18,6 +19,7 @@ pub fn opts() -> TargetOptions {
// Currently this is the only supported method of debuginfo on MSVC
// where `*.pdb` files show up next to the final artifact.
split_debuginfo: SplitDebuginfo::Packed,
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Packed]),

..Default::default()
}
Expand Down
7 changes: 6 additions & 1 deletion compiler/rustc_target/src/spec/windows_gnu_base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::spec::crt_objects::{self, LinkSelfContainedDefault};
use crate::spec::{cvs, LinkerFlavor, TargetOptions};
use crate::spec::{cvs, DebuginfoKind, LinkerFlavor, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;

pub fn opts() -> TargetOptions {
let mut pre_link_args = TargetOptions::link_args(
Expand Down Expand Up @@ -86,6 +87,10 @@ pub fn opts() -> TargetOptions {
emit_debug_gdb_scripts: false,
requires_uwtable: true,
eh_frame_header: false,
// FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to
// output DWO, despite using DWARF, doesn't use ELF..
debuginfo_kind: DebuginfoKind::Pdb,
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
..Default::default()
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_target/src/spec/windows_msvc_base.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::spec::{cvs, TargetOptions};
use crate::spec::{cvs, DebuginfoKind, TargetOptions};

pub fn opts() -> TargetOptions {
let base = super::msvc_base::opts();
Expand Down Expand Up @@ -28,6 +28,7 @@ pub fn opts() -> TargetOptions {
// not ever be possible for us to pass this flag.
no_default_libraries: false,
has_thread_local: true,
debuginfo_kind: DebuginfoKind::Pdb,

..base
}
Expand Down
30 changes: 14 additions & 16 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1759,23 +1759,21 @@ impl<'a> Builder<'a> {
},
);

if !target.contains("windows") {
let needs_unstable_opts = target.contains("linux")
|| target.contains("solaris")
|| target.contains("windows")
|| target.contains("bsd")
|| target.contains("dragonfly")
|| target.contains("illumos");

if needs_unstable_opts {
rustflags.arg("-Zunstable-options");
}
match self.config.rust_split_debuginfo {
SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"),
SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"),
SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"),
};
let split_debuginfo_is_stable = target.contains("linux")
|| target.contains("apple")
|| (target.contains("msvc")
&& self.config.rust_split_debuginfo == SplitDebuginfo::Packed)
|| (target.contains("windows")
&& self.config.rust_split_debuginfo == SplitDebuginfo::Off);

if !split_debuginfo_is_stable {
rustflags.arg("-Zunstable-options");
}
match self.config.rust_split_debuginfo {
SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"),
SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"),
SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"),
};

if self.config.cmd.bless() {
// Bless `expect!` tests.
Expand Down
4 changes: 2 additions & 2 deletions src/test/incremental/split_debuginfo_cached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
// only-x86_64-unknown-linux-gnu
// revisions:rpass1 rpass2

// [rpass1]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
// [rpass2]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
// [rpass1]compile-flags: -g -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
// [rpass2]compile-flags: -g -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split

#![feature(rustc_attrs)]
// For `rpass2`, nothing has changed so everything should re-used.
Expand Down
8 changes: 4 additions & 4 deletions src/test/incremental/split_debuginfo_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
// only-x86_64-unknown-linux-gnu
// revisions:rpass1 rpass2 rpass3 rpass4

// [rpass1]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
// [rpass2]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
// [rpass3]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=on
// [rpass4]compile-flags: -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=off
// [rpass1]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=unpacked -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
// [rpass2]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=single -Zsplit-dwarf-inlining=on
// [rpass3]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=on
// [rpass4]compile-flags: -Zquery-dep-graph -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split -Zsplit-dwarf-inlining=off

#![feature(rustc_attrs)]
// For rpass2 we change -Csplit-debuginfo and thus expect every CGU to be recompiled
Expand Down
Loading

0 comments on commit cf2c492

Please sign in to comment.