Skip to content

no_std support #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ description = """
A library to acquire a stack trace (backtrace) at runtime in a Rust program.
"""
[dependencies]
libc = "0.2"
libc = { version = "0.2", default-features = false }
cfg-if = "0.1"
rustc-demangle = "0.1.4"

# Optionally enable the ability to serialize a `Backtrace`
serde = { version = "1.0", optional = true }
serde = { version = "1.0", optional = true, default-features = false }
serde_derive = { version = "1.0", optional = true }
rustc-serialize = { version = "0.3", optional = true }

Expand All @@ -27,7 +27,7 @@ cpp_demangle = { version = "0.2", optional = true }
[target.'cfg(windows)'.dependencies]
dbghelp-sys = { version = "0.2", optional = true }
kernel32-sys = { version = "0.2", optional = true }
winapi = { version = "0.2.5", optional = true }
winapi = { version = "0.2.5", optional = true, default-features = false }

[target.'cfg(all(unix, not(target_os = "emscripten"), not(target_os = "macos"), not(target_os = "ios")))'.dependencies]
backtrace-sys = { path = "backtrace-sys", version = "0.1.3", optional = true }
Expand All @@ -41,7 +41,9 @@ backtrace-sys = { path = "backtrace-sys", version = "0.1.3", optional = true }
# Note that not all features are available on all platforms, so even though a
# feature is enabled some other feature may be used instead.
[features]
default = ["libunwind", "libbacktrace", "coresymbolication", "dladdr", "dbghelp", "cpp_demangle"]
default = ["std", "libunwind", "libbacktrace", "coresymbolication", "dladdr", "dbghelp", "cpp_demangle"]

std = []

#=======================================
# Methods of acquiring a backtrace
Expand Down
2 changes: 1 addition & 1 deletion backtrace-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Bindings to the libbacktrace gcc library
"""

[dependencies]
libc = "0.2"
libc = { version = "0.2", default-features = false }

[build-dependencies]
gcc = "0.3"
2 changes: 1 addition & 1 deletion backtrace-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
extern crate libc;

use libc::uintptr_t;
use std::os::raw::{c_void, c_char, c_int};
use libc::{c_void, c_char, c_int};

pub type backtrace_syminfo_callback =
extern fn(data: *mut c_void,
Expand Down
2 changes: 1 addition & 1 deletion src/backtrace/dbghelp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#![allow(bad_style)]

use std::mem;
use core::mem;
use winapi::*;
use kernel32;

Expand Down
5 changes: 2 additions & 3 deletions src/backtrace/libunwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::os::raw::c_void;
use libc::c_void;

pub struct Frame {
ctx: *mut uw::_Unwind_Context,
Expand Down Expand Up @@ -83,8 +83,7 @@ pub fn trace(mut cb: &mut FnMut(&super::Frame) -> bool) {
mod uw {
pub use self::_Unwind_Reason_Code::*;

use libc;
use std::os::raw::{c_int, c_void};
use libc::{self, c_int, c_void};

#[repr(C)]
pub enum _Unwind_Reason_Code {
Expand Down
5 changes: 2 additions & 3 deletions src/backtrace/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::fmt;

use std::os::raw::c_void;
use lib::fmt;
use libc::c_void;

/// Inspects the current call-stack, passing all active frames into the closure
/// provided to calculate a stack trace.
Expand Down
2 changes: 1 addition & 1 deletion src/backtrace/noop.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::os::raw::c_void;
use libc::c_void;

#[inline(always)]
pub fn trace(_cb: &mut FnMut(&super::Frame) -> bool) {}
Expand Down
4 changes: 2 additions & 2 deletions src/backtrace/unix_backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem;
use std::os::raw::{c_void, c_int};
use lib::mem;
use libc::{c_void, c_int};

pub struct Frame {
addr: *mut c_void,
Expand Down
28 changes: 21 additions & 7 deletions src/capture.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use std::fmt;
use std::mem;
use std::os::raw::c_void;
#[cfg(feature = "std")]
use lib::fmt;
#[cfg(feature = "std")]
use lib::mem;
use libc::c_void;
#[cfg(feature = "std")]
use std::path::{Path, PathBuf};

#[cfg(feature = "std")]
use {trace, resolve, SymbolName};

/// Representation of an owned and self-contained backtrace.
Expand All @@ -12,6 +16,7 @@ use {trace, resolve, SymbolName};
#[derive(Clone)]
#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))]
#[cfg(feature = "std")]
pub struct Backtrace {
frames: Vec<BacktraceFrame>,
}
Expand All @@ -26,6 +31,7 @@ pub struct Backtrace {
pub struct BacktraceFrame {
ip: usize,
symbol_address: usize,
#[cfg(feature = "std")]
symbols: Vec<BacktraceSymbol>,
}

Expand All @@ -37,12 +43,15 @@ pub struct BacktraceFrame {
#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
#[cfg_attr(feature = "serialize-serde", derive(Deserialize, Serialize))]
pub struct BacktraceSymbol {
name: Option<Vec<u8>>,
addr: Option<usize>,
filename: Option<PathBuf>,
lineno: Option<u32>,
#[cfg(feature = "std")]
name: Option<Vec<u8>>,
#[cfg(feature = "std")]
filename: Option<PathBuf>,
}

#[cfg(feature = "std")]
impl Backtrace {
/// Captures a backtrace at the callsite of this function, returning an
/// owned representation.
Expand Down Expand Up @@ -92,6 +101,7 @@ impl Backtrace {
}
}

#[cfg(feature = "std")]
impl From<Vec<BacktraceFrame>> for Backtrace {
fn from(frames: Vec<BacktraceFrame>) -> Self {
Backtrace {
Expand All @@ -100,6 +110,7 @@ impl From<Vec<BacktraceFrame>> for Backtrace {
}
}

#[cfg(feature = "std")]
impl Into<Vec<BacktraceFrame>> for Backtrace {
fn into(self) -> Vec<BacktraceFrame> {
self.frames
Expand All @@ -116,22 +127,22 @@ impl BacktraceFrame {
pub fn symbol_address(&self) -> *mut c_void {
self.symbol_address as *mut c_void
}
}

impl BacktraceFrame {
/// Returns the list of symbols that this frame corresponds to.
///
/// Normally there is only one symbol per frame, but sometimes if a number
/// of functions are inlined into one frame then multiple symbols will be
/// returned. The first symbol listed is the "innermost function", whereas
/// the last symbol is the outermost (last caller).
#[cfg(feature = "std")]
pub fn symbols(&self) -> &[BacktraceSymbol] {
&self.symbols
}
}

impl BacktraceSymbol {
/// Same as `Symbol::name`
#[cfg(feature = "std")]
pub fn name(&self) -> Option<SymbolName> {
self.name.as_ref().map(|s| SymbolName::new(s))
}
Expand All @@ -142,6 +153,7 @@ impl BacktraceSymbol {
}

/// Same as `Symbol::filename`
#[cfg(feature = "std")]
pub fn filename(&self) -> Option<&Path> {
self.filename.as_ref().map(|p| &**p)
}
Expand All @@ -152,6 +164,7 @@ impl BacktraceSymbol {
}
}

#[cfg(feature = "std")]
impl fmt::Debug for Backtrace {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let hex_width = mem::size_of::<usize>() * 2 + 2;
Expand Down Expand Up @@ -187,6 +200,7 @@ impl fmt::Debug for Backtrace {
}
}

#[cfg(feature = "std")]
impl Default for Backtrace {
fn default() -> Backtrace {
Backtrace::new()
Expand Down
26 changes: 20 additions & 6 deletions src/dylib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::ffi::CString;
use std::marker;
use std::mem;
use std::sync::atomic::{AtomicUsize, Ordering};
use lib::marker;
use lib::mem;
use lib::sync::atomic::{AtomicUsize, Ordering};

use libc::{self, c_char, c_void};

Expand All @@ -22,12 +21,27 @@ impl Dylib {
})
}

#[cfg(feature = "std")]
unsafe fn dlopen(path: &str) -> *mut libc::c_void {
let name = ::std::ffi::CString::new(path).unwrap();
libc::dlopen(name.as_ptr() as *const c_char, libc::RTLD_LAZY)
}

#[cfg(not(feature = "std"))]
unsafe fn dlopen(path: &str) -> *mut libc::c_void {
use lib::ptr;
assert!(path.len() + 1 < ::BUF.len());
let buf_ptr = ::BUF.as_ptr() as *const u8;
ptr::write(buf_ptr as *mut _, path);
ptr::write(buf_ptr.offset(path.len() as isize) as *mut u8, 0);
libc::dlopen(buf_ptr as *const c_char, libc::RTLD_LAZY)
}

pub unsafe fn init(&self, path: &str) -> bool {
if self.init.load(Ordering::SeqCst) != 0 {
return true
}
let name = CString::new(path).unwrap();
let ptr = libc::dlopen(name.as_ptr() as *const c_char, libc::RTLD_LAZY);
let ptr = Dylib::dlopen(path);
if ptr.is_null() {
return false
}
Expand Down
40 changes: 39 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
//! }
//! ```

#![cfg_attr(not(feature = "std"), no_std)]

#![doc(html_root_url = "http://alexcrichton.com/backtrace-rs")]
#![deny(missing_docs)]
#![deny(warnings)]
Expand Down Expand Up @@ -92,6 +94,29 @@ extern crate rustc_demangle;
#[cfg(feature = "cpp_demangle")]
extern crate cpp_demangle;

mod lib {
#[cfg(feature = "std")]
pub use std::*;
#[cfg(not(feature = "std"))]
pub use core::*;
}

mod helpers {
use libc;
use lib::slice;

pub unsafe fn make_slice<'a>(ptr: *const u8) -> &'a [u8] {
let len = libc::strlen(ptr as *const i8);
slice::from_raw_parts(ptr, len as usize + 1)
}
}

#[cfg(not(feature = "std"))]
#[allow(unused)]
static mut BUF: [u8; 1024] = [0; 1024];

const INVALID_UTF8_SYMBOL: &str = "<not valid utf-8 for symbol>";

#[allow(dead_code)] // not used everywhere
#[cfg(unix)]
#[macro_use]
Expand All @@ -103,7 +128,9 @@ mod backtrace;
pub use symbolize::{resolve, Symbol, SymbolName};
mod symbolize;

pub use capture::{Backtrace, BacktraceFrame, BacktraceSymbol};
#[cfg(feature = "std")]
pub use capture::Backtrace;
pub use capture::{BacktraceFrame, BacktraceSymbol};
mod capture;

#[allow(dead_code)]
Expand All @@ -121,6 +148,7 @@ impl Drop for Bomb {
}

#[allow(dead_code)]
#[cfg(feature = "std")]
mod lock {
use std::cell::Cell;
use std::mem;
Expand Down Expand Up @@ -155,6 +183,16 @@ mod lock {
}
}

#[allow(dead_code)]
#[cfg(not(feature = "std"))]
mod lock {
pub struct LockGuard;

pub fn lock() -> Option<LockGuard> {
None
}
}

// requires external synchronization
#[cfg(all(windows, feature = "dbghelp"))]
unsafe fn dbghelp_init() {
Expand Down
Loading