[elf] Ressurect elf library

Resurrect the existing but unused ELF library in libraries/elf, and use
it instead of boot/elf.h for parsing ELF files in the bootloader.

Also adds a const version of offset_iterator called
const_offset_iterator.
This commit is contained in:
Justin C. Miller
2021-07-31 15:10:03 -07:00
parent 5e2cfab7ba
commit 363d30eadc
9 changed files with 189 additions and 250 deletions

View File

@@ -1,83 +0,0 @@
/// \file elf.h
/// Definitions and related constants for ELF64 structures
#pragma once
#include <stdint.h>
namespace boot {
namespace elf {
constexpr uint8_t version = 1;
constexpr uint8_t word_size = 2;
constexpr uint8_t endianness = 1;
constexpr uint8_t os_abi = 0;
constexpr uint16_t machine = 0x3e;
const unsigned PT_LOAD = 1;
const unsigned ST_PROGBITS = 1;
const unsigned ST_NOBITS = 8;
const unsigned long SHF_ALLOC = 0x2;
struct header
{
char magic[4];
uint8_t word_size;
uint8_t endianness;
uint8_t header_version;
uint8_t os_abi;
uint64_t reserved;
uint16_t type;
uint16_t machine;
uint32_t version;
uint64_t entrypoint;
uint64_t ph_offset;
uint64_t sh_offset;
uint32_t flags;
uint16_t eh_size;
uint16_t ph_entsize;
uint16_t ph_num;
uint16_t sh_entsize;
uint16_t sh_num;
uint16_t sh_str_idx;
} __attribute__ ((packed));
struct program_header
{
uint32_t type;
uint32_t flags;
uint64_t offset;
uint64_t vaddr;
uint64_t paddr;
uint64_t file_size;
uint64_t mem_size;
uint64_t align;
} __attribute__ ((packed));
struct 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));
} // namespace elf
} // namespace boot

View File

@@ -3,7 +3,8 @@
#include "allocator.h"
#include "console.h"
#include "elf.h"
#include "elf/file.h"
#include "elf/headers.h"
#include "error.h"
#include "fs.h"
#include "init_args.h"
@@ -35,21 +36,6 @@ load_file(
}
static bool
is_elfheader_valid(const elf::header *header)
{
return
header->magic[0] == 0x7f &&
header->magic[1] == 'E' &&
header->magic[2] == 'L' &&
header->magic[3] == 'F' &&
header->word_size == elf::word_size &&
header->endianness == elf::endianness &&
header->os_abi == elf::os_abi &&
header->machine == elf::machine &&
header->header_version == elf::version;
}
static void
create_module(buffer data, const program_desc &desc, bool loaded)
{
@@ -82,55 +68,45 @@ load_program(
if (add_module)
create_module(data, desc, true);
const elf::header *header = reinterpret_cast<const elf::header*>(data.pointer);
uintptr_t program_base = reinterpret_cast<uintptr_t>(data.pointer);
if (data.count < sizeof(elf::header) || !is_elfheader_valid(header))
elf::file program(data.pointer, data.count);
if (!program.valid())
error::raise(uefi::status::load_error, L"ELF file not valid");
size_t num_sections = 0;
for (int i = 0; i < header->ph_num; ++i) {
ptrdiff_t offset = header->ph_offset + i * header->ph_entsize;
const elf::program_header *pheader =
offset_ptr<elf::program_header>(data.pointer, offset);
if (pheader->type == elf::PT_LOAD)
for (auto &seg : program.programs()) {
if (seg.type == elf::segment_type::load)
++num_sections;
}
init::program_section *sections = new init::program_section [num_sections];
size_t next_section = 0;
for (int i = 0; i < header->ph_num; ++i) {
ptrdiff_t offset = header->ph_offset + i * header->ph_entsize;
const elf::program_header *pheader =
offset_ptr<elf::program_header>(data.pointer, offset);
if (pheader->type != elf::PT_LOAD)
for (auto &seg : program.programs()) {
if (seg.type != elf::segment_type::load)
continue;
init::program_section &section = sections[next_section++];
size_t page_count = memory::bytes_to_pages(pheader->mem_size);
size_t page_count = memory::bytes_to_pages(seg.mem_size);
if (pheader->mem_size > pheader->file_size) {
if (seg.mem_size > seg.file_size) {
void *pages = g_alloc.allocate_pages(page_count, alloc_type::program, true);
void *source = offset_ptr<void>(data.pointer, pheader->offset);
g_alloc.copy(pages, source, pheader->file_size);
void *source = offset_ptr<void>(data.pointer, seg.offset);
g_alloc.copy(pages, source, seg.file_size);
section.phys_addr = reinterpret_cast<uintptr_t>(pages);
} else {
section.phys_addr = program_base + pheader->offset;
section.phys_addr = program.base() + seg.offset;
}
section.virt_addr = pheader->vaddr;
section.size = pheader->mem_size;
section.type = static_cast<init::section_flags>(pheader->flags);
section.virt_addr = seg.vaddr;
section.size = seg.mem_size;
section.type = static_cast<init::section_flags>(seg.flags);
}
init::program *prog = new init::program;
prog->sections = { .pointer = sections, .count = num_sections };
prog->phys_base = program_base;
prog->entrypoint = header->entrypoint;
prog->phys_base = program.base();
prog->entrypoint = program.entrypoint();
return prog;
}

View File

@@ -2,7 +2,7 @@ name = "boot"
kind = "exe"
output = "boot.efi"
targets = ["boot"]
deps = ["cpu", "kutil"]
deps = ["cpu", "elf", "kutil"]
sources = [
"allocator.cpp",
"console.cpp",