From 44ba260f7d5f34e91b5103b8a3a1b95260c8d597 Mon Sep 17 00:00:00 2001 From: s1341 Date: Fri, 23 Apr 2021 11:07:24 +0300 Subject: [PATCH 1/5] Add the ability to print module_name:offset, or address of frame --- Cargo.toml | 2 ++ src/lib.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a3e6042..000b6ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,8 +19,10 @@ keywords = [ [features] default = ["gimli-symbolize"] gimli-symbolize = ["backtrace/gimli-symbolize"] +print-addresses = ["regex"] [dependencies] termcolor = "1.0" atty = "0.2" backtrace = "0.3" +regex = { version = "1.4", optional = true } diff --git a/src/lib.rs b/src/lib.rs index a49f026..74a369a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -156,6 +156,7 @@ pub struct Frame { pub name: Option, pub lineno: Option, pub filename: Option, + pub ip: usize, _private_ctor: (), } @@ -293,12 +294,67 @@ impl Frame { Ok(()) } + /// Get the module's name by walking /proc/self/maps + #[cfg(all( + feature = "print-addresses", + unix, + not(any(target_os = "macos", target_os = "ios")) + ))] + fn module_info(&self) -> Result<(String, usize), String> { + use regex::Regex; + use std::path::Path; + let re = Regex::new(r"^(?P[0-9a-f]{8,16})-(?P[0-9a-f]{8,16}) (?P[-rwxp]{4}) (?P[0-9a-f]{8}) [0-9a-f]+:[0-9a-f]+ [0-9]+\s+(?P.*)$") + .unwrap(); + + let mapsfile = File::open("/proc/self/maps").expect("Unable to open /proc/self/maps"); + + for line in BufReader::new(mapsfile).lines() { + let line = line.unwrap(); + if let Some(caps) = re.captures(&line) { + let (start, end, path) = ( + usize::from_str_radix(caps.name("start").unwrap().as_str(), 16).unwrap(), + usize::from_str_radix(caps.name("end").unwrap().as_str(), 16).unwrap(), + caps.name("path").unwrap().as_str().to_string(), + ); + if self.ip >= start && self.ip < end { + return Ok(( + Path::new(&path) + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string(), + start, + )); + } + } + } + + Err(format!( + "Couldn't locate a module for address: 0x{:016x}", + self.ip + )) + } + fn print(&self, i: usize, out: &mut impl WriteColor, s: &BacktracePrinter) -> IOResult { let is_dependency_code = self.is_dependency_code(); // Print frame index. write!(out, "{:>2}: ", i)?; + #[cfg(all( + feature = "print-addresses", + unix, + not(any(target_os = "macos", target_os = "ios")) + ))] + if s.should_print_addresses() { + if let Ok((module_name, module_base)) = self.module_info() { + write!(out, "{}:0x{:08x} - ", module_name, self.ip - module_base)?; + } else { + write!(out, "0x{:016x} - ", self.ip)?; + } + } + // Does the function have a hash suffix? // (dodging a dep on the regex crate here) let name = self @@ -441,6 +497,7 @@ pub struct BacktracePrinter { is_panic_handler: bool, colors: ColorScheme, filters: Vec>, + should_print_addresses: bool, } impl Default for BacktracePrinter { @@ -453,6 +510,7 @@ impl Default for BacktracePrinter { colors: ColorScheme::classic(), is_panic_handler: false, filters: vec![Arc::new(default_frame_filter)], + should_print_addresses: false, } } } @@ -465,6 +523,7 @@ impl std::fmt::Debug for BacktracePrinter { .field("lib_verbosity", &self.lib_verbosity) .field("strip_function_hash", &self.strip_function_hash) .field("is_panic_handler", &self.is_panic_handler) + .field("print_addresses", &self.should_print_addresses) .field("colors", &self.colors) .finish() } @@ -517,6 +576,19 @@ impl BacktracePrinter { self } + /// Controls whether addresses (or module offsets if available) should be printed. + /// + /// Defaults to `false`. + #[cfg(all( + feature = "print-addresses", + unix, + not(any(target_os = "macos", target_os = "ios")) + ))] + pub fn print_addresses(mut self, val: bool) -> Self { + self.should_print_addresses = val; + self + } + /// Add a custom filter to the set of frame filters /// /// Filters are run in the order they are added. @@ -582,13 +654,14 @@ impl BacktracePrinter { let frames: Vec<_> = trace .frames() .iter() - .flat_map(|frame| frame.symbols()) + .flat_map(|frame| frame.symbols().iter().map(move |sym| (frame.ip(), sym))) .zip(1usize..) - .map(|(sym, n)| Frame { + .map(|((ip, sym), n)| Frame { name: sym.name().map(|x| x.to_string()), lineno: sym.lineno(), filename: sym.filename().map(|x| x.into()), n, + ip: ip as usize, _private_ctor: (), }) .collect(); @@ -723,6 +796,15 @@ impl BacktracePrinter { self.lib_verbosity } } + + #[cfg(all( + feature = "print-addresses", + unix, + not(any(target_os = "macos", target_os = "ios")) + ))] + fn should_print_addresses(&self) -> bool { + self.should_print_addresses + } } // ============================================================================================== // From d3f4bc40c5a5ec957eb99cb1ddf28f9fc66e4d0d Mon Sep 17 00:00:00 2001 From: s1341 Date: Sun, 25 Apr 2021 12:53:51 +0300 Subject: [PATCH 2/5] Resolve review issues --- Cargo.toml | 2 +- src/lib.rs | 59 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 000b6ca..56e12ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ keywords = [ [features] default = ["gimli-symbolize"] gimli-symbolize = ["backtrace/gimli-symbolize"] -print-addresses = ["regex"] +resolve-modules = ["regex"] [dependencies] termcolor = "1.0" diff --git a/src/lib.rs b/src/lib.rs index 74a369a..ea95996 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -296,15 +296,33 @@ impl Frame { /// Get the module's name by walking /proc/self/maps #[cfg(all( - feature = "print-addresses", + feature = "resolve-modules", unix, not(any(target_os = "macos", target_os = "ios")) ))] - fn module_info(&self) -> Result<(String, usize), String> { + fn module_info(&self) -> Option<(String, usize)> { use regex::Regex; use std::path::Path; - let re = Regex::new(r"^(?P[0-9a-f]{8,16})-(?P[0-9a-f]{8,16}) (?P[-rwxp]{4}) (?P[0-9a-f]{8}) [0-9a-f]+:[0-9a-f]+ [0-9]+\s+(?P.*)$") - .unwrap(); + let re = Regex::new( + r"(?x) + ^ + (?P[0-9a-f]{8,16}) + - + (?P[0-9a-f]{8,16}) + \s + (?P[-rwxp]{4}) + \s + (?P[0-9a-f]{8}) + \s + [0-9a-f]+:[0-9a-f]+ + \s + [0-9]+ + \s+ + (?P.*) + $ + ", + ) + .unwrap(); let mapsfile = File::open("/proc/self/maps").expect("Unable to open /proc/self/maps"); @@ -317,7 +335,7 @@ impl Frame { caps.name("path").unwrap().as_str().to_string(), ); if self.ip >= start && self.ip < end { - return Ok(( + return Some(( Path::new(&path) .file_name() .unwrap() @@ -330,10 +348,15 @@ impl Frame { } } - Err(format!( - "Couldn't locate a module for address: 0x{:016x}", - self.ip - )) + None + } + + #[cfg(all( + feature = "resolve-modules", + any(target_os = "macos", target_os = "ios") + ))] + fn module_info(&self) -> Option<(String, usize)> { + None } fn print(&self, i: usize, out: &mut impl WriteColor, s: &BacktracePrinter) -> IOResult { @@ -342,13 +365,9 @@ impl Frame { // Print frame index. write!(out, "{:>2}: ", i)?; - #[cfg(all( - feature = "print-addresses", - unix, - not(any(target_os = "macos", target_os = "ios")) - ))] + #[cfg(feature = "resolve-modules")] if s.should_print_addresses() { - if let Ok((module_name, module_base)) = self.module_info() { + if let Some((module_name, module_base)) = self.module_info() { write!(out, "{}:0x{:08x} - ", module_name, self.ip - module_base)?; } else { write!(out, "0x{:016x} - ", self.ip)?; @@ -579,11 +598,6 @@ impl BacktracePrinter { /// Controls whether addresses (or module offsets if available) should be printed. /// /// Defaults to `false`. - #[cfg(all( - feature = "print-addresses", - unix, - not(any(target_os = "macos", target_os = "ios")) - ))] pub fn print_addresses(mut self, val: bool) -> Self { self.should_print_addresses = val; self @@ -797,11 +811,6 @@ impl BacktracePrinter { } } - #[cfg(all( - feature = "print-addresses", - unix, - not(any(target_os = "macos", target_os = "ios")) - ))] fn should_print_addresses(&self) -> bool { self.should_print_addresses } From 940341b4e183b051645c2370af01f3bd77f7b48f Mon Sep 17 00:00:00 2001 From: s1341 Date: Sun, 25 Apr 2021 13:59:48 +0300 Subject: [PATCH 3/5] Fix bug when there is no filename --- src/lib.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ea95996..2da8965 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -335,15 +335,11 @@ impl Frame { caps.name("path").unwrap().as_str().to_string(), ); if self.ip >= start && self.ip < end { - return Some(( - Path::new(&path) - .file_name() - .unwrap() - .to_str() - .unwrap() - .to_string(), - start, - )); + return if let Some(filename) = Path::new(&path).file_name() { + Some((filename.to_str().unwrap().to_string(), start)) + } else { + None + }; } } } From fc26f7258ae0782775dc7f7f0d12844a3e16c8e0 Mon Sep 17 00:00:00 2001 From: s1341 Date: Sun, 25 Apr 2021 17:41:11 +0300 Subject: [PATCH 4/5] Fix cfg condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joel Höner --- src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2da8965..8d12474 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -347,10 +347,11 @@ impl Frame { None } - #[cfg(all( + #[cfg(not(all( feature = "resolve-modules", - any(target_os = "macos", target_os = "ios") - ))] + unix, + not(any(target_os = "macos", target_os = "ios")) + )))] fn module_info(&self) -> Option<(String, usize)> { None } From 2db731e9a94bf5c1ad4570d2660568f926db7375 Mon Sep 17 00:00:00 2001 From: s1341 Date: Sun, 25 Apr 2021 18:07:28 +0300 Subject: [PATCH 5/5] Get rid of feature-flag guard on the printing of addresses/module:offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Joel Höner --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 8d12474..54f4db0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -362,7 +362,6 @@ impl Frame { // Print frame index. write!(out, "{:>2}: ", i)?; - #[cfg(feature = "resolve-modules")] if s.should_print_addresses() { if let Some((module_name, module_base)) = self.module_info() { write!(out, "{}:0x{:08x} - ", module_name, self.ip - module_base)?;