vxBoot - 1.2.0 : RELA patch

@add
<> vxBoot/builtin/log : log builtin which handle log level
<> vxBoot/cli/entry : add log buitin
<> vxBoot/loader/elf/rela : relocalize special reloc type (R_SH_DIR32)
<> vxBoot/terminal/write : add terminal_vwrite which use a va_list arg

@update
<> CMakeList.txt : dump version + add new sources files
<> include/vxBoot/loader : rework the API and add Elf32_Rela information
<> include/vxBoot/terminal : add log information
<> vxBoot/loader/elf/got : rework information fetching
<> vxBoot/loader/elf/header : rework information fetching
<> vxBoot/loader/elf/image : rework information fetching
<> vxBoot/loader/elf/entry : rework information fetching
<> vxBoot/loader/scan : rework information fetching

@fix
<> vxBoot/loader/rela : relocalize special reloc type (R_SH_DIR32)
<> vxBoot/builtin/ls : help display
This commit is contained in:
Yann MAGNIN 2022-01-29 20:45:35 +01:00
parent 3971b78a29
commit b4f6fd74e9
15 changed files with 531 additions and 159 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.15)
project(vxBoot VERSION 1.1.1 LANGUAGES C)
project(vxBoot VERSION 1.1.2 LANGUAGES C)
include(GenerateG1A)
include(GenerateG3A)
@ -20,14 +20,17 @@ set(SOURCES
src/terminal/read.c
src/terminal/util.c
src/terminal/write.c
src/terminal/log.c
src/builtin/ls.c
src/builtin/help.c
src/builtin/hw.c
src/builtin/ld.c
src/builtin/log.c
src/loader/scan.c
src/loader/elf/header.c
src/loader/elf/image.c
src/loader/elf/got.c
src/loader/elf/rela.c
src/loader/error.c
src/loader/entry.c
src/loader/info.c

View File

@ -9,5 +9,6 @@ extern int os_main(int argc, char **argv);
extern int hw_main(int argc, char **argv);
extern int ld_main(int argc, char **argv);
extern int help_main(int argc, char **argv);
extern int log_main(int argc, char **argv);
#endif /*__VXBOOT_BUILTIN_H__*/

View File

@ -113,6 +113,62 @@ typedef struct {
#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */
#define SHT_NUM 19 /* Number of defined types. */
/* Relocation table entry with addend (in section of type SHT_RELA). */
typedef struct {
uint32_t r_offset; /* Address */
uint32_t r_info; /* Relocation type and symbol index */
int32_t r_addend; /* Addend */
} Elf32_Rela;
/* How to extract and insert information held in the r_info field. */
#define ELF32_R_SYM(val) ((val) >> 8)
#define ELF32_R_TYPE(val) ((val) & 0xff)
#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
/* SH relocs. */
#define R_SH_NONE 0
#define R_SH_DIR32 1
#define R_SH_REL32 2
#define R_SH_DIR8WPN 3
#define R_SH_IND12W 4
#define R_SH_DIR8WPL 5
#define R_SH_DIR8WPZ 6
#define R_SH_DIR8BP 7
#define R_SH_DIR8W 8
#define R_SH_DIR8L 9
#define R_SH_SWITCH16 25
#define R_SH_SWITCH32 26
#define R_SH_USES 27
#define R_SH_COUNT 28
#define R_SH_ALIGN 29
#define R_SH_CODE 30
#define R_SH_DATA 31
#define R_SH_LABEL 32
#define R_SH_SWITCH8 33
#define R_SH_GNU_VTINHERIT 34
#define R_SH_GNU_VTENTRY 35
#define R_SH_TLS_GD_32 144
#define R_SH_TLS_LD_32 145
#define R_SH_TLS_LDO_32 146
#define R_SH_TLS_IE_32 147
#define R_SH_TLS_LE_32 148
#define R_SH_TLS_DTPMOD32 149
#define R_SH_TLS_DTPOFF32 150
#define R_SH_TLS_TPOFF32 151
#define R_SH_GOT32 160
#define R_SH_PLT32 161
#define R_SH_COPY 162
#define R_SH_GLOB_DAT 163
#define R_SH_JMP_SLOT 164
#define R_SH_RELATIVE 165
#define R_SH_GOTOFF 166
#define R_SH_GOTPC 167
/* Keep this the last entry. */
#define R_SH_NUM 256
/* Symbol table entry. */
typedef struct {
@ -129,7 +185,7 @@ typedef struct {
//---
/* kernel loading information */
struct kernel_info {
struct kernel {
/* kernel entry */
uintptr_t entry;
@ -147,6 +203,24 @@ struct kernel_info {
/* hardware information */
struct hwinfo hardware;
/* file information */
struct smemfs_inode const *inode;
/* ELF information */
struct {
Elf32_Ehdr hdr;
Elf32_Shdr *shdr;
Elf32_Phdr *phdr;
struct {
Elf32_Sym *tab;
int nb;
} sym;
char * shstrtab;
char * strtab;
uintptr_t * got;
int got_nb;
} elf;
};
/* internal kernel image list */
@ -174,8 +248,6 @@ extern int loader_kernel_img_count(void);
#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
@ -207,10 +279,13 @@ enum {
/* loader_header_get() : get / check ELF header information */
extern int loader_header_get(
struct smemfs_inode const * restrict const inode,
Elf32_Ehdr *hdr
Elf32_Ehdr *header
);
/* loader_header_check() : load and check the file header validity */
extern int loader_header_check(struct smemfs_inode * restrict const inode);
extern int loader_header_check(struct kernel * const kernel);
/* loader_header_error() : display error message */
extern int loader_header_error(int errnum);
@ -219,6 +294,8 @@ extern int loader_header_error(int errnum);
//---
// ELF image ldpers
//---
/* returned value */
enum {
ld_image_success = 0,
ld_image_size_error = -1,
@ -226,28 +303,25 @@ enum {
ld_image_mem_error = -3,
ld_image_mem_not_available = -4,
};
/* loader_image_load() : try to load the entier image data */
extern int loader_image_load(
struct smemfs_inode const * restrict const inode,
struct kernel_info * restrict const info,
Elf32_Ehdr *hdr
);
extern int loader_image_load(struct kernel * const kernel);
/* loader_image_error() : Display error message */
extern int loader_image_error(int const errnum);
//---
// GOT helpers
// Relocs 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
);
extern int loader_got_patch(struct kernel * const kernel);
/* loader_rela_patch() : Try to patch the RELA section */
extern int loader_rela_patch(struct kernel * const kernel);
#endif /*__VXBOOT_LOADER_H__*/

View File

@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdarg.h>
#include <gint/defs/types.h>
/* internal terminal hardcoded information */
@ -63,8 +64,21 @@ extern struct terminal terminal;
//---
// User interface
//---
enum {
LOG_EMERG,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG
};
extern int terminal_open(void);
extern int terminal_write(const char *format, ...);
extern int terminal_vwrite(const char *format, va_list ap);
extern int terminal_log(int level, const char *format, ...);
extern int terminal_read(void *buffer, size_t nb);
extern int terminal_close(void);

40
src/builtin/log.c Normal file
View File

@ -0,0 +1,40 @@
#include "vxBoot/builtin.h"
#include "vxBoot/terminal.h"
/* current log level */
extern int user_log_level;
/* log_help() : display help message */
static int log_help(void)
{
terminal_write(
"+---+-----------+---------------------+\n"
"|Lvl|Name |Description |\n"
"| 0 |LOG_EMERG |system is unusable |\n"
"| 1 |LOG_ALERT |action must be taken |\n"
"| 2 |LOG_CRIT |critical condition |\n"
"| 3 |LOG_ERR |error condition |\n"
"| 4 |LOG_WARNING|warning condition |\n"
"| 5 |LOG_NOTICE |significant condition|\n"
"| 6 |LOG_INFO |informational message|\n"
"| 7 |LOG_DEBUG |debug-level message |\n"
"\n"
"current level = %d\n",
user_log_level
);
return (0);
}
/* ls_main() : entry of the "ls" builtin */
int log_main(int argc, char **argv)
{
if (argc <= 1)
return (log_help());
if (argv[1][0] < '0' || argv[1][0] > '7') {
terminal_write("log: argument not recognized\n");
return (-1);
}
user_log_level = argv[1][0] - '0';
return (0);
}

View File

@ -18,7 +18,7 @@ static void ls_help(void)
"\n"
"DESCRIPTION\n"
" List file information about FILEs (from the root directory only). The"
" display is inspired from the utilitary `tree` in UNIX environment.\n"
" display is inspired from the utilitary `tree` in UNIX environment.\n"
"\n"
" -h,--help\n"
" Display this help message\n"

View File

@ -15,6 +15,7 @@ struct {
{.name = "ld", &ld_main},
{.name = "hw", &hw_main},
{.name = "help", &help_main},
{.name = "log", &log_main},
{.name = NULL, NULL}
};

View File

@ -1,106 +1,60 @@
#include "vxBoot/loader.h"
#include "vxBoot/fs/smemfs.h"
#include "vxBoot/terminal.h"
#include <string.h>
/* loader_get_section() : Try to find section information using its name */
static int loader_get_section(
Elf32_Shdr *shdr,
char const * const name,
struct smemfs_inode const * restrict const inode,
Elf32_Ehdr *hdr
) {
char buff[16];
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, buff, 16, shdr->sh_name + stroff);
if (strcmp(buff, name) == 0)
return (0);
shoff += sizeof(Elf32_Shdr);
}
return (-1);
}
/* loader_get_symbols() : get symbols information */
static int loader_get_symbol(
Elf32_Sym *sym,
char const * const name,
struct smemfs_inode const * restrict const inode,
Elf32_Ehdr *hdr
){
Elf32_Shdr symhdr;
Elf32_Shdr strhdr;
char buff[64];
int off;
static void *loader_get_symbol(
struct kernel * restrict const kernel,
char const * restrict const name
) {
char * strtab;
uintptr_t sym;
/* frist, find the symtab section */
loader_get_section(&symhdr, ".symtab", inode, hdr);
loader_get_section(&strhdr, ".strtab", inode, hdr);
/* walk throut the table */
off = symhdr.sh_offset;
for (uint32_t i = 0 ; i < symhdr.sh_size / sizeof(Elf32_Sym) ; ++i) {
smemfs_pread(inode, sym, sizeof(Elf32_Sym), off);
smemfs_pread(inode, buff, 64, sym->st_name + strhdr.sh_offset);
if (strcmp(buff, name) == 0)
return (0);
off += sizeof(Elf32_Sym);
strtab = kernel->elf.strtab;
for (int i = 0 ; i < kernel->elf.sym.nb ; ++i) {
if (strcmp(&strtab[kernel->elf.sym.tab[i].st_name], name) != 0)
continue;
sym = (uintptr_t)kernel->elf.sym.tab[i].st_value;
sym += (uintptr_t)kernel->hardware.ram.physical.kernel_addr;
sym |= (uintptr_t)0xa0000000;
return((void*)sym);
}
return (-1);
return (NULL);
}
/* loader_got_patch() : Try to patch the GOT/PLT section */
int loader_got_patch(
struct smemfs_inode const * restrict const inode,
struct kernel_info * const kernel,
Elf32_Ehdr *hdr
) {
Elf32_Shdr shdr;
Elf32_Sym sym;
int loader_got_patch(struct kernel * const kernel)
{
uintptr_t *__got__;
uintptr_t *got;
uintptr_t addr;
uintptr_t got;
/* first, try to find the __GLOBAL_OFFSET_TABLE__ symbol */
if (loader_get_symbol(&sym, "_GLOBAL_OFFSET_TABLE_", inode, hdr)) {
terminal_write("_GLOBAL_OFFSET_TABLE_ not found...\n");
/* first, try to find the _GLOBAL_OFFSET_TABLE_ symbol */
__got__ = loader_get_symbol(kernel, "_GLOBAL_OFFSET_TABLE_");
if (__got__ == NULL) {
terminal_log(
LOG_NOTICE,
"_GLOBAL_OFFSET_TABLE_ not found...\n"
);
return (0);
}
__got__ = kernel->memory.program.start;
__got__ = (void*)((uintptr_t)__got__ + (uintptr_t)sym.st_value);
terminal_write(" __GOT__ found at %p...\n", __got__);
/* and we need to relocalise the "real" GOT section and update the
hardcoded address in the same time */
loader_get_section(&shdr, ".got", inode, hdr);
got = kernel->memory.program.start;
got = (void*)((uintptr_t)got + (uintptr_t)shdr.sh_addr);
terminal_write(" GOT found at %p...\n", got);
got = (uintptr_t)kernel->elf.got;
got += (uintptr_t)kernel->hardware.ram.physical.kernel_addr;
got |= (uintptr_t)0xa0000000;
/* perform transation */
for (uint32_t i = 0 ; i < shdr.sh_size >> 2 ; ++i) {
terminal_write(" path symbols %p...\n", got[i]);
addr = got[i];
terminal_log(LOG_DEBUG, " _GOT_ found at %p...\n", __got__);
terminal_log(LOG_DEBUG, " .got found at %p...\n", got);
for (int i = 0 ; i < kernel->elf.got_nb ; ++i) {
terminal_log(
LOG_DEBUG,
" patch symbols %p...\n",
((uintptr_t*)got)[i]
);
addr = ((uintptr_t*)got)[i];
addr += (uintptr_t)kernel->hardware.ram.physical.kernel_addr;
addr |= (uintptr_t)0x80000000;
__got__[i] = addr;

View File

@ -2,6 +2,9 @@
#include "vxBoot/fs/smemfs.h"
#include "vxBoot/loader.h"
#include <stdlib.h>
#include <string.h>
/* error string list */
const struct ld_error_db header_error_db[] = {
{.id = ld_header_valid, .strerror = "valid"},
@ -23,9 +26,14 @@ int loader_header_error(int const errnum)
/* loader_header_get(): Get ELF header and check validity */
int loader_header_get(
struct smemfs_inode const * restrict const inode,
Elf32_Ehdr *header
struct smemfs_inode const * restrict const inode,
Elf32_Ehdr *header
) {
Elf32_Ehdr tmp;
if (header == NULL)
header = &tmp;
/* try to read the ELF header */
if (smemfs_pread(inode, header, sizeof(*header), 0) != sizeof(*header))
return (ld_header_size_error);
@ -60,9 +68,102 @@ int loader_header_get(
return (ld_header_valid);
}
/* hypervisor_elf_loader_header_check(): Check ELF header validity */
int loader_header_check(struct smemfs_inode * restrict const inode)
/* hypervisor_elf_loader_header_check():
Check ELF header validity and dump usefull sections information */
int loader_header_check(struct kernel * const kernel)
{
Elf32_Ehdr header;
return (loader_header_get(inode, &header));
Elf32_Shdr *shdr;
char * shstrtab;
int error;
error = loader_header_get(kernel->inode, &kernel->elf.hdr);
if (error != ld_header_valid)
return (error);
kernel->elf.shdr = malloc(
kernel->elf.hdr.e_shnum * kernel->elf.hdr.e_shentsize
);
smemfs_pread(
kernel->inode,
kernel->elf.shdr,
kernel->elf.hdr.e_shnum * kernel->elf.hdr.e_shentsize,
kernel->elf.hdr.e_shoff
);
kernel->elf.shstrtab = malloc(
kernel->elf.shdr[kernel->elf.hdr.e_shstrndx].sh_size
);
smemfs_pread(
kernel->inode,
kernel->elf.shstrtab,
kernel->elf.shdr[kernel->elf.hdr.e_shstrndx].sh_size,
kernel->elf.shdr[kernel->elf.hdr.e_shstrndx].sh_offset
);
kernel->elf.phdr = malloc(kernel->elf.hdr.e_phnum * sizeof(Elf32_Phdr));
smemfs_pread(
kernel->inode,
kernel->elf.phdr,
kernel->elf.hdr.e_phnum * sizeof(Elf32_Phdr),
kernel->elf.hdr.e_phoff
);
shdr = kernel->elf.shdr;
shstrtab = kernel->elf.shstrtab;
kernel->elf.sym.tab = NULL;
kernel->elf.sym.nb = 0;
kernel->elf.strtab = NULL;
kernel->elf.got = NULL;
for (int i = 0; i < kernel->elf.hdr.e_shnum; ++i) {
if (shdr[i].sh_type == SHT_SYMTAB) {
if (kernel->elf.sym.tab == NULL) {
kernel->elf.sym.tab = malloc(shdr[i].sh_size);
smemfs_pread(
kernel->inode,
kernel->elf.sym.tab,
shdr[i].sh_size,
shdr[i].sh_offset
);
kernel->elf.sym.nb = shdr[i].sh_size;
kernel->elf.sym.nb /= sizeof(Elf32_Sym);
}
continue;
}
if (kernel->elf.strtab == NULL) {
if (strcmp(".strtab", &shstrtab[shdr[i].sh_name]) == 0){
kernel->elf.strtab = malloc(shdr[i].sh_size);
smemfs_pread(
kernel->inode,
kernel->elf.strtab,
shdr[i].sh_size,
shdr[i].sh_offset
);
continue;
}
}
if (kernel->elf.got == NULL) {
if (strcmp(".got", &shstrtab[shdr[i].sh_name]) == 0) {
kernel->elf.got = (void*)(uintptr_t)shdr[i].sh_addr;
kernel->elf.got_nb = shdr[i].sh_size;
kernel->elf.got_nb /= sizeof(uintptr_t);
continue;
}
}
}
terminal_log(
LOG_DEBUG,
"symtab = %p with %d entries\n"
"shstrtab = %p\n"
"strtab = %p\n"
"shdr = %p\n"
"phdr = %p\n"
"got = %p\n",
kernel->elf.sym.tab, kernel->elf.sym.nb,
kernel->elf.shstrtab,
kernel->elf.strtab,
kernel->elf.shdr,
kernel->elf.phdr,
kernel->elf.got
);
return (0);
}

View File

@ -22,41 +22,40 @@ int loader_image_error(int const errnum)
}
/* loader_load_image() - Load the program into Virtual Memory */
int loader_image_load(
struct smemfs_inode const * restrict const inode,
struct kernel_info * restrict const kernel,
Elf32_Ehdr *hdr
) {
Elf32_Phdr program;
int loader_image_load(struct kernel * const kernel)
{
Elf32_Phdr *phdr;
uintptr_t paddress;
uintptr_t origin;
uintptr_t vmin;
uintptr_t vmax;
off_t offset;
uint16_t i;
/* Walk one time to get the entier program size and check ELF
validity. */
i = -1;
vmin = 0xffffffff;
vmax = 0x00000000;
phdr = kernel->elf.phdr;
kernel->memory.program.size = 0;
while (++i < hdr->e_phnum) {
offset = hdr->e_phoff + (i * sizeof(Elf32_Phdr));
if (smemfs_pread(inode, &program, sizeof(Elf32_Phdr), offset)
!= sizeof(Elf32_Phdr)) {
return (ld_image_size_error);
}
if (program.p_vaddr < vmin)
vmin = program.p_vaddr;
if (program.p_vaddr + program.p_memsz > vmax)
vmax = program.p_vaddr + program.p_memsz;
for (int i = 0; i < kernel->elf.hdr.e_phnum; ++i) {
if (phdr[i].p_vaddr < vmin)
vmin = phdr[i].p_vaddr;
if (phdr[i].p_vaddr + phdr[i].p_memsz > vmax)
vmax = phdr[i].p_vaddr + phdr[i].p_memsz;
}
kernel->memory.program.size = vmax - vmin;
kernel->memory.program.elf.vmin = vmin;
kernel->memory.program.elf.vmax = vmax;
terminal_log(
LOG_DEBUG,
"program size = %d\n"
"program vmin = %p\n"
"program vmax = %p\n",
kernel->memory.program.size,
kernel->memory.program.elf.vmin,
kernel->memory.program.elf.vmax
);
/* check available space in RAM to load the image */
if (kernel->memory.program.size >= kernel->hardware.ram.available)
return (ld_image_mem_not_available);
@ -72,25 +71,22 @@ int loader_image_load(
Note that the p_filesz can be smaller than p_memsz so, we need to
wipe the segment area before the dump. */
i = -1;
while (++i < hdr->e_phnum) {
offset = hdr->e_phoff + (i * sizeof(Elf32_Phdr));
smemfs_pread(inode, &program, sizeof(Elf32_Phdr), offset);
paddress = (uintptr_t)program.p_vaddr - vmin;
for (int i = 0; i < kernel->elf.hdr.e_phnum; ++i) {
paddress = (uintptr_t)phdr[i].p_vaddr - vmin;
paddress += (uintptr_t)kernel->memory.program.start;
memset((void*)paddress, 0x00, program.p_memsz);
memset((void*)paddress, 0x00, phdr[i].p_memsz);
smemfs_pread(
inode,
kernel->inode,
(void*)paddress,
program.p_filesz,
program.p_offset
phdr[i].p_filesz,
phdr[i].p_offset
);
}
/* Generate program entry address */
kernel->entry = (uintptr_t)hdr->e_entry - vmin;
kernel->entry = (uintptr_t)kernel->elf.hdr.e_entry - vmin;
kernel->entry += (uintptr_t)kernel->hardware.ram.physical.kernel_addr;
kernel->entry |= (uintptr_t)0x80000000;
return (ld_image_success);

154
src/loader/elf/rela.c Normal file
View File

@ -0,0 +1,154 @@
#include "vxBoot/loader.h"
#include "vxBoot/fs/smemfs.h"
#include "vxBoot/terminal.h"
#include <string.h>
#include <stdlib.h>
struct {
char const * restrict const name;
uint16_t id;
} const table[] = {
{"R_SH_NONE", 0},
{"R_SH_DIR32", 1},
{"R_SH_REL32", 2},
{"R_SH_DIR8WPN", 3},
{"R_SH_IND12W", 4},
{"R_SH_DIR8WPL", 5},
{"R_SH_DIR8WPZ", 6},
{"R_SH_DIR8BP", 7},
{"R_SH_DIR8W", 8},
{"R_SH_DIR8L", 9},
{"R_SH_SWITCH16", 25},
{"R_SH_SWITCH32", 26},
{"R_SH_USES", 27},
{"R_SH_COUNT", 28},
{"R_SH_ALIGN", 29},
{"R_SH_CODE", 30},
{"R_SH_DATA", 31},
{"R_SH_LABEL", 32},
{"R_SH_SWITCH8", 33},
{"R_SH_GNU_VTINHERIT", 4},
{"R_SH_GNU_VTENTRY", 5},
{"R_SH_TLS_GD_32", 144},
{"R_SH_TLS_LD_32", 145},
{"R_SH_TLS_LDO_32", 146},
{"R_SH_TLS_IE_32", 147},
{"R_SH_TLS_LE_32", 148},
{"R_SH_TLS_DTPMOD32", 49},
{"R_SH_TLS_DTPOFF32", 50},
{"R_SH_TLS_TPOFF32", 51},
{"R_SH_GOT32", 160},
{"R_SH_PLT32", 161},
{"R_SH_COPY", 162},
{"R_SH_GLOB_DAT", 163},
{"R_SH_JMP_SLOT", 164},
{"R_SH_RELATIVE", 165},
{"R_SH_GOTOFF", 166},
{"R_SH_GOTPC", 167},
{"R_SH_NUM", 256},
{NULL, 0}
};
/* loader_reloc_symbols() : relocalize symbols */
static int loader_reloc_section(
Elf32_Rela *rela,
int nb_rela,
char const * const name,
struct kernel * const kernel
) {
uintptr_t voff;
uintptr_t val;
uintptr_t loc;
int type;
/* logs */
terminal_log(
LOG_INFO,
" section '%s' with %d entries\n",
name, nb_rela
);
/* precalculate relocalisation operation */
voff = (uintptr_t)kernel->hardware.ram.physical.kernel_addr;
voff |= (uintptr_t)0x80000000;
/* try to relocalise symbols */
for (int i = 0; i < nb_rela; ++i) {
type = -1;
for (int j = 0; table[j].name != NULL; ++j) {
if (table[j].id != ELF32_R_TYPE(rela[i].r_info))
continue;
if (ELF32_R_TYPE(rela[i].r_info) == R_SH_NUM)
return (0);
type = j;
break;
}
if (type < 0) {
terminal_write("unable to relocalize symbols %d\n", i);
return (-1);
}
loc = rela[i].r_offset;
loc += (uintptr_t)kernel->hardware.ram.physical.kernel_addr;
loc |= (uintptr_t)0xa0000000;
val = kernel->elf.sym.tab[ELF32_R_SYM(rela[i].r_info)].st_value;
switch (table[type].id) {
case R_SH_GOT32:
case R_SH_PLT32:
case R_SH_GOTPC:
case R_SH_GOTOFF:
break;
case R_SH_DIR32:
//terminal_log(
// LOG_DEBUG,
// " %08x %-8s %08x\n",
// rela[i].r_offset,
// table[type].name,
// val
//);
*(uintptr_t *)loc = voff + val;
break;
default:
terminal_log(
LOG_ALERT,
" [%d] type %s not supported yet o(x_x)o\n",
i, table[type].name
);
return (-1);
}
}
return (0);
}
/* loader_rela_patch() : Try to patch the GOT/PLT section */
int loader_rela_patch(struct kernel * const kernel)
{
Elf32_Rela *rela;
int error;
rela = NULL;
for (int i = 0; i < kernel->elf.hdr.e_shnum; ++i) {
if (kernel->elf.shdr[i].sh_type != SHT_RELA)
continue;
rela = realloc(rela, kernel->elf.shdr[i].sh_size);
smemfs_pread(
kernel->inode,
rela,
kernel->elf.shdr[i].sh_size,
kernel->elf.shdr[i].sh_offset
);
error = loader_reloc_section(
rela,
kernel->elf.shdr[i].sh_size / sizeof(Elf32_Rela),
&kernel->elf.shstrtab[kernel->elf.shdr[i].sh_name],
kernel
);
if (error != 0)
return (error);
}
return (0);
}

View File

@ -10,7 +10,8 @@
#include <string.h>
static int dump_reloc(struct kernel_info *kernel)
/* dump_reloc() : dump the relocalized image */
static int dump_reloc(struct kernel *kernel)
{
int handle;
int size;
@ -30,45 +31,41 @@ static int dump_reloc(struct kernel_info *kernel)
/* loader_inode: Load a ELF programm (PIE) */
int loader(struct smemfs_inode const * restrict const inode, int mode)
{
struct kernel_info kernel;
Elf32_Ehdr header;
struct kernel kernel;
int err;
if (inode == NULL)
return (-1);
terminal_write("> try to load ELF file \"%s\"\n", inode->name);
memset(&kernel, 0x00, sizeof(struct kernel));
kernel.inode = inode;
terminal_write("> check header information...\n");
err = loader_header_get(inode, &header);
err = loader_header_check(&kernel);
if (err != 0) {
loader_header_error(err);
return (-2);
}
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");
err = loader_image_load(inode, &kernel, &header);
err = loader_image_load(&kernel);
if (err != 0) {
loader_image_error(err);
return (-3);
}
terminal_write("> path the GOT table...\n");
loader_got_patch(inode, &kernel, &header);
//FIXME: check returned value
terminal_write("> relocalize symbols...\n");
loader_rela_patch(&kernel);
if (mode == LOADER_CHECK)
return (0);
terminal_write("> path the GOT table...\n");
loader_got_patch(&kernel);
terminal_write("%s successfully loaded !\n", inode->name);
if (mode == LOADER_DUMP) {
if (mode == LOADER_DUMP || mode == LOADER_CHECK) {
terminal_write(
"kernel information:\n"
"|-- kernel entry: %p\n"
@ -85,6 +82,9 @@ int loader(struct smemfs_inode const * restrict const inode, int mode)
kernel.memory.program.elf.vmin,
kernel.memory.program.elf.vmax
);
if (mode == LOADER_CHECK)
return (0);
gint_world_switch(GINT_CALL((void*)&dump_reloc, (void*)&kernel));
return (0);
}

View File

@ -26,7 +26,7 @@ static int loader_list_img(struct ldimg **image, struct smemfs_inode *inode)
counter += loader_list_img(image, inode->child);
goto anchor;
}
if (loader_header_check(inode) == ld_header_valid) {
if (loader_header_get(inode, NULL) == ld_header_valid) {
(*image) = calloc(1, sizeof(struct ldimg));
if ((*image) == NULL) {
terminal_write("hypervisor: out of memory :(\n");

24
src/terminal/log.c Normal file
View File

@ -0,0 +1,24 @@
#include "vxBoot/terminal.h"
/* define the user log level */
int user_log_level = LOG_INFO;
int terminal_log(int level, const char *format, ...)
{
va_list ap;
int nb;
if (level > user_log_level)
return (0);
va_start(ap, format);
nb = terminal_vwrite(format, ap);
va_end(ap);
if (level == LOG_DEBUG) {
int tmp;
terminal_read(&tmp, 4);
}
return (nb);
}

View File

@ -6,17 +6,14 @@
#include <string.h>
#include <stdio.h>
/* terminal_write() - printf wrapper for the terminal device */
int terminal_write(const char *format, ...)
/* terminal_vwrite() : printf wrapper for the terminal device with va_list */
int terminal_vwrite(const char *format, va_list ap)
{
char buffer[1024];
va_list ap;
int nb;
/* process the format */
va_start(ap, format);
nb = vsnprintf(buffer, 1024, format, ap);
va_end(ap);
/* update the internal buffer */
terminal_buffer_insert(buffer, nb);
@ -27,3 +24,16 @@ int terminal_write(const char *format, ...)
dupdate();
return (nb);
}
/* terminal_write() - printf wrapper for the terminal device */
int terminal_write(const char *format, ...)
{
va_list ap;
int nb;
va_start(ap, format);
nb = terminal_vwrite(format, ap);
va_end(ap);
return (nb);
}