diff --git a/tool/build/renamestr.c b/tool/build/renamestr.c index 8f2ceacf2..f47a8416b 100644 --- a/tool/build/renamestr.c +++ b/tool/build/renamestr.c @@ -199,170 +199,6 @@ static void GetOpts(int argc, char *argv[]) { exepath = argv[optind]; } -static void ValidateElfImage(Elf64_Ehdr *e, Elf64_Off esize, // - const char *epath) { - - // validate elf header - if (e->e_type != ET_EXEC && e->e_type != ET_DYN) - Die(epath, "elf binary isn't an executable"); - if (!e->e_phnum) - Die(epath, "elf executable needs at least one program header"); - if (e->e_phnum > 65534) - Die(epath, "elf with more than 65534 phdrs not supported"); - if (e->e_phentsize != sizeof(Elf64_Phdr)) - Die(epath, "elf e_phentsize isn't sizeof(Elf64_Phdr)"); - if (e->e_phoff > esize) - Die(epath, "elf program header offset points past image eof"); - if (e->e_phoff & 7) - Die(epath, "elf e_phoff must be aligned on an 8-byte boundary"); - if (e->e_phoff + e->e_phoff + e->e_phnum * sizeof(Elf64_Phdr) > esize) - Die(epath, "elf program header array overlaps image eof"); - - // determine microprocessor page size requirement - // - // even though operating systems (windows) and c libraries (cosmo) - // sometimes impose a larger page size requirement than the actual - // microprocessor itself, the cpu page size is still the only page - // size that actually matters when it comes to executable loading. - unsigned long pagesz; - if (e->e_machine == EM_AARCH64) { - pagesz = 16384; // apple m1 (xnu, linux) - } else { // - pagesz = 4096; // x86-64, raspberry pi - } - - // remove empty segment loads - // empty loads should be inconsequential; linux ignores them - // however they tend to trip up many systems such as openbsd - int i, j; - Elf64_Phdr *p = (Elf64_Phdr *)((char *)e + e->e_phoff); - - for (i = 0; i < e->e_phnum;) { - if (p[i].p_type == PT_LOAD && !p[i].p_memsz) { - if (i + 1 < e->e_phnum) { - memmove(p + i, p + i + 1, (e->e_phnum - (i + 1)) * sizeof(*p)); - } - --e->e_phnum; - } else { - ++i; - } - } - - // oracle says loadable segment entries in the program header table - // appear in ascending order, sorted on the p_vaddr member. - int found_load = 0; - Elf64_Addr last_vaddr = 0; - for (i = 0; i < e->e_phnum; ++i) { - if (p[i].p_type != PT_LOAD) - continue; - if (found_load && p[i].p_vaddr <= last_vaddr) { - Die(epath, "ELF PT_LOAD segments must be ordered by p_vaddr"); - } - last_vaddr = p[i].p_vaddr; - found_load = 1; - } - if (!found_load) { - Die(epath, "ELF must have at least one PT_LOAD segment"); - } - - // merge adjacent loads that are contiguous with equal protection - for (i = 0; i + 1 < e->e_phnum;) { - if (p[i].p_type == PT_LOAD && p[i + 1].p_type == PT_LOAD && - ((p[i].p_flags & (PF_R | PF_W | PF_X)) == - (p[i + 1].p_flags & (PF_R | PF_W | PF_X))) && - ((p[i].p_offset + p[i].p_filesz + (pagesz - 1)) & -pagesz) - - (p[i + 1].p_offset & -pagesz) <= - pagesz && - ((p[i].p_vaddr + p[i].p_memsz + (pagesz - 1)) & -pagesz) - - (p[i + 1].p_vaddr & -pagesz) <= - pagesz) { - p[i].p_memsz = (p[i + 1].p_vaddr + p[i + 1].p_memsz) - p[i].p_vaddr; - p[i].p_filesz = (p[i + 1].p_offset + p[i + 1].p_filesz) - p[i].p_offset; - if (i + 2 < e->e_phnum) { - memmove(p + i + 1, p + i + 2, (e->e_phnum - (i + 2)) * sizeof(*p)); - } - --e->e_phnum; - } else { - ++i; - } - } - - // validate program headers - bool found_entry = false; - for (i = 0; i < e->e_phnum; ++i) { - if (p[i].p_type == PT_INTERP) { - Die(epath, "ELF has PT_INTERP which isn't supported"); - } - if (p[i].p_type == PT_DYNAMIC) { - Die(epath, "ELF has PT_DYNAMIC which isn't supported"); - } - if (p[i].p_type != PT_LOAD) { - continue; - } - if (!p[i].p_memsz) { - Die(epath, "ELF PT_LOAD p_memsz was zero"); - } - if (p[i].p_offset > esize) { - Die(epath, "ELF PT_LOAD p_offset points past EOF"); - } - if (p[i].p_filesz > p[i].p_memsz) { - Die(epath, "ELF PT_LOAD p_filesz exceeds p_memsz"); - } - if (p[i].p_align > 1 && (p[i].p_align & (p[i].p_align - 1))) { - Die(epath, "ELF PT_LOAD p_align must be two power"); - } - if (p[i].p_vaddr + p[i].p_memsz < p[i].p_vaddr || - p[i].p_vaddr + p[i].p_memsz + (pagesz - 1) < p[i].p_vaddr) { - Die(epath, "ELF PT_LOAD p_vaddr + p_memsz overflow"); - } - if (p[i].p_offset + p[i].p_filesz < p[i].p_offset || - p[i].p_offset + p[i].p_filesz + (pagesz - 1) < p[i].p_offset) { - Die(epath, "ELF PT_LOAD p_offset + p_filesz overflow"); - } - if (p[i].p_align > 1 && ((p[i].p_vaddr & (p[i].p_align - 1)) != - (p[i].p_offset & (p[i].p_align - 1)))) { - Die(epath, "ELF p_vaddr incongruent w/ p_offset modulo p_align"); - } - if ((p[i].p_vaddr & (pagesz - 1)) != (p[i].p_offset & (pagesz - 1))) { - Die(epath, "ELF p_vaddr incongruent w/ p_offset modulo AT_PAGESZ"); - } - if (p[i].p_offset + p[i].p_filesz > esize) { - Die(epath, "ELF PT_LOAD p_offset and p_filesz overlaps image EOF"); - } - Elf64_Off a = p[i].p_vaddr & -pagesz; - Elf64_Off b = (p[i].p_vaddr + p[i].p_memsz + (pagesz - 1)) & -pagesz; - for (j = i + 1; j < e->e_phnum; ++j) { - if (p[j].p_type != PT_LOAD) - continue; - Elf64_Off c = p[j].p_vaddr & -pagesz; - Elf64_Off d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz; - if (MAX(a, c) < MIN(b, d)) { - Die(epath, - "ELF PT_LOAD phdrs %d and %d overlap each others virtual memory"); - } - } - if (e->e_machine == EM_AARCH64 && - p[i].p_vaddr + p[i].p_memsz > 0x0001000000000000) { - Die(epath, "this is an ARM ELF program but it loads to virtual" - " memory addresses outside the legal range [0,2^48)"); - } - if (e->e_machine == EM_NEXGEN32E && - !(-140737488355328 <= (Elf64_Sxword)p[i].p_vaddr && - (Elf64_Sxword)(p[i].p_vaddr + p[i].p_memsz) <= 140737488355328)) { - Die(epath, "this is an x86-64 ELF program, but it loads to virtual" - " memory addresses outside the legal range [-2^47,2^47)"); - } - if ((p[i].p_flags & PF_X) && // - p[i].p_vaddr <= e->e_entry && - e->e_entry < p[i].p_vaddr + p[i].p_memsz) { - found_entry = 1; - } - } - if (!found_entry) { - Die(epath, "ELF entrypoint not found in PT_LOAD with PF_X"); - } -} - struct Input { union { char *map; @@ -417,7 +253,6 @@ int main(int argc, char *argv[]) { GetOpts(argc, argv); OpenInput(exepath); - ValidateElfImage(input.elf, input.size, input.path); rodata = FindElfSectionByName( input.elf, input.size, GetElfSectionNameStringTable(input.elf, input.size), ".rodata");