Created
June 29, 2020 14:42
-
-
Save helgoboss/1c4f9ef260f5001cd85fbad53d337809 to your computer and use it in GitHub Desktop.
Resolve Rust symbols from address-only backtrace
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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