Created
September 27, 2017 13:31
-
-
Save mitsuhiko/fb0861ca30295db489c2240f52517b92 to your computer and use it in GitHub Desktop.
This file contains 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
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