about summary refs log tree commit diff
path: root/src/libstd/sys_common/gnu
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2019-05-15 07:30:15 -0700
committerAlex Crichton <alex@alexcrichton.com>2019-05-25 17:09:45 -0700
commitd1040fe329a8db99ae0aae47975830a0829d7792 (patch)
tree18357e26a9a8ece5f85cf8b77d9a1f1f174ff5cb /src/libstd/sys_common/gnu
parent02f5786a324c40b2d8b2d0df98456e48fb45d30c (diff)
downloadrust-d1040fe329a8db99ae0aae47975830a0829d7792.tar.gz
rust-d1040fe329a8db99ae0aae47975830a0829d7792.zip
std: Depend on `backtrace` crate from crates.io
This commit removes all in-tree support for generating backtraces in
favor of depending on the `backtrace` crate on crates.io. This resolves
a very longstanding piece of duplication where the standard library has
long contained the ability to generate a backtrace on panics, but the
code was later extracted and duplicated on crates.io with the
`backtrace` crate. Since that fork each implementation has seen various
improvements one way or another, but typically `backtrace`-the-crate has
lagged behind libstd in one way or another.

The goal here is to remove this duplication of a fairly critical piece
of code and ensure that there's only one source of truth for generating
backtraces between the standard library and the crate on crates.io.
Recently I've been working to bring the `backtrace` crate on crates.io
up to speed with the support in the standard library which includes:

* Support for `StackWalkEx` on MSVC to recover inline frames with
  debuginfo.
* Using `libbacktrace` by default on MinGW targets.
* Supporting `libbacktrace` on OSX as an option.
* Ensuring all the requisite support in `backtrace`-the-crate compiles
  with `#![no_std]`.
* Updating the `libbacktrace` implementation in `backtrace`-the-crate to
  initialize the global state with the correct filename where necessary.

After reviewing the code in libstd the `backtrace` crate should be at
exact feature parity with libstd today. The backtraces generated should
have the same symbols and same number of frames in general, and there's
not known divergence from libstd currently.

Note that one major difference between libstd's backtrace support and
the `backtrace` crate is that on OSX the crates.io crate enables the
`coresymbolication` feature by default. This feature, however, uses
private internal APIs that aren't published for OSX. While they provide
more accurate backtraces this isn't appropriate for libstd distributed
as a binary, so libstd's dependency on the `backtrace` crate explicitly
disables this feature and forces OSX to use `libbacktrace` as a
symbolication strategy.

The long-term goal of this refactoring is to eventually move us towards
a world where we can drop `libbacktrace` entirely and simply use Gimli
and the surrounding crates for backtrace support. That's still aways off
but hopefully will much more easily enabled by having the source of
truth for backtraces live in crates.io!

