@@ -162,6 +162,10 @@ impl ArchArm {
162162}
163163
164164impl Arch for ArchArm {
165+ fn pre_init ( & mut self , sections : & [ Section ] , symbols : & [ Symbol ] , _symbol_indices : & [ usize ] ) {
166+ self . disasm_modes = Self :: get_mapping_symbols ( sections, symbols) ;
167+ }
168+
165169 fn post_init ( & mut self , sections : & [ Section ] , symbols : & [ Symbol ] , _symbol_indices : & [ usize ] ) {
166170 self . disasm_modes = Self :: get_mapping_symbols ( sections, symbols) ;
167171 }
@@ -474,20 +478,24 @@ impl Arch for ArchArm {
474478 section : & Section ,
475479 mut next_address : u64 ,
476480 ) -> Result < u64 > {
477- // TODO: This should probably check the disasm mode and trim accordingly,
478- // but self.disasm_modes isn't populated until post_init, so it needs a refactor.
479-
480481 // Trim any trailing 2-byte zeroes from the end (padding)
481482 while next_address >= symbol. address + 2
483+ && !symbol. section . is_some_and ( |section_idx| {
484+ self . disasm_modes
485+ . get ( & section_idx)
486+ . and_then ( |mappings| {
487+ mappings. iter ( ) . rfind ( |mapping| mapping. address as u64 <= next_address - 2 )
488+ } )
489+ . is_some_and ( |mapping| mapping. ends_with_complete_data_words ( next_address) )
490+ } )
482491 && let Some ( data) = section. data_range ( next_address - 2 , 2 )
483492 && data == [ 0u8 ; 2 ]
493+ && !section. relocation_at ( next_address. saturating_sub ( 4 ) , 4 ) . is_some_and ( |relocation| {
494+ relocation. address + self . data_reloc_size ( relocation. flags ) as u64
495+ > next_address - 2
496+ } )
484497 {
485498 next_address -= 2 ;
486- if let Some ( relocation) = section. relocation_at ( next_address, 2 ) {
487- // Avoid cutting trailing relocations in half.
488- next_address += self . data_reloc_size ( relocation. flags ) as u64 ;
489- break ;
490- }
491499 }
492500 Ok ( next_address. saturating_sub ( symbol. address ) )
493501 }
@@ -500,6 +508,11 @@ struct DisasmMode {
500508}
501509
502510impl DisasmMode {
511+ fn ends_with_complete_data_words ( self , end_address : u64 ) -> bool {
512+ let data_size = end_address. saturating_sub ( self . address as u64 ) ;
513+ self . mapping == unarm:: ParseMode :: Data && data_size >= 4 && data_size. is_multiple_of ( 4 )
514+ }
515+
503516 fn from_object_symbol < ' a > ( sym : & object:: Symbol < ' a , ' _ , & ' a [ u8 ] > ) -> Option < Self > {
504517 sym. name ( )
505518 . ok ( )
@@ -645,3 +658,18 @@ impl unarm::FormatIns for ArgsFormatter<'_> {
645658 Ok ( ( ) )
646659 }
647660}
661+
662+ #[ cfg( test) ]
663+ mod tests {
664+ use super :: DisasmMode ;
665+
666+ #[ test]
667+ fn complete_data_words_exclude_trailing_halfword_padding ( ) {
668+ let mapping = DisasmMode { address : 0x1000 , mapping : unarm:: ParseMode :: Data } ;
669+
670+ assert ! ( !mapping. ends_with_complete_data_words( 0x1002 ) ) ;
671+ assert ! ( mapping. ends_with_complete_data_words( 0x1004 ) ) ;
672+ assert ! ( !mapping. ends_with_complete_data_words( 0x1006 ) ) ;
673+ assert ! ( mapping. ends_with_complete_data_words( 0x1008 ) ) ;
674+ }
675+ }
0 commit comments