|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
//! User space probes.
|
|
|
|
|
use libc::pid_t;
|
|
|
|
|
use object::{Object, ObjectSymbol};
|
|
|
|
|
use object::{Object, ObjectSection, ObjectSymbol};
|
|
|
|
|
use std::{
|
|
|
|
|
error::Error,
|
|
|
|
|
ffi::CStr,
|
|
|
|
@ -319,15 +319,41 @@ enum ResolveSymbolError {
|
|
|
|
|
|
|
|
|
|
#[error("unknown symbol `{0}`")]
|
|
|
|
|
Unknown(String),
|
|
|
|
|
|
|
|
|
|
#[error("symbol `{0}` does not appear in section")]
|
|
|
|
|
NotInSection(String),
|
|
|
|
|
|
|
|
|
|
#[error("symbol `{0}` in section `{1:?}` which has no offset")]
|
|
|
|
|
SectionFileRangeNone(String, Result<String, object::Error>),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn resolve_symbol(path: &str, symbol: &str) -> Result<u64, ResolveSymbolError> {
|
|
|
|
|
let data = fs::read(path)?;
|
|
|
|
|
let obj = object::read::File::parse(&*data)?;
|
|
|
|
|
|
|
|
|
|
obj.dynamic_symbols()
|
|
|
|
|
let sym = obj
|
|
|
|
|
.dynamic_symbols()
|
|
|
|
|
.chain(obj.symbols())
|
|
|
|
|
.find(|sym| sym.name().map(|name| name == symbol).unwrap_or(false))
|
|
|
|
|
.map(|s| s.address())
|
|
|
|
|
.ok_or_else(|| ResolveSymbolError::Unknown(symbol.to_string()))
|
|
|
|
|
.ok_or_else(|| ResolveSymbolError::Unknown(symbol.to_string()))?;
|
|
|
|
|
|
|
|
|
|
let needs_addr_translation = matches!(
|
|
|
|
|
obj.kind(),
|
|
|
|
|
object::ObjectKind::Dynamic | object::ObjectKind::Executable
|
|
|
|
|
);
|
|
|
|
|
if !needs_addr_translation {
|
|
|
|
|
Ok(sym.address())
|
|
|
|
|
} else {
|
|
|
|
|
let index = sym
|
|
|
|
|
.section_index()
|
|
|
|
|
.ok_or_else(|| ResolveSymbolError::NotInSection(symbol.to_string()))?;
|
|
|
|
|
let section = obj.section_by_index(index)?;
|
|
|
|
|
let (offset, _size) = section.file_range().ok_or_else(|| {
|
|
|
|
|
ResolveSymbolError::SectionFileRangeNone(
|
|
|
|
|
symbol.to_string(),
|
|
|
|
|
section.name().map(str::to_owned),
|
|
|
|
|
)
|
|
|
|
|
})?;
|
|
|
|
|
Ok(sym.address() - section.address() + offset)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|