@@ -553,6 +553,53 @@ where R: Read + Seek + ?Sized {
553
553
Ok ( ( header, obj) )
554
554
}
555
555
556
+ pub fn print_relocations < R > ( reader : & mut R , header : & RelHeader ) -> Result < ( ) >
557
+ where R : Read + Seek + ?Sized {
558
+ let imp_end = ( header. imp_offset + header. imp_size ) as u64 ;
559
+ reader. seek ( SeekFrom :: Start ( header. imp_offset as u64 ) ) ?;
560
+ while reader. stream_position ( ) ? < imp_end {
561
+ let import = RelImport :: from_reader ( reader, Endian :: Big ) ?;
562
+ println ! ( "Module {} (file offset {:#X}):" , import. module_id, import. offset) ;
563
+
564
+ let position = reader. stream_position ( ) ?;
565
+ reader. seek ( SeekFrom :: Start ( import. offset as u64 ) ) ?;
566
+ let mut address = 0u32 ;
567
+ let mut section = u8:: MAX ;
568
+ loop {
569
+ let reloc = RelRelocRaw :: from_reader ( reader, Endian :: Big ) ?;
570
+ let kind = match reloc. kind as u32 {
571
+ elf:: R_PPC_NONE => continue ,
572
+ elf:: R_PPC_ADDR32 | elf:: R_PPC_UADDR32 => ObjRelocKind :: Absolute ,
573
+ elf:: R_PPC_ADDR16_LO => ObjRelocKind :: PpcAddr16Lo ,
574
+ elf:: R_PPC_ADDR16_HI => ObjRelocKind :: PpcAddr16Hi ,
575
+ elf:: R_PPC_ADDR16_HA => ObjRelocKind :: PpcAddr16Ha ,
576
+ elf:: R_PPC_REL24 => ObjRelocKind :: PpcRel24 ,
577
+ elf:: R_PPC_REL14 => ObjRelocKind :: PpcRel14 ,
578
+ R_DOLPHIN_NOP => {
579
+ address += reloc. offset as u32 ;
580
+ continue ;
581
+ }
582
+ R_DOLPHIN_SECTION => {
583
+ address = 0 ;
584
+ section = reloc. section ;
585
+ continue ;
586
+ }
587
+ R_DOLPHIN_END => break ,
588
+ // R_DOLPHIN_MRKREF => ?
589
+ reloc_type => bail ! ( "Unhandled REL relocation type {reloc_type}" ) ,
590
+ } ;
591
+ address += reloc. offset as u32 ;
592
+ println ! (
593
+ " {}:{:#X} {:?} -> {}:{}:{:#X}" ,
594
+ reloc. section, address, kind, import. module_id, section, reloc. addend
595
+ ) ;
596
+ }
597
+ reader. seek ( SeekFrom :: Start ( position) ) ?;
598
+ }
599
+
600
+ Ok ( ( ) )
601
+ }
602
+
556
603
/// REL relocation.
557
604
#[ derive( Debug , Clone ) ]
558
605
pub struct RelReloc {
@@ -663,29 +710,41 @@ pub fn write_rel<W>(
663
710
where
664
711
W : Write + Seek + ?Sized ,
665
712
{
666
- relocations. sort_by ( |a, b| {
667
- if a. module_id == 0 {
668
- if b. module_id == 0 {
669
- Ordering :: Equal
670
- } else {
671
- Ordering :: Greater
672
- }
673
- } else if a. module_id == info. module_id {
674
- if b. module_id == 0 {
713
+ if info. version >= 3 {
714
+ // Version 3 RELs put module ID 0 and self-relocations last,
715
+ // so that the space can be reclaimed via OSLinkFixed. (See fix_size)
716
+ relocations. sort_by ( |a, b| {
717
+ if a. module_id == 0 {
718
+ if b. module_id == 0 {
719
+ Ordering :: Equal
720
+ } else {
721
+ Ordering :: Greater
722
+ }
723
+ } else if a. module_id == info. module_id {
724
+ if b. module_id == 0 {
725
+ Ordering :: Less
726
+ } else if b. module_id == info. module_id {
727
+ Ordering :: Equal
728
+ } else {
729
+ Ordering :: Greater
730
+ }
731
+ } else if b. module_id == 0 || b. module_id == info. module_id {
675
732
Ordering :: Less
676
- } else if b. module_id == info. module_id {
677
- Ordering :: Equal
678
733
} else {
679
- Ordering :: Greater
734
+ a . module_id . cmp ( & b . module_id )
680
735
}
681
- } else if b. module_id == 0 || b. module_id == info. module_id {
682
- Ordering :: Less
683
- } else {
684
- a. module_id . cmp ( & b. module_id )
685
- }
686
- . then ( a. section . cmp ( & b. section ) )
687
- . then ( a. address . cmp ( & b. address ) )
688
- } ) ;
736
+ . then ( a. section . cmp ( & b. section ) )
737
+ . then ( a. address . cmp ( & b. address ) )
738
+ } ) ;
739
+ } else {
740
+ // Version 1 and 2 RELs use simple ascending order.
741
+ relocations. sort_by ( |a, b| {
742
+ a. module_id
743
+ . cmp ( & b. module_id )
744
+ . then ( a. section . cmp ( & b. section ) )
745
+ . then ( a. address . cmp ( & b. address ) )
746
+ } ) ;
747
+ }
689
748
690
749
let mut apply_relocations = vec ! [ ] ;
691
750
relocations. retain ( |r| {
@@ -779,27 +838,28 @@ where
779
838
header. section_info_offset = offset;
780
839
offset += num_sections * RelSectionHeader :: STATIC_SIZE as u32 ;
781
840
let section_data_offset = offset;
782
- for ( idx, section) in file. sections ( ) . filter ( is_permitted_section) . enumerate ( ) {
783
- if !should_write_section ( & section) {
784
- continue ;
785
- }
841
+ for ( idx, section) in file
842
+ . sections ( )
843
+ . filter ( is_permitted_section)
844
+ . enumerate ( )
845
+ . filter ( |( _, s) | should_write_section ( s) )
846
+ {
786
847
let align = section_align ( idx, & section, info) - 1 ;
787
848
offset = ( offset + align) & !align;
788
849
offset += section. size ( ) as u32 ;
789
850
}
790
- header. imp_offset = offset;
791
- let imp_count = relocations. iter ( ) . map ( |r| r. module_id ) . dedup ( ) . count ( ) ;
792
- header. imp_size = imp_count as u32 * RelImport :: STATIC_SIZE as u32 ;
793
- offset += header. imp_size ;
794
- header. rel_offset = offset;
795
851
796
- let mut imp_entries = Vec :: < RelImport > :: with_capacity ( imp_count) ;
797
- let mut raw_relocations = vec ! [ ] ;
798
- {
852
+ fn do_relocation_layout (
853
+ relocations : & [ RelReloc ] ,
854
+ header : & mut RelHeader ,
855
+ imp_entries : & mut Vec < RelImport > ,
856
+ raw_relocations : & mut Vec < RelRelocRaw > ,
857
+ offset : & mut u32 ,
858
+ ) -> Result < ( ) > {
799
859
let mut address = 0u32 ;
800
860
let mut section = u8:: MAX ;
801
861
let mut last_module_id = u32:: MAX ;
802
- for reloc in & relocations {
862
+ for reloc in relocations {
803
863
if reloc. module_id != last_module_id {
804
864
if last_module_id != u32:: MAX {
805
865
raw_relocations. push ( RelRelocRaw {
@@ -808,17 +868,17 @@ where
808
868
section : 0 ,
809
869
addend : 0 ,
810
870
} ) ;
811
- offset += 8 ;
871
+ * offset += 8 ;
812
872
}
813
- imp_entries. push ( RelImport { module_id : reloc. module_id , offset } ) ;
873
+ imp_entries. push ( RelImport { module_id : reloc. module_id , offset : * offset } ) ;
814
874
section = u8:: MAX ;
815
875
last_module_id = reloc. module_id ;
816
876
}
817
- if info . version >= 3
877
+ if header . version >= 3
818
878
&& header. fix_size . is_none ( )
819
- && ( reloc. module_id == 0 || reloc. module_id == info . module_id )
879
+ && ( reloc. module_id == 0 || reloc. module_id == header . module_id )
820
880
{
821
- header. fix_size = Some ( offset) ;
881
+ header. fix_size = Some ( * offset) ;
822
882
}
823
883
if reloc. section != section {
824
884
raw_relocations. push ( RelRelocRaw {
@@ -827,7 +887,7 @@ where
827
887
section : reloc. section ,
828
888
addend : 0 ,
829
889
} ) ;
830
- offset += 8 ;
890
+ * offset += 8 ;
831
891
address = 0 ;
832
892
section = reloc. section ;
833
893
}
@@ -839,7 +899,7 @@ where
839
899
section : 0 ,
840
900
addend : 0 ,
841
901
} ) ;
842
- offset += 8 ;
902
+ * offset += 8 ;
843
903
reloc_offset -= 0xffff ;
844
904
}
845
905
raw_relocations. push ( RelRelocRaw {
@@ -857,16 +917,47 @@ where
857
917
addend : reloc. addend ,
858
918
} ) ;
859
919
address = reloc. address ;
860
- offset += 8 ;
920
+ * offset += 8 ;
861
921
}
922
+ raw_relocations. push ( RelRelocRaw {
923
+ offset : 0 ,
924
+ kind : R_DOLPHIN_END as u8 ,
925
+ section : 0 ,
926
+ addend : 0 ,
927
+ } ) ;
928
+ * offset += 8 ;
929
+ Ok ( ( ) )
930
+ }
931
+
932
+ let imp_count = relocations. iter ( ) . map ( |r| r. module_id ) . dedup ( ) . count ( ) ;
933
+ let mut imp_entries = Vec :: < RelImport > :: with_capacity ( imp_count) ;
934
+ let mut raw_relocations = vec ! [ ] ;
935
+ if info. version < 3 {
936
+ // Version 1 and 2 RELs write relocations before the import table.
937
+ header. rel_offset = offset;
938
+ do_relocation_layout (
939
+ & relocations,
940
+ & mut header,
941
+ & mut imp_entries,
942
+ & mut raw_relocations,
943
+ & mut offset,
944
+ ) ?;
945
+ }
946
+ header. imp_offset = offset;
947
+ header. imp_size = imp_count as u32 * RelImport :: STATIC_SIZE as u32 ;
948
+ offset += header. imp_size ;
949
+ if info. version >= 3 {
950
+ // Version 3 RELs write relocations after the import table,
951
+ // so that the import table isn't clobbered by OSLinkFixed.
952
+ header. rel_offset = offset;
953
+ do_relocation_layout (
954
+ & relocations,
955
+ & mut header,
956
+ & mut imp_entries,
957
+ & mut raw_relocations,
958
+ & mut offset,
959
+ ) ?;
862
960
}
863
- raw_relocations. push ( RelRelocRaw {
864
- offset : 0 ,
865
- kind : R_DOLPHIN_END as u8 ,
866
- section : 0 ,
867
- addend : 0 ,
868
- } ) ;
869
- offset += 8 ;
870
961
871
962
for symbol in file. symbols ( ) . filter ( |s| s. is_definition ( ) ) {
872
963
let Some ( symbol_section) = symbol. section_index ( ) else {
@@ -919,11 +1010,12 @@ where
919
1010
}
920
1011
}
921
1012
ensure ! ( w. stream_position( ) ? as u32 == section_data_offset) ;
922
- for ( idx, section) in file. sections ( ) . filter ( is_permitted_section) . enumerate ( ) {
923
- if !should_write_section ( & section) {
924
- continue ;
925
- }
926
-
1013
+ for ( idx, section) in file
1014
+ . sections ( )
1015
+ . filter ( is_permitted_section)
1016
+ . enumerate ( )
1017
+ . filter ( |( _, s) | should_write_section ( s) )
1018
+ {
927
1019
fn calculate_padding ( position : u64 , align : u64 ) -> u64 {
928
1020
let align = align - 1 ;
929
1021
( ( position + align) & !align) - position
@@ -943,13 +1035,23 @@ where
943
1035
}
944
1036
w. write_all ( & section_data) ?;
945
1037
}
1038
+ if info. version < 3 {
1039
+ // Version 1 and 2 RELs write relocations before the import table.
1040
+ ensure ! ( w. stream_position( ) ? as u32 == header. rel_offset) ;
1041
+ for reloc in & raw_relocations {
1042
+ reloc. to_writer ( w, Endian :: Big ) ?;
1043
+ }
1044
+ }
946
1045
ensure ! ( w. stream_position( ) ? as u32 == header. imp_offset) ;
947
- for entry in imp_entries {
1046
+ for entry in & imp_entries {
948
1047
entry. to_writer ( w, Endian :: Big ) ?;
949
1048
}
950
- ensure ! ( w. stream_position( ) ? as u32 == header. rel_offset) ;
951
- for reloc in raw_relocations {
952
- reloc. to_writer ( w, Endian :: Big ) ?;
1049
+ if info. version >= 3 {
1050
+ // Version 3 RELs write relocations after the import table. See above.
1051
+ ensure ! ( w. stream_position( ) ? as u32 == header. rel_offset) ;
1052
+ for reloc in & raw_relocations {
1053
+ reloc. to_writer ( w, Endian :: Big ) ?;
1054
+ }
953
1055
}
954
1056
ensure ! ( w. stream_position( ) ? as u32 == offset) ;
955
1057
Ok ( ( ) )
0 commit comments