@@ -26,6 +26,7 @@ use crate::helpers::{get_attr_die, get_name, get_uid, DieReference};
2626use crate :: types:: parse_variable;
2727
2828use binaryninja:: binary_view:: BinaryViewBase ;
29+ use binaryninja:: debuginfo:: DebugFunctionInfo ;
2930use 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]
742862pub 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