From dab3d0348c31b94cc5936761673b565326347595 Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Wed, 16 Oct 2019 13:32:01 -0500 Subject: [PATCH 01/13] Implemented Debug newtypes for BacktraceFrame and BacktraceSymbol --- src/capture.rs | 42 ++++++++----------------------------- src/lib.rs | 2 +- src/print.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/capture.rs b/src/capture.rs index 7b37bd1bc..c9f89c332 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -1,5 +1,4 @@ -use crate::PrintFmt; -use crate::{resolve, resolve_frame, trace, BacktraceFmt, Symbol, SymbolName}; +use crate::{resolve, resolve_frame, trace, DebugBacktraceFrame, Symbol, SymbolName}; use std::ffi::c_void; use std::fmt; use std::path::{Path, PathBuf}; @@ -322,41 +321,18 @@ impl BacktraceSymbol { pub fn lineno(&self) -> Option { self.lineno } + + /// Returns whether the BacktraceSymbol has any data associated with it + pub fn is_empty(&self) -> bool { + self.name.is_none() && self.addr.is_none() && self.filename.is_none() && self.lineno.is_none() + } } impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let full = fmt.alternate(); - let (frames, style) = if full { - (&self.frames[..], PrintFmt::Full) - } else { - (&self.frames[self.actual_start_index..], PrintFmt::Short) - }; - - // When printing paths we try to strip the cwd if it exists, otherwise - // we just print the path as-is. Note that we also only do this for the - // short format, because if it's full we presumably want to print - // everything. - let cwd = std::env::current_dir(); - let mut print_path = move |fmt: &mut fmt::Formatter, path: crate::BytesOrWideString| { - let path = path.into_path_buf(); - if !full { - if let Ok(cwd) = &cwd { - if let Ok(suffix) = path.strip_prefix(cwd) { - return fmt::Display::fmt(&suffix.display(), fmt); - } - } - } - fmt::Display::fmt(&path.display(), fmt) - }; - - let mut f = BacktraceFmt::new(fmt, style, &mut print_path); - f.add_context()?; - for frame in frames { - f.frame().backtrace_frame(frame)?; - } - f.finish()?; - Ok(()) + fmt.debug_list() + .entries(self.frames().iter().flat_map(|frame| DebugBacktraceFrame::new(frame).symbols_skip_empty())) + .finish() } } diff --git a/src/lib.rs b/src/lib.rs index 69a283e67..56b712b4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,7 +90,7 @@ mod types; pub use crate::symbolize::clear_symbol_cache; mod print; -pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt}; +pub use print::{BacktraceFmt, BacktraceFrameFmt, DebugBacktraceFrame, PrintFmt}; cfg_if::cfg_if! { if #[cfg(feature = "std")] { diff --git a/src/print.rs b/src/print.rs index ce26f962e..9482e4058 100644 --- a/src/print.rs +++ b/src/print.rs @@ -7,6 +7,63 @@ const HEX_WIDTH: usize = 2 + 2 * core::mem::size_of::(); #[cfg(target_os = "fuchsia")] mod fuchsia; +/// A formatter for BacktraceFrames. +pub struct DebugBacktraceFrame<'a>(&'a crate::BacktraceFrame); + +impl<'a> DebugBacktraceFrame<'a> { + #[allow(missing_docs)] + pub fn new(frame: &'a crate::BacktraceFrame) -> Self { + Self(frame) + } + + /// Iterates over symbols in wrapped BacktraceFrame, and wraps them in DebugBacktraceSymbols. + pub fn symbols(&self) -> std::vec::Vec> { + self.0.symbols().iter().map(DebugBacktraceSymbol::new).collect() + } + + /// Same as symbols(), but filters out symbols that have no data + pub fn symbols_skip_empty(&self) -> std::vec::Vec> { + self.0.symbols().iter().filter(|symbol| !symbol.is_empty()).map(DebugBacktraceSymbol::new).collect() + } +} + +impl<'a> fmt::Debug for DebugBacktraceFrame<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut d = f.debug_list(); + if !self.0.symbols().is_empty() { + d.entries(self.0.symbols().iter().map(|symbol| DebugBacktraceSymbol::new(symbol))); + } + d.finish() + } +} + +/// A formatter for BacktraceSymbols. +pub struct DebugBacktraceSymbol<'a>(&'a crate::BacktraceSymbol); + +impl<'a> DebugBacktraceSymbol<'a> { + /// Create a new DebugBacktraceSymbol. + pub fn new(frame: &'a crate::BacktraceSymbol) -> Self { + Self(frame) + } +} + +impl<'a> fmt::Debug for DebugBacktraceSymbol<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.0.name().is_none() { return Ok(()); } + let mut d = f.debug_map(); + let name = self.0.name(); + let file = self.0 + .filename() + .and_then(|p| Some(BytesOrWideString::Bytes(p.to_str()?.as_bytes()))); + let line = self.0.lineno(); + + if let Some(ref name) = name { d.entry(&"function", name); } + if let Some(ref file) = file { d.entry(&"file", file); } + if let Some(ref line) = line { d.entry(&"line", line); } + d.finish() + } +} + /// A formatter for backtraces. /// /// This type can be used to print a backtrace regardless of where the backtrace From 5393e9ed21674d545bdc86049e2e3398fa55563e Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Wed, 16 Oct 2019 13:33:06 -0500 Subject: [PATCH 02/13] Revert "Implemented Debug newtypes for BacktraceFrame and BacktraceSymbol" This reverts commit 46644de66cd3c46a268f21f55aad4968ce222030. --- src/capture.rs | 42 +++++++++++++++++++++++++++++-------- src/lib.rs | 2 +- src/print.rs | 57 -------------------------------------------------- 3 files changed, 34 insertions(+), 67 deletions(-) diff --git a/src/capture.rs b/src/capture.rs index c9f89c332..7b37bd1bc 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -1,4 +1,5 @@ -use crate::{resolve, resolve_frame, trace, DebugBacktraceFrame, Symbol, SymbolName}; +use crate::PrintFmt; +use crate::{resolve, resolve_frame, trace, BacktraceFmt, Symbol, SymbolName}; use std::ffi::c_void; use std::fmt; use std::path::{Path, PathBuf}; @@ -321,18 +322,41 @@ impl BacktraceSymbol { pub fn lineno(&self) -> Option { self.lineno } - - /// Returns whether the BacktraceSymbol has any data associated with it - pub fn is_empty(&self) -> bool { - self.name.is_none() && self.addr.is_none() && self.filename.is_none() && self.lineno.is_none() - } } impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_list() - .entries(self.frames().iter().flat_map(|frame| DebugBacktraceFrame::new(frame).symbols_skip_empty())) - .finish() + let full = fmt.alternate(); + let (frames, style) = if full { + (&self.frames[..], PrintFmt::Full) + } else { + (&self.frames[self.actual_start_index..], PrintFmt::Short) + }; + + // When printing paths we try to strip the cwd if it exists, otherwise + // we just print the path as-is. Note that we also only do this for the + // short format, because if it's full we presumably want to print + // everything. + let cwd = std::env::current_dir(); + let mut print_path = move |fmt: &mut fmt::Formatter, path: crate::BytesOrWideString| { + let path = path.into_path_buf(); + if !full { + if let Ok(cwd) = &cwd { + if let Ok(suffix) = path.strip_prefix(cwd) { + return fmt::Display::fmt(&suffix.display(), fmt); + } + } + } + fmt::Display::fmt(&path.display(), fmt) + }; + + let mut f = BacktraceFmt::new(fmt, style, &mut print_path); + f.add_context()?; + for frame in frames { + f.frame().backtrace_frame(frame)?; + } + f.finish()?; + Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 56b712b4f..69a283e67 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,7 +90,7 @@ mod types; pub use crate::symbolize::clear_symbol_cache; mod print; -pub use print::{BacktraceFmt, BacktraceFrameFmt, DebugBacktraceFrame, PrintFmt}; +pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt}; cfg_if::cfg_if! { if #[cfg(feature = "std")] { diff --git a/src/print.rs b/src/print.rs index 9482e4058..ce26f962e 100644 --- a/src/print.rs +++ b/src/print.rs @@ -7,63 +7,6 @@ const HEX_WIDTH: usize = 2 + 2 * core::mem::size_of::(); #[cfg(target_os = "fuchsia")] mod fuchsia; -/// A formatter for BacktraceFrames. -pub struct DebugBacktraceFrame<'a>(&'a crate::BacktraceFrame); - -impl<'a> DebugBacktraceFrame<'a> { - #[allow(missing_docs)] - pub fn new(frame: &'a crate::BacktraceFrame) -> Self { - Self(frame) - } - - /// Iterates over symbols in wrapped BacktraceFrame, and wraps them in DebugBacktraceSymbols. - pub fn symbols(&self) -> std::vec::Vec> { - self.0.symbols().iter().map(DebugBacktraceSymbol::new).collect() - } - - /// Same as symbols(), but filters out symbols that have no data - pub fn symbols_skip_empty(&self) -> std::vec::Vec> { - self.0.symbols().iter().filter(|symbol| !symbol.is_empty()).map(DebugBacktraceSymbol::new).collect() - } -} - -impl<'a> fmt::Debug for DebugBacktraceFrame<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut d = f.debug_list(); - if !self.0.symbols().is_empty() { - d.entries(self.0.symbols().iter().map(|symbol| DebugBacktraceSymbol::new(symbol))); - } - d.finish() - } -} - -/// A formatter for BacktraceSymbols. -pub struct DebugBacktraceSymbol<'a>(&'a crate::BacktraceSymbol); - -impl<'a> DebugBacktraceSymbol<'a> { - /// Create a new DebugBacktraceSymbol. - pub fn new(frame: &'a crate::BacktraceSymbol) -> Self { - Self(frame) - } -} - -impl<'a> fmt::Debug for DebugBacktraceSymbol<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.0.name().is_none() { return Ok(()); } - let mut d = f.debug_map(); - let name = self.0.name(); - let file = self.0 - .filename() - .and_then(|p| Some(BytesOrWideString::Bytes(p.to_str()?.as_bytes()))); - let line = self.0.lineno(); - - if let Some(ref name) = name { d.entry(&"function", name); } - if let Some(ref file) = file { d.entry(&"file", file); } - if let Some(ref line) = line { d.entry(&"line", line); } - d.finish() - } -} - /// A formatter for backtraces. /// /// This type can be used to print a backtrace regardless of where the backtrace From 569821326d4af476fd16efc5d7675bdca11893cb Mon Sep 17 00:00:00 2001 From: 0paIescent <35069603+0paIescent@users.noreply.github.com> Date: Thu, 17 Oct 2019 11:41:59 -0500 Subject: [PATCH 03/13] added new_debug branch to on push workflows trigger --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cd0fc4bf9..002c4ab99 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - new_debug pull_request: branches: - master From c509ab16d5dfc13aabbb60ed057f3f6541fc40c6 Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Wed, 16 Oct 2019 13:40:20 -0500 Subject: [PATCH 04/13] Implemented Debug newtypes for BacktraceFrame and BacktraceSymbol --- src/capture.rs | 42 ++++++++----------------------------- src/lib.rs | 2 +- src/print.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/capture.rs b/src/capture.rs index 7b37bd1bc..c9f89c332 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -1,5 +1,4 @@ -use crate::PrintFmt; -use crate::{resolve, resolve_frame, trace, BacktraceFmt, Symbol, SymbolName}; +use crate::{resolve, resolve_frame, trace, DebugBacktraceFrame, Symbol, SymbolName}; use std::ffi::c_void; use std::fmt; use std::path::{Path, PathBuf}; @@ -322,41 +321,18 @@ impl BacktraceSymbol { pub fn lineno(&self) -> Option { self.lineno } + + /// Returns whether the BacktraceSymbol has any data associated with it + pub fn is_empty(&self) -> bool { + self.name.is_none() && self.addr.is_none() && self.filename.is_none() && self.lineno.is_none() + } } impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let full = fmt.alternate(); - let (frames, style) = if full { - (&self.frames[..], PrintFmt::Full) - } else { - (&self.frames[self.actual_start_index..], PrintFmt::Short) - }; - - // When printing paths we try to strip the cwd if it exists, otherwise - // we just print the path as-is. Note that we also only do this for the - // short format, because if it's full we presumably want to print - // everything. - let cwd = std::env::current_dir(); - let mut print_path = move |fmt: &mut fmt::Formatter, path: crate::BytesOrWideString| { - let path = path.into_path_buf(); - if !full { - if let Ok(cwd) = &cwd { - if let Ok(suffix) = path.strip_prefix(cwd) { - return fmt::Display::fmt(&suffix.display(), fmt); - } - } - } - fmt::Display::fmt(&path.display(), fmt) - }; - - let mut f = BacktraceFmt::new(fmt, style, &mut print_path); - f.add_context()?; - for frame in frames { - f.frame().backtrace_frame(frame)?; - } - f.finish()?; - Ok(()) + fmt.debug_list() + .entries(self.frames().iter().flat_map(|frame| DebugBacktraceFrame::new(frame).symbols_skip_empty())) + .finish() } } diff --git a/src/lib.rs b/src/lib.rs index 69a283e67..56b712b4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,7 +90,7 @@ mod types; pub use crate::symbolize::clear_symbol_cache; mod print; -pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt}; +pub use print::{BacktraceFmt, BacktraceFrameFmt, DebugBacktraceFrame, PrintFmt}; cfg_if::cfg_if! { if #[cfg(feature = "std")] { diff --git a/src/print.rs b/src/print.rs index ce26f962e..9482e4058 100644 --- a/src/print.rs +++ b/src/print.rs @@ -7,6 +7,63 @@ const HEX_WIDTH: usize = 2 + 2 * core::mem::size_of::(); #[cfg(target_os = "fuchsia")] mod fuchsia; +/// A formatter for BacktraceFrames. +pub struct DebugBacktraceFrame<'a>(&'a crate::BacktraceFrame); + +impl<'a> DebugBacktraceFrame<'a> { + #[allow(missing_docs)] + pub fn new(frame: &'a crate::BacktraceFrame) -> Self { + Self(frame) + } + + /// Iterates over symbols in wrapped BacktraceFrame, and wraps them in DebugBacktraceSymbols. + pub fn symbols(&self) -> std::vec::Vec> { + self.0.symbols().iter().map(DebugBacktraceSymbol::new).collect() + } + + /// Same as symbols(), but filters out symbols that have no data + pub fn symbols_skip_empty(&self) -> std::vec::Vec> { + self.0.symbols().iter().filter(|symbol| !symbol.is_empty()).map(DebugBacktraceSymbol::new).collect() + } +} + +impl<'a> fmt::Debug for DebugBacktraceFrame<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut d = f.debug_list(); + if !self.0.symbols().is_empty() { + d.entries(self.0.symbols().iter().map(|symbol| DebugBacktraceSymbol::new(symbol))); + } + d.finish() + } +} + +/// A formatter for BacktraceSymbols. +pub struct DebugBacktraceSymbol<'a>(&'a crate::BacktraceSymbol); + +impl<'a> DebugBacktraceSymbol<'a> { + /// Create a new DebugBacktraceSymbol. + pub fn new(frame: &'a crate::BacktraceSymbol) -> Self { + Self(frame) + } +} + +impl<'a> fmt::Debug for DebugBacktraceSymbol<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.0.name().is_none() { return Ok(()); } + let mut d = f.debug_map(); + let name = self.0.name(); + let file = self.0 + .filename() + .and_then(|p| Some(BytesOrWideString::Bytes(p.to_str()?.as_bytes()))); + let line = self.0.lineno(); + + if let Some(ref name) = name { d.entry(&"function", name); } + if let Some(ref file) = file { d.entry(&"file", file); } + if let Some(ref line) = line { d.entry(&"line", line); } + d.finish() + } +} + /// A formatter for backtraces. /// /// This type can be used to print a backtrace regardless of where the backtrace From 35a5a94d75a6c9b173ce778cb0cc053bcb88131b Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Thu, 17 Oct 2019 10:54:44 -0500 Subject: [PATCH 05/13] Removed DebugBacktraceFrame and DebugBacktraceSymbol, added is_first_frame field to BacktraceFrameFmt, and resorted back to previous method of printing just with some new formatting. --- examples/backtrace.rs | 4 +- src/capture.rs | 43 +++++++++++++-- src/lib.rs | 2 +- src/print.rs | 118 ++++++++++-------------------------------- 4 files changed, 70 insertions(+), 97 deletions(-) diff --git a/examples/backtrace.rs b/examples/backtrace.rs index 7f9042ed7..4cd2696c4 100644 --- a/examples/backtrace.rs +++ b/examples/backtrace.rs @@ -3,5 +3,7 @@ extern crate backtrace; use backtrace::Backtrace; fn main() { - println!("{:?}", Backtrace::new()); + let backtrace = Backtrace::new(); + println!("No Precision:\n{:?}\n", backtrace); + println!("Precision of 4:\n{:.4?}", backtrace); } diff --git a/src/capture.rs b/src/capture.rs index c9f89c332..306cdcc08 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -1,4 +1,4 @@ -use crate::{resolve, resolve_frame, trace, DebugBacktraceFrame, Symbol, SymbolName}; +use crate::{resolve, resolve_frame, trace, BacktraceFmt, PrintFmt, Symbol, SymbolName}; use std::ffi::c_void; use std::fmt; use std::path::{Path, PathBuf}; @@ -330,9 +330,44 @@ impl BacktraceSymbol { impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_list() - .entries(self.frames().iter().flat_map(|frame| DebugBacktraceFrame::new(frame).symbols_skip_empty())) - .finish() + let full = fmt.alternate(); + let precision = fmt.precision(); + + let (frames, style) = if full { + (&self.frames[..], PrintFmt::Full) + } else { + (&self.frames[self.actual_start_index..], PrintFmt::Short) + }; + + let frames = match precision { + Some(precision) => &frames[..precision], + None => frames, + }; + + // When printing paths we try to strip the cwd if it exists, otherwise + // we just print the path as-is. Note that we also only do this for the + // short format, because if it's full we presumably want to print + // everything. + let cwd = std::env::current_dir(); + let mut print_path = move |fmt: &mut fmt::Formatter, path: crate::BytesOrWideString| { + let path = path.into_path_buf(); + if !full { + if let Ok(cwd) = &cwd { + if let Ok(suffix) = path.strip_prefix(cwd) { + return fmt::Display::fmt(&suffix.display(), fmt); + } + } + } + fmt::Display::fmt(&path.display(), fmt) + }; + + let mut f = BacktraceFmt::new(fmt, style, &mut print_path); + f.add_context()?; + for frame in frames { + f.frame().backtrace_frame(frame)?; + } + f.finish()?; + Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 56b712b4f..69a283e67 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,7 +90,7 @@ mod types; pub use crate::symbolize::clear_symbol_cache; mod print; -pub use print::{BacktraceFmt, BacktraceFrameFmt, DebugBacktraceFrame, PrintFmt}; +pub use print::{BacktraceFmt, BacktraceFrameFmt, PrintFmt}; cfg_if::cfg_if! { if #[cfg(feature = "std")] { diff --git a/src/print.rs b/src/print.rs index 9482e4058..1d78ce1dd 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,69 +1,11 @@ use crate::BytesOrWideString; use core::ffi::c_void; use core::fmt; - -const HEX_WIDTH: usize = 2 + 2 * core::mem::size_of::(); +use cfg_if::cfg_if; #[cfg(target_os = "fuchsia")] mod fuchsia; -/// A formatter for BacktraceFrames. -pub struct DebugBacktraceFrame<'a>(&'a crate::BacktraceFrame); - -impl<'a> DebugBacktraceFrame<'a> { - #[allow(missing_docs)] - pub fn new(frame: &'a crate::BacktraceFrame) -> Self { - Self(frame) - } - - /// Iterates over symbols in wrapped BacktraceFrame, and wraps them in DebugBacktraceSymbols. - pub fn symbols(&self) -> std::vec::Vec> { - self.0.symbols().iter().map(DebugBacktraceSymbol::new).collect() - } - - /// Same as symbols(), but filters out symbols that have no data - pub fn symbols_skip_empty(&self) -> std::vec::Vec> { - self.0.symbols().iter().filter(|symbol| !symbol.is_empty()).map(DebugBacktraceSymbol::new).collect() - } -} - -impl<'a> fmt::Debug for DebugBacktraceFrame<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut d = f.debug_list(); - if !self.0.symbols().is_empty() { - d.entries(self.0.symbols().iter().map(|symbol| DebugBacktraceSymbol::new(symbol))); - } - d.finish() - } -} - -/// A formatter for BacktraceSymbols. -pub struct DebugBacktraceSymbol<'a>(&'a crate::BacktraceSymbol); - -impl<'a> DebugBacktraceSymbol<'a> { - /// Create a new DebugBacktraceSymbol. - pub fn new(frame: &'a crate::BacktraceSymbol) -> Self { - Self(frame) - } -} - -impl<'a> fmt::Debug for DebugBacktraceSymbol<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.0.name().is_none() { return Ok(()); } - let mut d = f.debug_map(); - let name = self.0.name(); - let file = self.0 - .filename() - .and_then(|p| Some(BytesOrWideString::Bytes(p.to_str()?.as_bytes()))); - let line = self.0.lineno(); - - if let Some(ref name) = name { d.entry(&"function", name); } - if let Some(ref file) = file { d.entry(&"file", file); } - if let Some(ref line) = line { d.entry(&"line", line); } - d.finish() - } -} - /// A formatter for backtraces. /// /// This type can be used to print a backtrace regardless of where the backtrace @@ -114,9 +56,13 @@ impl<'a, 'b> BacktraceFmt<'a, 'b> { /// sumbolicated later, and otherwise this should just be the first method /// you call after creating a `BacktraceFmt`. pub fn add_context(&mut self) -> fmt::Result { - self.fmt.write_str("stack backtrace:\n")?; - #[cfg(target_os = "fuchsia")] - fuchsia::print_dso_context(self.fmt)?; + cfg_if! { + if #[cfg(target_os = "fuchsia")] { + fuchsia::print_dso_context(self.fmt)?; + } else { + self.fmt.write_str("[")?; + } + } Ok(()) } @@ -126,18 +72,20 @@ impl<'a, 'b> BacktraceFmt<'a, 'b> { /// to actually print a frame, and on destruction it will increment the /// frame counter. pub fn frame(&mut self) -> BacktraceFrameFmt<'_, 'a, 'b> { + let is_first_frame = self.frame_index == 0; BacktraceFrameFmt { fmt: self, + is_first_frame, symbol_index: 0, } } /// Completes the backtrace output. - /// - /// This is currently a no-op but is added for future compatibility with - /// backtrace formats. + /// + /// If not running on fuchsia, then close the list, otherwise this is a no-op. pub fn finish(&mut self) -> fmt::Result { - // Currently a no-op-- including this hook to allow for future additions. + #[cfg(not(target_os = "fuchsia"))] + self.fmt.write_str("]")?; Ok(()) } } @@ -147,6 +95,7 @@ impl<'a, 'b> BacktraceFmt<'a, 'b> { /// This type is created by the `BacktraceFmt::frame` function. pub struct BacktraceFrameFmt<'fmt, 'a, 'b> { fmt: &'fmt mut BacktraceFmt<'a, 'b>, + is_first_frame: bool, symbol_index: usize, } @@ -259,51 +208,38 @@ impl BacktraceFrameFmt<'_, '_, '_> { frame_ip = usize::wrapping_sub(frame_ip as usize, image_base as _) as _; } - // Print the index of the frame as well as the optional instruction - // pointer of the frame. If we're beyond the first symbol of this frame - // though we just print appropriate whitespace. - if self.symbol_index == 0 { - write!(self.fmt.fmt, "{:4}: ", self.fmt.frame_index)?; - if let PrintFmt::Full = self.fmt.format { - write!(self.fmt.fmt, "{:1$?} - ", frame_ip, HEX_WIDTH)?; - } - } else { - write!(self.fmt.fmt, " ")?; - if let PrintFmt::Full = self.fmt.format { - write!(self.fmt.fmt, "{:1$}", "", HEX_WIDTH + 3)?; - } + // If we are not printing the first frame, print a comma and space before opening the "map" + if !self.is_first_frame { + self.fmt.fmt.write_str(", ")?; } + self.fmt.fmt.write_str("{ ")?; // Next up write out the symbol name, using the alternate formatting for // more information if we're a full backtrace. Here we also handle // symbols which don't have a name, match (symbol_name, &self.fmt.format) { - (Some(name), PrintFmt::Short) => write!(self.fmt.fmt, "{:#}", name)?, - (Some(name), PrintFmt::Full) => write!(self.fmt.fmt, "{}", name)?, - (None, _) | (_, PrintFmt::__Nonexhaustive) => write!(self.fmt.fmt, "")?, + (Some(name), PrintFmt::Short) => write!(self.fmt.fmt, "function: \"{:#}\"", name)?, + (Some(name), PrintFmt::Full) => write!(self.fmt.fmt, "function: \"{}\"", name)?, + (None, _) | (_, PrintFmt::__Nonexhaustive) => write!(self.fmt.fmt, "function: \"\"")?, } - self.fmt.fmt.write_str("\n")?; // And last up, print out the filename/line number if they're available. if let (Some(file), Some(line)) = (filename, lineno) { self.print_fileline(file, line)?; } + // Close the "map" + self.fmt.fmt.write_str(" }")?; + Ok(()) } fn print_fileline(&mut self, file: BytesOrWideString, line: u32) -> fmt::Result { - // Filename/line are printed on lines under the symbol name, so print - // some appropriate whitespace to sort of right-align ourselves. - if let PrintFmt::Full = self.fmt.format { - write!(self.fmt.fmt, "{:1$}", "", HEX_WIDTH)?; - } - write!(self.fmt.fmt, " at ")?; - // Delegate to our internal callback to print the filename and then // print out the line number. + self.fmt.fmt.write_str(", file: \"")?; (self.fmt.print_path)(self.fmt.fmt, file)?; - write!(self.fmt.fmt, ":{}\n", line)?; + write!(self.fmt.fmt, "\", line :{}", line)?; Ok(()) } From 5cdf76bbb5d06531a6fa81d67522fc9ff292788c Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Thu, 17 Oct 2019 11:31:44 -0500 Subject: [PATCH 06/13] Added pretty print examples and fixed an out of place comma in the line output. --- examples/backtrace.rs | 4 +++- src/print.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/backtrace.rs b/examples/backtrace.rs index 4cd2696c4..6a210fe27 100644 --- a/examples/backtrace.rs +++ b/examples/backtrace.rs @@ -5,5 +5,7 @@ use backtrace::Backtrace; fn main() { let backtrace = Backtrace::new(); println!("No Precision:\n{:?}\n", backtrace); - println!("Precision of 4:\n{:.4?}", backtrace); + println!("No Precision Pretty:\n{:#?}\n", backtrace); + println!("Precision of 4:\n{:.4?}\n", backtrace); + println!("Precision of 4 Pretty:\n{:#.4?}", backtrace); } diff --git a/src/print.rs b/src/print.rs index 1d78ce1dd..415b58359 100644 --- a/src/print.rs +++ b/src/print.rs @@ -239,7 +239,7 @@ impl BacktraceFrameFmt<'_, '_, '_> { // print out the line number. self.fmt.fmt.write_str(", file: \"")?; (self.fmt.print_path)(self.fmt.fmt, file)?; - write!(self.fmt.fmt, "\", line :{}", line)?; + write!(self.fmt.fmt, "\", line: {}", line)?; Ok(()) } From 2b040313b65ef34be2db00e47f965654b10a6540 Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Thu, 17 Oct 2019 11:38:41 -0500 Subject: [PATCH 07/13] CI --- examples/backtrace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/backtrace.rs b/examples/backtrace.rs index 6a210fe27..d4b8c22c2 100644 --- a/examples/backtrace.rs +++ b/examples/backtrace.rs @@ -8,4 +8,4 @@ fn main() { println!("No Precision Pretty:\n{:#?}\n", backtrace); println!("Precision of 4:\n{:.4?}\n", backtrace); println!("Precision of 4 Pretty:\n{:#.4?}", backtrace); -} +} \ No newline at end of file From 9f5698fa366219c90aaa1ade063b4e311d8942bb Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Fri, 18 Oct 2019 09:38:44 -0500 Subject: [PATCH 08/13] Change method of printing the filepath --- src/capture.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/capture.rs b/src/capture.rs index 306cdcc08..90067e728 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -354,11 +354,11 @@ impl fmt::Debug for Backtrace { if !full { if let Ok(cwd) = &cwd { if let Ok(suffix) = path.strip_prefix(cwd) { - return fmt::Display::fmt(&suffix.display(), fmt); + return write!(fmt, "{}", &suffix.display()); } } } - fmt::Display::fmt(&path.display(), fmt) + write!(fmt, "{}", &path.display()) }; let mut f = BacktraceFmt::new(fmt, style, &mut print_path); From 2bca99678743d7798f786123076f784a78674a00 Mon Sep 17 00:00:00 2001 From: 0paIescent <35069603+0paIescent@users.noreply.github.com> Date: Thu, 17 Oct 2019 11:43:14 -0500 Subject: [PATCH 09/13] added new_debug to workflow branches on push trigger From e25829eb9216456fb44b240f59dab1e2436045d2 Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Fri, 18 Oct 2019 09:45:00 -0500 Subject: [PATCH 10/13] rustfmt --- examples/backtrace.rs | 2 +- src/print.rs | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/backtrace.rs b/examples/backtrace.rs index d4b8c22c2..6a210fe27 100644 --- a/examples/backtrace.rs +++ b/examples/backtrace.rs @@ -8,4 +8,4 @@ fn main() { println!("No Precision Pretty:\n{:#?}\n", backtrace); println!("Precision of 4:\n{:.4?}\n", backtrace); println!("Precision of 4 Pretty:\n{:#.4?}", backtrace); -} \ No newline at end of file +} diff --git a/src/print.rs b/src/print.rs index 415b58359..7077fe1b1 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,7 +1,7 @@ use crate::BytesOrWideString; +use cfg_if::cfg_if; use core::ffi::c_void; use core::fmt; -use cfg_if::cfg_if; #[cfg(target_os = "fuchsia")] mod fuchsia; @@ -81,7 +81,7 @@ impl<'a, 'b> BacktraceFmt<'a, 'b> { } /// Completes the backtrace output. - /// + /// /// If not running on fuchsia, then close the list, otherwise this is a no-op. pub fn finish(&mut self) -> fmt::Result { #[cfg(not(target_os = "fuchsia"))] @@ -220,7 +220,9 @@ impl BacktraceFrameFmt<'_, '_, '_> { match (symbol_name, &self.fmt.format) { (Some(name), PrintFmt::Short) => write!(self.fmt.fmt, "function: \"{:#}\"", name)?, (Some(name), PrintFmt::Full) => write!(self.fmt.fmt, "function: \"{}\"", name)?, - (None, _) | (_, PrintFmt::__Nonexhaustive) => write!(self.fmt.fmt, "function: \"\"")?, + (None, _) | (_, PrintFmt::__Nonexhaustive) => { + write!(self.fmt.fmt, "function: \"\"")? + } } // And last up, print out the filename/line number if they're available. From 3184c77b877034b24c21751fe2735e19c777a6c2 Mon Sep 17 00:00:00 2001 From: 0paIescent <35069603+0paIescent@users.noreply.github.com> Date: Fri, 18 Oct 2019 10:14:33 -0500 Subject: [PATCH 11/13] Update main.yml --- .github/workflows/main.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 002c4ab99..a864e6f0e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,11 +3,10 @@ name: CI on: push: branches: - - master - new_debug pull_request: branches: - - master + - new_debug jobs: test: From 251ea4285f8b905bfc62146872e3b6d5f32715c3 Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Mon, 21 Oct 2019 09:56:32 -0500 Subject: [PATCH 12/13] Updated workflow --- .github/workflows/main.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a864e6f0e..5dcda59f6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,10 +3,10 @@ name: CI on: push: branches: - - new_debug + - master pull_request: branches: - - new_debug + - master jobs: test: @@ -43,7 +43,7 @@ jobs: os: windows-latest rust: nightly-i686-gnu steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@master with: submodules: true - name: Install Rust (rustup) @@ -86,7 +86,7 @@ jobs: name: Windows AArch64 runs-on: windows-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@master with: submodules: true - name: Install Rust @@ -119,7 +119,7 @@ jobs: - target: x86_64-apple-ios sdk: iphonesimulator steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@master with: submodules: true - name: Install Rust ( @@ -154,7 +154,7 @@ jobs: - i686-linux-android - x86_64-linux-android steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@master with: submodules: true - name: Install Rust @@ -167,7 +167,7 @@ jobs: name: Rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@master with: submodules: true - name: Install Rust @@ -181,7 +181,7 @@ jobs: matrix: target: [wasm32-unknown-unknown, wasm32-wasi, x86_64-fuchsia, x86_64-fortanix-unknown-sgx] steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@master with: submodules: true - name: Install Rust @@ -193,7 +193,7 @@ jobs: name: MSRV runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@master with: submodules: true - name: Install Rust From f4c13110d74cce0431e412908bc4000544f64543 Mon Sep 17 00:00:00 2001 From: Andrew DeFilippo <0palescent@protonmail.com> Date: Mon, 21 Oct 2019 09:58:25 -0500 Subject: [PATCH 13/13] Removed is_empty from BacktraceSymbol that was added earlier --- src/capture.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/capture.rs b/src/capture.rs index 90067e728..094cec278 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -321,11 +321,6 @@ impl BacktraceSymbol { pub fn lineno(&self) -> Option { self.lineno } - - /// Returns whether the BacktraceSymbol has any data associated with it - pub fn is_empty(&self) -> bool { - self.name.is_none() && self.addr.is_none() && self.filename.is_none() && self.lineno.is_none() - } } impl fmt::Debug for Backtrace {