Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to print module_name:offset, or address of frame #44

Merged
merged 5 commits into from Apr 25, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Expand Up @@ -19,8 +19,10 @@ keywords = [
[features]
default = ["gimli-symbolize"]
gimli-symbolize = ["backtrace/gimli-symbolize"]
resolve-modules = ["regex"]

[dependencies]
termcolor = "1.0"
atty = "0.2"
backtrace = "0.3"
regex = { version = "1.4", optional = true }
91 changes: 89 additions & 2 deletions src/lib.rs
Expand Up @@ -156,6 +156,7 @@ pub struct Frame {
pub name: Option<String>,
pub lineno: Option<u32>,
pub filename: Option<PathBuf>,
pub ip: usize,
_private_ctor: (),
}

Expand Down Expand Up @@ -293,12 +294,82 @@ impl Frame {
Ok(())
}

/// Get the module's name by walking /proc/self/maps
#[cfg(all(
feature = "resolve-modules",
unix,
not(any(target_os = "macos", target_os = "ios"))
))]
fn module_info(&self) -> Option<(String, usize)> {
use regex::Regex;
use std::path::Path;
let re = Regex::new(
r"(?x)
^
(?P<start>[0-9a-f]{8,16})
-
(?P<end>[0-9a-f]{8,16})
\s
(?P<perm>[-rwxp]{4})
\s
(?P<offset>[0-9a-f]{8})
\s
[0-9a-f]+:[0-9a-f]+
\s
[0-9]+
\s+
(?P<path>.*)
$
",
)
.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 if let Some(filename) = Path::new(&path).file_name() {
Some((filename.to_str().unwrap().to_string(), start))
} else {
None
};
}
}
}

None
}

#[cfg(all(
feature = "resolve-modules",
any(target_os = "macos", target_os = "ios")
))]
s1341 marked this conversation as resolved.
Show resolved Hide resolved
fn module_info(&self) -> Option<(String, usize)> {
None
}

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(feature = "resolve-modules")]
s1341 marked this conversation as resolved.
Show resolved Hide resolved
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)?;
} 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
Expand Down Expand Up @@ -441,6 +512,7 @@ pub struct BacktracePrinter {
is_panic_handler: bool,
colors: ColorScheme,
filters: Vec<Arc<FilterCallback>>,
should_print_addresses: bool,
}

impl Default for BacktracePrinter {
Expand All @@ -453,6 +525,7 @@ impl Default for BacktracePrinter {
colors: ColorScheme::classic(),
is_panic_handler: false,
filters: vec![Arc::new(default_frame_filter)],
should_print_addresses: false,
}
}
}
Expand All @@ -465,6 +538,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()
}
Expand Down Expand Up @@ -517,6 +591,14 @@ impl BacktracePrinter {
self
}

/// Controls whether addresses (or module offsets if available) should be printed.
///
/// Defaults to `false`.
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.
Expand Down Expand Up @@ -582,13 +664,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();
Expand Down Expand Up @@ -723,6 +806,10 @@ impl BacktracePrinter {
self.lib_verbosity
}
}

fn should_print_addresses(&self) -> bool {
self.should_print_addresses
}
}

// ============================================================================================== //
Expand Down