binfmt/elf: switch to phdrs instead of (incorrect) shdrs loader

This commit is contained in:
Mark
2020-10-19 15:58:46 +03:00
parent c2db4e94a6
commit 593ffd4e0c
+20 -55
View File
@@ -17,7 +17,7 @@
// uintptr_t amd64_map_get(const mm_space_t space, uintptr_t vaddr, uint64_t *flags);
// int amd64_map_single(mm_space_t pml4, uintptr_t virt_addr, uintptr_t phys, uint32_t flags);
static int elf_map_section(mm_space_t space, uintptr_t vma_dst, size_t size) {
static int elf_map_region(mm_space_t space, uintptr_t vma_dst, size_t size) {
uintptr_t page_aligned = vma_dst & ~0xFFF;
uintptr_t page_offset = vma_dst & 0xFFF;
size_t npages = (size + page_offset + 4095) / 4096;
@@ -141,7 +141,7 @@ int elf_load(struct process *proc, struct vfs_ioctx *ctx, struct ofile *fd, uint
int res;
ssize_t bread;
Elf64_Ehdr ehdr;
Elf64_Shdr *shdrs;
Elf64_Phdr phdr;
if ((res = elf_read(ctx, fd, 0, &ehdr, sizeof(Elf64_Ehdr))) != 0) {
kerror("elf: failed to read file header\n");
@@ -159,65 +159,34 @@ int elf_load(struct process *proc, struct vfs_ioctx *ctx, struct ofile *fd, uint
return -EINVAL;
}
shdrs = kmalloc(ehdr.e_shentsize * ehdr.e_shnum);
_assert(shdrs);
// Read all section headers
if ((res = elf_read(ctx, fd, ehdr.e_shoff, shdrs, ehdr.e_shentsize * ehdr.e_shnum)) != 0) {
kerror("elf: failed to read section headers\n");
goto end;
}
_assert(ehdr.e_phnum);
proc->image_end = 0;
proc->brk = 0;
//const char *shstrtabd = (const char *) (shdrs[ehdr->e_shstrndx].sh_offset + (uintptr_t) from);
// Load the sections
for (size_t i = 0; i < ehdr.e_shnum; ++i) {
Elf64_Shdr *shdr = &shdrs[i];
//const char *name = &shstrtabd[shdr->sh_name];
// Load program segments
for (size_t i = 0; i < ehdr.e_phnum; ++i) {
size_t off = ehdr.e_phoff + ehdr.e_phentsize * i;
if (shdr->sh_flags & SHF_ALLOC) {
//if (!strncmp(name, ".note", 5)) {
// // Fuck you, gcc
// continue;
//}
//if (!strncmp(name, ".gnu", 4)) {
// // Fuck you, gcc
// continue;
//}
if ((res = elf_read(ctx, fd, off, &phdr, ehdr.e_phentsize)) != 0) {
kerror("elf: failed to read program header\n");
}
//kdebug("Loading %s\n", name);
if (phdr.p_type == PT_LOAD) {
uintptr_t start_aligned = phdr.p_vaddr & ~0xFFF;
size_t size_aligned = ((phdr.p_vaddr + phdr.p_memsz + 0xFFF) & ~0xFFF) - start_aligned;
// If the section is below what is allowed
if (shdr->sh_addr < ELF_ADDR_MIN) {
kerror("elf: section address is below allowed\n");
res = -EINVAL;
goto end;
kdebug("[%2d] vaddr=%p\n", i, phdr.p_vaddr);
if (elf_map_region(proc->space, start_aligned, size_aligned) != 0) {
panic("Failed to map segment\n");
}
// Map the pages of this section
_assert(elf_map_section(proc->space, shdr->sh_addr, shdr->sh_size) == 0);
switch (shdr->sh_type) {
case SHT_PROGBITS:
_assert(elf_load_bytes(proc->space,
ctx,
fd,
shdr->sh_addr,
shdr->sh_offset,
shdr->sh_size) == 0);
break;
case SHT_NOBITS:
_assert(elf_bzero(proc->space,
shdr->sh_addr,
shdr->sh_size) == 0);
break;
if (elf_load_bytes(proc->space, ctx, fd, phdr.p_vaddr, phdr.p_offset, phdr.p_filesz) != 0) {
panic("Failed to load filesz data\n");
}
uintptr_t section_end = shdr->sh_addr + shdr->sh_size;
if (section_end > proc->image_end) {
proc->image_end = section_end;
if (phdr.p_memsz > phdr.p_filesz) {
_assert(elf_bzero(proc->space, phdr.p_vaddr + phdr.p_filesz, phdr.p_memsz - phdr.p_filesz) == 0);
}
}
}
@@ -227,9 +196,5 @@ int elf_load(struct process *proc, struct vfs_ioctx *ctx, struct ofile *fd, uint
*entry = ehdr.e_entry;
res = 0;
end:
// Free all the stuff we've allocated
kfree(shdrs);
return res;
}