Skip to content

Commit c31174f

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

File tree

1 file changed

+53
-43
lines changed

1 file changed

+53
-43
lines changed

src/capture.rs

+53-43
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,48 +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

255+
// we don't want implementing `impl From<Backtrace> for Vec<BacktraceFrame>` on purpose,
256+
// because "... additional directions for Vec<T> can weaken type inference ..."
257+
// more information on https://github.com/rust-lang/backtrace-rs/pull/526
261258
impl Into<Vec<BacktraceFrame>> for Backtrace {
262259
fn into(self) -> Vec<BacktraceFrame> {
263260
self.frames
@@ -314,6 +311,20 @@ impl BacktraceFrame {
314311
pub fn symbols(&self) -> &[BacktraceSymbol] {
315312
self.symbols.as_ref().map(|s| &s[..]).unwrap_or(&[])
316313
}
314+
315+
/// Resolve all addresses in this frame to their symbolic names.
316+
///
317+
/// If this frame has been previously resolved, this function does nothing.
318+
///
319+
/// # Required features
320+
///
321+
/// This function requires the `std` feature of the `backtrace` crate to be
322+
/// enabled, and the `std` feature is enabled by default.
323+
pub fn resolve(&mut self) {
324+
if self.symbols.is_none() {
325+
self.symbols = Some(self.frame.resolve_symbols());
326+
}
327+
}
317328
}
318329

319330
impl BacktraceSymbol {
@@ -370,11 +381,10 @@ impl BacktraceSymbol {
370381

371382
impl fmt::Debug for Backtrace {
372383
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)
384+
let style = if fmt.alternate() {
385+
PrintFmt::Full
376386
} else {
377-
(&self.frames[self.actual_start_index..], PrintFmt::Short)
387+
PrintFmt::Short
378388
};
379389

380390
// When printing paths we try to strip the cwd if it exists, otherwise
@@ -385,7 +395,7 @@ impl fmt::Debug for Backtrace {
385395
let mut print_path =
386396
move |fmt: &mut fmt::Formatter<'_>, path: crate::BytesOrWideString<'_>| {
387397
let path = path.into_path_buf();
388-
if !full {
398+
if style == PrintFmt::Full {
389399
if let Ok(cwd) = &cwd {
390400
if let Ok(suffix) = path.strip_prefix(cwd) {
391401
return fmt::Display::fmt(&suffix.display(), fmt);
@@ -397,7 +407,7 @@ impl fmt::Debug for Backtrace {
397407

398408
let mut f = BacktraceFmt::new(fmt, style, &mut print_path);
399409
f.add_context()?;
400-
for frame in frames {
410+
for frame in &self.frames {
401411
f.frame().backtrace_frame(frame)?;
402412
}
403413
f.finish()?;

0 commit comments

Comments
 (0)