Skip to content

Commit 5a4f807

Browse files
author
Aaron Power
committed
no_std support
1 parent a73a623 commit 5a4f807

18 files changed

+184
-65
lines changed

Cargo.toml

+28-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ documentation = "https://docs.rs/backtrace"
1111
description = """
1212
A library to acquire a stack trace (backtrace) at runtime in a Rust program.
1313
"""
14+
autoexamples = true
15+
autotests = true
16+
1417
[dependencies]
1518
cfg-if = "0.1"
1619
rustc-demangle = "0.1.4"
@@ -47,7 +50,10 @@ backtrace-sys = { path = "backtrace-sys", version = "0.1.17", optional = true }
4750
# Note that not all features are available on all platforms, so even though a
4851
# feature is enabled some other feature may be used instead.
4952
[features]
50-
default = ["libunwind", "libbacktrace", "coresymbolication", "dladdr", "dbghelp"]
53+
default = ["std", "libunwind", "libbacktrace", "coresymbolication", "dladdr", "dbghelp"]
54+
55+
# Include std support.
56+
std = []
5157

5258
#=======================================
5359
# Methods of acquiring a backtrace
@@ -86,7 +92,7 @@ kernel32 = []
8692
# the moment, this is only possible when targetting Linux, since macOS
8793
# splits DWARF out into a separate object file. Enabling this feature
8894
# means one less C dependency.
89-
libbacktrace = ["backtrace-sys"]
95+
libbacktrace = ["backtrace-sys", "std"]
9096
dladdr = []
9197
coresymbolication = []
9298
gimli-symbolize = ["addr2line", "findshlibs", "gimli", "memmap", "object" ]
@@ -97,3 +103,23 @@ gimli-symbolize = ["addr2line", "findshlibs", "gimli", "memmap", "object" ]
97103
# Various features used for enabling rustc-serialize or syntex codegen.
98104
serialize-rustc = ["rustc-serialize"]
99105
serialize-serde = ["serde", "serde_derive"]
106+
107+
[[example]]
108+
name = "backtrace"
109+
required-features = ["std"]
110+
111+
[[example]]
112+
name = "raw"
113+
required-features = ["std"]
114+
115+
[[test]]
116+
name = "skip_inner_frames"
117+
required-features = ["std"]
118+
119+
[[test]]
120+
name = "long_fn_name"
121+
required-features = ["std"]
122+
123+
[[test]]
124+
name = "smoke"
125+
required-features = ["std"]

backtrace-sys/src/lib.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
extern crate libc;
44

5-
use libc::uintptr_t;
6-
use std::os::raw::{c_void, c_char, c_int};
5+
use libc::{c_void, c_char, c_int, uintptr_t};
76

