use std::collections::BTreeSet;
use std::fmt;
use crate::dwarf::{DwarfData, DwarfSection};
use crate::object::{Object, ObjectTarget};
use crate::symbols::SymbolTable;
fn has_dwarf_unwind_info(object: &Object) -> bool {
object.get_dwarf_section(DwarfSection::EhFrame).is_some()
|| object.get_dwarf_section(DwarfSection::DebugFrame).is_some()
}
fn has_breakpad_record(object: &Object, record: &[u8]) -> bool {
for line in object.as_bytes().split(|b| *b == b'\n') {
if line.starts_with(record) {
return true;
}
}
false
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ObjectFeature {
SymbolTable,
DebugInfo,
UnwindInfo,
Mapping,
}
impl fmt::Display for ObjectFeature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ObjectFeature::SymbolTable => write!(f, "symtab"),
ObjectFeature::DebugInfo => write!(f, "debug"),
ObjectFeature::UnwindInfo => write!(f, "unwind"),
ObjectFeature::Mapping => write!(f, "mapping"),
}
}
}
pub trait DebugFeatures {
fn has_symbol_table(&self) -> bool;
fn has_debug_info(&self) -> bool;
fn has_unwind_info(&self) -> bool;
fn has_mapping(&self) -> bool;
fn has_feature(&self, tag: ObjectFeature) -> bool;
fn features(&self) -> BTreeSet<ObjectFeature>;
}
impl<'a> DebugFeatures for Object<'a> {
fn has_symbol_table(&self) -> bool {
self.has_symbols()
}
fn has_debug_info(&self) -> bool {
match self.target {
ObjectTarget::Elf(..) => self.has_dwarf_data(),
ObjectTarget::MachOSingle(..) => self.has_dwarf_data(),
ObjectTarget::MachOFat(..) => self.has_dwarf_data(),
ObjectTarget::Breakpad(..) => has_breakpad_record(self, b"FUNC"),
}
}
fn has_unwind_info(&self) -> bool {
match self.target {
ObjectTarget::Elf(..) => has_dwarf_unwind_info(self),
ObjectTarget::MachOSingle(..) => has_dwarf_unwind_info(self),
ObjectTarget::MachOFat(..) => has_dwarf_unwind_info(self),
ObjectTarget::Breakpad(..) => has_breakpad_record(self, b"STACK"),
}
}
fn has_mapping(&self) -> bool {
false
}
fn has_feature(&self, feature: ObjectFeature) -> bool {
match feature {
ObjectFeature::SymbolTable => self.has_symbol_table(),
ObjectFeature::DebugInfo => self.has_debug_info(),
ObjectFeature::UnwindInfo => self.has_unwind_info(),
ObjectFeature::Mapping => self.has_mapping(),
}
}
fn features(&self) -> BTreeSet<ObjectFeature> {
let mut features = BTreeSet::new();
if self.has_feature(ObjectFeature::SymbolTable) {
features.insert(ObjectFeature::SymbolTable);
}
if self.has_feature(ObjectFeature::DebugInfo) {
features.insert(ObjectFeature::DebugInfo);
}
if self.has_feature(ObjectFeature::UnwindInfo) {
features.insert(ObjectFeature::UnwindInfo);
}
if self.has_feature(ObjectFeature::Mapping) {
features.insert(ObjectFeature::Mapping);
}
features
}
}