@@ -17,7 +17,7 @@ use failure::Error;
17
17
use goblin;
18
18
19
19
use indexmap:: IndexMap ;
20
- use scroll:: IOwrite ;
20
+ use scroll:: { IOwrite , Pwrite } ;
21
21
use std:: collections:: { hash_map, HashMap } ;
22
22
use std:: fmt;
23
23
use std:: io:: SeekFrom :: * ;
@@ -111,8 +111,8 @@ impl<'a> SymbolBuilder<'a> {
111
111
}
112
112
/// Set the section index
113
113
pub fn section_index ( mut self , shndx : usize ) -> Self {
114
- // Underlying representation is only 16 bits. Catch this early!
115
- debug_assert ! ( shndx < u16 :: max_value( ) as usize ) ;
114
+ // Underlying representation is only 32 bits. Catch this early!
115
+ debug_assert ! ( shndx < u32 :: max_value( ) as usize ) ;
116
116
self . shndx = shndx;
117
117
self
118
118
}
@@ -190,6 +190,7 @@ enum SectionType {
190
190
StrTab ,
191
191
SymTab ,
192
192
Relocation ,
193
+ SymTabShndx ,
193
194
None ,
194
195
}
195
196
@@ -305,6 +306,11 @@ impl SectionBuilder {
305
306
shdr. sh_flags = 0 ;
306
307
shdr. sh_type = SHT_RELA
307
308
}
309
+ SectionType :: SymTabShndx => {
310
+ shdr. sh_entsize = 4 ;
311
+ shdr. sh_addralign = 4 ;
312
+ shdr. sh_type = SHT_SYMTAB_SHNDX ;
313
+ }
308
314
SectionType :: None => shdr. sh_type = SHT_NULL ,
309
315
}
310
316
shdr
@@ -382,7 +388,7 @@ struct Elf<'a> {
382
388
sizeof_strtab : Offset ,
383
389
strings : DefaultStringInterner ,
384
390
sizeof_bits : Offset ,
385
- nsections : u16 ,
391
+ nsections : u32 ,
386
392
ctx : Ctx ,
387
393
architecture : Architecture ,
388
394
nlocals : usize ,
@@ -719,25 +725,58 @@ impl<'a> Elf<'a> {
719
725
self . nsections += 1 ;
720
726
}
721
727
}
728
+ fn align ( offset : & mut u64 , sizeof_t : u64 ) {
729
+ let alignment = * offset % sizeof_t;
730
+ if alignment != 0 {
731
+ * offset += sizeof_t - alignment;
732
+ }
733
+ }
722
734
pub fn write < T : Write + Seek > ( mut self , file : T ) -> goblin:: error:: Result < ( ) > {
735
+ use goblin:: elf:: section_header:: { SHN_LORESERVE , SHN_XINDEX } ;
723
736
let mut file = BufWriter :: new ( file) ;
737
+
724
738
/////////////////////////////////////
725
739
// Compute Offsets
726
740
/////////////////////////////////////
727
- let sizeof_symtab = ( self . symbols . len ( ) + self . special_symbols . len ( ) + self . sections . len ( ) )
728
- * Symbol :: size ( self . ctx . container ) ;
741
+ let symbol_count = self . symbols . len ( ) + self . special_symbols . len ( ) + self . sections . len ( ) ;
742
+ let sizeof_symtab = symbol_count * Symbol :: size ( self . ctx . container ) ;
743
+ // This check is a bit lax, we really only need .symtab_shndx if there is a symbol
744
+ // that has a large section index, but we currently add symbols for most sections
745
+ // so it's ok.
746
+ let mut sizeof_symtab_shndx = 0 ;
747
+ let mut symtab_shndx_name_offset = 0 ;
748
+ let mut need_symtab_shndx = false ;
749
+ if self . nsections >= SHN_LORESERVE . into ( ) {
750
+ self . nsections += 1 ;
751
+ sizeof_symtab_shndx = symbol_count as u64 * 4 ;
752
+ symtab_shndx_name_offset = self . new_string ( ".symtab_shndx" . into ( ) ) . 1 ;
753
+ need_symtab_shndx = true ;
754
+ } ;
729
755
let sizeof_relocs = self
730
756
. relocations
731
757
. iter ( )
732
758
. fold ( 0 , |acc, ( _, & ( ref _shdr, ref rels) ) | rels. len ( ) + acc)
733
759
* Relocation :: size ( true , self . ctx ) ;
734
760
let nonexec_stack_note_name_offset = self . new_string ( ".note.GNU-stack" . into ( ) ) . 1 ;
735
761
let strtab_offset = self . sizeof_bits as u64 ;
736
- let symtab_offset = strtab_offset + self . sizeof_strtab as u64 ;
737
- let reloc_offset = symtab_offset + sizeof_symtab as u64 ;
738
- let sh_offset = reloc_offset + sizeof_relocs as u64 ;
739
762
740
- debug ! (
763
+ // alignment required for below
764
+ let mut symtab_offset = strtab_offset + self . sizeof_strtab as u64 ;
765
+ let symtab_align = self . ctx . size ( ) as u64 ;
766
+ Self :: align ( & mut symtab_offset, symtab_align) ;
767
+ let mut symtab_shndx_offset = symtab_offset + sizeof_symtab as u64 ;
768
+ let symtab_shndx_align = 4 ;
769
+ if need_symtab_shndx {
770
+ Self :: align ( & mut symtab_shndx_offset, symtab_shndx_align) ;
771
+ }
772
+ let mut reloc_offset = symtab_shndx_offset + sizeof_symtab_shndx;
773
+ let reloc_align = self . ctx . size ( ) as u64 ;
774
+ Self :: align ( & mut reloc_offset, reloc_align) ;
775
+ let mut sh_offset = reloc_offset + sizeof_relocs as u64 ;
776
+ let shdr_align = self . ctx . size ( ) as u64 ;
777
+ Self :: align ( & mut sh_offset, shdr_align) ;
778
+
779
+ info ! (
741
780
"strtab: {:#x} symtab {:#x} relocs {:#x} sh_offset {:#x}" ,
742
781
strtab_offset, symtab_offset, reloc_offset, sh_offset
743
782
) ;
@@ -750,7 +789,11 @@ impl<'a> Elf<'a> {
750
789
header. e_machine = machine. 0 ;
751
790
header. e_type = header:: ET_REL ;
752
791
header. e_shoff = sh_offset;
753
- header. e_shnum = self . nsections ;
792
+ header. e_shnum = if self . nsections >= SHN_LORESERVE . into ( ) {
793
+ 0
794
+ } else {
795
+ self . nsections as u16
796
+ } ;
754
797
header. e_shstrndx = STRTAB_LINK ;
755
798
756
799
file. iowrite_with ( header, self . ctx ) ?;
@@ -774,6 +817,9 @@ impl<'a> Elf<'a> {
774
817
/////////////////////////////////////
775
818
776
819
let mut section_headers = vec ! [ SectionHeader :: default ( ) ] ;
820
+ if self . nsections >= SHN_LORESERVE . into ( ) {
821
+ section_headers[ 0 ] . sh_size = self . nsections as u64 ;
822
+ }
777
823
let mut strtab = {
778
824
let offset = * ( self . offsets . get ( & 0 ) . unwrap ( ) ) ;
779
825
SectionBuilder :: new ( self . sizeof_strtab as u64 )
@@ -808,37 +854,93 @@ impl<'a> Elf<'a> {
808
854
file. write_all ( string. as_bytes ( ) ) ?;
809
855
file. iowrite ( 0u8 ) ?;
810
856
}
811
- let after_strtab = file. seek ( Current ( 0 ) ) ?;
812
- debug ! ( "after_strtab {:#x}" , after_strtab) ;
813
- assert_eq ! ( after_strtab, symtab_offset) ;
857
+ {
858
+ let mut after_strtab = file. seek ( Current ( 0 ) ) ?;
859
+ Self :: align ( & mut after_strtab, symtab_align) ;
860
+ debug ! ( "after_strtab {:#x}" , after_strtab) ;
861
+ assert_eq ! ( after_strtab, symtab_offset) ;
862
+ }
814
863
815
864
/////////////////////////////////////
816
865
// Symtab
817
866
/////////////////////////////////////
867
+ let mut symtab_shndx_data: Vec < u8 > = if need_symtab_shndx {
868
+ vec ! [ 0 ; symbol_count * 4 ]
869
+ } else {
870
+ Vec :: new ( )
871
+ } ;
872
+ let mut offset = 0 ;
873
+ file. seek ( Start ( symtab_offset) ) ?;
818
874
for symbol in self . special_symbols . into_iter ( ) {
819
875
debug ! ( "Special Symbol: {:?}" , symbol) ;
876
+ // the special symbols's section indexs have special meanings
877
+ // so we don't do the shn conversion here
878
+ if need_symtab_shndx {
879
+ symtab_shndx_data
880
+ . gwrite_with ( symbol. st_shndx as u32 , & mut offset, self . ctx . le )
881
+ . expect ( "preallocated shndx vector has enough space for special symbols" ) ;
882
+ }
820
883
file. iowrite_with ( symbol, self . ctx ) ?;
821
884
}
822
885
for ( _id, section) in self . sections . into_iter ( ) {
823
886
debug ! ( "Section Symbol: {:?}" , section. symbol) ;
824
- file. iowrite_with ( section. symbol , self . ctx ) ?;
887
+ let mut sym = section. symbol . clone ( ) ;
888
+ if need_symtab_shndx {
889
+ symtab_shndx_data
890
+ . gwrite_with ( sym. st_shndx as u32 , & mut offset, self . ctx . le )
891
+ . expect ( "preallocated shndx vector has enough space for sections" ) ;
892
+ }
893
+ if sym. st_shndx >= SHN_LORESERVE as usize {
894
+ sym. st_shndx = SHN_XINDEX as usize ;
895
+ }
896
+ file. iowrite_with ( sym, self . ctx ) ?;
825
897
section_headers. push ( section. header ) ;
826
898
}
827
899
for ( _id, symbol) in self . symbols . into_iter ( ) {
828
900
debug ! ( "Symbol: {:?}" , symbol) ;
829
- file. iowrite_with ( symbol, self . ctx ) ?;
901
+ let mut sym = symbol. clone ( ) ;
902
+ if need_symtab_shndx {
903
+ symtab_shndx_data
904
+ . gwrite_with ( sym. st_shndx as u32 , & mut offset, self . ctx . le )
905
+ . expect ( "preallocated shndx vector has enough space for symbols" ) ;
906
+ }
907
+ if sym. st_shndx >= SHN_LORESERVE as usize {
908
+ sym. st_shndx = SHN_XINDEX as usize ;
909
+ }
910
+ file. iowrite_with ( sym, self . ctx ) ?;
911
+ }
912
+ if need_symtab_shndx {
913
+ {
914
+ let mut after_symtab = file. seek ( Current ( 0 ) ) ?;
915
+ Self :: align ( & mut after_symtab, symtab_shndx_align) ;
916
+ debug ! ( "after_symtab {:#x}" , after_symtab) ;
917
+ assert_eq ! ( after_symtab, symtab_shndx_offset) ;
918
+ }
919
+ file. seek ( Start ( symtab_shndx_offset) ) ?;
920
+ file. write_all ( & symtab_shndx_data) ?;
921
+ let mut section = SectionBuilder :: new ( sizeof_symtab_shndx)
922
+ . name_offset ( symtab_shndx_name_offset)
923
+ . section_type ( SectionType :: SymTabShndx )
924
+ . create ( & self . ctx ) ;
925
+ section. sh_link = 2 ;
926
+ section. sh_offset = symtab_shndx_offset;
927
+ section_headers. push ( section) ;
928
+ }
929
+ {
930
+ let mut after_symtab_shndx = file. seek ( Current ( 0 ) ) ?;
931
+ Self :: align ( & mut after_symtab_shndx, reloc_align) ;
932
+ debug ! (
933
+ "after_symtab_shndx {:#x} - shdr_size {}" ,
934
+ after_symtab_shndx,
935
+ Section :: size( & self . ctx)
936
+ ) ;
937
+ assert_eq ! ( after_symtab_shndx, reloc_offset) ;
830
938
}
831
- let after_symtab = file. seek ( Current ( 0 ) ) ?;
832
- debug ! (
833
- "after_symtab {:#x} - shdr_size {}" ,
834
- after_symtab,
835
- Section :: size( & self . ctx)
836
- ) ;
837
- assert_eq ! ( after_symtab, reloc_offset) ;
838
939
839
940
/////////////////////////////////////
840
941
// Relocations
841
942
/////////////////////////////////////
943
+ file. seek ( Start ( reloc_offset) ) ?;
842
944
let mut roffset = reloc_offset;
843
945
for ( _, ( mut section, mut relocations) ) in self . relocations . into_iter ( ) {
844
946
section. sh_offset = roffset;
@@ -849,9 +951,12 @@ impl<'a> Elf<'a> {
849
951
file. iowrite_with ( relocation, ( relocation. r_addend . is_some ( ) , self . ctx ) ) ?;
850
952
}
851
953
}
852
- let after_relocs = file. seek ( Current ( 0 ) ) ?;
853
- debug ! ( "after_relocs {:#x}" , after_relocs) ;
854
- assert_eq ! ( after_relocs, sh_offset) ;
954
+ {
955
+ let mut after_relocs = file. seek ( Current ( 0 ) ) ?;
956
+ Self :: align ( & mut after_relocs, shdr_align) ;
957
+ debug ! ( "after_relocs {:#x}" , after_relocs) ;
958
+ assert_eq ! ( after_relocs, sh_offset) ;
959
+ }
855
960
856
961
/////////////////////////////////////
857
962
// Non-executable stack note.
@@ -865,16 +970,22 @@ impl<'a> Elf<'a> {
865
970
/////////////////////////////////////
866
971
// Sections
867
972
/////////////////////////////////////
868
- let shdr_size = section_headers. len ( ) as u64 * Section :: size ( & self . ctx ) as u64 ;
973
+ let sizeof_shdr = Section :: size ( & self . ctx ) as u64 ;
974
+ let shdr_size = section_headers. len ( ) as u64 * sizeof_shdr;
975
+
976
+ file. seek ( Start ( sh_offset) ) ?;
869
977
for shdr in section_headers {
870
978
debug ! ( "Section: {:?}" , shdr) ;
871
979
file. iowrite_with ( shdr, self . ctx ) ?;
872
980
}
873
981
874
- let after_shdrs = file. seek ( Current ( 0 ) ) ?;
875
- let expected = sh_offset + shdr_size;
876
- debug ! ( "after_shdrs {:#x}" , after_shdrs) ;
877
- assert_eq ! ( after_shdrs, expected) ;
982
+ {
983
+ let after_shdrs = file. seek ( Current ( 0 ) ) ?;
984
+ let expected = sh_offset + shdr_size;
985
+ debug ! ( "after_shdrs {:#x}" , after_shdrs) ;
986
+ assert_eq ! ( after_shdrs, expected) ;
987
+ }
988
+
878
989
debug ! ( "done" ) ;
879
990
Ok ( ( ) )
880
991
}
0 commit comments