From 9362a422a8d9938dbe63e17c3f0ca5a6d0d3be4c Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Mon, 13 Dec 2021 01:30:27 +0500 Subject: [PATCH] Start working on ELF utils --- .gitignore | 1 + Makefile.am | 5 ++ README.md | 2 +- include/kernaux/elf.h | 136 ++++++++++++++++++++++++++++++++++++++++++ tests/test_elf.c | 29 +++++++++ 5 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 include/kernaux/elf.h create mode 100644 tests/test_elf.c diff --git a/.gitignore b/.gitignore index 4132e95..0406059 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ /tests/multiboot2_print1 /tests/multiboot2_print2 /tests/test_cmdline +/tests/test_elf /tests/test_multiboot2_helpers /tests/test_multiboot2_print /tests/test_multiboot2_validation diff --git a/Makefile.am b/Makefile.am index f415210..90129c7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,6 +12,7 @@ lib_LIBRARIES = libkernaux.a TESTS = \ examples/printf \ examples/printf_va \ + tests/test_elf \ tests/test_printf \ tests/test_stdlib @@ -83,6 +84,10 @@ tests_test_cmdline_SOURCES = \ $(libkernaux_a_SOURCES) \ tests/test_cmdline.c +tests_test_elf_SOURCES = \ + $(libkernaux_a_SOURCES) \ + tests/test_elf.c + tests_test_multiboot2_helpers_SOURCES = \ $(libkernaux_a_SOURCES) \ tests/test_multiboot2_helpers.c diff --git a/README.md b/README.md index 14df540..16ca1ad 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ API * [Multiboot 2 (GRUB 2) information parser](/include/kernaux/multiboot2.h) * [Serial console](/include/kernaux/console.h) * [Page Frame Allocator](/include/kernaux/pfa.h) *(work in progress)* -* ELF utils *(planned)* +* [ELF utils](/include/kernaux/elf.h) *(work in progress)* * [Architecture-specific helpers](/include/kernaux/arch/) * [printf replacement](/include/kernaux/printf.h) *(work in progress)* * [stdlib replacement](/include/kernaux/stdlib.h): diff --git a/include/kernaux/elf.h b/include/kernaux/elf.h new file mode 100644 index 0000000..d4ccee8 --- /dev/null +++ b/include/kernaux/elf.h @@ -0,0 +1,136 @@ +#ifndef KERNAUX_INCLUDED_ELF +#define KERNAUX_INCLUDED_ELF 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct KernAux_ELF_Header { + unsigned char magic_0x7F : 8; + unsigned char magic_E : 8; + unsigned char magic_L : 8; + unsigned char magic_F : 8; + unsigned char bitness : 8; + unsigned char endianness : 8; + unsigned char header_version : 8; + unsigned char os_abi : 8; + unsigned long unused1 : 32; + unsigned long unused2 : 32; + unsigned short obj_type : 16; + unsigned short isa : 16; + unsigned long elf_version : 32; + unsigned long entrypoint : 32; + unsigned long prog_table_pos : 32; + unsigned long sect_table_pos : 32; + unsigned long arch_flags : 32; + unsigned short header_size : 16; + unsigned short prog_entr_size : 16; + unsigned short prog_entr_num : 16; + unsigned short sect_entr_size : 16; + unsigned short sect_entr_num : 16; + unsigned short sect_names_idx : 16; +} +__attribute__((packed)); + +struct KernAux_ELF_ProgramEntry { + unsigned long type : 32; + unsigned long offset : 32; + unsigned long virt_addr : 32; + unsigned long phys_addr : 32; + unsigned long file_size : 32; + unsigned long mem_size : 32; + unsigned long flags : 32; + unsigned long align : 32; +} +__attribute__((packed)); + +struct KernAux_ELF_SectionEntry { + unsigned long name : 32; + unsigned long type : 32; + unsigned long flags : 32; + unsigned long vaddr : 32; + unsigned long file_offset : 32; + unsigned long file_size : 32; + unsigned long link : 32; + unsigned long info : 32; + unsigned long alignment : 32; + unsigned long ent_size : 32; +} +__attribute__((packed)); + +struct KernAux_ELF_RelocationEntry { + unsigned long virt_addr : 32; + unsigned long info : 32; +} +__attribute__((packed)); + +typedef struct KernAux_ELF_ProgramEntry KernAux_ELF_ProgramTable[]; + +typedef struct KernAux_ELF_SectionEntry KernAux_ELF_SectionTable[]; + +typedef struct KernAux_ELF_RelocationEntry KernAux_ELF_RelocationTable[]; + +inline static bool KernAux_ELF_Header_is_valid( + const struct KernAux_ELF_Header *header +); + +bool KernAux_ELF_Header_is_valid( + const struct KernAux_ELF_Header *const header +) { + if (!( + header->magic_0x7F == 0x7F && + header->magic_E == 'E' && + header->magic_L == 'L' && + header->magic_F == 'F' && + header->header_version == 1 && + header->elf_version == 1 + )) { + return false; + } + + if (!( + header->bitness == 1 || // 32 bit + header->bitness == 2 // 64 bit + )) { + return false; + } + + if (!( + header->endianness == 1 || // Little endian + header->endianness == 2 // Big endian + )) { + return false; + } + + if (!( + header->os_abi >= 0 && + header->os_abi <= 0x12 && + header->os_abi != 0x05 + )) { + return false; + } + + if (!( + header->obj_type == 0x00 || // NONE + header->obj_type == 0x01 || // REL + header->obj_type == 0x02 || // EXEC + header->obj_type == 0x03 || // DYN + header->obj_type == 0x04 || // CORE + header->obj_type == 0xFE00 || // LOOS + header->obj_type == 0xFEFF || // HIOS + header->obj_type == 0xFF00 || // LOPROC + header->obj_type == 0xFFFF // HIPROC + )) { + return false; + } + + return true; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/test_elf.c b/tests/test_elf.c new file mode 100644 index 0000000..72725c6 --- /dev/null +++ b/tests/test_elf.c @@ -0,0 +1,29 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include + +#define BUFFER_SIZE (1024 * 1024) + +int main(int argc, char **argv) +{ + assert(argc >= 1); + + FILE *const fd = fopen(argv[0], "r"); + assert(fd); + + unsigned char buffer[BUFFER_SIZE]; + const size_t size = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, fd); + assert(size > 0); + + assert(KernAux_ELF_Header_is_valid(buffer)); + + fclose(fd); + + return 0; +}