Skip to content

Commit caf2368

Browse files
authored
Merge pull request #126 from Aaronepower/master
Add no_std support
2 parents a73a623 + ea8dffd commit caf2368

21 files changed

+501
-250
lines changed

.travis.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ matrix:
2727
- cargo test --no-default-features --features 'unix-backtrace'
2828
- cargo test --no-default-features --features 'unix-backtrace dladdr'
2929
- cargo test --no-default-features --features 'unix-backtrace libbacktrace'
30-
- cargo test --no-default-features --features 'serialize-serde'
31-
- cargo test --no-default-features --features 'serialize-rustc'
32-
- cargo test --no-default-features --features 'serialize-rustc serialize-serde'
33-
- cargo test --no-default-features --features 'cpp_demangle'
34-
- cargo test --no-default-features --features 'gimli-symbolize'
30+
- cargo test --no-default-features --features 'serialize-serde std'
31+
- cargo test --no-default-features --features 'serialize-rustc std'
32+
- cargo test --no-default-features --features 'serialize-rustc serialize-serde std'
33+
- cargo test --no-default-features --features 'cpp_demangle std'
34+
- cargo test --no-default-features --features 'gimli-symbolize std'
3535
- cd ./cpp_smoke_test && cargo test && cd ..
3636
- cargo clean && cargo build
3737

Cargo.toml

Lines changed: 31 additions & 5 deletions
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"
@@ -30,10 +33,10 @@ memmap = { version = "0.7.0", optional = true }
3033
object = { version = "0.9.0", optional = true }
3134

3235
[target.'cfg(unix)'.dependencies]
33-
libc = "0.2"
36+
libc = { version = "0.2", default-features = false }
3437

3538
[target.'cfg(windows)'.dependencies]
36-
winapi = { version = "0.3.3", optional = true, features = ["std", "dbghelp", "processthreadsapi", "winnt", "minwindef"] }
39+
winapi = { version = "0.3.3", features = ["dbghelp", "processthreadsapi", "winnt", "minwindef"] }
3740

3841
[target.'cfg(all(unix, not(target_os = "fuchsia"), not(target_os = "emscripten"), not(target_os = "macos"), not(target_os = "ios")))'.dependencies]
3942
backtrace-sys = { path = "backtrace-sys", version = "0.1.17", optional = true }
@@ -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
@@ -64,7 +70,7 @@ default = ["libunwind", "libbacktrace", "coresymbolication", "dladdr", "dbghelp"
6470
# function to acquire a backtrace
6571
libunwind = []
6672
unix-backtrace = []
67-
dbghelp = ["winapi"]
73+
dbghelp = []
6874
kernel32 = []
6975

7076
#=======================================
@@ -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"]

appveyor.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ build: false
1818

1919
test_script:
2020
- cargo test --target %TARGET%
21+
- cargo build --target %TARGET% --no-default-features
22+
- cargo build --target %TARGET% --no-default-features --features dbghelp
2123

2224
branches:
2325
only:

backtrace-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Bindings to the libbacktrace gcc library
1212
"""
1313

1414
[dependencies]
15-
libc = "0.2"
15+
libc = { version = "0.2", default-features = false }
1616

1717
[build-dependencies]
1818
cc = "1.0"

backtrace-sys/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#![allow(bad_style)]
2+
#![no_std]
23

34
extern crate libc;
45

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

88
pub type backtrace_syminfo_callback =
99
extern fn(data: *mut c_void,

src/backtrace/dbghelp.rs

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@
1010

1111
#![allow(bad_style)]
1212

13-
use std::mem;
14-
use winapi::ctypes::*;
13+
use core::mem;
14+
use core::prelude::v1::*;
15+
1516
use winapi::shared::minwindef::*;
1617
use winapi::um::processthreadsapi;
1718
use winapi::um::winnt::{self, CONTEXT};
1819
use winapi::um::dbghelp;
1920
use winapi::um::dbghelp::*;
2021

22+
use types::c_void;
23+
2124
pub struct Frame {
2225
inner: STACKFRAME64,
2326
}
@@ -32,50 +35,43 @@ impl Frame {
3235
}
3336
}
3437

35-
#[inline(always)]
36-
pub fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
37-
// According to windows documentation, all dbghelp functions are
38-
// single-threaded.
39-
let _g = ::lock::lock();
38+
#[repr(C, align(16))] // required by `CONTEXT`, is a FIXME in winapi right now
39+
struct MyContext(CONTEXT);
4040

41-
unsafe {
42-
// Allocate necessary structures for doing the stack walk
43-
let process = processthreadsapi::GetCurrentProcess();
44-
let thread = processthreadsapi::GetCurrentThread();
41+
#[inline(always)]
42+
pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
43+
// Allocate necessary structures for doing the stack walk
44+
let process = processthreadsapi::GetCurrentProcess();
45+
let thread = processthreadsapi::GetCurrentThread();
4546

46-
// The CONTEXT structure needs to be aligned on a 16-byte boundary for
47-
// 64-bit Windows, but currently we don't have a way to express that in
48-
// Rust. Allocations are generally aligned to 16-bytes, though, so we
49-
// box this up.
50-
let mut context = Box::new(mem::zeroed::<CONTEXT>());
51-
winnt::RtlCaptureContext(&mut *context);
52-
let mut frame = super::Frame {
53-
inner: Frame { inner: mem::zeroed() },
54-
};
55-
let image = init_frame(&mut frame.inner.inner, &context);
47+
let mut context = mem::zeroed::<MyContext>();
48+
winnt::RtlCaptureContext(&mut context.0);
49+
let mut frame = super::Frame {
50+
inner: Frame { inner: mem::zeroed() },
51+
};
52+
let image = init_frame(&mut frame.inner.inner, &context.0);
5653

57-
// Initialize this process's symbols
58-
let _c = ::dbghelp_init();
54+
// Initialize this process's symbols
55+
let _c = ::dbghelp_init();
5956

60-
// And now that we're done with all the setup, do the stack walking!
61-
while dbghelp::StackWalk64(image as DWORD,
62-
process,
63-
thread,
64-
&mut frame.inner.inner,
65-
&mut *context as *mut _ as *mut _,
66-
None,
67-
Some(dbghelp::SymFunctionTableAccess64),
68-
Some(dbghelp::SymGetModuleBase64),
69-
None) == TRUE {
70-
if frame.inner.inner.AddrPC.Offset == frame.inner.inner.AddrReturn.Offset ||
71-
frame.inner.inner.AddrPC.Offset == 0 ||
72-
frame.inner.inner.AddrReturn.Offset == 0 {
73-
break
74-
}
57+
// And now that we're done with all the setup, do the stack walking!
58+
while dbghelp::StackWalk64(image as DWORD,
59+
process,
60+
thread,
61+
&mut frame.inner.inner,
62+
&mut context.0 as *mut CONTEXT as *mut _,
63+
None,
64+
Some(dbghelp::SymFunctionTableAccess64),
65+
Some(dbghelp::SymGetModuleBase64),
66+
None) == TRUE {
67+
if frame.inner.inner.AddrPC.Offset == frame.inner.inner.AddrReturn.Offset ||
68+
frame.inner.inner.AddrPC.Offset == 0 ||
69+
frame.inner.inner.AddrReturn.Offset == 0 {
70+
break
71+
}
7572

76-
if !cb(&frame) {
77-
break
78-
}
73+
if !cb(&frame) {
74+
break
7975
}
8076
}
8177
}

src/backtrace/libunwind.rs

Lines changed: 5 additions & 7 deletions
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,
@@ -48,10 +48,8 @@ impl Frame {
4848
}
4949

5050
#[inline(always)]
51-
pub fn trace(mut cb: &mut FnMut(&super::Frame) -> bool) {
52-
unsafe {
53-
uw::_Unwind_Backtrace(trace_fn, &mut cb as *mut _ as *mut _);
54-
}
51+
pub unsafe fn trace(mut cb: &mut FnMut(&super::Frame) -> bool) {
52+
uw::_Unwind_Backtrace(trace_fn, &mut cb as *mut _ as *mut _);
5553

5654
extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
5755
arg: *mut c_void) -> uw::_Unwind_Reason_Code {
@@ -83,8 +81,8 @@ pub fn trace(mut cb: &mut FnMut(&super::Frame) -> bool) {
8381
mod uw {
8482
pub use self::_Unwind_Reason_Code::*;
8583

86-
use libc;
87-
use std::os::raw::{c_int, c_void};
84+
use libc::{self, c_int};
85+
use types::c_void;
8886

8987
#[repr(C)]
9088
pub enum _Unwind_Reason_Code {

src/backtrace/mod.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::fmt;
2-
3-
use std::os::raw::c_void;
1+
use core::fmt;
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.
@@ -23,6 +22,11 @@ use std::os::raw::c_void;
2322
/// example, capture a backtrace to be inspected later, then the `Backtrace`
2423
/// type may be more appropriate.
2524
///
25+
/// # Required features
26+
///
27+
/// This function requires the `std` feature of the `backtrace` crate to be
28+
/// enabled, and the `std` feature is enabled by default.
29+
///
2630
/// # Example
2731
///
2832
/// ```
@@ -36,11 +40,24 @@ use std::os::raw::c_void;
3640
/// });
3741
/// }
3842
/// ```
43+
#[inline(always)]
44+
#[cfg(feature = "std")]
45+
pub fn trace<F: FnMut(&Frame) -> bool>(cb: F) {
46+
let _guard = ::lock::lock();
47+
unsafe { trace_unsynchronized(cb) }
48+
}
49+
50+
/// Same as `trace`, only unsafe as it's unsynchronized.
51+
///
52+
/// This function does not have synchronization guarentees but is available
53+
/// when the `std` feature of this crate isn't compiled in. See the `trace`
54+
/// function for more documentation and examples.
3955
#[inline(never)]
40-
pub fn trace<F: FnMut(&Frame) -> bool>(mut cb: F) {
56+
pub unsafe fn trace_unsynchronized<F: FnMut(&Frame) -> bool>(mut cb: F) {
4157
trace_imp(&mut cb)
4258
}
4359

60+
4461
/// A trait representing one frame of a backtrace, yielded to the `trace`
4562
/// function of this crate.
4663
///

src/backtrace/noop.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::mem;
12-
use std::os::raw::{c_void, c_int};
11+
use core::mem;
12+
use libc::c_int;
13+
14+
use types::c_void;
1315

1416
pub struct Frame {
1517
addr: *mut c_void,
@@ -25,15 +27,14 @@ extern {
2527
}
2628

2729
#[inline(always)]
28-
pub fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
30+
pub unsafe fn trace(cb: &mut FnMut(&super::Frame) -> bool) {
2931
const SIZE: usize = 100;
3032

3133
let mut buf: [*mut c_void; SIZE];
3234
let cnt;
33-
unsafe {
34-
buf = mem::zeroed();
35-
cnt = backtrace(buf.as_mut_ptr(), SIZE as c_int);
36-
}
35+
36+
buf = mem::zeroed();
37+
cnt = backtrace(buf.as_mut_ptr(), SIZE as c_int);
3738

3839
for addr in buf[..cnt as usize].iter() {
3940
let cx = super::Frame {

src/capture.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
use std::prelude::v1::*;
12
use std::fmt;
23
use std::mem;
3-
use std::os::raw::c_void;
44
use std::path::{Path, PathBuf};
55

66
use {trace, resolve, SymbolName};
7+
use types::c_void;
78

89
/// Representation of an owned and self-contained backtrace.
910
///
@@ -144,7 +145,7 @@ impl Backtrace {
144145
symbols.push(BacktraceSymbol {
145146
name: symbol.name().map(|m| m.as_bytes().to_vec()),
146147
addr: symbol.addr().map(|a| a as usize),
147-
filename: symbol.filename().map(|m| m.to_path_buf()),
148+
filename: symbol.filename().map(|m| m.to_owned()),
148149
lineno: symbol.lineno(),
149150
});
150151
});

0 commit comments

Comments
 (0)