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
This commit is contained in:
Yann MAGNIN 2022-01-14 11:40:24 +01:00
parent ce1f594a53
commit 7bbb33f50f
10 changed files with 241 additions and 15 deletions

View File

@ -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
)

View File

@ -9,6 +9,7 @@ struct hwinfo {
struct {
struct {
uintptr_t origin_addr;
uintptr_t kernel_addr;
uintptr_t user_addr;
} physical;
size_t size;

View File

@ -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
);

View File

@ -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

View File

@ -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') {

View File

@ -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);
}

49
src/loader/elf/got.c Normal file
View File

@ -0,0 +1,49 @@
#include "vxBoot/loader.h"
#include "vxBoot/fs/smemfs.h"
#include "vxBoot/terminal.h"
#include <string.h>
/* 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);
}

View File

@ -1,5 +1,6 @@
#include "vxBoot/fs/smemfs.h"
#include "vxBoot/loader.h"
#include "vxBoot/terminal.h"
#include <stdlib.h>
#include <string.h>
@ -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);
}

View File

@ -6,7 +6,7 @@
#include <gint/gint.h>
#include <gint/bfile.h>
//#include <gintrace/tracer.h>
#include <gintrace/tracer.h>
#include <string.h>
@ -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);
}

107
src/loader/info.c Normal file
View File

@ -0,0 +1,107 @@
#include "vxBoot/loader.h"
#include "vxBoot/terminal.h"
#include "vxBoot/fs/smemfs.h"
#include <stdio.h>
#include <string.h>
/* 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);
}