From 7bbb33f50fd4edb3e292a419d8d90148a21a55dc Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Fri, 14 Jan 2022 11:40:24 +0100 Subject: [PATCH] vxBoot - 1.1.0 : GOT patch @add <> vxBoot/builtin/ld : add two new mode "INFO" and "CHECK" used for debugging <> vxBoot/elf/got : manually patch the GOT section <> vxBoot/loader/info : display information about ELF file @update <> CMakeList.txt : dump version + add new sources files <> include/vxBoot/hardware : add ELF section header information <> vxBoot/builtin/hw : add kernel origin address <> vxBoot/builtin/ld : change file name to a more appropriate one @fix <> vxBoot/hardware/get_info : fetch the kernel origin address <> vxBoot/elf/image : use the "real" kernel address <> vxBoot/loader/entry : add the GOT patch step --- CMakeLists.txt | 6 +- include/vxBoot/hardware.h | 1 + include/vxBoot/loader.h | 47 ++++++++++++++- src/builtin/hw.c | 4 +- src/builtin/{loader.c => ld.c} | 8 +++ src/hardware/get_info.c | 4 +- src/loader/elf/got.c | 49 +++++++++++++++ src/loader/elf/image.c | 5 +- src/loader/entry.c | 25 +++++--- src/loader/info.c | 107 +++++++++++++++++++++++++++++++++ 10 files changed, 241 insertions(+), 15 deletions(-) rename src/builtin/{loader.c => ld.c} (88%) create mode 100644 src/loader/elf/got.c create mode 100644 src/loader/info.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e53f98..2e1cbb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.15) -project(vxBoot VERSION 1.0.0 LANGUAGES C) +project(vxBoot VERSION 1.1.0 LANGUAGES C) include(GenerateG1A) include(GenerateG3A) @@ -23,12 +23,14 @@ set(SOURCES src/builtin/ls.c src/builtin/help.c src/builtin/hw.c - src/builtin/loader.c + src/builtin/ld.c src/loader/scan.c src/loader/elf/header.c src/loader/elf/image.c + src/loader/elf/got.c src/loader/error.c src/loader/entry.c + src/loader/info.c src/loader/kernel.c src/hardware/get_info.c ) diff --git a/include/vxBoot/hardware.h b/include/vxBoot/hardware.h index 17b8285..aa71c09 100644 --- a/include/vxBoot/hardware.h +++ b/include/vxBoot/hardware.h @@ -9,6 +9,7 @@ struct hwinfo { struct { struct { uintptr_t origin_addr; + uintptr_t kernel_addr; uintptr_t user_addr; } physical; size_t size; diff --git a/include/vxBoot/loader.h b/include/vxBoot/loader.h index a8f680a..f1a4333 100644 --- a/include/vxBoot/loader.h +++ b/include/vxBoot/loader.h @@ -77,8 +77,41 @@ typedef struct { uint32_t p_align; /* Segment alignment */ } Elf32_Phdr; +/* Section header */ +typedef struct { + uint32_t sh_name; /* Section name (string tbl index) */ + uint32_t sh_type; /* Section type */ + uint32_t sh_flags; /* Section flags */ + uint32_t sh_addr; /* Section virtual addr at execution */ + uint32_t sh_offset; /* Section file offset */ + uint32_t sh_size; /* Section size in bytes */ + uint32_t sh_link; /* Link to another section */ + uint32_t sh_info; /* Additional section information */ + uint32_t sh_addralign; /* Section alignment */ + uint32_t sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */ +#define SHT_NUM 19 /* Number of defined types. */ //--- // Loader API @@ -126,8 +159,12 @@ extern int loader_kernel_img_count(void); #define LOADER_DEFAULT 0 #define LOADER_DUMP 1 #define LOADER_TRACE 2 +#define LOADER_INFO 3 +#define LOADER_CHECK 4 extern int loader(struct smemfs_inode const * restrict const inode, int mode); +/* loader_info() : display ELF PIE file information */ +extern int loader_info(struct smemfs_inode const * inode, Elf32_Ehdr *header); //--- // Error ldpers @@ -189,8 +226,16 @@ extern int loader_image_error(int const errnum); +//--- +// GOT helpers +//--- - +/* loader_got_patch() : Try to patch the GOT section */ +extern int loader_got_patch( + struct smemfs_inode const * restrict const inode, + struct kernel_info * const kernel, + Elf32_Ehdr *hdr +); diff --git a/src/builtin/hw.c b/src/builtin/hw.c index 5ead07f..742c0e3 100644 --- a/src/builtin/hw.c +++ b/src/builtin/hw.c @@ -14,11 +14,13 @@ int hw_main(int argc, char **argv) hardware_get_info(&hwinfo); terminal_write( - "- user RAM physical addr: %p\n" + "- user RAM physical addr: %p\n" + "- kernel RAM physical addr: %p\n" "- RAM physical addr: %p\n" "- RAM size: %d\n" "- Kernel RAM space: %d o\n", hwinfo.ram.physical.user_addr, + hwinfo.ram.physical.kernel_addr, hwinfo.ram.physical.origin_addr, hwinfo.ram.size, hwinfo.ram.available diff --git a/src/builtin/loader.c b/src/builtin/ld.c similarity index 88% rename from src/builtin/loader.c rename to src/builtin/ld.c index 19b5ac9..50f680f 100644 --- a/src/builtin/loader.c +++ b/src/builtin/ld.c @@ -47,6 +47,14 @@ int ld_main(int argc, char **argv) path = argv[2]; mode = LOADER_TRACE; } + if (strcmp(argv[1], "info") == 0) { + path = argv[2]; + mode = LOADER_INFO; + } + if (strcmp(argv[1], "check") == 0) { + path = argv[2]; + mode = LOADER_CHECK; + } img = kernel_img_list; idx = strtol(path, &endptr, 10) + 1; if (endptr == NULL || endptr[0] != '\0') { diff --git a/src/hardware/get_info.c b/src/hardware/get_info.c index 1707f07..a602ad9 100644 --- a/src/hardware/get_info.c +++ b/src/hardware/get_info.c @@ -30,8 +30,10 @@ int hardware_get_info(struct hwinfo * const hwinfo) return (-1); uintptr_t uram = mmu_translate(0x08100000, NULL); hwinfo->ram.physical.origin_addr = uram & 0xff000000; + hwinfo->ram.physical.kernel_addr = uram + mmu_uram_size(); hwinfo->ram.physical.user_addr = uram; hwinfo->ram.size = __ram_get_size(uram | 0xa0000000); - hwinfo->ram.available = hwinfo->ram.size - (uram & 0x00ffffff); + hwinfo->ram.available = hwinfo->ram.size; + hwinfo->ram.available -= hwinfo->ram.physical.kernel_addr & 0x00ffffff; return (0); } diff --git a/src/loader/elf/got.c b/src/loader/elf/got.c new file mode 100644 index 0000000..09858ac --- /dev/null +++ b/src/loader/elf/got.c @@ -0,0 +1,49 @@ +#include "vxBoot/loader.h" +#include "vxBoot/fs/smemfs.h" +#include "vxBoot/terminal.h" + +#include + +/* loader_got_patch() : Try to patch the GOT section */ +int loader_got_patch( + struct smemfs_inode const * restrict const inode, + struct kernel_info * const kernel, + Elf32_Ehdr *hdr +) { + Elf32_Shdr shdr; + uintptr_t *got; + char name[5]; + off_t stroff; + off_t shoff; + + /* find the section header table */ + shoff = hdr->e_shoff; + + /* find the section string table ".strtable" */ + smemfs_pread( + inode, + &shdr, sizeof(Elf32_Shdr), + shoff + (sizeof(Elf32_Shdr) * hdr->e_shstrndx) + ); + stroff = shdr.sh_offset; + + /* walk throught each section and find the .got section */ + for (int i = 0; i < hdr->e_shnum; ++i) { + smemfs_pread(inode, &shdr, sizeof(Elf32_Shdr), shoff); + smemfs_pread(inode, name, 5, shdr.sh_name + stroff); + if (strcmp(name, ".got") != 0) { + shoff += sizeof(Elf32_Shdr); + continue; + } + got = kernel->memory.program.start; + got = (void*)((uintptr_t)got + (uintptr_t)shdr.sh_addr); + terminal_write(" GOT section found at %p...\n", got); + for (uint32_t j = 0 ; j < shdr.sh_size >> 2 ; ++j) { + terminal_write(" path symbols %p...\n", got[j]); + got[j] += (uintptr_t)kernel->hardware.ram.physical.kernel_addr; + got[j] |= (uintptr_t)0x80000000; + } + return (0); + } + return (-1); +} diff --git a/src/loader/elf/image.c b/src/loader/elf/image.c index 6519579..870237c 100644 --- a/src/loader/elf/image.c +++ b/src/loader/elf/image.c @@ -1,5 +1,6 @@ #include "vxBoot/fs/smemfs.h" #include "vxBoot/loader.h" +#include "vxBoot/terminal.h" #include #include @@ -61,7 +62,7 @@ int loader_image_load( return (ld_image_mem_not_available); /* set the kernel's origin address */ - origin = kernel->hardware.ram.physical.user_addr; + origin = kernel->hardware.ram.physical.kernel_addr; origin |= 0xa0000000; kernel->memory.program.start = (void*)origin; @@ -90,7 +91,7 @@ int loader_image_load( /* Generate program entry address */ kernel->entry = (uintptr_t)hdr->e_entry - vmin; - kernel->entry += (uintptr_t)kernel->hardware.ram.physical.user_addr; + kernel->entry += (uintptr_t)kernel->hardware.ram.physical.kernel_addr; kernel->entry |= (uintptr_t)0x80000000; return (ld_image_success); } diff --git a/src/loader/entry.c b/src/loader/entry.c index 16dc4e0..43e249c 100644 --- a/src/loader/entry.c +++ b/src/loader/entry.c @@ -6,7 +6,7 @@ #include #include -//#include +#include #include @@ -37,26 +37,37 @@ int loader(struct smemfs_inode const * restrict const inode, int mode) if (inode == NULL) return (-1); - terminal_write("- try to load ELF file \"%s\"\n", inode->name); + terminal_write("> try to load ELF file \"%s\"\n", inode->name); - terminal_write("- check header information...\n"); + terminal_write("> check header information...\n"); err = loader_header_get(inode, &header); if (err != 0) { loader_header_error(err); return (-2); } - terminal_write("- generate kernel geometry...\n"); + if (mode == LOADER_INFO) + return loader_info(inode, &header); + + terminal_write("> generate kernel geometry...\n"); memset(&kernel, 0x00, sizeof(struct kernel_info)); hardware_get_info(&kernel.hardware); - terminal_write("- load image...\n"); + terminal_write("> load image...\n"); err = loader_image_load(inode, &kernel, &header); if (err != 0) { loader_image_error(err); return (-3); } - terminal_write("image successfully loaded !\n"); + + terminal_write("> path the GOT table...\n"); + loader_got_patch(inode, &kernel, &header); + //FIXME: check returned value + + if (mode == LOADER_CHECK) + return (0); + + terminal_write("%s successfully loaded !\n", inode->name); if (mode == LOADER_DUMP) { terminal_write( "kernel information:\n" @@ -77,7 +88,6 @@ int loader(struct smemfs_inode const * restrict const inode, int mode) gint_world_switch(GINT_CALL((void*)&dump_reloc, (void*)&kernel)); return (0); } -#if 0 if (mode == LOADER_TRACE) { struct tsession *session; @@ -87,7 +97,6 @@ int loader(struct smemfs_inode const * restrict const inode, int mode) ); tracer_set_session(session); } -#endif gint_world_switch(GINT_CALL((void*)kernel.entry)); return (0); } diff --git a/src/loader/info.c b/src/loader/info.c new file mode 100644 index 0000000..98efa34 --- /dev/null +++ b/src/loader/info.c @@ -0,0 +1,107 @@ +#include "vxBoot/loader.h" +#include "vxBoot/terminal.h" +#include "vxBoot/fs/smemfs.h" + +#include +#include + +/* section_get_id() : generate id string */ +static char *section_get_id(int id) +{ + static char buff[6]; + + snprintf(buff, 6, "[%2d]", id); + return (buff); +} + +/* section_get_name() : get the section name*/ +static char *section_get_name(void const *inode, int nameoff, off_t shstroff) +{ + static char buff[10]; + + smemfs_pread(inode, buff, 9, nameoff + shstroff); + if (strlen(buff) >= 8) { + buff[8] = '\0'; + buff[7] = '.'; + } + return (buff); +} + +/* section_get_type() : return the section type*/ +static char const *section_get_type(int type) +{ + static struct { + int type; + char const * const name; + } const types[] = { + {.type = SHT_NULL, .name = "NULL"}, + {.type = SHT_PROGBITS, .name = "PROGBITS"}, + {.type = SHT_SYMTAB, .name = "SYMTAB"}, + {.type = SHT_STRTAB, .name = "STRTAB"}, + {.type = SHT_RELA, .name = "RELA"}, + {.type = SHT_HASH, .name = "HASH"}, + {.type = SHT_DYNAMIC, .name = "DYNAMIC"}, + {.type = SHT_NOTE, .name = "NOTE"}, + {.type = SHT_NOBITS, .name = "NOBITS"}, + {.type = SHT_REL, .name = "REL"}, + {.type = SHT_SHLIB, .name = "SHLIB"}, + {.type = SHT_DYNSYM, .name = "DYNSYM"}, + {.type = SHT_INIT_ARRAY, .name = "INIT_ARRAY"}, + {.type = SHT_FINI_ARRAY, .name = "FINI_ARRAY"}, + {.type = SHT_PREINIT_ARRAY, .name = "PREINIT_ARRAY"}, + {.type = SHT_GROUP, .name = "GROUP"}, + {.type = SHT_SYMTAB_SHNDX, .name = "SYMTAB SECTION INDICES"}, + {.type = -1, .name = NULL}, + }; + for (int i = 0; types[i].name != NULL; ++i) { + if (types[i].type == type) + return (types[i].name); + } + return ("UNKNOWN"); +} + + + +/* loader_info() : display ELF PIE file information */ +//TODO: secure +int loader_info(struct smemfs_inode const * inode, Elf32_Ehdr *hdr) +{ + Elf32_Shdr shdr; + off_t stroff; + off_t shoff; + + /* find the section header table */ + shoff = hdr->e_shoff; + + /* find the section string table ".strtable" */ + smemfs_pread( + inode, + &shdr, sizeof(Elf32_Shdr), + shoff + (sizeof(Elf32_Shdr) * hdr->e_shstrndx) + ); + stroff = shdr.sh_offset; + + /* display section information */ + terminal_write( + "There are %d section headers, startting at offset %#x\n", + hdr->e_shnum, hdr->e_shoff + ); + terminal_write("Section Headers:\n"); + terminal_write( + "%4s %-8s %-8s %-8s %-8s\n", + "[Nr]", "Name", "Type", "Address", "Offset" + ); + for (int i = 0; i < hdr->e_shnum; ++i) { + smemfs_pread(inode, &shdr, sizeof(Elf32_Shdr), shoff); + terminal_write( + "%4s %-8s %-8s %08x %08x\n", + section_get_id(i), + section_get_name(inode, shdr.sh_name, stroff), + section_get_type(shdr.sh_type), + shdr.sh_addr, + shdr.sh_offset + ); + shoff += sizeof(Elf32_Shdr); + } + return (0); +}