Skip to content

Instantly share code, notes, and snippets.

@mitsuhiko
Created September 27, 2017 13:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mitsuhiko/fb0861ca30295db489c2240f52517b92 to your computer and use it in GitHub Desktop.
Save mitsuhiko/fb0861ca30295db489c2240f52517b92 to your computer and use it in GitHub Desktop.
pub trait Addr {
fn from_u64(addr: u64) -> Self;
fn to_u64(&self) -> u64;
}
#[derive(Copy, Clone, Default, Debug)]
pub struct Addr32 {
val: u32,
}
#[derive(Copy, Clone, Default, Debug)]
pub struct Addr48 {
low: u32,
high: u16,
}
impl Addr for Addr32 {
fn from_u64(addr: u64) -> Addr32 {
Addr32 {
val: addr as u32
}
}
fn to_u64(&self) -> u64 {
self.val as u64
}
}
impl Addr for Addr48 {
fn from_u64(addr: u64) -> Addr48 {
Addr48 {
low: (addr & 0xffffffff) as u32,
high: ((addr >> 32) & 0xffff) as u16,
}
}
fn to_u64(&self) -> u64 {
((self.high as u64) << 32) | self.low as u64
}
}
#[repr(C, packed)]
#[derive(Default, Copy, Clone, Debug)]
pub struct FuncRecord<A: Addr> {
/// The address of the record.
pub addr: A,
/// the length of the function.
pub len: u16,
/// The line record of this function. If it fully overlaps
/// with an inline the record could be ~0
pub line_records: Seg<LineRecord, u16>,
/// The comp dir of the file record
pub comp_dir: Seg<u8, u8>,
/// The ID offset of the parent funciton. Will be ~0 if the function has
/// no parent.
pub parent_offset: u16,
/// The low bits of the ID of the symbol of this function or ~0 if no symbol.
pub symbol_id_low: u16,
/// The high bits of the ID of the symbol of this function or ~0 if no symbol.
pub symbol_id_high: u8,
/// The language of the func record.
pub lang: u8,
}
impl<A: Addr> FuncRecord<A> {
pub fn symbol_id(&self) -> u32 {
((self.symbol_id_high as u32) << 16) | self.symbol_id_low as u32
}
pub fn addr_start(&self) -> u64 {
self.addr.to_u64()
}
pub fn addr_end(&self) -> u64 {
self.addr_start() + self.len as u64
}
pub fn addr_in_range(&self, addr: u64) -> bool {
addr >= self.addr_start() && addr <= self.addr_end()
}
pub fn parent(&self, func_id: usize) -> Option<usize> {
if self.parent_offset == !0 {
None
} else {
Some(func_id + (self.parent_offset as usize))
}
}
}
/// A view of a single function in a sym cache.
pub struct Function<'a> {
cache: &'a SymCache<'a>,
id: u32,
fun: &'a FuncRecord<Addr>,
}
pub struct Functions<'a> {
cache: &'a SymCache<'a>,
idx: usize,
}
impl<'a> Iterator for Functions<'a> {
type Item = Result<Function<'a>>;
fn next(&mut self) -> Option<Result<Function<'a>>> {
let records_32 = itry!(self.cache.function_records_32());
let records_48 = itry!(self.cache.function_records_48());
if let Some(fun) = records_48.get(self.idx) {
self.idx += 1;
Some(Ok(Function {
cache: self.cache,
id: (self.idx - 1) as u32,
fun: fun as &FuncRecord<Addr>,
}))
} else {
None
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment