Load ELF file by sections to get addresses right

This commit is contained in:
Justin C. Miller
2018-05-06 22:03:44 -07:00
parent 97fb8ef653
commit cce892e92f
5 changed files with 89 additions and 17 deletions

View File

@@ -22,6 +22,9 @@
#endif
const unsigned ELF_PT_LOAD = 1;
const unsigned ELF_ST_PROGBITS = 1;
const unsigned ELF_ST_NOBITS = 8;
const unsigned long ELF_SHF_ALLOC = 0x2;
struct elf_ident
{
@@ -75,3 +78,17 @@ struct elf_program_header
uint64_t align;
} __attribute__ ((packed));
struct elf_section_header
{
uint32_t name;
uint32_t type;
uint64_t flags;
uint64_t addr;
uint64_t offset;
uint64_t size;
uint32_t link;
uint32_t info;
uint64_t align;
uint64_t entry_size;
} __attribute__ ((packed));

View File

@@ -144,9 +144,6 @@ loader_load_elf(
if (prog_header.type != ELF_PT_LOAD) continue;
status = file->SetPosition(file, prog_header.offset);
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
length = prog_header.mem_size;
void *addr = (void *)(prog_header.vaddr - KERNEL_VIRT_ADDRESS);
status = loader_alloc_pages(bootsvc, KERNEL_MEMTYPE, &length, &addr);
@@ -155,10 +152,39 @@ loader_load_elf(
if (data->kernel == 0)
data->kernel = addr;
data->kernel_length = (uint64_t)addr + length - (uint64_t)data->kernel;
}
length = prog_header.file_size;
status = file->Read(file, &length, addr);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file");
struct elf_section_header sec_header;
for (int i = 0; i < header.sh_num; ++i) {
status = file->SetPosition(file, header.sh_offset + i * header.sh_entsize);
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
length = header.sh_entsize;
status = file->Read(file, &length, &sec_header);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF section header");
if ((sec_header.flags & ELF_SHF_ALLOC) == 0) continue;
void *addr = (void *)(sec_header.addr - KERNEL_VIRT_ADDRESS);
if (sec_header.type == ELF_ST_PROGBITS) {
status = file->SetPosition(file, sec_header.offset);
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
length = sec_header.size;
status = file->Read(file, &length, addr);
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file");
con_printf(L"Loaded %lx bytes %lx - %lx\n",
sec_header.size,
addr,
sec_header.addr + sec_header.size - KERNEL_VIRT_ADDRESS);
} else if (sec_header.type == ELF_ST_NOBITS) {
bootsvc->SetMem(addr, sec_header.size, 0);
con_printf(L"Zeroed %lx bytes %lx - %lx\n",
sec_header.size,
addr,
sec_header.addr + sec_header.size - KERNEL_VIRT_ADDRESS);
}
}
status = file->Close(file);