Auto merge of #44251 - kennytm:osx-backtrace, r=alexcrichton
Add libbacktrace support for Apple platforms (resubmitted) Resubmitting #43422 rebased on the current master (cc @JohnColanduoni). I have added an additional commit to fallback to `dladdr`-based `resolve_symbol` if `libbacktrace` returns `None`, otherwise the stack trace will be full of `<unknown>` when you forget to pass the `-g` flag (actually it seems — at least on macOS — the `dladdr` symbol is more accurate than the `libbacktrace` one).
This commit is contained in:
3
src/libbacktrace/configure
vendored
3
src/libbacktrace/configure
vendored
@@ -11844,6 +11844,9 @@ elf*) FORMAT_FILE="elf.lo" ;;
|
|||||||
pecoff) FORMAT_FILE="pecoff.lo"
|
pecoff) FORMAT_FILE="pecoff.lo"
|
||||||
backtrace_supports_data=no
|
backtrace_supports_data=no
|
||||||
;;
|
;;
|
||||||
|
macho*) FORMAT_FILE="macho.lo"
|
||||||
|
backtrace_supports_data=no
|
||||||
|
;;
|
||||||
*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not determine output file type" >&5
|
*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not determine output file type" >&5
|
||||||
$as_echo "$as_me: WARNING: could not determine output file type" >&2;}
|
$as_echo "$as_me: WARNING: could not determine output file type" >&2;}
|
||||||
FORMAT_FILE="unknown.lo"
|
FORMAT_FILE="unknown.lo"
|
||||||
|
|||||||
@@ -231,6 +231,9 @@ elf*) FORMAT_FILE="elf.lo" ;;
|
|||||||
pecoff) FORMAT_FILE="pecoff.lo"
|
pecoff) FORMAT_FILE="pecoff.lo"
|
||||||
backtrace_supports_data=no
|
backtrace_supports_data=no
|
||||||
;;
|
;;
|
||||||
|
macho*) FORMAT_FILE="macho.lo"
|
||||||
|
backtrace_supports_data=no
|
||||||
|
;;
|
||||||
*) AC_MSG_WARN([could not determine output file type])
|
*) AC_MSG_WARN([could not determine output file type])
|
||||||
FORMAT_FILE="unknown.lo"
|
FORMAT_FILE="unknown.lo"
|
||||||
backtrace_supported=no
|
backtrace_supported=no
|
||||||
|
|||||||
@@ -3,3 +3,9 @@
|
|||||||
/\177ELF\002/ { if (NR == 1) { print "elf64"; exit } }
|
/\177ELF\002/ { if (NR == 1) { print "elf64"; exit } }
|
||||||
/\114\001/ { if (NR == 1) { print "pecoff"; exit } }
|
/\114\001/ { if (NR == 1) { print "pecoff"; exit } }
|
||||||
/\144\206/ { if (NR == 1) { print "pecoff"; exit } }
|
/\144\206/ { if (NR == 1) { print "pecoff"; exit } }
|
||||||
|
/\xFE\xED\xFA\xCE/ { if (NR == 1) { print "macho32"; exit } }
|
||||||
|
/\xCE\xFA\xED\xFE/ { if (NR == 1) { print "macho32"; exit } }
|
||||||
|
/\xFE\xED\xFA\xCF/ { if (NR == 1) { print "macho64"; exit } }
|
||||||
|
/\xCF\xFA\xED\xFE/ { if (NR == 1) { print "macho64"; exit } }
|
||||||
|
/\xCA\xFE\xBA\xBE/ { if (NR == 1) { print "macho-fat"; exit } }
|
||||||
|
/\xBE\xBA\xFE\xCA/ { if (NR == 1) { print "macho-fat"; exit } }
|
||||||
|
|||||||
1416
src/libbacktrace/macho.c
Normal file
1416
src/libbacktrace/macho.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@ use build_helper::{run, native_lib_boilerplate};
|
|||||||
fn main() {
|
fn main() {
|
||||||
let target = env::var("TARGET").expect("TARGET was not set");
|
let target = env::var("TARGET").expect("TARGET was not set");
|
||||||
let host = env::var("HOST").expect("HOST was not set");
|
let host = env::var("HOST").expect("HOST was not set");
|
||||||
if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
|
if cfg!(feature = "backtrace") && !target.contains("msvc") &&
|
||||||
!target.contains("emscripten") && !target.contains("fuchsia") {
|
!target.contains("emscripten") && !target.contains("fuchsia") {
|
||||||
let _ = build_libbacktrace(&host, &target);
|
let _ = build_libbacktrace(&host, &target);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,15 +91,29 @@ mod tracing;
|
|||||||
// symbol resolvers:
|
// symbol resolvers:
|
||||||
mod printing;
|
mod printing;
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "emscripten")))]
|
#[cfg(not(target_os = "emscripten"))]
|
||||||
pub mod gnu {
|
pub mod gnu {
|
||||||
use io;
|
use io;
|
||||||
use fs;
|
use fs;
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
|
||||||
pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
|
pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "Not implemented"))
|
Err(io::Error::new(io::ErrorKind::Other, "Not implemented"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
|
pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> {
|
||||||
|
use env;
|
||||||
|
use os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
|
let filename = env::current_exe()?;
|
||||||
|
let file = fs::File::open(&filename)?;
|
||||||
|
let mut filename_cstr: Vec<_> = filename.as_os_str().as_bytes().iter()
|
||||||
|
.map(|&x| x as c_char).collect();
|
||||||
|
filename_cstr.push(0); // Null terminate
|
||||||
|
Ok((filename_cstr, file))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BacktraceContext;
|
pub struct BacktraceContext;
|
||||||
|
|||||||
@@ -31,14 +31,6 @@ pub fn resolve_symname<F>(frame: Frame,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn foreach_symbol_fileline<F>(_symbol_addr: Frame,
|
|
||||||
_f: F,
|
|
||||||
_: &BacktraceContext) -> io::Result<bool>
|
|
||||||
where F: FnMut(&[u8], libc::c_int) -> io::Result<()>
|
|
||||||
{
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct Dl_info {
|
struct Dl_info {
|
||||||
dli_fname: *const libc::c_char,
|
dli_fname: *const libc::c_char,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
|
// Copyright 2014-2017 The Rust Project Developers. See the COPYRIGHT
|
||||||
// file at the top-level directory of this distribution and at
|
// file at the top-level directory of this distribution and at
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
//
|
//
|
||||||
@@ -8,15 +8,36 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
pub use self::imp::{foreach_symbol_fileline, resolve_symname};
|
mod dladdr;
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios",
|
use sys::backtrace::BacktraceContext;
|
||||||
target_os = "emscripten"))]
|
use sys_common::backtrace::Frame;
|
||||||
#[path = "dladdr.rs"]
|
use io;
|
||||||
mod imp;
|
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "macos", target_os = "ios",
|
#[cfg(target_os = "emscripten")]
|
||||||
target_os = "emscripten")))]
|
pub use self::dladdr::resolve_symname;
|
||||||
mod imp {
|
|
||||||
pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname};
|
#[cfg(target_os = "emscripten")]
|
||||||
|
pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool>
|
||||||
|
where
|
||||||
|
F: FnMut(&[u8], ::libc::c_int) -> io::Result<()>
|
||||||
|
{
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "emscripten"))]
|
||||||
|
pub use sys_common::gnu::libbacktrace::foreach_symbol_fileline;
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "emscripten"))]
|
||||||
|
pub fn resolve_symname<F>(frame: Frame, callback: F, bc: &BacktraceContext) -> io::Result<()>
|
||||||
|
where
|
||||||
|
F: FnOnce(Option<&str>) -> io::Result<()>
|
||||||
|
{
|
||||||
|
::sys_common::gnu::libbacktrace::resolve_symname(frame, |symname| {
|
||||||
|
if symname.is_some() {
|
||||||
|
callback(symname)
|
||||||
|
} else {
|
||||||
|
dladdr::resolve_symname(frame, callback, bc)
|
||||||
|
}
|
||||||
|
}, bc)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ pub use sys::net;
|
|||||||
pub mod net;
|
pub mod net;
|
||||||
|
|
||||||
#[cfg(feature = "backtrace")]
|
#[cfg(feature = "backtrace")]
|
||||||
#[cfg(any(all(unix, not(any(target_os = "macos", target_os = "ios", target_os = "emscripten"))),
|
#[cfg(any(all(unix, not(target_os = "emscripten")),
|
||||||
all(windows, target_env = "gnu"),
|
all(windows, target_env = "gnu"),
|
||||||
target_os = "redox"))]
|
target_os = "redox"))]
|
||||||
pub mod gnu;
|
pub mod gnu;
|
||||||
|
|||||||
@@ -33,9 +33,7 @@ macro_rules! dump_and_die {
|
|||||||
($($pos:expr),*) => ({
|
($($pos:expr),*) => ({
|
||||||
// FIXME(#18285): we cannot include the current position because
|
// FIXME(#18285): we cannot include the current position because
|
||||||
// the macro span takes over the last frame's file/line.
|
// the macro span takes over the last frame's file/line.
|
||||||
if cfg!(any(target_os = "macos",
|
if cfg!(any(target_os = "android",
|
||||||
target_os = "ios",
|
|
||||||
target_os = "android",
|
|
||||||
all(target_os = "linux", target_arch = "arm"),
|
all(target_os = "linux", target_arch = "arm"),
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
target_os = "dragonfly",
|
target_os = "dragonfly",
|
||||||
|
|||||||
Reference in New Issue
Block a user