Skip to content

Commit 8571cef

Browse files
committed
Use custom backtrace formatting for Fuchsia
1 parent f3b9631 commit 8571cef

File tree

4 files changed

+114
-65
lines changed

4 files changed

+114
-65
lines changed

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ winapi = { version = "0.3.3", optional = true }
4040
goblin = { version = "0.0.24", optional = true, default-features = false, features = ['pe32', 'pe64'] }
4141
[target.'cfg(target_os = "macos")'.dependencies]
4242
goblin = { version = "0.0.24", optional = true, default-features = false, features = ['mach32', 'mach64'] }
43-
[target.'cfg(not(any(target_os = "macos", windows)))'.dependencies]
43+
[target.'cfg(not(any(target_os = "fuchsia", target_os = "macos", windows)))'.dependencies]
4444
goblin = { version = "0.0.24", optional = true, default-features = false, features = ['elf32', 'elf64'] }
45+
[target.'cfg(target_os = "fuchsia")'.dependencies]
46+
fuchsia_backtrace = "0.1"
4547

4648
# Each feature controls the two phases of finding a backtrace: getting a
4749
# backtrace and then resolving instruction pointers to symbols. The default

src/capture.rs

Lines changed: 14 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ cfg_if::cfg_if! {
120120

121121
impl BacktraceSymbolImpl {
122122
fn from_symbol(symbol: &Symbol) -> Self {
123-
BacktraceSymbol {
123+
BacktraceSymbolImpl {
124124
name: symbol.name().map(|m| m.as_bytes().to_vec()),
125125
addr: symbol.addr().map(|a| a as usize),
126126
filename: symbol.filename().map(|m| m.to_owned()),
@@ -129,13 +129,13 @@ cfg_if::cfg_if! {
129129
}
130130

131131
fn name(&self) -> Option<&[u8]> {
132-
self.name.as_ref().map(|x| x.deref())
132+
self.name.as_ref().map(|x| &**x)
133133
}
134134
fn addr(&self) -> Option<usize> {
135135
self.addr
136136
}
137137
fn filename(&self) -> Option<&Path> {
138-
self.filename.as_ref().map(|x| x.deref())
138+
self.filename.as_ref().map(|x| &**x)
139139
}
140140
fn lineno(&self) -> Option<u32> {
141141
self.lineno
@@ -373,69 +373,19 @@ impl BacktraceSymbol {
373373
}
374374
}
375375

376+
cfg_if::cfg_if! {
377+
if #[cfg(target_os = "fuchsia")] {
378+
mod fuchsia_backtrace_fmt;
379+
use fuchsia_backtrace_fmt::fmt_backtrace;
380+
} else {
381+
mod default_backtrace_fmt;
382+
use default_backtrace_fmt::fmt_backtrace;
383+
}
384+
}
385+
376386
impl fmt::Debug for Backtrace {
377387
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
378-
write!(fmt, "stack backtrace:")?;
379-
380-
let iter = if fmt.alternate() {
381-
self.frames.iter()
382-
} else {
383-
self.frames[self.actual_start_index..].iter()
384-
};
385-
386-
for (idx, frame) in iter.enumerate() {
387-
// To reduce TCB size in Sgx enclave, we do not want to implement symbol resolution functionality.
388-
// Rather, we can print the offset of the address here, which could be later mapped to
389-
// correct function.
390-
let ip: *mut c_void;
391-
#[cfg(target_env = "sgx")]
392-
{
393-
ip = usize::wrapping_sub(
394-
frame.ip() as _,
395-
std::os::fortanix_sgx::mem::image_base() as _,
396-
) as _;
397-
}
398-
#[cfg(not(target_env = "sgx"))]
399-
{
400-
ip = frame.ip();
401-
}
402-
403-
write!(fmt, "\n{:4}: ", idx)?;
404-
405-
let symbols = match frame.symbols {
406-
Some(ref s) => s,
407-
None => {
408-
write!(fmt, "<unresolved> ({:?})", ip)?;
409-
continue;
410-
}
411-
};
412-
if symbols.len() == 0 {
413-
write!(fmt, "<no info> ({:?})", ip)?;
414-
continue;
415-
}
416-
417-
for (idx, symbol) in symbols.iter().enumerate() {
418-
if idx != 0 {
419-
write!(fmt, "\n ")?;
420-
}
421-
422-
if let Some(name) = symbol.name() {
423-
write!(fmt, "{}", name)?;
424-
} else {
425-
write!(fmt, "<unknown>")?;
426-
}
427-
428-
if idx == 0 {
429-
write!(fmt, " ({:?})", ip)?;
430-
}
431-
432-
if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) {
433-
write!(fmt, "\n at {}:{}", file.display(), line)?;
434-
}
435-
}
436-
}
437-
438-
Ok(())
388+
fmt_backtrace(self, fmt)
439389
}
440390
}
441391

src/capture/default_backtrace_fmt.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use crate::Backtrace;
2+
use std::ffi::c_void;
3+
use std::fmt;
4+
5+
pub(super) fn fmt_backtrace(bt: &Backtrace, fmt: &mut fmt::Formatter) -> fmt::Result {
6+
write!(fmt, "stack backtrace:")?;
7+
8+
let iter = if fmt.alternate() {
9+
bt.frames.iter()
10+
} else {
11+
bt.frames[bt.actual_start_index..].iter()
12+
};
13+
14+
for (idx, frame) in iter.enumerate() {
15+
// To reduce TCB size in Sgx enclave, we do not want to implement symbol resolution functionality.
16+
// Rather, we can print the offset of the address here, which could be later mapped to
17+
// correct function.
18+
let ip: *mut c_void;
19+
#[cfg(target_env = "sgx")]
20+
{
21+
ip = usize::wrapping_sub(
22+
frame.ip() as _,
23+
std::os::fortanix_sgx::mem::image_base() as _,
24+
) as _;
25+
}
26+
#[cfg(not(target_env = "sgx"))]
27+
{
28+
ip = frame.ip();
29+
}
30+
31+
write!(fmt, "\n{:4}: ", idx)?;
32+
33+
let symbols = match frame.symbols {
34+
Some(ref s) => s,
35+
None => {
36+
write!(fmt, "<unresolved> ({:?})", ip)?;
37+
continue;
38+
}
39+
};
40+
if symbols.len() == 0 {
41+
write!(fmt, "<no info> ({:?})", ip)?;
42+
continue;
43+
}
44+
45+
for (idx, symbol) in symbols.iter().enumerate() {
46+
if idx != 0 {
47+
write!(fmt, "\n ")?;
48+
}
49+
50+
if let Some(name) = symbol.name() {
51+
write!(fmt, "{}", name)?;
52+
} else {
53+
write!(fmt, "<unknown>")?;
54+
}
55+
56+
if idx == 0 {
57+
write!(fmt, " ({:?})", ip)?;
58+
}
59+
60+
if let (Some(file), Some(line)) = (symbol.filename(), symbol.lineno()) {
61+
write!(fmt, "\n at {}:{}", file.display(), line)?;
62+
}
63+
}
64+
}
65+
66+
Ok(())
67+
}

src/capture/fuchsia_backtrace_fmt.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use crate::Backtrace;
2+
use libc::c_void;
3+
use std::fmt;
4+
5+
pub(super) fn fmt_backtrace(bt: &Backtrace, fmt: &mut fmt::Formatter) -> fmt::Result {
6+
fmt.write_str("stack backtrace:\n")?;
7+
8+
// Print the DSO context to tell the logger where our libs are loaded into memory.
9+
let mut dso_cx = vec![];
10+
fuchsia_backtrace::print_dso_context(&mut dso_cx).map_err(|_| fmt::Error)?;
11+
if let Ok(s) = std::string::String::from_utf8(dso_cx) {
12+
fmt.write_str(&s)?;
13+
}
14+
15+
let iter = if fmt.alternate() {
16+
bt.frames.iter()
17+
} else {
18+
bt.frames[bt.actual_start_index..].iter()
19+
};
20+
21+
// Print the addresses of the backtrace frames
22+
for (idx, frame) in iter.enumerate() {
23+
let ip: *mut c_void = frame.ip();
24+
fmt.write_str("{{{bt:")?;
25+
write!(fmt, "{}:{:?}", idx, ip)?;
26+
fmt.write_str("}}}\n")?;
27+
}
28+
29+
Ok(())
30+
}

0 commit comments

Comments
 (0)