Skip to content

Commit 2c8a5be

Browse files
committed
WIP
1 parent dad833e commit 2c8a5be

File tree

6 files changed

+179
-7
lines changed

6 files changed

+179
-7
lines changed

src/Cargo.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2726,7 +2726,9 @@ dependencies = [
27262726
"alloc_system 0.0.0",
27272727
"build_helper 0.1.0",
27282728
"cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
2729+
"gimli 0.16.0 (git+https://github.com/est31/gimli?rev=304caacf8b73f117813b1a0d436ce24403459bf2)",
27292730
"libc 0.0.0",
2731+
"object 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
27302732
"panic_abort 0.0.0",
27312733
"panic_unwind 0.0.0",
27322734
"profiler_builtins 0.0.0",

src/bootstrap/builder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,8 @@ impl<'a> Builder<'a> {
841841
let suffix = match mode {
842842
Mode::Std => "rustc-std",
843843
Mode::Test => "rustc-test",
844-
Mode::Codegen | Mode::Rustc => "rustc-rustc",
844+
Mode::Codegen => "rustc-codegen",
845+
Mode::Rustc => "rustc-rustc",
845846
Mode::ToolStd | Mode::ToolTest | Mode::ToolRustc => "rustc-tools",
846847
};
847848
cargo.env("RUSTC_METADATA_SUFFIX", suffix);

src/libstd/Cargo.toml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,15 @@ panic_abort = { path = "../libpanic_abort" }
2020
libc = { path = "../rustc/libc_shim" }
2121
profiler_builtins = { path = "../libprofiler_builtins", optional = true }
2222
unwind = { path = "../libunwind" }
23+
object = { version = "0.9", default-features = false, optional = true }
24+
25+
[dependencies.gimli]
26+
version = "0.16"
27+
default-features = false
28+
features = ["alloc"]
29+
git = "https://github.com/est31/gimli"
30+
rev = "304caacf8b73f117813b1a0d436ce24403459bf2"
31+
optional = true
2332

2433
[dependencies.addr2line]
2534
git = "https://github.com/est31/addr2line"
@@ -46,7 +55,7 @@ cc = "1.0"
4655
build_helper = { path = "../build_helper" }
4756

4857
[features]
49-
backtrace = ["addr2line"]
58+
backtrace = ["addr2line", "object", "gimli"]
5059
debug-jemalloc = ["alloc_jemalloc/debug"]
5160
jemalloc = ["alloc_jemalloc"]
5261
force_alloc_system = []

src/libstd/sys/unix/backtrace/printing/mod.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ where
2525
Ok(false)
2626
}
2727

28-
#[cfg(not(target_os = "emscripten"))]
28+
#[cfg(target_os = "fuchsia")]
2929
pub use sys_common::gnu::libbacktrace::foreach_symbol_fileline;
3030

31-
#[cfg(not(target_os = "emscripten"))]
31+
#[cfg(target_os = "fuchsia")]
3232
pub fn resolve_symname<F>(frame: Frame, callback: F, bc: &BacktraceContext) -> io::Result<()>
3333
where
3434
F: FnOnce(Option<&str>) -> io::Result<()>
@@ -41,3 +41,20 @@ where
4141
}
4242
}, bc)
4343
}
44+
45+
#[cfg(not(any(target_os = "fuchsia", target_os = "emscripten")))]
46+
pub use sys_common::addr2line::foreach_symbol_fileline;
47+
48+
#[cfg(not(any(target_os = "fuchsia", target_os = "emscripten")))]
49+
pub fn resolve_symname<F>(frame: Frame, callback: F, bc: &BacktraceContext) -> io::Result<()>
50+
where
51+
F: FnOnce(Option<&str>) -> io::Result<()>
52+
{
53+
::sys_common::addr2line::resolve_symname(frame, |symname| {
54+
if symname.is_some() {
55+
callback(symname)
56+
} else {
57+
dladdr::resolve_symname(frame, callback, bc)
58+
}
59+
}, bc)
60+
}

src/libstd/sys_common/addr2line.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern crate addr2line;
12+
extern crate gimli;
13+
extern crate object;
14+
15+
use libc::{mmap, size_t, PROT_READ, MAP_SHARED, MAP_FAILED};
16+
17+
use io;
18+
use ptr;
19+
20+
use cell::UnsafeCell;
21+
use marker::Sync;
22+
use sys::backtrace::BacktraceContext;
23+
use sys_common::backtrace::Frame;
24+
use os::unix::io::AsRawFd;
25+
use fs::File;
26+
use slice::from_raw_parts;
27+
use self::addr2line::Context;
28+
use self::gimli::{EndianRcSlice, RunTimeEndian};
29+
30+
struct ThreadSafe<T>(UnsafeCell<T>);
31+
32+
unsafe impl<T> Sync for ThreadSafe<T> {}
33+
34+
macro_rules! err {
35+
($e:expr) => {
36+
return Err(io::Error::new(
37+
io::ErrorKind::Other,
38+
$e)
39+
);
40+
}
41+
}
42+
43+
struct Ctx {
44+
ctx: Context<EndianRcSlice<RunTimeEndian>>,
45+
_file: File,
46+
}
47+
48+
impl Ctx {
49+
fn init() -> io::Result<Ctx> {
50+
let (_filename, file) = ::sys::backtrace::gnu::get_executable_filename()?;
51+
let file_len = file.metadata()?.len();
52+
53+
let map_ptr = unsafe {
54+
mmap(ptr::null_mut(),
55+
file_len as size_t,
56+
PROT_READ,
57+
MAP_SHARED,
58+
file.as_raw_fd(),
59+
0)
60+
};
61+
if map_ptr == MAP_FAILED {
62+
err!("mapping the executable into memory failed");
63+
}
64+
65+
let map = unsafe { from_raw_parts(map_ptr as * mut u8, file_len as usize) };
66+
let object_file = match object::File::parse(&*map) {
67+
Ok(v) => v,
68+
Err(_) => err!("could not parse the object file for backtrace creation"),
69+
};
70+
let ctx = match Context::new(&object_file) {
71+
Ok(v) => v,
72+
Err(_) => err!("could not create backtrace parsing context"),
73+
};
74+
75+
Ok(Ctx {
76+
ctx,
77+
_file: file,
78+
})
79+
}
80+
fn with_static<T, F: FnOnce(&Ctx) -> io::Result<T>>(f: F) -> io::Result<T> {
81+
static CTX_CELL: ThreadSafe<Option<Ctx>> = ThreadSafe(UnsafeCell::new(None));
82+
let cell_ref: &mut Option<_> = unsafe { &mut *CTX_CELL.0.get() };
83+
if cell_ref.is_none() {
84+
*cell_ref = Some(Ctx::init()?);
85+
}
86+
let ctx = if let Some(c) = cell_ref {
87+
c
88+
} else {
89+
unreachable!()
90+
};
91+
f(ctx)
92+
}
93+
}
94+
95+
pub fn foreach_symbol_fileline<F>(frame: Frame,
96+
mut f: F,
97+
_: &BacktraceContext) -> io::Result<bool>
98+
where F: FnMut(&[u8], u32) -> io::Result<()>
99+
{
100+
Ctx::with_static(|ctx|{
101+
let mut frames_iter = match ctx.ctx.find_frames(frame.exact_position as u64) {
102+
Ok(v) => v,
103+
Err(_) => err!("error during binary parsing"),
104+
};
105+
for frame_opt in frames_iter.next() {
106+
let loc_opt = frame_opt.and_then(|v| v.location);
107+
let file_line_opt = loc_opt.map(|v| (v.file, v.line));
108+
if let Some((Some(file), Some(line))) = file_line_opt {
109+
f(file.as_bytes(), line as u32)?;
110+
}
111+
}
112+
// FIXME: when should we return true here?
113+
Ok(false)
114+
})
115+
}
116+
117+
/// Converts a pointer to symbol to its string value.
118+
pub fn resolve_symname<F>(frame: Frame,
119+
callback: F,
120+
_: &BacktraceContext) -> io::Result<()>
121+
where F: FnOnce(Option<&str>) -> io::Result<()>
122+
{
123+
Ctx::with_static(|ctx|{
124+
let mut frames_iter = match ctx.ctx.find_frames(frame.symbol_addr as u64) {
125+
Ok(v) => v,
126+
Err(_) => err!("error during binary parsing"),
127+
};
128+
let frame_opt = match frames_iter.next() {
129+
Ok(v) => v,
130+
Err(_) => err!("error during symbolification"),
131+
};
132+
match frame_opt.and_then(|v| v.function) {
133+
Some(n) => match n.raw_name() {
134+
Ok(v) => callback(Some(&*v))?,
135+
Err(_) => err!("error during name resolval"),
136+
},
137+
None => callback(None)?,
138+
}
139+
Ok(())
140+
})
141+
}

src/libstd/sys_common/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,13 @@ cfg_if! {
6666
}
6767

6868
#[cfg(feature = "backtrace")]
69-
#[cfg(any(all(unix, not(target_os = "emscripten")),
70-
all(windows, target_env = "gnu"),
71-
target_os = "redox"))]
69+
#[cfg(target_os = "fuchsia")]
7270
pub mod gnu;
7371

72+
#[cfg(feature = "backtrace")]
73+
#[cfg(not(target_os = "fuchsia"))]
74+
pub mod addr2line;
75+
7476
// common error constructors
7577

7678
/// A trait for viewing representations from std types

0 commit comments

Comments
 (0)