Crates.io | wholesym |
lib.rs | wholesym |
version | 0.7.0 |
source | src |
created_at | 2022-12-08 20:36:03.988958 |
updated_at | 2024-06-28 18:16:47.028419 |
description | A complete solution for fetching symbol files and resolving code addresses to symbols and debuginfo. |
homepage | https://github.com/mstange/samply/tree/main/wholesym |
repository | https://github.com/mstange/samply |
max_upload_size | |
id | 732800 |
size | 125,427 |
wholesym
is a fully-featured library for fetching symbol files and for
resolving code addresses to symbols and debug info. It supports Windows, macOS
and Linux. It is lightning-fast and optimized for minimal time-to-first-symbol.
Use it as follows:
SymbolManager
] using [SymbolManager::with_config
].SymbolMap
] with [SymbolManager::load_symbol_map_for_binary_at_path
].SymbolMap::lookup_relative_address
].AddressInfo
], which gives you the symbol name, and
potentially file and line information, along with inlined function info.Behind the scenes, wholesym
loads symbol files much like a debugger would.
It supports symbol servers, collecting information from multiple files, and
all kinds of different ways to embed symbol information in various file formats.
use wholesym::{SymbolManager, SymbolManagerConfig, FramesLookupResult};
use std::path::Path;
# async fn run() -> Result<(), wholesym::Error> {
let symbol_manager = SymbolManager::with_config(SymbolManagerConfig::default());
let symbol_map = symbol_manager
.load_symbol_map_for_binary_at_path(Path::new("/usr/bin/ls"), None)
.await?;
println!("Looking up 0xd6f4 in /usr/bin/ls. Results:");
if let Some(address_info) = symbol_map.lookup_relative_address(0xd6f4) {
println!(
"Symbol: {:#x} {}",
address_info.symbol.address, address_info.symbol.name
);
let frames = match address_info.frames {
FramesLookupResult::Available(frames) => Some(frames),
FramesLookupResult::External(ext_ref) => {
symbol_manager
.lookup_external(&symbol_map.symbol_file_origin(), &ext_ref)
.await
}
FramesLookupResult::Unavailable => None,
};
if let Some(frames) = frames {
for (i, frame) in frames.into_iter().enumerate() {
let function = frame.function.unwrap();
let file = frame.file_path.unwrap().display_path();
let line = frame.line_number.unwrap();
println!(" #{i:02} {function} at {file}:{line}");
}
}
} else {
println!("No symbol for 0xd6f4 was found.");
}
# Ok(())
# }
This example prints the following output on my machine:
Looking up 0xd6f4 in /usr/bin/ls. Results:
Symbol: 0xd5d4 gobble_file.constprop.0
#00 do_lstat at ./src/ls.c:1184
#01 gobble_file at ./src/ls.c:3403
The example demonstrates support for debuglink
and debugaltlink
. It gets the symbol
information from local debug files at
/usr/lib/debug/.build-id/63/260a3e6e46db57abf718f6a3562c6eedccf269.debug
and at /usr/lib/debug/.dwz/aarch64-linux-gnu/coreutils.debug
, which were installed
by the coreutils-dbgsym
package. If these files are not present, it will fall back
to whichever information is available.
Supported symbol file sources:
_NT_SYMBOL_PATH
environment variableUnsupported for now (patches accepted):
/DEBUG:FASTLINK
PDB files (issue #53)Supported symbol file sources:
Unsupported for now (patches accepted):
Supported symbol file sources:
dwz
(using debugaltlink
)DEBUGINFOD_URLS
environment variableThe most computationally intense part of symbol resolution is the parsing of debug info.
Debug info can be very large, for example 700MB to 1500MB for Firefox's libxul.
wholesym
uses the addr2line
and pdb-addr2line
crates for parsing DWARF and PDB, respectively. It also has its own code for parsing the
Breakpad sym format. All of these parsers have been optimized extensively
to minimize the time it takes to get the first symbol result, and to cache
things so that repeated lookups in the same functions are fast. This means: