Skip to content

Commit 875e4b4

Browse files
frailltMindaugas Vinkelis
authored and
Mindaugas Vinkelis
committed
make it easy to resolve symbols by frame
1 parent 0533d47 commit 875e4b4

File tree

3 files changed

+56
-66
lines changed

3 files changed

+56
-66
lines changed

src/capture.rs

+53-46
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ use serde::{Deserialize, Serialize};
2626
pub struct Backtrace {
2727
// Frames here are listed from top-to-bottom of the stack
2828
frames: Vec<BacktraceFrame>,
29-
// The index we believe is the actual start of the backtrace, omitting
30-
// frames like `Backtrace::new` and `backtrace::trace`.
31-
actual_start_index: usize,
3229
}
3330

3431
fn _assert_send_sync() {
@@ -86,6 +83,27 @@ impl Frame {
8683
} => module_base_address.map(|addr| addr as *mut c_void),
8784
}
8885
}
86+
87+
/// Resolve all addresses in the frame to their symbolic names.
88+
fn resolve_symbols(&self) -> Vec<BacktraceSymbol> {
89+
let mut symbols = Vec::new();
90+
let sym = |symbol: &Symbol| {
91+
symbols.push(BacktraceSymbol {
92+
name: symbol.name().map(|m| m.as_bytes().to_vec()),
93+
addr: symbol.addr().map(|a| a as usize),
94+
filename: symbol.filename().map(|m| m.to_owned()),
95+
lineno: symbol.lineno(),
96+
colno: symbol.colno(),
97+
});
98+
};
99+
match *self {
100+
Frame::Raw(ref f) => resolve_frame(f, sym),
101+
Frame::Deserialized { ip, .. } => {
102+
resolve(ip as *mut c_void, sym);
103+
}
104+
}
105+
symbols
106+
}
89107
}
90108

