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

std: Use rustc_demangle from crates.io #56832

Merged
merged 1 commit into from
Dec 16, 2018
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
21 changes: 13 additions & 8 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ dependencies = [
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]

Expand Down Expand Up @@ -1813,7 +1813,7 @@ name = "rand_chacha"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]

Expand All @@ -1835,7 +1835,7 @@ name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
Expand All @@ -1860,7 +1860,7 @@ name = "rand_xorshift"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
Expand Down Expand Up @@ -2195,8 +2195,12 @@ dependencies = [

[[package]]
name = "rustc-demangle"
version = "0.1.9"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-core 1.0.0",
]

[[package]]
name = "rustc-hash"
Expand Down Expand Up @@ -2315,7 +2319,7 @@ dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_llvm 0.0.0",
]

Expand All @@ -2331,7 +2335,7 @@ dependencies = [
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_allocator 0.0.0",
"rustc_apfloat 0.0.0",
"rustc_codegen_utils 0.0.0",
Expand Down Expand Up @@ -2892,6 +2896,7 @@ dependencies = [
"panic_unwind 0.0.0",
"profiler_builtins 0.0.0",
"rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_asan 0.0.0",
"rustc_lsan 0.0.0",
"rustc_msan 0.0.0",
Expand Down Expand Up @@ -3578,7 +3583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rustc-ap-serialize 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2c0e8161e956647592a737074736e6ce05ea36b70c770ea8cca3eb9cb33737"
"checksum rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1adc189e5e4500a4167b9afa04e67067f40d0039e0e05870c977bebb561f065a"
"checksum rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d42c430dbb0be4377bfe6aa5099074c63ac8796b24098562c2e2154aecc5652"
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
"checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
"checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
Expand Down
1 change: 1 addition & 0 deletions src/libstd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ libc = { version = "0.2.44", default-features = false, features = ['rustc-dep-of
compiler_builtins = { version = "0.1.1" }
profiler_builtins = { path = "../libprofiler_builtins", optional = true }
unwind = { path = "../libunwind" }
rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] }

[dev-dependencies]
rand = "0.6.1"
Expand Down
1 change: 1 addition & 0 deletions src/libstd/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ pub use core::{unreachable, unimplemented, write, writeln, try};
extern crate alloc as alloc_crate;
#[doc(masked)]
extern crate libc;
extern crate rustc_demangle;

// We always need an unwinder currently for backtraces
#[doc(masked)]
Expand Down
239 changes: 11 additions & 228 deletions src/libstd/sys_common/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
use env;
use io::prelude::*;
use io;
use path::{self, Path};
use ptr;
use rustc_demangle::demangle;
use str;
use sync::atomic::{self, Ordering};
use path::{self, Path};
use sys::mutex::Mutex;
use ptr;

pub use sys::backtrace::{
unwind_backtrace,
Expand Down Expand Up @@ -191,7 +192,14 @@ fn output(w: &mut dyn Write, idx: usize, frame: Frame,
PrintFormat::Short => write!(w, " {:2}: ", idx)?,
}
match s {
Some(string) => demangle(w, string, format)?,
Some(string) => {
let symbol = demangle(string);
match format {
PrintFormat::Full => write!(w, "{}", symbol)?,
// strip the trailing hash if short mode
PrintFormat::Short => write!(w, "{:#}", symbol)?,
}
}
None => w.write_all(b"<unknown>")?,
}
w.write_all(b"\n")
Expand Down Expand Up @@ -235,228 +243,3 @@ fn output_fileline(w: &mut dyn Write,
w.write_all(b"\n")
}


// All rust symbols are in theory lists of "::"-separated identifiers. Some
// assemblers, however, can't handle these characters in symbol names. To get
// around this, we use C++-style mangling. The mangling method is:
//
// 1. Prefix the symbol with "_ZN"
// 2. For each element of the path, emit the length plus the element
// 3. End the path with "E"
//
// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar".
//
// We're the ones printing our backtraces, so we can't rely on anything else to
// demangle our symbols. It's *much* nicer to look at demangled symbols, so
// this function is implemented to give us nice pretty output.
//
// Note that this demangler isn't quite as fancy as it could be. We have lots
// of other information in our symbols like hashes, version, type information,
// etc. Additionally, this doesn't handle glue symbols at all.
pub fn demangle(writer: &mut dyn Write, mut s: &str, format: PrintFormat) -> io::Result<()> {
// During ThinLTO LLVM may import and rename internal symbols, so strip out
// those endings first as they're one of the last manglings applied to
// symbol names.
let llvm = ".llvm.";
if let Some(i) = s.find(llvm) {
let candidate = &s[i + llvm.len()..];
let all_hex = candidate.chars().all(|c| {
match c {
'A' ..= 'F' | '0' ..= '9' => true,
_ => false,
}
});

if all_hex {
s = &s[..i];
}
}

// Validate the symbol. If it doesn't look like anything we're
// expecting, we just print it literally. Note that we must handle non-rust
// symbols because we could have any function in the backtrace.
let mut valid = true;
let mut inner = s;
if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
inner = &s[3 .. s.len() - 1];
// On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too.
} else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") {
inner = &s[2 .. s.len() - 1];
} else {
valid = false;
}

if valid {
let mut chars = inner.chars();
while valid {
let mut i = 0;
for c in chars.by_ref() {
if c.is_numeric() {
i = i * 10 + c as usize - '0' as usize;
} else {
break
}
}
if i == 0 {
valid = chars.next().is_none();
break
} else if chars.by_ref().take(i - 1).count() != i - 1 {
valid = false;
}
}
}

// Alright, let's do this.
if !valid {
writer.write_all(s.as_bytes())?;
} else {
// remove the `::hfc2edb670e5eda97` part at the end of the symbol.
if format == PrintFormat::Short {
// The symbol in still mangled.
let mut split = inner.rsplitn(2, "17h");
match (split.next(), split.next()) {
(Some(addr), rest) => {
if addr.len() == 16 &&
addr.chars().all(|c| c.is_digit(16))
{
inner = rest.unwrap_or("");
}
}
_ => (),
}
}

let mut first = true;
while !inner.is_empty() {
if !first {
writer.write_all(b"::")?;
} else {
first = false;
}
let mut rest = inner;
while rest.chars().next().unwrap().is_numeric() {
rest = &rest[1..];
}
let i: usize = inner[.. (inner.len() - rest.len())].parse().unwrap();
inner = &rest[i..];
rest = &rest[..i];
if rest.starts_with("_$") {
rest = &rest[1..];
}
while !rest.is_empty() {
if rest.starts_with(".") {
if let Some('.') = rest[1..].chars().next() {
writer.write_all(b"::")?;
rest = &rest[2..];
} else {
writer.write_all(b".")?;
rest = &rest[1..];
}
} else if rest.starts_with("$") {
macro_rules! demangle {
($($pat:expr => $demangled:expr),*) => ({
$(if rest.starts_with($pat) {
writer.write_all($demangled)?;
rest = &rest[$pat.len()..];
} else)*
{
writer.write_all(rest.as_bytes())?;
break;
}

})
}

// see src/librustc/back/link.rs for these mappings
demangle! (
"$SP$" => b"@",
"$BP$" => b"*",
"$RF$" => b"&",
"$LT$" => b"<",
"$GT$" => b">",
"$LP$" => b"(",
"$RP$" => b")",
"$C$" => b",",

// in theory we can demangle any Unicode code point, but
// for simplicity we just catch the common ones.
"$u7e$" => b"~",
"$u20$" => b" ",
"$u27$" => b"'",
"$u5b$" => b"[",
"$u5d$" => b"]",
"$u7b$" => b"{",
"$u7d$" => b"}",
"$u3b$" => b";",
"$u2b$" => b"+",
"$u22$" => b"\""
)
} else {
let idx = match rest.char_indices().find(|&(_, c)| c == '$' || c == '.') {
None => rest.len(),
Some((i, _)) => i,
};
writer.write_all(rest[..idx].as_bytes())?;
rest = &rest[idx..];
}
}
}
}

Ok(())
}

#[cfg(test)]
mod tests {
use sys_common;
macro_rules! t { ($a:expr, $b:expr) => ({
let mut m = Vec::new();
sys_common::backtrace::demangle(&mut m,
$a,
super::PrintFormat::Full).unwrap();
assert_eq!(String::from_utf8(m).unwrap(), $b);
}) }

#[test]
fn demangle() {
t!("test", "test");
t!("_ZN4testE", "test");
t!("_ZN4test", "_ZN4test");
t!("_ZN4test1a2bcE", "test::a::bc");
}

#[test]
fn demangle_dollars() {
t!("_ZN4$RP$E", ")");
t!("_ZN8$RF$testE", "&test");
t!("_ZN8$BP$test4foobE", "*test::foob");
t!("_ZN9$u20$test4foobE", " test::foob");
t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>");
}

#[test]
fn demangle_many_dollars() {
t!("_ZN13test$u20$test4foobE", "test test::foob");
t!("_ZN12test$BP$test4foobE", "test*test::foob");
}

#[test]
fn demangle_windows() {
t!("ZN4testE", "test");
t!("ZN13test$u20$test4foobE", "test test::foob");
t!("ZN12test$RF$test4foobE", "test&test::foob");
}

#[test]
fn demangle_elements_beginning_with_underscore() {
t!("_ZN13_$LT$test$GT$E", "<test>");
t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}");
t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR");
}

#[test]
fn demangle_trait_impls() {
t!("_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE",
"<Test + 'static as foo::Bar<Test>>::bar");
}
}
1 change: 1 addition & 0 deletions src/tools/tidy/src/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const WHITELIST: &[Crate] = &[
Crate("chalk-macros"),
Crate("cloudabi"),
Crate("cmake"),
Crate("compiler_builtins"),
Crate("crc"),
Crate("crc32fast"),
Crate("crossbeam-deque"),
Expand Down