use fallible_iterator::FallibleIterator;
use gimli;
use ir;
use object::{self, Object};
use std::borrow::{Borrow, Cow};
use traits;
use typed_arena::Arena;
use super::Parse;
mod compilation_unit_parse;
mod die_parse;
use self::compilation_unit_parse::{CompUnitEdgesExtra, CompUnitItemsExtra};
fn load_section<'a, 'file, 'input, Sect, Endian>(
arena: &'a Arena<Cow<'file, [u8]>>,
file: &'file object::File<'input>,
endian: Endian,
) -> Sect
where
Sect: gimli::Section<gimli::EndianSlice<'a, Endian>>,
Endian: gimli::Endianity,
'file: 'input,
'a: 'file,
{
let data = file
.section_data_by_name(Sect::section_name())
.unwrap_or(Cow::Borrowed(&[]));
let data_ref = (*arena.alloc(data)).borrow();
Sect::from(gimli::EndianSlice::new(data_ref, endian))
}
impl<'input> Parse<'input> for object::File<'input> {
type ItemsExtra = ();
fn parse_items(
&self,
items: &mut ir::ItemsBuilder,
_extra: Self::ItemsExtra,
) -> Result<(), traits::Error> {
let arena = Arena::new();
let endian = if self.is_little_endian() {
gimli::RunTimeEndian::Little
} else {
gimli::RunTimeEndian::Big
};
let debug_abbrev: gimli::DebugAbbrev<_> = load_section(&arena, self, endian);
let debug_ranges: gimli::DebugRanges<_> = load_section(&arena, self, endian);
let debug_rnglists: gimli::DebugRngLists<_> = load_section(&arena, self, endian);
let debug_str: gimli::DebugStr<_> = load_section(&arena, self, endian);
let rnglists = &gimli::RangeLists::new(debug_ranges, debug_rnglists)?;
let debug_info: gimli::DebugInfo<_> = load_section(&arena, self, endian);
let mut compilation_units = debug_info.units().enumerate();
while let Some((unit_id, unit)) = compilation_units.next()? {
let extra = CompUnitItemsExtra {
unit_id,
debug_abbrev,
debug_str,
rnglists,
};
unit.parse_items(items, extra)?
}
Ok(())
}
type EdgesExtra = ();
fn parse_edges(
&self,
items: &mut ir::ItemsBuilder,
_extra: Self::EdgesExtra,
) -> Result<(), traits::Error> {
let arena = Arena::new();
let endian = if self.is_little_endian() {
gimli::RunTimeEndian::Little
} else {
gimli::RunTimeEndian::Big
};
let debug_abbrev: gimli::DebugAbbrev<_> = load_section(&arena, self, endian);
let debug_info: gimli::DebugInfo<_> = load_section(&arena, self, endian);
let mut compilation_units = debug_info.units().enumerate();
while let Some((unit_id, unit)) = compilation_units.next()? {
let extra = CompUnitEdgesExtra {
unit_id,
debug_abbrev,
};
unit.parse_edges(items, extra)?
}
Ok(())
}
}