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:
parent
ce1f594a53
commit
7bbb33f50f
|
@ -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
|
||||
)
|
||||
|
|
|
@ -9,6 +9,7 @@ struct hwinfo {
|
|||
struct {
|
||||
struct {
|
||||
uintptr_t origin_addr;
|
||||
uintptr_t kernel_addr;
|
||||
uintptr_t user_addr;
|
||||
} physical;
|
||||
size_t size;
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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') {
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue