diff options
| author | bors <bors@rust-lang.org> | 2017-08-15 19:27:29 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-08-15 19:27:29 +0000 |
| commit | f25c2283b3f8a7518b2f83a252b50d29d9bfbfda (patch) | |
| tree | 81e0cf4ecfa74ef8b45750580d7b02172a7e8d70 /src/libstd/sys | |
| parent | 82be83cf744611a016fb09ae1afbffc04b3ed2e1 (diff) | |
| parent | 9d67d5a71dafe105167acf0e8b960f5aa118652b (diff) | |
| download | rust-f25c2283b3f8a7518b2f83a252b50d29d9bfbfda.tar.gz rust-f25c2283b3f8a7518b2f83a252b50d29d9bfbfda.zip | |
Auto merge of #43635 - ids1024:backtrace-redox, r=alexcrichton
Make backtraces work on Redox, copying Unix implementation The `backtrace/` directory here is the same as the Unix one, except for adding an implementation of `get_executable_filename`.
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/redox/backtrace.rs | 32 | ||||
| -rw-r--r-- | src/libstd/sys/redox/backtrace/mod.rs | 42 | ||||
| -rw-r--r-- | src/libstd/sys/redox/backtrace/printing.rs | 11 | ||||
| -rw-r--r-- | src/libstd/sys/redox/backtrace/tracing.rs | 106 |
4 files changed, 159 insertions, 32 deletions
diff --git a/src/libstd/sys/redox/backtrace.rs b/src/libstd/sys/redox/backtrace.rs deleted file mode 100644 index 6cafe3e69ba..00000000000 --- a/src/libstd/sys/redox/backtrace.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use io; -use sys_common::backtrace::Frame; - -pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname}; -pub struct BacktraceContext; - -#[inline(never)] -pub fn unwind_backtrace(_frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ - Ok((0, BacktraceContext)) -} - -pub mod gnu { - use io; - use fs; - use libc::c_char; - - pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> { - Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) - } -} diff --git a/src/libstd/sys/redox/backtrace/mod.rs b/src/libstd/sys/redox/backtrace/mod.rs new file mode 100644 index 00000000000..40b957d847b --- /dev/null +++ b/src/libstd/sys/redox/backtrace/mod.rs @@ -0,0 +1,42 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// See sys/unix/backtrace/mod.rs for an explanation of the method used here. + +pub use self::tracing::unwind_backtrace; +pub use self::printing::{foreach_symbol_fileline, resolve_symname}; + +// tracing impls: +mod tracing; +// symbol resolvers: +mod printing; + +pub mod gnu { + use io; + use fs; + use libc::c_char; + use vec::Vec; + use ffi::OsStr; + use os::unix::ffi::OsStrExt; + use io::Read; + + pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> { + let mut exefile = fs::File::open("sys:exe")?; + let mut exename = Vec::new(); + exefile.read_to_end(&mut exename)?; + if exename.last() == Some(&b'\n') { + exename.pop(); + } + let file = fs::File::open(OsStr::from_bytes(&exename))?; + Ok((exename.into_iter().map(|c| c as c_char).collect(), file)) + } +} + +pub struct BacktraceContext; diff --git a/src/libstd/sys/redox/backtrace/printing.rs b/src/libstd/sys/redox/backtrace/printing.rs new file mode 100644 index 00000000000..3e937dbe623 --- /dev/null +++ b/src/libstd/sys/redox/backtrace/printing.rs @@ -0,0 +1,11 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname}; diff --git a/src/libstd/sys/redox/backtrace/tracing.rs b/src/libstd/sys/redox/backtrace/tracing.rs new file mode 100644 index 00000000000..cfeabaddda9 --- /dev/null +++ b/src/libstd/sys/redox/backtrace/tracing.rs @@ -0,0 +1,106 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use error::Error; +use io; +use libc; +use sys::backtrace::BacktraceContext; +use sys_common::backtrace::Frame; + +use unwind as uw; + +struct Context<'a> { + idx: usize, + frames: &'a mut [Frame], +} + +#[derive(Debug)] +struct UnwindError(uw::_Unwind_Reason_Code); + +impl Error for UnwindError { + fn description(&self) -> &'static str { + "unexpected return value while unwinding" + } +} + +impl ::fmt::Display for UnwindError { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + write!(f, "{}: {:?}", self.description(), self.0) + } +} + +#[inline(never)] // if we know this is a function call, we can skip it when + // tracing +pub fn unwind_backtrace(frames: &mut [Frame]) + -> io::Result<(usize, BacktraceContext)> +{ + let mut cx = Context { + idx: 0, + frames: frames, + }; + let result_unwind = unsafe { + uw::_Unwind_Backtrace(trace_fn, + &mut cx as *mut Context + as *mut libc::c_void) + }; + // See libunwind:src/unwind/Backtrace.c for the return values. + // No, there is no doc. + match result_unwind { + // These return codes seem to be benign and need to be ignored for backtraces + // to show up properly on all tested platforms. + uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => { + Ok((cx.idx, BacktraceContext)) + } + _ => { + Err(io::Error::new(io::ErrorKind::Other, + UnwindError(result_unwind))) + } + } +} + +extern fn trace_fn(ctx: *mut uw::_Unwind_Context, + arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code { + let cx = unsafe { &mut *(arg as *mut Context) }; + let mut ip_before_insn = 0; + let mut ip = unsafe { + uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void + }; + if !ip.is_null() && ip_before_insn == 0 { + // this is a non-signaling frame, so `ip` refers to the address + // after the calling instruction. account for that. + ip = (ip as usize - 1) as *mut _; + } + + // dladdr() on osx gets whiny when we use FindEnclosingFunction, and + // it appears to work fine without it, so we only use + // FindEnclosingFunction on non-osx platforms. In doing so, we get a + // slightly more accurate stack trace in the process. + // + // This is often because panic involves the last instruction of a + // function being "call std::rt::begin_unwind", with no ret + // instructions after it. This means that the return instruction + // pointer points *outside* of the calling function, and by + // unwinding it we go back to the original function. + let symaddr = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { + ip + } else { + unsafe { uw::_Unwind_FindEnclosingFunction(ip) } + }; + + if cx.idx < cx.frames.len() { + cx.frames[cx.idx] = Frame { + symbol_addr: symaddr, + exact_position: ip, + }; + cx.idx += 1; + } + + uw::_URC_NO_REASON +} |
