Skip to content

Commit 7890843

Browse files
committed
unmap unneeded REL mappings
1 parent c8900f2 commit 7890843

File tree

1 file changed

+61
-12
lines changed

1 file changed

+61
-12
lines changed

reloc.c

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ typedef Elf64_Half Elf64_Section;
3939
#endif
4040

4141
int apply_relocate_add(Elf64_Shdr **sechdrs,
42-
unsigned int symsec,
43-
unsigned int relsec);
42+
unsigned int symsec,
43+
unsigned int relsec);
4444

4545
/* Following code based on IBM s390 ELF relocation sample */
4646
/* https://www.ibm.com/docs/en/zos/2.2.0?topic=file-example-relocating-addresses-within-elf */
@@ -267,12 +267,18 @@ static int
267267
return 0;
268268
}
269269

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+
270275
/* Load ELF file section and symbol tables; relocate sections and symbols based on loading/mapping vaddr
271276
*/
272277
static int
273278
_load_elf_file_details(
274279
Elf *elf,
275280
ElfDetails *ret_details,
281+
unsigned *ret_caps,
276282
void *rawdata_rw,
277283
void *rawdata_ro)
278284
{
@@ -293,6 +299,7 @@ static int
293299
Elf64_Section text_idx = 0;
294300
Elf64_Section rel_text_idx = 0;
295301
Elf64_Section rela_text_idx = 0;
302+
unsigned caps = 0;
296303
int rc;
297304

298305
/* Determine if 64-bit or 32-bit ELF file */
@@ -472,8 +479,12 @@ static int
472479
} else {
473480
if (scn_idx == text_idx || scn_idx == rodata_idx) {
474481
shdr64->sh_addr = (Elf64_Addr)(rawdata_ro + shdr64->sh_offset);
482+
caps |= REL_CAPS_RO_SECTIONS;
475483
} else {
476484
shdr64->sh_addr = (Elf64_Addr)(rawdata_rw + shdr64->sh_offset);
485+
if (shdr64->sh_type == SHT_PROGBITS) {
486+
caps |= REL_CAPS_RW_SECTIONS;
487+
}
477488
}
478489
}
479490
}
@@ -493,6 +504,7 @@ static int
493504

494505
/* Return the ElfDetails object to the caller */
495506
*ret_details = details;
507+
*ret_caps = caps;
496508

497509
return 0;
498510
}
@@ -522,6 +534,7 @@ static int
522534
relocate_elf_load_cu(
523535
Elf *elf,
524536
void **start,
537+
unsigned *caps,
525538
void *rawdata_rw,
526539
void *rawdata_ro,
527540
int flag_quiet)
@@ -531,12 +544,12 @@ static int
531544
uint64 n_symbols, i;
532545
int rc;
533546

534-
if (!elf || !start || !rawdata_rw || !rawdata_ro) {
547+
if (!elf || !start || !caps || !rawdata_rw || !rawdata_ro) {
535548
return -1;
536549
}
537550

538551
/* 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);
540553
if (rc)
541554
goto term;
542555

@@ -616,13 +629,22 @@ static void print_usage(char **argv)
616629
"\t--help : this message\n", argv[0]);
617630
}
618631

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+
619638
int main(int argc, char **argv)
620639
{
621640
size_t areas_capacity = 0, objs_capacity = 0;
622641
#if __linux__ != 0
623642
struct char_ptr_arr_t areas = { .count = 0, .arr = NULL };
624643
#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 };
626648
Elf *prev_elf = NULL;
627649
void *start = NULL;
628650
int flag_quiet = 0;
@@ -660,10 +682,10 @@ int main(int argc, char **argv)
660682
#endif
661683
/* Unprefixed arg must be a file */
662684
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));
664686
}
665687

666-
objs.arr[objs.count++] = argv[i];
688+
objs.arr[objs.count++].name = argv[i];
667689
}
668690

669691
if (objs.count == 0) {
@@ -678,8 +700,9 @@ int main(int argc, char **argv)
678700
void *p, *q;
679701
Elf *elf;
680702
Elf64_Ehdr *ehdr64;
703+
unsigned caps;
681704

682-
const int fd = open(objs.arr[i], O_RDONLY);
705+
const int fd = open(objs.arr[i].name, O_RDONLY);
683706

684707
if (fd < 0) {
685708
fprintf(stderr, "error: cannot open file\n");
@@ -720,14 +743,40 @@ int main(int argc, char **argv)
720743
ehdr64->e_entry = (Elf64_Addr)prev_elf;
721744
prev_elf = elf;
722745

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)) {
724747
fprintf(stderr, "error: cannot relocate_elf_load_cu\n");
725748
return -1;
726749
}
727750

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+
}
731780
}
732781
}
733782

0 commit comments

Comments
 (0)