@@ -39,8 +39,8 @@ typedef Elf64_Half Elf64_Section;
39
39
#endif
40
40
41
41
int apply_relocate_add (Elf64_Shdr * * sechdrs ,
42
- unsigned int symsec ,
43
- unsigned int relsec );
42
+ unsigned int symsec ,
43
+ unsigned int relsec );
44
44
45
45
/* Following code based on IBM s390 ELF relocation sample */
46
46
/* https://www.ibm.com/docs/en/zos/2.2.0?topic=file-example-relocating-addresses-within-elf */
@@ -267,12 +267,18 @@ static int
267
267
return 0 ;
268
268
}
269
269
270
+ enum {
271
+ REL_CAPS_RW_SECTIONS = 1U , /* REL has RW SHT_PROGBITS sections */
272
+ REL_CAPS_RO_SECTIONS = 2U /* REL has RO SHT_PROGBITS sections */
273
+ };
274
+
270
275
/* Load ELF file section and symbol tables; relocate sections and symbols based on loading/mapping vaddr
271
276
*/
272
277
static int
273
278
_load_elf_file_details (
274
279
Elf * elf ,
275
280
ElfDetails * ret_details ,
281
+ unsigned * ret_caps ,
276
282
void * rawdata_rw ,
277
283
void * rawdata_ro )
278
284
{
@@ -293,6 +299,7 @@ static int
293
299
Elf64_Section text_idx = 0 ;
294
300
Elf64_Section rel_text_idx = 0 ;
295
301
Elf64_Section rela_text_idx = 0 ;
302
+ unsigned caps = 0 ;
296
303
int rc ;
297
304
298
305
/* Determine if 64-bit or 32-bit ELF file */
@@ -472,8 +479,12 @@ static int
472
479
} else {
473
480
if (scn_idx == text_idx || scn_idx == rodata_idx ) {
474
481
shdr64 -> sh_addr = (Elf64_Addr )(rawdata_ro + shdr64 -> sh_offset );
482
+ caps |= REL_CAPS_RO_SECTIONS ;
475
483
} else {
476
484
shdr64 -> sh_addr = (Elf64_Addr )(rawdata_rw + shdr64 -> sh_offset );
485
+ if (shdr64 -> sh_type == SHT_PROGBITS ) {
486
+ caps |= REL_CAPS_RW_SECTIONS ;
487
+ }
477
488
}
478
489
}
479
490
}
@@ -493,6 +504,7 @@ static int
493
504
494
505
/* Return the ElfDetails object to the caller */
495
506
* ret_details = details ;
507
+ * ret_caps = caps ;
496
508
497
509
return 0 ;
498
510
}
@@ -522,6 +534,7 @@ static int
522
534
relocate_elf_load_cu (
523
535
Elf * elf ,
524
536
void * * start ,
537
+ unsigned * caps ,
525
538
void * rawdata_rw ,
526
539
void * rawdata_ro ,
527
540
int flag_quiet )
@@ -531,12 +544,12 @@ static int
531
544
uint64 n_symbols , i ;
532
545
int rc ;
533
546
534
- if (!elf || !start || !rawdata_rw || !rawdata_ro ) {
547
+ if (!elf || !start || !caps || ! rawdata_rw || !rawdata_ro ) {
535
548
return -1 ;
536
549
}
537
550
538
551
/* Load ELF file section and symbol tables */
539
- rc = _load_elf_file_details (elf , & details , rawdata_rw , rawdata_ro );
552
+ rc = _load_elf_file_details (elf , & details , caps , rawdata_rw , rawdata_ro );
540
553
if (rc )
541
554
goto term ;
542
555
@@ -616,13 +629,22 @@ static void print_usage(char **argv)
616
629
"\t--help : this message\n" , argv [0 ]);
617
630
}
618
631
632
+ struct rel_info_t {
633
+ char * name ; /* File name */
634
+ void * vma_rw ; /* Ptr to RW VMA */
635
+ size_t size ; /* File size */
636
+ };
637
+
619
638
int main (int argc , char * * argv )
620
639
{
621
640
size_t areas_capacity = 0 , objs_capacity = 0 ;
622
641
#if __linux__ != 0
623
642
struct char_ptr_arr_t areas = { .count = 0 , .arr = NULL };
624
643
#endif
625
- struct char_ptr_arr_t objs = { .count = 0 , .arr = NULL };
644
+ struct {
645
+ size_t count ;
646
+ struct rel_info_t * arr ;
647
+ } objs = { .count = 0 , .arr = NULL };
626
648
Elf * prev_elf = NULL ;
627
649
void * start = NULL ;
628
650
int flag_quiet = 0 ;
@@ -660,10 +682,10 @@ int main(int argc, char **argv)
660
682
#endif
661
683
/* Unprefixed arg must be a file */
662
684
if (objs .count == objs_capacity ) {
663
- objs .arr = (char * * )realloc (objs .arr , sizeof (* objs .arr ) * (objs_capacity = (objs_capacity + 1 ) * 2 ));
685
+ objs .arr = (struct rel_info_t * )realloc (objs .arr , sizeof (* objs .arr ) * (objs_capacity = (objs_capacity + 1 ) * 2 ));
664
686
}
665
687
666
- objs .arr [objs .count ++ ] = argv [i ];
688
+ objs .arr [objs .count ++ ]. name = argv [i ];
667
689
}
668
690
669
691
if (objs .count == 0 ) {
@@ -678,8 +700,9 @@ int main(int argc, char **argv)
678
700
void * p , * q ;
679
701
Elf * elf ;
680
702
Elf64_Ehdr * ehdr64 ;
703
+ unsigned caps ;
681
704
682
- const int fd = open (objs .arr [i ], O_RDONLY );
705
+ const int fd = open (objs .arr [i ]. name , O_RDONLY );
683
706
684
707
if (fd < 0 ) {
685
708
fprintf (stderr , "error: cannot open file\n" );
@@ -720,14 +743,40 @@ int main(int argc, char **argv)
720
743
ehdr64 -> e_entry = (Elf64_Addr )prev_elf ;
721
744
prev_elf = elf ;
722
745
723
- if (relocate_elf_load_cu (elf , & start , p , q , flag_quiet )) {
746
+ if (relocate_elf_load_cu (elf , & start , & caps , p , q , flag_quiet )) {
724
747
fprintf (stderr , "error: cannot relocate_elf_load_cu\n" );
725
748
return -1 ;
726
749
}
727
750
728
- if (mprotect (q , sb .st_size , PROT_READ | PROT_EXEC )) {
729
- fprintf (stderr , "error: cannot mprotect\n" );
730
- return -1 ;
751
+ /* Finalize RO mapping depending on presence of RO SHT_PROGBITS */
752
+ if (caps & REL_CAPS_RO_SECTIONS ) {
753
+ if (mprotect (q , sb .st_size , PROT_READ | PROT_EXEC )) {
754
+ fprintf (stderr , "error: cannot mprotect\n" );
755
+ return -1 ;
756
+ }
757
+ } else {
758
+ if (munmap (q , sb .st_size )) {
759
+ fprintf (stderr , "error: cannot munmap\n" );
760
+ return -1 ;
761
+ }
762
+ }
763
+
764
+ /* Defer unmapping of RW mapping depending on presence of RW SHT_PROGBITS */
765
+ if (caps & REL_CAPS_RW_SECTIONS ) {
766
+ objs .arr [i ].vma_rw = NULL ;
767
+ } else {
768
+ objs .arr [i ].vma_rw = p ;
769
+ objs .arr [i ].size = sb .st_size ;
770
+ }
771
+ }
772
+
773
+ /* All SHN_UNDEFs have been processed -- unmap unneeded RW mappings */
774
+ for (i = 0 ; i < objs .count ; ++ i ) {
775
+ if (objs .arr [i ].vma_rw != NULL ) {
776
+ if (munmap (objs .arr [i ].vma_rw , objs .arr [i ].size )) {
777
+ fprintf (stderr , "error: cannot munmap\n" );
778
+ return -1 ;
779
+ }
731
780
}
732
781
}
733
782
0 commit comments