@@ -166,7 +166,7 @@ impl Arch for ArchPpc {
166
166
relocations : & [ Relocation ] ,
167
167
symbols : & [ Symbol ] ,
168
168
) -> Vec < Relocation > {
169
- generate_fake_pool_reloc_for_addr_mapping ( address, code, relocations, symbols)
169
+ generate_fake_pool_relocations_for_function ( address, code, relocations, symbols)
170
170
}
171
171
172
172
fn implcit_addend (
@@ -513,28 +513,34 @@ fn guess_data_type_from_load_store_inst_op(inst_op: ppc750cl::Opcode) -> Option<
513
513
}
514
514
}
515
515
516
- // Given an instruction, determine if it could accessing data at the address in a register.
517
- // If so, return the offset added to the register's address, the register containing that address,
518
- // and (optionally) which destination register the address is being copied into.
519
- fn get_offset_and_addr_gpr_for_possible_pool_reference (
516
+ struct PoolReference {
517
+ addr_src_gpr : ppc750cl:: GPR ,
518
+ addr_offset : i16 ,
519
+ addr_dst_gpr : Option < ppc750cl:: GPR > ,
520
+ }
521
+
522
+ // Given an instruction, check if it could be accessing pooled data at the address in a register.
523
+ // If so, return information pertaining to where the instruction is getting that address from and
524
+ // what it's doing with the address (e.g. copying it into another register, adding an offset, etc).
525
+ fn get_pool_reference_for_inst (
520
526
opcode : ppc750cl:: Opcode ,
521
527
simplified : & ppc750cl:: ParsedIns ,
522
- ) -> Option < ( i16 , ppc750cl :: GPR , Option < ppc750cl :: GPR > ) > {
528
+ ) -> Option < PoolReference > {
523
529
use ppc750cl:: { Argument , Opcode } ;
524
530
let args = & simplified. args ;
525
531
if guess_data_type_from_load_store_inst_op ( opcode) . is_some ( ) {
526
532
match ( args[ 1 ] , args[ 2 ] ) {
527
533
( Argument :: Offset ( offset) , Argument :: GPR ( addr_src_gpr) ) => {
528
534
// e.g. lwz. Immediate offset.
529
- Some ( ( offset. 0 , addr_src_gpr , None ) )
535
+ Some ( PoolReference { addr_src_gpr , addr_offset : offset. 0 , addr_dst_gpr : None } )
530
536
}
531
537
( Argument :: GPR ( addr_src_gpr) , Argument :: GPR ( _offset_gpr) ) => {
532
538
// e.g. lwzx. The offset is in a register and was likely calculated from an index.
533
539
// Treat the offset as being 0 in this case to show the first element of the array.
534
540
// It may be possible to show all elements by figuring out the stride of the array
535
541
// from the calculations performed on the index before it's put into offset_gpr, but
536
542
// this would be much more complicated, so it's not currently done.
537
- Some ( ( 0 , addr_src_gpr, None ) )
543
+ Some ( PoolReference { addr_src_gpr, addr_offset : 0 , addr_dst_gpr : None } )
538
544
}
539
545
_ => None ,
540
546
}
@@ -552,20 +558,32 @@ fn get_offset_and_addr_gpr_for_possible_pool_reference(
552
558
Argument :: GPR ( addr_dst_gpr) ,
553
559
Argument :: GPR ( addr_src_gpr) ,
554
560
Argument :: Simm ( simm) ,
555
- ) => Some ( ( simm. 0 , addr_src_gpr, Some ( addr_dst_gpr) ) ) ,
561
+ ) => Some ( PoolReference {
562
+ addr_src_gpr,
563
+ addr_offset : simm. 0 ,
564
+ addr_dst_gpr : Some ( addr_dst_gpr) ,
565
+ } ) ,
556
566
(
557
567
// `mr` or `mr.`
558
568
Opcode :: Or ,
559
569
Argument :: GPR ( addr_dst_gpr) ,
560
570
Argument :: GPR ( addr_src_gpr) ,
561
571
Argument :: None ,
562
- ) => Some ( ( 0 , addr_src_gpr, Some ( addr_dst_gpr) ) ) ,
572
+ ) => Some ( PoolReference {
573
+ addr_src_gpr,
574
+ addr_offset : 0 ,
575
+ addr_dst_gpr : Some ( addr_dst_gpr) ,
576
+ } ) ,
563
577
(
564
578
Opcode :: Add ,
565
579
Argument :: GPR ( addr_dst_gpr) ,
566
580
Argument :: GPR ( addr_src_gpr) ,
567
581
Argument :: GPR ( _offset_gpr) ,
568
- ) => Some ( ( 0 , addr_src_gpr, Some ( addr_dst_gpr) ) ) ,
582
+ ) => Some ( PoolReference {
583
+ addr_src_gpr,
584
+ addr_offset : 0 ,
585
+ addr_dst_gpr : Some ( addr_dst_gpr) ,
586
+ } ) ,
569
587
_ => None ,
570
588
}
571
589
}
@@ -607,16 +625,13 @@ fn make_fake_pool_reloc(
607
625
let pool_reloc = resolve_relocation ( symbols, pool_reloc) ;
608
626
let offset_from_pool = pool_reloc. relocation . addend + offset as i64 ;
609
627
let target_address = pool_reloc. symbol . address . checked_add_signed ( offset_from_pool) ?;
610
-
611
628
let section_index = pool_reloc. symbol . section ?;
612
-
613
629
let target_symbol = symbols. iter ( ) . position ( |s| {
614
630
s. section == Some ( section_index)
615
631
&& s. size > 0
616
632
&& ( s. address ..s. address + s. size ) . contains ( & target_address)
617
633
} ) ?;
618
634
let addend = target_address. checked_sub ( symbols[ target_symbol] . address ) ? as i64 ;
619
-
620
635
Some ( Relocation {
621
636
flags : RelocationFlags :: Elf ( elf:: R_PPC_NONE ) ,
622
637
address : cur_addr as u64 ,
@@ -644,7 +659,7 @@ fn make_fake_pool_reloc(
644
659
// It should be possible to implement jump tables properly by reading them out of .data. But this
645
660
// will require keeping track of what value is loaded into each register so we can retrieve the jump
646
661
// table symbol when we encounter a `bctr`.
647
- fn generate_fake_pool_reloc_for_addr_mapping (
662
+ fn generate_fake_pool_relocations_for_function (
648
663
func_address : u64 ,
649
664
code : & [ u8 ] ,
650
665
relocations : & [ Relocation ] ,
@@ -754,18 +769,16 @@ fn generate_fake_pool_reloc_for_addr_mapping(
754
769
clear_overwritten_gprs ( ins, & mut gpr_pool_relocs) ;
755
770
}
756
771
}
757
- } else if let Some ( ( offset, addr_src_gpr, addr_dst_gpr) ) =
758
- get_offset_and_addr_gpr_for_possible_pool_reference ( ins. op , & simplified)
759
- {
772
+ } else if let Some ( pool_ref) = get_pool_reference_for_inst ( ins. op , & simplified) {
760
773
// This instruction doesn't have a real relocation, so it may be a reference to one of
761
774
// the already-loaded pools.
762
- if let Some ( pool_reloc) = gpr_pool_relocs. get ( & addr_src_gpr. 0 ) {
775
+ if let Some ( pool_reloc) = gpr_pool_relocs. get ( & pool_ref . addr_src_gpr . 0 ) {
763
776
if let Some ( fake_pool_reloc) =
764
- make_fake_pool_reloc ( offset , cur_addr, pool_reloc, symbols)
777
+ make_fake_pool_reloc ( pool_ref . addr_offset , cur_addr, pool_reloc, symbols)
765
778
{
766
779
pool_reloc_for_addr. insert ( cur_addr, fake_pool_reloc) ;
767
780
}
768
- if let Some ( addr_dst_gpr) = addr_dst_gpr {
781
+ if let Some ( addr_dst_gpr) = pool_ref . addr_dst_gpr {
769
782
// If the address of the pool relocation got copied into another register, we
770
783
// need to keep track of it in that register too as future instructions may
771
784
// reference the symbol indirectly via this new register, instead of the
@@ -775,7 +788,7 @@ fn generate_fake_pool_reloc_for_addr_mapping(
775
788
// with the offset within the .data section of an array variable into r21.
776
789
// Then the body of the loop will `lwzx` one of the array elements from r21.
777
790
let mut new_reloc = pool_reloc. clone ( ) ;
778
- new_reloc. addend += offset as i64 ;
791
+ new_reloc. addend += pool_ref . addr_offset as i64 ;
779
792
gpr_pool_relocs. insert ( addr_dst_gpr. 0 , new_reloc) ;
780
793
} else {
781
794
clear_overwritten_gprs ( ins, & mut gpr_pool_relocs) ;
0 commit comments