@@ -15,7 +15,7 @@ use crate::{
1515 diff:: { ArmArchVersion , ArmR9Usage , DiffObjConfig , display:: InstructionPart } ,
1616 obj:: {
1717 InstructionRef , Relocation , RelocationFlags , ResolvedInstructionRef , ResolvedRelocation ,
18- ScannedInstruction , SymbolFlag , SymbolFlagSet , SymbolKind ,
18+ ScannedInstruction , Section , SectionKind , Symbol , SymbolFlag , SymbolFlagSet , SymbolKind ,
1919 } ,
2020} ;
2121
@@ -32,7 +32,8 @@ impl ArchArm {
3232 let endianness = file. endianness ( ) ;
3333 match file {
3434 object:: File :: Elf32 ( _) => {
35- let disasm_modes = Self :: elf_get_mapping_symbols ( file) ;
35+ // The disasm_modes mapping is populated later in the post_init step so that we have access to merged sections.
36+ let disasm_modes = BTreeMap :: new ( ) ;
3637 let detected_version = Self :: elf_detect_arm_version ( file) ?;
3738 Ok ( Self { disasm_modes, detected_version, endianness } )
3839 }
@@ -73,18 +74,22 @@ impl ArchArm {
7374 Ok ( None )
7475 }
7576
76- fn elf_get_mapping_symbols ( file : & object:: File ) -> BTreeMap < usize , Vec < DisasmMode > > {
77- file. sections ( )
78- . filter ( |s| s. kind ( ) == object:: SectionKind :: Text )
79- . map ( |s| {
80- let index = s. index ( ) ;
81- let mut mapping_symbols: Vec < _ > = file
82- . symbols ( )
83- . filter ( |s| s. section_index ( ) . map ( |i| i == index) . unwrap_or ( false ) )
84- . filter_map ( |s| DisasmMode :: from_symbol ( & s) )
77+ fn get_mapping_symbols (
78+ sections : & [ Section ] ,
79+ symbols : & [ Symbol ] ,
80+ ) -> BTreeMap < usize , Vec < DisasmMode > > {
81+ sections
82+ . iter ( )
83+ . enumerate ( )
84+ . filter ( |( _, section) | section. kind == SectionKind :: Code )
85+ . map ( |( index, _) | {
86+ let mut mapping_symbols: Vec < _ > = symbols
87+ . iter ( )
88+ . filter ( |s| s. section . map ( |i| i == index) . unwrap_or ( false ) )
89+ . filter_map ( DisasmMode :: from_symbol)
8590 . collect ( ) ;
8691 mapping_symbols. sort_unstable_by_key ( |x| x. address ) ;
87- ( s . index ( ) . 0 - 1 , mapping_symbols)
92+ ( index, mapping_symbols)
8893 } )
8994 . collect ( )
9095 }
@@ -178,6 +183,10 @@ impl ArchArm {
178183}
179184
180185impl Arch for ArchArm {
186+ fn post_init ( & mut self , sections : & [ Section ] , symbols : & [ Symbol ] ) {
187+ self . disasm_modes = Self :: get_mapping_symbols ( sections, symbols) ;
188+ }
189+
181190 fn scan_instructions (
182191 & self ,
183192 address : u64 ,
@@ -338,6 +347,7 @@ impl Arch for ArchArm {
338347 cb ( InstructionPart :: reloc ( ) ) ?;
339348 } else {
340349 push_args (
350+ ins,
341351 & parsed_ins,
342352 resolved. relocation ,
343353 resolved. ins_ref . address as u32 ,
@@ -441,7 +451,7 @@ impl Arch for ArchArm {
441451
442452 fn extra_symbol_flags ( & self , symbol : & object:: Symbol ) -> SymbolFlagSet {
443453 let mut flags = SymbolFlagSet :: default ( ) ;
444- if DisasmMode :: from_symbol ( symbol) . is_some ( ) {
454+ if DisasmMode :: from_object_symbol ( symbol) . is_some ( ) {
445455 flags |= SymbolFlag :: Hidden ;
446456 }
447457 flags
@@ -455,15 +465,21 @@ struct DisasmMode {
455465}
456466
457467impl DisasmMode {
458- fn from_symbol < ' a > ( sym : & object:: Symbol < ' a , ' _ , & ' a [ u8 ] > ) -> Option < Self > {
468+ fn from_object_symbol < ' a > ( sym : & object:: Symbol < ' a , ' _ , & ' a [ u8 ] > ) -> Option < Self > {
459469 sym. name ( )
460470 . ok ( )
461471 . and_then ( unarm:: ParseMode :: from_mapping_symbol)
462472 . map ( |mapping| DisasmMode { address : sym. address ( ) as u32 , mapping } )
463473 }
474+
475+ fn from_symbol ( sym : & Symbol ) -> Option < Self > {
476+ unarm:: ParseMode :: from_mapping_symbol ( & sym. name )
477+ . map ( |mapping| DisasmMode { address : sym. address as u32 , mapping } )
478+ }
464479}
465480
466481fn push_args (
482+ ins : unarm:: Ins ,
467483 parsed_ins : & unarm:: ParsedIns ,
468484 relocation : Option < ResolvedRelocation > ,
469485 cur_addr : u32 ,
@@ -609,6 +625,14 @@ fn push_args(
609625 arg_cb ( InstructionPart :: opaque ( "!" ) ) ?;
610626 }
611627 }
628+
629+ let branch_dest = get_pc_relative_load_address ( ins, cur_addr) ;
630+ if let Some ( branch_dest) = branch_dest {
631+ arg_cb ( InstructionPart :: basic ( " (->" ) ) ?;
632+ arg_cb ( InstructionPart :: branch_dest ( branch_dest) ) ?;
633+ arg_cb ( InstructionPart :: basic ( ")" ) ) ?;
634+ }
635+
612636 Ok ( ( ) )
613637}
614638
@@ -636,3 +660,21 @@ fn find_reloc_arg(
636660 None
637661 }
638662}
663+
664+ fn get_pc_relative_load_address ( ins : unarm:: Ins , address : u32 ) -> Option < u32 > {
665+ match ins {
666+ unarm:: Ins :: Arm ( ins)
667+ if ins. op == arm:: Opcode :: Ldr
668+ && ins. modifier_addr_ldr_str ( ) == arm:: AddrLdrStr :: Imm
669+ && ins. field_rn_deref ( ) . reg == args:: Register :: Pc =>
670+ {
671+ let offset = ins. field_offset_12 ( ) . value ;
672+ Some ( address. wrapping_add_signed ( offset + 8 ) )
673+ }
674+ unarm:: Ins :: Thumb ( ins) if ins. op == thumb:: Opcode :: LdrPc => {
675+ let offset = ins. field_rel_immed_8 ( ) . value ;
676+ Some ( ( address & !3 ) . wrapping_add_signed ( offset + 4 ) )
677+ }
678+ _ => None ,
679+ }
680+ }
0 commit comments