91109
/// Captured version of a symbol in a backtrace.
@@ -172,23 +190,22 @@ impl Backtrace {
172190

173191
fn create(ip: usize) -> Backtrace {
174192
let mut frames = Vec::new();
175-
let mut actual_start_index = None;
176193
trace(|frame| {
177194
frames.push(BacktraceFrame {
178195
frame: Frame::Raw(frame.clone()),
179196
symbols: None,
180197
});
181198

182-
if frame.symbol_address() as usize == ip && actual_start_index.is_none() {
183-
actual_start_index = Some(frames.len());
199+
// clear inner frames, and start with call site.
200+
if frame.symbol_address() as usize == ip {
201+
frames.clear();
184202
}
203+
185204
true
186205
});
206+
frames.shrink_to_fit();
187207

188-
Backtrace {
189-
frames,
190-
actual_start_index: actual_start_index.unwrap_or(0),
191-
}
208+
Backtrace { frames }
192209
}
193210

194211
/// Returns the frames from when this backtrace was captured.
@@ -202,7 +219,7 @@ impl Backtrace {
202219
/// This function requires the `std` feature of the `backtrace` crate to be
203220
/// enabled, and the `std` feature is enabled by default.
204221
pub fn frames(&self) -> &[BacktraceFrame] {
205-
&self.frames[self.actual_start_index..]
222+
self.frames.as_slice()
206223
}
207224

208225
/// If this backtrace was created from `new_unresolved` then this function
@@ -216,51 +233,28 @@ impl Backtrace {
216233
/// This function requires the `std` feature of the `backtrace` crate to be
217234
/// enabled, and the `std` feature is enabled by default.
218235
pub fn resolve(&mut self) {
219-
for frame in self.frames.iter_mut().filter(|f| f.symbols.is_none()) {
220-
let mut symbols = Vec::new();
221-
{
222-
let sym = |symbol: &Symbol| {
223-
symbols.push(BacktraceSymbol {
224-
name: symbol.name().map(|m| m.as_bytes().to_vec()),
225-
addr: symbol.addr().map(|a| a as usize),
226-
filename: symbol.filename().map(|m| m.to_owned()),
227-
lineno: symbol.lineno(),
228-
colno: symbol.colno(),
229-
});
230-
};
231-
match frame.frame {
232-
Frame::Raw(ref f) => resolve_frame(f, sym),
233-
Frame::Deserialized { ip, .. } => {
234-
resolve(ip as *mut c_void, sym);
235-
}
236-
}
237-
}
238-
frame.symbols = Some(symbols);
239-
}
236+
self.frames.iter_mut().for_each(BacktraceFrame::resolve);
240237
}
241238
}
242239

243240
impl From<Vec<BacktraceFrame>> for Backtrace {
244241
fn from(frames: Vec<BacktraceFrame>) -> Self {
245-
Backtrace {
246-
frames,
247-
actual_start_index: 0,
248-
}
242+
Backtrace { frames }
249243
}
250244
}
251245

252246
impl From<crate::Frame> for BacktraceFrame {
253-
fn from(frame: crate::Frame) -> BacktraceFrame {
247+
fn from(frame: crate::Frame) -> Self {
254248
BacktraceFrame {
255249
frame: Frame::Raw(frame),
256250
symbols: None,
257251
}
258252
}
259253
}
260254

261-
impl Into<Vec<BacktraceFrame>> for Backtrace {
262-
fn into(self) -> Vec<BacktraceFrame> {
263-
self.frames
255+
impl From<Backtrace> for Vec<BacktraceFrame> {
256+
fn from(bt: Backtrace) -> Self {
257+
bt.frames
264258
}
265259
}
266260

@@ -314,6 +308,20 @@ impl BacktraceFrame {
314308
pub fn symbols(&self) -> &[BacktraceSymbol] {
315309
self.symbols.as_ref().map(|s| &s[..]).unwrap_or(&[])
316310
}
311+
312+
/// Resolve all addresses in this frame to their symbolic names.
313+
///
314+
/// If this frame has been previously resolved, this function does nothing.
315+
///
316+
/// # Required features
317+
///
318+
/// This function requires the `std` feature of the `backtrace` crate to be
319+
/// enabled, and the `std` feature is enabled by default.
320+
pub fn resolve(&mut self) {
321+
if self.symbols.is_none() {
322+
self.symbols = Some(self.frame.resolve_symbols());
323+
}
324+
}
317325
}
318326

319327
impl BacktraceSymbol {
@@ -370,11 +378,10 @@ impl BacktraceSymbol {
370378

371379
impl fmt::Debug for Backtrace {
372380
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
373-
let full = fmt.alternate();
374-
let (frames, style) = if full {
375-
(&self.frames[..], PrintFmt::Full)
381+
let style = if fmt.alternate() {
382+
PrintFmt::Full
376383
} else {
377-
(&self.frames[self.actual_start_index..], PrintFmt::Short)
384+
PrintFmt::Short
378385
};
379386

380387
// When printing paths we try to strip the cwd if it exists, otherwise
@@ -385,7 +392,7 @@ impl fmt::Debug for Backtrace {
385392
let mut print_path =
386393
move |fmt: &mut fmt::Formatter<'_>, path: crate::BytesOrWideString<'_>| {
387394
let path = path.into_path_buf();
388-
if !full {
395+
if style == PrintFmt::Full {
389396
if let Ok(cwd) = &cwd {
390397
if let Ok(suffix) = path.strip_prefix(cwd) {
391398
return fmt::Display::fmt(&suffix.display(), fmt);
@@ -397,7 +404,7 @@ impl fmt::Debug for Backtrace {
397404

398405
let mut f = BacktraceFmt::new(fmt, style, &mut print_path);
399406
f.add_context()?;
400-
for frame in frames {
407+
for frame in &self.frames {
401408
f.frame().backtrace_frame(frame)?;
402409
}
403410
f.finish()?;

src/symbolize/gimli.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use self::gimli::NativeEndian as Endian;
77
use self::mmap::Mmap;
88
use self::stash::Stash;
99
use super::BytesOrWideString;
10-
use super::ResolveWhat;
1110
use super::SymbolName;
1211
use addr2line::gimli;
1312
use core::convert::TryInto;
@@ -382,8 +381,7 @@ impl Cache {
382381
}
383382
}
384383

385-
pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol)) {
386-
let addr = what.address_or_ip();
384+
pub unsafe fn resolve(addr: *mut c_void, cb: &mut dyn FnMut(&super::Symbol)) {
387385
let mut call = |sym: Symbol<'_>| {
388386
// Extend the lifetime of `sym` to `'static` since we are unfortunately
389387
// required to here, but it's only ever going out as a reference so no

src/symbolize/mod.rs

+2-17
Original file line numberDiff line numberDiff line change
@@ -105,21 +105,6 @@ pub fn resolve_frame<F: FnMut(&Symbol)>(frame: &Frame, cb: F) {
105105
unsafe { resolve_frame_unsynchronized(frame, cb) }
106106
}
107107

108-
pub enum ResolveWhat<'a> {
109-
Address(*mut c_void),
110-
Frame(&'a Frame),
111-
}
112-
113-
impl<'a> ResolveWhat<'a> {
114-
#[allow(dead_code)]
115-
fn address_or_ip(&self) -> *mut c_void {
116-
match self {
117-
ResolveWhat::Address(a) => adjust_ip(*a),
118-
ResolveWhat::Frame(f) => adjust_ip(f.ip()),
119-
}
120-
}
121-
}
122-
123108
// IP values from stack frames are typically (always?) the instruction
124109
// *after* the call that's the actual stack trace. Symbolizing this on
125110
// causes the filename/line number to be one ahead and perhaps into
@@ -159,7 +144,7 @@ pub unsafe fn resolve_unsynchronized<F>(addr: *mut c_void, mut cb: F)
159144
where
160145
F: FnMut(&Symbol),
161146
{
162-
imp::resolve(ResolveWhat::Address(addr), &mut cb)
147+
imp::resolve(adjust_ip(addr), &mut cb)
163148
}
164149

165150
/// Same as `resolve_frame`, only unsafe as it's unsynchronized.
@@ -175,7 +160,7 @@ pub unsafe fn resolve_frame_unsynchronized<F>(frame: &Frame, mut cb: F)
175160
where
176161
F: FnMut(&Symbol),
177162
{
178-
imp::resolve(ResolveWhat::Frame(frame), &mut cb)
163+
imp::resolve(adjust_ip(frame.ip()), &mut cb)
179164
}
180165

181166
/// A trait representing the resolution of a symbol in a file.

0 commit comments

Comments
 (0)