Skip to content

Instantly share code, notes, and snippets.

@helgoboss
Created June 29, 2020 14:42
Show Gist options
  • Save helgoboss/1c4f9ef260f5001cd85fbad53d337809 to your computer and use it in GitHub Desktop.
Save helgoboss/1c4f9ef260f5001cd85fbad53d337809 to your computer and use it in GitHub Desktop.
Resolve Rust symbols from address-only backtrace
use backtrace::Symbol;
use regex::Regex;
/// A (far from perfect) attempt to resolve symbols for an address-only backtrace (e.g. reported by a user which runs your
/// binary without access to debug info).
///
/// Takes a backtrace produced by backtrace-rs which doesn't contain symbols but addresses in hexadecimal form.
/// Tries to resolve all addresses to symbols and prints the result. This only works if this code runs in exactly the same
/// build like the one which produced the original (symbol-less) backtrace AND the symbols are available.
pub fn resolve_symbols_from_address_only_backtrace(text: &str) -> Result<(), &'static str> {
let regex = Regex::new(r" 0x[0-9a-f]+ ")
.map_err(|_| "Couldn't find any addresses (e.g. 0x7ffac481cec1) in text.")?;
let address_strings = regex
.find_iter(text)
.map(|m| m.as_str().trim().trim_start_matches("0x"));
let addresses: Result<Vec<isize>, _> = address_strings
.map(|s| isize::from_str_radix(s, 16).map_err(|_| "invalid address"))
.collect();
resolve_multiple_symbols(&addresses?);
Ok(())
}
fn resolve_multiple_symbols(addresses: &Vec<isize>) {
println!(
"Attempting to resolve symbols for {} addresses...\n\n",
addresses.len()
);
for a in addresses {
print_resolved_symbol(*a);
}
}
fn print_resolved_symbol(address: isize) {
backtrace::resolve(address as _, |sym| {
println!("{}\n\n", format_symbol(sym));
});
}
fn format_symbol(sym: &Symbol) -> String {
let segments: Vec<String> = vec![
sym.addr().map(|a| format!("{:x?}", a as isize)),
sym.name().map(|n| n.to_string()),
sym.filename().map(|p| {
format!(
"{}{}",
p.to_string_lossy(),
sym.lineno()
.map(|n| format!(" (line {})", n))
.unwrap_or_else(|| "".to_string())
)
}),
]
.into_iter()
.flatten()
.collect();
segments.join("\n")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment