use goblin::{elf, mach};
use object::{Object, ObjectTarget};
use elf::{find_elf_section, has_elf_section};
use mach::{find_mach_section, has_mach_segment};
pub trait DwarfData {
fn has_dwarf_data(&self) -> bool;
fn get_dwarf_section<'input>(
&'input self,
section: DwarfSection,
) -> Option<DwarfSectionData<'input>>;
}
impl<'input> DwarfData for Object<'input> {
fn has_dwarf_data(&self) -> bool {
match self.target {
ObjectTarget::Elf(ref elf) => has_elf_section(
elf,
elf::section_header::SHT_PROGBITS,
DwarfSection::DebugInfo.elf_name(),
),
ObjectTarget::MachOSingle(ref macho) => has_mach_segment(macho, "__DWARF"),
ObjectTarget::MachOFat(_, ref macho) => has_mach_segment(macho, "__DWARF"),
_ => false,
}
}
fn get_dwarf_section<'data>(
&'data self,
section: DwarfSection,
) -> Option<DwarfSectionData<'data>> {
match self.target {
ObjectTarget::Elf(ref elf) => read_elf_dwarf_section(elf, self.as_bytes(), section),
ObjectTarget::MachOSingle(ref macho) => read_mach_dwarf_section(macho, section),
ObjectTarget::MachOFat(_, ref macho) => read_mach_dwarf_section(macho, section),
_ => None,
}
}
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub enum DwarfSection {
EhFrame,
DebugFrame,
DebugAbbrev,
DebugAranges,
DebugLine,
DebugLoc,
DebugPubNames,
DebugRanges,
DebugStr,
DebugInfo,
DebugTypes,
}
impl DwarfSection {
pub fn elf_name(&self) -> &'static str {
match *self {
DwarfSection::EhFrame => ".eh_frame",
DwarfSection::DebugFrame => ".debug_frame",
DwarfSection::DebugAbbrev => ".debug_abbrev",
DwarfSection::DebugAranges => ".debug_aranges",
DwarfSection::DebugLine => ".debug_line",
DwarfSection::DebugLoc => ".debug_loc",
DwarfSection::DebugPubNames => ".debug_pubnames",
DwarfSection::DebugRanges => ".debug_ranges",
DwarfSection::DebugStr => ".debug_str",
DwarfSection::DebugInfo => ".debug_info",
DwarfSection::DebugTypes => ".debug_types",
}
}
pub fn macho_name(&self) -> &'static str {
match *self {
DwarfSection::EhFrame => "__eh_frame",
DwarfSection::DebugFrame => "__debug_frame",
DwarfSection::DebugAbbrev => "__debug_abbrev",
DwarfSection::DebugAranges => "__debug_aranges",
DwarfSection::DebugLine => "__debug_line",
DwarfSection::DebugLoc => "__debug_loc",
DwarfSection::DebugPubNames => "__debug_pubnames",
DwarfSection::DebugRanges => "__debug_ranges",
DwarfSection::DebugStr => "__debug_str",
DwarfSection::DebugInfo => "__debug_info",
DwarfSection::DebugTypes => "__debug_types",
}
}
pub fn name(&self) -> &'static str {
match *self {
DwarfSection::EhFrame => "eh_frame",
DwarfSection::DebugFrame => "debug_frame",
DwarfSection::DebugAbbrev => "debug_abbrev",
DwarfSection::DebugAranges => "debug_aranges",
DwarfSection::DebugLine => "debug_line",
DwarfSection::DebugLoc => "debug_loc",
DwarfSection::DebugPubNames => "debug_pubnames",
DwarfSection::DebugRanges => "debug_ranges",
DwarfSection::DebugStr => "debug_str",
DwarfSection::DebugInfo => "debug_info",
DwarfSection::DebugTypes => "debug_types",
}
}
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct DwarfSectionData<'data> {
section: DwarfSection,
data: &'data [u8],
offset: u64,
}
impl<'data> DwarfSectionData<'data> {
pub fn new(section: DwarfSection, data: &'data [u8], offset: u64) -> DwarfSectionData<'data> {
DwarfSectionData {
section: section,
data: data,
offset: offset,
}
}
pub fn as_bytes(&self) -> &'data [u8] {
self.data
}
pub fn offset(&self) -> u64 {
self.offset
}
pub fn section(&self) -> DwarfSection {
self.section
}
}
fn read_elf_dwarf_section<'data>(
elf: &elf::Elf<'data>,
data: &'data [u8],
sect: DwarfSection,
) -> Option<DwarfSectionData<'data>> {
let sh_type = elf::section_header::SHT_PROGBITS;
find_elf_section(elf, data, sh_type, sect.elf_name())
.map(|section| DwarfSectionData::new(sect, section.data, section.header.sh_offset))
}
fn read_mach_dwarf_section<'data>(
macho: &mach::MachO<'data>,
sect: DwarfSection,
) -> Option<DwarfSectionData<'data>> {
find_mach_section(macho, sect.macho_name())
.map(|section| DwarfSectionData::new(sect, section.data, section.header.offset as u64))
}