Skip to content

Commit 58dc01b

Browse files
committed
Add eh_frame debug info parser
1 parent 9262278 commit 58dc01b

File tree

1 file changed

+121
-0
lines changed
  • plugins/dwarf/dwarf_import/src

1 file changed

+121
-0
lines changed

plugins/dwarf/dwarf_import/src/lib.rs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::helpers::{get_attr_die, get_name, get_uid, DieReference};
2626
use crate::types::parse_variable;
2727

2828
use binaryninja::binary_view::BinaryViewBase;
29+
use binaryninja::debuginfo::DebugFunctionInfo;
2930
use binaryninja::{
3031
binary_view::{BinaryView, BinaryViewExt},
3132
debuginfo::{CustomDebugInfoParser, DebugInfo, DebugInfoParser},
@@ -738,6 +739,125 @@ impl CustomDebugInfoParser for DWARFParser {
738739
}
739740
}
740741

742+
743+
struct EhFrameParser;
744+
745+
impl CustomDebugInfoParser for EhFrameParser {
746+
fn is_valid(&self, view: &BinaryView) -> bool {
747+
view.parent_view().is_some() &&
748+
(
749+
view.section_by_name(".eh_frame").is_some() ||
750+
view.section_by_name("__eh_frame").is_some()
751+
)
752+
}
753+
754+
fn parse_info(
755+
&self,
756+
debug_info: &mut DebugInfo,
757+
bv: &BinaryView,
758+
_debug_file: &BinaryView,
759+
_progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>,
760+
) -> bool {
761+
let mut bases = gimli::BaseAddresses::default();
762+
763+
let view_start = bv.start();
764+
765+
if let Some(section) = bv
766+
.section_by_name(".eh_frame_hdr")
767+
.or(bv.section_by_name("__eh_frame_hdr"))
768+
{
769+
bases = bases.set_eh_frame_hdr(section.start() - view_start);
770+
}
771+
772+
if let Some(section) = bv
773+
.section_by_name(".eh_frame")
774+
.or(bv.section_by_name("__eh_frame"))
775+
{
776+
bases = bases.set_eh_frame(section.start() - view_start);
777+
} else if let Some(section) = bv
778+
.section_by_name(".debug_frame")
779+
.or(bv.section_by_name("__debug_frame"))
780+
{
781+
bases = bases.set_eh_frame(section.start() - view_start);
782+
}
783+
784+
if let Some(section) = bv
785+
.section_by_name(".text")
786+
.or(bv.section_by_name("__text"))
787+
{
788+
bases = bases.set_text(section.start() - view_start);
789+
}
790+
791+
if let Some(section) = bv
792+
.section_by_name(".got")
793+
.or(bv.section_by_name("__got"))
794+
{
795+
bases = bases.set_got(section.start() - view_start);
796+
}
797+
798+
let mut cies = HashMap::new();
799+
800+
let eh_frame_endian = get_endian(bv);
801+
let eh_frame_section_reader = |section_id: SectionId| -> _ {
802+
create_section_reader(section_id, bv, eh_frame_endian, false)
803+
};
804+
let mut eh_frame = gimli::EhFrame::load(eh_frame_section_reader).unwrap();
805+
if let Some(view_arch) = bv.default_arch() {
806+
if view_arch.name().as_str() == "aarch64" {
807+
eh_frame.set_vendor(gimli::Vendor::AArch64);
808+
}
809+
}
810+
eh_frame.set_address_size(bv.address_size() as u8);
811+
812+
let mut entries = eh_frame.entries(&bases);
813+
loop {
814+
match entries.next() {
815+
Ok(None) => {
816+
break
817+
},
818+
Ok(Some(gimli::CieOrFde::Cie(_cie))) => {
819+
// TODO: do we want to do anything with standalone CIEs?
820+
}
821+
Ok(Some(gimli::CieOrFde::Fde(partial))) => {
822+
let fde = match partial.parse(|_, bases, o| {
823+
cies.entry(o)
824+
.or_insert_with(|| eh_frame.cie_from_offset(bases, o))
825+
.clone()
826+
}) {
827+
Ok(fde) => fde,
828+
Err(e) => {
829+
error!("Failed to parse FDE: {}", e);
830+
continue;
831+
}
832+
};
833+
834+
let func_addr = view_start + fde.initial_address();
835+
836+
// Do not create a function here if one already exists
837+
if bv.functions_at(func_addr).is_empty() {
838+
debug_info.add_function(&DebugFunctionInfo::new(
839+
None,
840+
None,
841+
None,
842+
None,
843+
Some(func_addr),
844+
None,
845+
vec![],
846+
vec![]
847+
));
848+
}
849+
},
850+
Err(x) => {
851+
error!("{}", x);
852+
return false;
853+
}
854+
}
855+
}
856+
true
857+
}
858+
}
859+
860+
741861
#[no_mangle]
742862
pub extern "C" fn CorePluginInit() -> bool {
743863
Logger::new("DWARF").init();
@@ -802,5 +922,6 @@ pub extern "C" fn CorePluginInit() -> bool {
802922
);
803923

804924
DebugInfoParser::register("DWARF", DWARFParser {});
925+
DebugInfoParser::register("EHFrame", EhFrameParser {});
805926
true
806927
}

0 commit comments

Comments
 (0)