@@ -496,6 +496,32 @@ void elf_add_reloc(struct elf *elf, struct reloc *reloc)
496
496
elf_hash_add (elf -> reloc_hash , & reloc -> hash , reloc_hash (reloc ));
497
497
}
498
498
499
+ static int read_rel_reloc (struct section * sec , int i , struct reloc * reloc , unsigned int * symndx )
500
+ {
501
+ if (!gelf_getrel (sec -> data , i , & reloc -> rel )) {
502
+ WARN_ELF ("gelf_getrel" );
503
+ return -1 ;
504
+ }
505
+ reloc -> type = GELF_R_TYPE (reloc -> rel .r_info );
506
+ reloc -> addend = 0 ;
507
+ reloc -> offset = reloc -> rel .r_offset ;
508
+ * symndx = GELF_R_SYM (reloc -> rel .r_info );
509
+ return 0 ;
510
+ }
511
+
512
+ static int read_rela_reloc (struct section * sec , int i , struct reloc * reloc , unsigned int * symndx )
513
+ {
514
+ if (!gelf_getrela (sec -> data , i , & reloc -> rela )) {
515
+ WARN_ELF ("gelf_getrela" );
516
+ return -1 ;
517
+ }
518
+ reloc -> type = GELF_R_TYPE (reloc -> rela .r_info );
519
+ reloc -> addend = reloc -> rela .r_addend ;
520
+ reloc -> offset = reloc -> rela .r_offset ;
521
+ * symndx = GELF_R_SYM (reloc -> rela .r_info );
522
+ return 0 ;
523
+ }
524
+
499
525
static int read_relocs (struct elf * elf )
500
526
{
501
527
struct section * sec ;
@@ -505,7 +531,8 @@ static int read_relocs(struct elf *elf)
505
531
unsigned long nr_reloc , max_reloc = 0 , tot_reloc = 0 ;
506
532
507
533
list_for_each_entry (sec , & elf -> sections , list ) {
508
- if (sec -> sh .sh_type != SHT_RELA )
534
+ if ((sec -> sh .sh_type != SHT_RELA ) &&
535
+ (sec -> sh .sh_type != SHT_REL ))
509
536
continue ;
510
537
511
538
sec -> base = find_section_by_index (elf , sec -> sh .sh_info );
@@ -525,16 +552,17 @@ static int read_relocs(struct elf *elf)
525
552
return -1 ;
526
553
}
527
554
memset (reloc , 0 , sizeof (* reloc ));
528
-
529
- if (!gelf_getrela (sec -> data , i , & reloc -> rela )) {
530
- WARN_ELF ("gelf_getrela" );
531
- return -1 ;
555
+ switch (sec -> sh .sh_type ) {
556
+ case SHT_REL :
557
+ if (read_rel_reloc (sec , i , reloc , & symndx ))
558
+ return -1 ;
559
+ break ;
560
+ case SHT_RELA :
561
+ if (read_rela_reloc (sec , i , reloc , & symndx ))
562
+ return -1 ;
563
+ break ;
564
+ default : return -1 ;
532
565
}
533
-
534
- reloc -> type = GELF_R_TYPE (reloc -> rela .r_info );
535
- reloc -> addend = reloc -> rela .r_addend ;
536
- reloc -> offset = reloc -> rela .r_offset ;
537
- symndx = GELF_R_SYM (reloc -> rela .r_info );
538
566
reloc -> sym = find_symbol_by_index (elf , symndx );
539
567
reloc -> sec = sec ;
540
568
if (!reloc -> sym ) {
@@ -722,7 +750,37 @@ struct section *elf_create_section(struct elf *elf, const char *name,
722
750
return sec ;
723
751
}
724
752
725
- struct section * elf_create_reloc_section (struct elf * elf , struct section * base )
753
+ static struct section * elf_create_rel_reloc_section (struct elf * elf , struct section * base )
754
+ {
755
+ char * relocname ;
756
+ struct section * sec ;
757
+
758
+ relocname = malloc (strlen (base -> name ) + strlen (".rel" ) + 1 );
759
+ if (!relocname ) {
760
+ perror ("malloc" );
761
+ return NULL ;
762
+ }
763
+ strcpy (relocname , ".rel" );
764
+ strcat (relocname , base -> name );
765
+
766
+ sec = elf_create_section (elf , relocname , sizeof (GElf_Rel ), 0 );
767
+ free (relocname );
768
+ if (!sec )
769
+ return NULL ;
770
+
771
+ base -> reloc = sec ;
772
+ sec -> base = base ;
773
+
774
+ sec -> sh .sh_type = SHT_REL ;
775
+ sec -> sh .sh_addralign = 8 ;
776
+ sec -> sh .sh_link = find_section_by_name (elf , ".symtab" )-> idx ;
777
+ sec -> sh .sh_info = base -> idx ;
778
+ sec -> sh .sh_flags = SHF_INFO_LINK ;
779
+
780
+ return sec ;
781
+ }
782
+
783
+ static struct section * elf_create_rela_reloc_section (struct elf * elf , struct section * base )
726
784
{
727
785
char * relocname ;
728
786
struct section * sec ;
@@ -752,16 +810,53 @@ struct section *elf_create_reloc_section(struct elf *elf, struct section *base)
752
810
return sec ;
753
811
}
754
812
755
- int elf_rebuild_reloc_section (struct section * sec )
813
+ struct section * elf_create_reloc_section (struct elf * elf ,
814
+ struct section * base ,
815
+ int reltype )
816
+ {
817
+ switch (reltype ) {
818
+ case SHT_REL : return elf_create_rel_reloc_section (elf , base );
819
+ case SHT_RELA : return elf_create_rela_reloc_section (elf , base );
820
+ default : return NULL ;
821
+ }
822
+ }
823
+
824
+ static int elf_rebuild_rel_reloc_section (struct section * sec , int nr )
756
825
{
757
826
struct reloc * reloc ;
758
- int nr , idx = 0 , size ;
759
- GElf_Rela * relocs ;
827
+ int idx = 0 , size ;
828
+ GElf_Rel * relocs ;
760
829
761
- nr = 0 ;
762
- list_for_each_entry (reloc , & sec -> reloc_list , list )
763
- nr ++ ;
830
+ /* Allocate a buffer for relocations */
831
+ size = nr * sizeof (* relocs );
832
+ relocs = malloc (size );
833
+ if (!relocs ) {
834
+ perror ("malloc" );
835
+ return -1 ;
836
+ }
837
+
838
+ sec -> data -> d_buf = relocs ;
839
+ sec -> data -> d_size = size ;
840
+
841
+ sec -> sh .sh_size = size ;
842
+
843
+ idx = 0 ;
844
+ list_for_each_entry (reloc , & sec -> reloc_list , list ) {
845
+ relocs [idx ].r_offset = reloc -> offset ;
846
+ relocs [idx ].r_info = GELF_R_INFO (reloc -> sym -> idx , reloc -> type );
847
+ idx ++ ;
848
+ }
849
+
850
+ return 0 ;
851
+ }
764
852
853
+ static int elf_rebuild_rela_reloc_section (struct section * sec , int nr )
854
+ {
855
+ struct reloc * reloc ;
856
+ int idx = 0 , size ;
857
+ GElf_Rela * relocs ;
858
+
859
+ /* Allocate a buffer for relocations with addends */
765
860
size = nr * sizeof (* relocs );
766
861
relocs = malloc (size );
767
862
if (!relocs ) {
@@ -785,6 +880,22 @@ int elf_rebuild_reloc_section(struct section *sec)
785
880
return 0 ;
786
881
}
787
882
883
+ int elf_rebuild_reloc_section (struct section * sec )
884
+ {
885
+ struct reloc * reloc ;
886
+ int nr ;
887
+
888
+ nr = 0 ;
889
+ list_for_each_entry (reloc , & sec -> reloc_list , list )
890
+ nr ++ ;
891
+
892
+ switch (sec -> sh .sh_type ) {
893
+ case SHT_REL : return elf_rebuild_rel_reloc_section (sec , nr );
894
+ case SHT_RELA : return elf_rebuild_rela_reloc_section (sec , nr );
895
+ default : return -1 ;
896
+ }
897
+ }
898
+
788
899
int elf_write (const struct elf * elf )
789
900
{
790
901
struct section * sec ;
0 commit comments