Procedurally if we go forward with this I'd like to transfer the
`backtrace-rs` crate to the rust-lang GitHub organization as well, but I
figured I'd hold off on that until we get closer to merging.
Diffstat (limited to 'src/libstd/sys_common/gnu')
-rw-r--r--src/libstd/sys_common/gnu/libbacktrace.rs175
-rw-r--r--src/libstd/sys_common/gnu/mod.rs5
2 files changed, 0 insertions, 180 deletions
diff --git a/src/libstd/sys_common/gnu/libbacktrace.rs b/src/libstd/sys_common/gnu/libbacktrace.rs
deleted file mode 100644
index 6cd050242dd..00000000000
--- a/src/libstd/sys_common/gnu/libbacktrace.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-use backtrace_sys::backtrace_state;
-
-use crate::ffi::CStr;
-use crate::io;
-use crate::mem;
-use crate::ptr;
-use crate::sys::backtrace::BacktraceContext;
-use crate::sys_common::backtrace::Frame;
-
-pub fn foreach_symbol_fileline<F>(frame: Frame,
-                                  mut f: F,
-                                  _: &BacktraceContext) -> io::Result<bool>
-where F: FnMut(&[u8], u32) -> io::Result<()>
-{
-    // pcinfo may return an arbitrary number of file:line pairs,
-    // in the order of stack trace (i.e., inlined calls first).
-    // in order to avoid allocation, we stack-allocate a fixed size of entries.
-    const FILELINE_SIZE: usize = 32;
-    let mut fileline_buf = [(ptr::null(), !0); FILELINE_SIZE];
-    let ret;
-    let fileline_count = {
-        let state = unsafe { init_state() };
-        if state.is_null() {
-            return Err(io::Error::new(
-                io::ErrorKind::Other,
-                "failed to allocate libbacktrace state")
-            )
-        }
-        let mut fileline_win: &mut [FileLine] = &mut fileline_buf;
-        let fileline_addr = &mut fileline_win as *mut &mut [FileLine];
-        ret = unsafe {
-            backtrace_sys::backtrace_pcinfo(
-                state,
-                frame.exact_position as libc::uintptr_t,
-                pcinfo_cb,
-                error_cb,
-                fileline_addr as *mut libc::c_void,
-            )
-        };
-        FILELINE_SIZE - fileline_win.len()
-    };
-    if ret == 0 {
-        for &(file, line) in &fileline_buf[..fileline_count] {
-            if file.is_null() { continue; } // just to be sure
-            let file = unsafe { CStr::from_ptr(file).to_bytes() };
-            f(file, line)?;
-        }
-        Ok(fileline_count == FILELINE_SIZE)
-    } else {
-        Ok(false)
-    }
-}
-
-/// Converts a pointer to symbol to its string value.
-pub fn resolve_symname<F>(frame: Frame,
-                          callback: F,
-                          _: &BacktraceContext) -> io::Result<()>
-    where F: FnOnce(Option<&str>) -> io::Result<()>
-{
-    let symname = {
-        let state = unsafe { init_state() };
-        if state.is_null() {
-            return Err(io::Error::new(
-                io::ErrorKind::Other,
-                "failed to allocate libbacktrace state")
-            )
-        }
-        let mut data: *const libc::c_char = ptr::null();
-        let data_addr = &mut data as *mut *const libc::c_char;
-        let ret = unsafe {
-            backtrace_sys::backtrace_syminfo(
-                state,
-                frame.symbol_addr as libc::uintptr_t,
-                syminfo_cb,
-                error_cb,
-                data_addr as *mut libc::c_void,
-            )
-        };
-        if ret == 0 || data.is_null() {
-            None
-        } else {
-            unsafe {
-                CStr::from_ptr(data).to_str().ok()
-            }
-        }
-    };
-    callback(symname)
-}
-
-////////////////////////////////////////////////////////////////////////
-// helper callbacks
-////////////////////////////////////////////////////////////////////////
-
-type FileLine = (*const libc::c_char, u32);
-
-extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char,
-                   _errnum: libc::c_int) {
-    // do nothing for now
-}
-extern fn syminfo_cb(data: *mut libc::c_void,
-                     _pc: libc::uintptr_t,
-                     symname: *const libc::c_char,
-                     _symval: libc::uintptr_t,
-                     _symsize: libc::uintptr_t) {
-    let slot = data as *mut *const libc::c_char;
-    unsafe { *slot = symname; }
-}
-extern fn pcinfo_cb(data: *mut libc::c_void,
-                    _pc: libc::uintptr_t,
-                    filename: *const libc::c_char,
-                    lineno: libc::c_int,
-                    _function: *const libc::c_char) -> libc::c_int {
-    if !filename.is_null() {
-        let slot = data as *mut &mut [FileLine];
-        let buffer = unsafe {ptr::read(slot)};
-
-        // if the buffer is not full, add file:line to the buffer
-        // and adjust the buffer for next possible calls to pcinfo_cb.
-        if !buffer.is_empty() {
-            buffer[0] = (filename, lineno as u32);
-            unsafe { ptr::write(slot, &mut buffer[1..]); }
-        }
-    }
-
-    0
-}
-
-// The libbacktrace API supports creating a state, but it does not
-// support destroying a state. I personally take this to mean that a
-// state is meant to be created and then live forever.
-//
-// I would love to register an at_exit() handler which cleans up this
-// state, but libbacktrace provides no way to do so.
-//
-// With these constraints, this function has a statically cached state
-// that is calculated the first time this is requested. Remember that
-// backtracing all happens serially (one global lock).
-//
-// Things don't work so well on not-Linux since libbacktrace can't track
-// down that executable this is. We at one point used env::current_exe but
-// it turns out that there are some serious security issues with that
-// approach.
-//
-// Specifically, on certain platforms like BSDs, a malicious actor can cause
-// an arbitrary file to be placed at the path returned by current_exe.
-// libbacktrace does not behave defensively in the presence of ill-formed
-// DWARF information, and has been demonstrated to segfault in at least one
-// case. There is no evidence at the moment to suggest that a more carefully
-// constructed file can't cause arbitrary code execution. As a result of all
-// of this, we don't hint libbacktrace with the path to the current process.
-unsafe fn init_state() -> *mut backtrace_state {
-    static mut STATE: *mut backtrace_state = ptr::null_mut();
-    if !STATE.is_null() { return STATE  }
-
-    let filename = match crate::sys::backtrace::gnu::get_executable_filename() {
-        Ok((filename, file)) => {
-            // filename is purposely leaked here since libbacktrace requires
-            // it to stay allocated permanently, file is also leaked so that
-            // the file stays locked
-            let filename_ptr = filename.as_ptr();
-            mem::forget(filename);
-            mem::forget(file);
-            filename_ptr
-        },
-        Err(_) => ptr::null(),
-    };
-
-    STATE = backtrace_sys::backtrace_create_state(
-        filename,
-        0,
-        error_cb,
-        ptr::null_mut(),
-    );
-    STATE
-}
diff --git a/src/libstd/sys_common/gnu/mod.rs b/src/libstd/sys_common/gnu/mod.rs
deleted file mode 100644
index d6959697f2a..00000000000
--- a/src/libstd/sys_common/gnu/mod.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![allow(missing_docs)]
-#![allow(non_camel_case_types)]
-#![allow(non_snake_case)]
-
-pub mod libbacktrace;