Add basic backtrace functionality

Whenever a failure happens, if a program is run with
`RUST_LOG=std::rt::backtrace` a backtrace will be printed to the task's stderr
handle. Stack traces are uncondtionally printed on double-failure and
rtabort!().

This ended up having a nontrivial implementation, and here's some highlights of
it:

* We're bundling libbacktrace for everything but OSX and Windows
* We use libgcc_s and its libunwind apis to get a backtrace of instruction
  pointers
* On OSX we use dladdr() to go from an instruction pointer to a symbol
* On unix that isn't OSX, we use libbacktrace to get symbols
* Windows, as usual, has an entirely separate implementation

Lots more fun details and comments can be found in the source itself.

Closes #10128
This commit is contained in:
Alex Crichton
2014-02-05 15:19:40 -08:00
parent 9a21b90077
commit 829df69f9f
9 changed files with 1094 additions and 101 deletions

View File

@@ -12,6 +12,7 @@ use container::Container;
use fmt;
use from_str::FromStr;
use io::IoResult;
use io;
use iter::Iterator;
use libc;
use option::{Some, None, Option};
@@ -70,20 +71,20 @@ pub fn default_sched_threads() -> uint {
}
}
pub fn dumb_println(args: &fmt::Arguments) {
use io;
pub struct Stderr;
struct Stderr;
impl io::Writer for Stderr {
fn write(&mut self, data: &[u8]) -> IoResult<()> {
unsafe {
libc::write(libc::STDERR_FILENO,
data.as_ptr() as *libc::c_void,
data.len() as libc::size_t);
}
Ok(()) // yes, we're lying
impl io::Writer for Stderr {
fn write(&mut self, data: &[u8]) -> IoResult<()> {
unsafe {
libc::write(libc::STDERR_FILENO,
data.as_ptr() as *libc::c_void,
data.len() as libc::size_t);
}
Ok(()) // yes, we're lying
}
}
pub fn dumb_println(args: &fmt::Arguments) {
let mut w = Stderr;
let _ = fmt::writeln(&mut w as &mut io::Writer, args);
}
@@ -140,6 +141,10 @@ memory and partly incapable of presentation to others.",
rterrln!("{}", "");
rterrln!("fatal runtime error: {}", msg);
{
let mut err = Stderr;
let _err = ::rt::backtrace::write(&mut err);
}
abort();
fn abort() -> ! {