From d855c0a219a180497c2e50f9bc19bfce69b937a6 Mon Sep 17 00:00:00 2001 From: Ada Christine Date: Thu, 23 Jan 2025 00:24:57 +0000 Subject: it printfs with the efi interface --- lib/elf64.c | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 165 insertions(+), 31 deletions(-) (limited to 'lib/elf64.c') diff --git a/lib/elf64.c b/lib/elf64.c index e880179..b5afc18 100644 --- a/lib/elf64.c +++ b/lib/elf64.c @@ -1,43 +1,130 @@ #include +#include #include +#include -bool elf64_validate(Elf64_Ehdr *ehdr, unsigned type, unsigned machine) +static bool is_valid_ident(Elf_Byte const e_ident[EI_NIDENT]) { - if (ehdr->e_ident[EI_MAG0] != ELFMAG0 - || ehdr->e_ident[EI_MAG1] != ELFMAG1 - || ehdr->e_ident[EI_MAG2] != ELFMAG2 - || ehdr->e_ident[EI_MAG3] != ELFMAG3 - || ehdr->e_ident[EI_CLASS] != ELFCLASS64 - || ehdr->e_ident[EI_DATA] != ELFDATA2LSB - || ehdr->e_ident[EI_VERSION] != EV_CURRENT - || ehdr->e_machine != machine - || ehdr->e_type != type) - { - return false; - } + return (e_ident[EI_MAG1] == ELFMAG1 + && e_ident[EI_MAG1] == ELFMAG1 + && e_ident[EI_MAG2] == ELFMAG2 + && e_ident[EI_MAG3] == ELFMAG3 + && e_ident[EI_CLASS] == ELFCLASS64 + && e_ident[EI_DATA] == ELFDATA2LSB + && e_ident[EI_VERSION] == EV_CURRENT); +} + +bool elf64_validate(Elf64_Ehdr const *ehdr, unsigned type, unsigned machine) +{ + return (is_valid_ident(ehdr->e_ident) + && ehdr->e_type == type + && ehdr->e_machine == machine); +} + +static ssize_t read_ehdr(int fd, Elf64_Ehdr *ehdr) +{ + ssize_t pos = lseek(fd, 0, SEEK_CUR); + + ssize_t result; + + if ((result = lseek(fd, 0, SEEK_SET)) == 0) + { + result = read(fd, ehdr, sizeof(*ehdr)); + } + + lseek(fd, pos, SEEK_SET); + + return result; +} + +static ssize_t read_phdr(int fd, Elf64_Ehdr *ehdr, int phdr_index, Elf64_Phdr *phdr) +{ + if (phdr_index > ehdr->e_phnum) + { + return -1; + } + + ssize_t pos = lseek(fd, 0, SEEK_CUR); + + ssize_t offset = ehdr->e_phoff + ehdr->e_phentsize * phdr_index; + + ssize_t result; + + if ((result = lseek(fd, offset, SEEK_SET)) == offset) + { + result = read(fd, phdr, ehdr->e_phentsize); + } + + lseek(fd, pos, SEEK_SET); + + return result; +} + +static ssize_t read_phdrs(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr phdrs[ehdr->e_phnum]) +{ + ssize_t result = 0; + + for (int i = 0; result >= 0 && i < ehdr->e_phnum; i++) + { + result = read_phdr(fd, ehdr, i, &phdrs[i]); + } + + return result; +} + +bool elf64_validate_fd(int fd, unsigned type, unsigned machine) +{ + Elf64_Ehdr ehdr; + read_ehdr(fd, &ehdr); + return elf64_validate(&ehdr, type, machine); +} + +static bool is_loadable(Elf64_Phdr const *phdr) +{ + return phdr != nullptr && phdr->p_type == PT_LOAD; +} + +static size_t aligned_size(Elf64_Phdr const *phdr) +{ + size_t size = phdr->p_offset + phdr->p_memsz; + return (size + phdr->p_align - 1) & ~(phdr->p_align - 1); +} + +static size_t segment_memsz(Elf64_Phdr const *phdr) +{ + return is_loadable(phdr) ? aligned_size(phdr) : 0; +} + +size_t elf64_size(Elf64_Ehdr const *ehdr, Elf64_Phdr *phdrs) +{ + size_t size = 0; + + for (int i = 0; i < ehdr->e_phnum; i++) + { + size_t size_next = segment_memsz(&phdrs[i]); + size = size_next > size ? size_next : size; + } - return true; + return size; } -size_t elf64_size(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs) +size_t elf64_size_fd(int fd) { - size_t size = 0; + size_t size = 0; - for (int i = 0; i < ehdr->e_phnum; i++) - { - if (phdrs[i].p_type != PT_LOAD) - { - continue; - } + Elf64_Ehdr ehdr; + Elf64_Phdr phdr; - size = phdrs[i].p_offset + phdrs[i].p_memsz; - if (phdrs[i].p_align > 1) - { - size = (size + phdrs[i].p_align - 1) & ~(phdrs[i].p_align - 1); - } - } + ssize_t result = read_ehdr(fd, &ehdr); - return size; + for (int i = 0; result >= 0 && i < ehdr.e_phnum; i++) + { + result = read_phdr(fd, &ehdr, i, &phdr); + size_t size_next = segment_memsz(&phdr); + size = size_next > size ? size_next : size; + } + + return result > 0 ? size : 0; } static Elf64_Dyn *get_dynent(Elf64_Dyn *dyntab, unsigned long dt_type) @@ -55,7 +142,7 @@ static Elf64_Dyn *get_dynent(Elf64_Dyn *dyntab, unsigned long dt_type) return nullptr; } -void *elf64_dt_ptr(void *base, Elf64_Dyn *dyntab, unsigned long dt_type) +void *elf64_dt_ptr(char *base, Elf64_Dyn *dyntab, unsigned long dt_type) { Elf64_Dyn *dynent = get_dynent(dyntab, dt_type); @@ -64,7 +151,7 @@ void *elf64_dt_ptr(void *base, Elf64_Dyn *dyntab, unsigned long dt_type) return nullptr; } - return dynent->d_ptr + (char *)base; + return dynent->d_ptr + base; } uintptr_t elf64_dt_val(Elf64_Dyn *dyntab, unsigned long dt_type) @@ -79,3 +166,50 @@ uintptr_t elf64_dt_val(Elf64_Dyn *dyntab, unsigned long dt_type) return dynent->d_val; } +static ssize_t load_segment(int fd, Elf64_Phdr *phdr, size_t buffer_size, char buffer[buffer_size]) +{ + if (!is_loadable(phdr)) + { + return 0; + } + + ssize_t pos = lseek(fd, 0, SEEK_CUR); + + ssize_t result; + + if ((result = lseek(fd, phdr->p_offset, SEEK_SET)) >= 0) + { + result = read(fd, &buffer[phdr->p_offset], phdr->p_memsz); + } + + lseek(fd, pos, SEEK_SET); + + return result; +} + +ssize_t elf64_load_segments(int fd, size_t buffer_size, char buffer[buffer_size]) +{ + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)&buffer[0]; + + ssize_t result; + + if ((result = read_ehdr(fd, ehdr)) < 0) + { + return result; + } + + Elf64_Phdr *phdrs = (Elf64_Phdr *)&buffer[ehdr->e_phoff]; + + if ((result = read_phdrs(fd, ehdr, phdrs)) < 0) + { + return result; + } + + for (int i = 0; result > 0 && i < ehdr->e_phnum; i++) + { + result = load_segment(fd, &phdrs[i], buffer_size, buffer); + } + + return result; +} + -- cgit v1.3.1-1-g115d