@@ -10,7 +10,7 @@ use object::{
1010 elf, File , Object , ObjectSection , ObjectSymbol , Relocation , RelocationFlags , RelocationTarget ,
1111 Symbol , SymbolKind ,
1212} ;
13- use ppc750cl:: { Argument , InsIter , Opcode , ParsedIns , GPR } ;
13+ use ppc750cl:: { Argument , Arguments , Ins , InsIter , Opcode , ParsedIns , GPR } ;
1414
1515use crate :: {
1616 arch:: { DataType , ObjArch , ProcessCodeResult } ,
@@ -445,16 +445,29 @@ fn get_offset_and_addr_gpr_for_possible_pool_reference(
445445 Argument :: Simm ( simm) ,
446446 ) => Some ( ( simm. 0 , addr_src_gpr, Some ( addr_dst_gpr) ) ) ,
447447 (
448+ // `mr` or `mr.`
448449 Opcode :: Or ,
449450 Argument :: GPR ( addr_dst_gpr) ,
450451 Argument :: GPR ( addr_src_gpr) ,
451452 Argument :: None ,
452- ) => Some ( ( 0 , addr_src_gpr, Some ( addr_dst_gpr) ) ) , // `mr` or `mr.`
453+ ) => Some ( ( 0 , addr_src_gpr, Some ( addr_dst_gpr) ) ) ,
453454 _ => None ,
454455 }
455456 }
456457}
457458
459+ // Remove the relocation we're keeping track of in a particular register when an instruction reuses
460+ // that register to hold some other value, unrelated to pool relocation addresses.
461+ fn clear_overwritten_gprs ( ins : Ins , active_pool_relocs : & mut HashMap < u8 , ObjReloc > ) {
462+ let mut def_args = Arguments :: default ( ) ;
463+ ins. parse_defs ( & mut def_args) ;
464+ for arg in def_args {
465+ if let Argument :: GPR ( gpr) = arg {
466+ active_pool_relocs. remove ( & gpr. 0 ) ;
467+ }
468+ }
469+ }
470+
458471// We create a fake relocation for an instruction, vaguely simulating what the actual relocation
459472// might have looked like if it wasn't pooled. This is so minimal changes are needed to display
460473// pooled accesses vs non-pooled accesses. We set the relocation type to R_PPC_NONE to indicate that
@@ -537,20 +550,22 @@ fn generate_fake_pool_reloc_for_addr_mapping(
537550 let args = & simplified. args ;
538551 match ( ins. op , args[ 0 ] , args[ 1 ] , args[ 2 ] ) {
539552 (
553+ // `lis` + `addi`
540554 Opcode :: Addi ,
541555 Argument :: GPR ( addr_dst_gpr) ,
542556 Argument :: GPR ( _addr_src_gpr) ,
543557 Argument :: Simm ( _simm) ,
544558 ) => {
545- active_pool_relocs. insert ( addr_dst_gpr. 0 , reloc. clone ( ) ) ; // `lis` + `addi`
559+ active_pool_relocs. insert ( addr_dst_gpr. 0 , reloc. clone ( ) ) ;
546560 }
547561 (
562+ // `lis` + `ori`
548563 Opcode :: Ori ,
549564 Argument :: GPR ( addr_dst_gpr) ,
550565 Argument :: GPR ( _addr_src_gpr) ,
551566 Argument :: Uimm ( _uimm) ,
552567 ) => {
553- active_pool_relocs. insert ( addr_dst_gpr. 0 , reloc. clone ( ) ) ; // `lis` + `ori`
568+ active_pool_relocs. insert ( addr_dst_gpr. 0 , reloc. clone ( ) ) ;
554569 }
555570 ( Opcode :: B , _, _, _) => {
556571 if simplified. mnemonic == "bl" {
@@ -562,7 +577,9 @@ fn generate_fake_pool_reloc_for_addr_mapping(
562577 }
563578 }
564579 }
565- _ => { }
580+ _ => {
581+ clear_overwritten_gprs ( ins, & mut active_pool_relocs) ;
582+ }
566583 }
567584 } else if let Some ( ( offset, addr_src_gpr, addr_dst_gpr) ) =
568585 get_offset_and_addr_gpr_for_possible_pool_reference ( ins. op , & simplified)
@@ -585,8 +602,14 @@ fn generate_fake_pool_reloc_for_addr_mapping(
585602 let mut new_reloc = pool_reloc. clone ( ) ;
586603 new_reloc. addend += offset as i64 ;
587604 active_pool_relocs. insert ( addr_dst_gpr. 0 , new_reloc) ;
605+ } else {
606+ clear_overwritten_gprs ( ins, & mut active_pool_relocs) ;
588607 }
608+ } else {
609+ clear_overwritten_gprs ( ins, & mut active_pool_relocs) ;
589610 }
611+ } else {
612+ clear_overwritten_gprs ( ins, & mut active_pool_relocs) ;
590613 }
591614 }
592615
0 commit comments