87
pub type backtrace_syminfo_callback =
98
extern fn(data: *mut c_void,

examples/raw.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn print() {
3333
}
3434
if let Some(file) = symbol.filename() {
3535
if let Some(l) = symbol.lineno() {
36-
print!("\n{:13}{:4$}@ {}:{}", "", "", file.display(), l,
36+
print!("\n{:13}{:4$}@ {}:{}", "", "", file.into_path_buf().display(), l,
3737
HEX_WIDTH);
3838
}
3939
}

src/backtrace/libunwind.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::os::raw::c_void;
11+
use types::c_void;
1212

1313
pub struct Frame {
1414
ctx: *mut uw::_Unwind_Context,
@@ -84,7 +84,7 @@ mod uw {
8484
pub use self::_Unwind_Reason_Code::*;
8585

8686
use libc;
87-
use std::os::raw::{c_int, c_void};
87+
use types::{c_int, c_void};
8888

8989
#[repr(C)]
9090
pub enum _Unwind_Reason_Code {

src/backtrace/mod.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::fmt;
2-
3-
use std::os::raw::c_void;
2+
use types::c_void;
43

54
/// Inspects the current call-stack, passing all active frames into the closure
65
/// provided to calculate a stack trace.
@@ -37,10 +36,20 @@ use std::os::raw::c_void;
3736
/// }
3837
/// ```
3938
#[inline(never)]
39+
#[cfg(feature = "std")]
4040
pub fn trace<F: FnMut(&Frame) -> bool>(mut cb: F) {
4141
trace_imp(&mut cb)
4242
}
4343

44+
/// Without std this function now does not have synchronization guarentees.
45+
/// Please refer to std documentation for examples and explaination.
46+
#[inline(never)]
47+
#[cfg(not(feature = "std"))]
48+
pub unsafe fn trace<F: FnMut(&Frame) -> bool>(mut cb: F) {
49+
trace_imp(&mut cb)
50+
}
51+
52+
4453
/// A trait representing one frame of a backtrace, yielded to the `trace`
4554
/// function of this crate.
4655
///

src/backtrace/noop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::os::raw::c_void;
1+
use types::c_void;
22

33
#[inline(always)]
44
pub fn trace(_cb: &mut FnMut(&super::Frame) -> bool) {}

src/backtrace/unix_backtrace.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use std::mem;
12-
use std::os::raw::{c_void, c_int};
12+
use types::{c_void, c_int};
1313

1414
pub struct Frame {
1515
addr: *mut c_void,

src/capture.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use std::fmt;
22
use std::mem;
3-
use std::os::raw::c_void;
43
use std::path::{Path, PathBuf};
54

65
use {trace, resolve, SymbolName};
6+
use types::c_void;
77

88
/// Representation of an owned and self-contained backtrace.
99
///
@@ -144,7 +144,7 @@ impl Backtrace {
144144
symbols.push(BacktraceSymbol {
145145
name: symbol.name().map(|m| m.as_bytes().to_vec()),
146146
addr: symbol.addr().map(|a| a as usize),
147-
filename: symbol.filename().map(|m| m.to_path_buf()),
147+
filename: symbol.filename().map(|m| m.into_path_buf()),
148148
lineno: symbol.lineno(),
149149
});
150150
});

src/lib.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
//! extern crate backtrace;
4747
//!
4848
//! fn main() {
49+
//! # // Unsafe here so test passes on no_std.
50+
//! # unsafe {
4951
//! backtrace::trace(|frame| {
5052
//! let ip = frame.ip();
5153
//! let symbol_address = frame.symbol_address();
@@ -63,10 +65,15 @@
6365
//! true // keep going to the next frame
6466
//! });
6567
//! }
68+
//! # }
6669
//! ```
6770
6871
#![doc(html_root_url = "https://docs.rs/backtrace")]
6972
#![deny(missing_docs)]
73+
#![cfg_attr(not(feature = "std"), no_std)]
74+
75+
#[cfg(not(feature = "std"))]
76+
extern crate core as std;
7077

7178
#[cfg(unix)]
7279
extern crate libc;
@@ -98,7 +105,7 @@ cfg_if! {
98105
}
99106

100107
#[allow(dead_code)] // not used everywhere
101-
#[cfg(unix)]
108+
#[cfg(all(unix, feature = "std"))]
102109
#[macro_use]
103110
mod dylib;
104111

@@ -108,9 +115,13 @@ mod backtrace;
108115
pub use symbolize::{resolve, Symbol, SymbolName};
109116
mod symbolize;
110117

118+
#[cfg(feature = "std")]
111119
pub use capture::{Backtrace, BacktraceFrame, BacktraceSymbol};
120+
#[cfg(feature = "std")]
112121
mod capture;
113122

123+
mod types;
124+
114125
#[allow(dead_code)]
115126
struct Bomb {
116127
enabled: bool,
@@ -126,6 +137,7 @@ impl Drop for Bomb {
126137
}
127138

128139
#[allow(dead_code)]
140+
#[cfg(feature = "std")]
129141
mod lock {
130142
use std::cell::Cell;
131143
use std::sync::{Once, Mutex, MutexGuard, ONCE_INIT};

src/symbolize/coresymbolication.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@
1010

1111
#![allow(bad_style)]
1212

13-
use std::ffi::{CStr, OsStr};
13+
use std::ffi::CStr;
1414
use std::mem;
15-
use std::os::raw::{c_void, c_char, c_int};
16-
use std::os::unix::prelude::*;
17-
use std::path::Path;
1815
use std::ptr;
1916
use std::sync::atomic::ATOMIC_USIZE_INIT;
2017

@@ -23,6 +20,7 @@ use libc::{self, Dl_info};
2320
use SymbolName;
2421
use dylib::Dylib;
2522
use dylib::Symbol as DylibSymbol;
23+
use types::{BytesOrWideString, c_void, c_char, c_int};
2624

2725
#[repr(C)]
2826
#[derive(Copy, Clone, PartialEq)]
@@ -69,15 +67,15 @@ impl Symbol {
6967
}
7068
}
7169

72-
pub fn filename(&self) -> Option<&Path> {
70+
pub fn filename(&self) -> Option<BytesOrWideString> {
7371
match *self {
7472
Symbol::Core { path, .. } => {
7573
if path.is_null() {
7674
None
7775
} else {
78-
Some(Path::new(OsStr::from_bytes(unsafe {
76+
Some(BytesOrWideString::Bytes(unsafe {
7977
CStr::from_ptr(path).to_bytes()
80-
})))
78+
}))
8179
}
8280
}
8381
Symbol::Dladdr(_) => None,

src/symbolize/dbghelp.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@
1010

1111
#![allow(bad_style)]
1212

13-
use std::ffi::OsString;
1413
use std::mem;
15-
use std::path::Path;
16-
use std::os::windows::prelude::*;
1714
use std::slice;
1815
use winapi::ctypes::*;
1916
use winapi::shared::basetsd::*;
@@ -25,10 +22,10 @@ use winapi::um::dbghelp::*;
2522
use SymbolName;
2623

2724
pub struct Symbol {
28-
name: OsString,
25+
name: BytesOrWideString,
2926
addr: *mut c_void,
3027
line: Option<u32>,
31-
filename: Option<OsString>,
28+
filename: Option<BytesOrWideString>,
3229
}
3330

3431
impl Symbol {
@@ -40,8 +37,8 @@ impl Symbol {
4037
Some(self.addr as *mut _)
4138
}
4239

43-
pub fn filename(&self) -> Option<&Path> {
44-
self.filename.as_ref().map(Path::new)
40+
pub fn filename(&self) -> Option<BytesOrWideString> {
41+
self.filename.clone()
4542
}
4643

4744
pub fn lineno(&self) -> Option<u32> {
@@ -83,7 +80,7 @@ pub fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) {
8380

8481
let name = slice::from_raw_parts(info.Name.as_ptr() as *const u16,
8582
name_len);
86-
let name = OsString::from_wide(name);
83+
let name = BytesOrWideString::Wide(name);
8784

8885
let mut line = mem::zeroed::<IMAGEHLP_LINEW64>();
8986
line.SizeOfStruct = mem::size_of::<IMAGEHLP_LINEW64>() as DWORD;
@@ -103,15 +100,15 @@ pub fn resolve(addr: *mut c_void, cb: &mut FnMut(&super::Symbol)) {
103100
len += 1;
104101
}
105102
let name = slice::from_raw_parts(base, len as usize);
106-
filename = Some(OsString::from_wide(name));
103+
filename = Some(BytesOrWideString::Wide(name));
107104
}
108105

109106
cb(&super::Symbol {
110107
inner: Symbol {
111-
name: name,
108+
name,
112109
addr: info.Address as *mut _,
113110
line: lineno,
114-
filename: filename,
111+
filename,
115112
},
116113
})
117114
}

src/symbolize/dladdr.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::ffi::CStr;
12-
use std::mem;
13-
use std::os::raw::c_void;
14-
use std::path::Path;
11+
use std::{mem, slice};
1512

13+
use types::{BytesOrWideString, c_void};
1614
use libc::{self, Dl_info};
1715

1816
use SymbolName;
@@ -26,17 +24,19 @@ impl Symbol {
2624
if self.inner.dli_sname.is_null() {
2725
None
2826
} else {
29-
Some(SymbolName::new(unsafe {
30-
CStr::from_ptr(self.inner.dli_sname).to_bytes()
31-
}))
27+
let ptr = self.inner.dli_sname as *const u8;
28+
unsafe {
29+
let len = libc::strlen(self.inner.dli_sname);
30+
Some(SymbolName::new(slice::from_raw_parts(ptr, len)))
31+
}
3232
}
3333
}
3434

3535
pub fn addr(&self) -> Option<*mut c_void> {
3636
Some(self.inner.dli_saddr as *mut _)
3737
}
3838

39-
pub fn filename(&self) -> Option<&Path> {
39+
pub fn filename(&self) -> Option<BytesOrWideString> {
4040
None
4141
}
4242

src/symbolize/gimli.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::cell::RefCell;
77
use std::env;
88
use std::fs::File;
99
use std::mem;
10-
use std::os::raw::c_void;
10+
use libc::c_void;
1111
use std::path::{Path, PathBuf};
1212
use std::u32;
1313

@@ -209,8 +209,8 @@ impl Symbol {
209209
Some(self.addr as *mut c_void)
210210
}
211211

212-
pub fn filename(&self) -> Option<&Path> {
213-
self.file.as_ref().map(|f| f.as_ref())
212+
pub fn filename(&self) -> Option<BytesOrWideString> {
213+
self.file.as_ref().map(|f| BytesOrWideString::Bytes(f.as_bytes()))
214214
}
215215

216216
pub fn lineno(&self) -> Option<u32> {

src/symbolize/libbacktrace.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212

1313
extern crate backtrace_sys as bt;
1414

15-
use libc::uintptr_t;
1615
use std::ffi::{CStr, OsStr};
17-
use std::os::raw::{c_void, c_char, c_int};
1816
use std::os::unix::prelude::*;
1917
use std::path::Path;
2018
use std::ptr;
2119
use std::sync::{ONCE_INIT, Once};
2220

21+
use libc::{c_char, c_int, c_void, uintptr_t};
22+
2323
use SymbolName;
2424

2525
pub enum Symbol {

0 commit comments

Comments
 (0)