FxBoot v0.4.0 - Shared Lib (not stable)

@add
<> worlds tracing using `hyp os trace <OSID>`
<> handle Gint has a shared library (Thank's to Lephenixnoir !)
<> Change drivers' management.
<> Push shared tests in <tests/*>, it's just to leave a trace of my notes.

@bug
<> When a ELF is relocalized, a crash occur when `hyp os run <OSID>` is
   involved. Visibly this is a stack corruption that occurs with the DMA
   interruption(?). But you can trace the world using the `hyp os trace <OSID>`
This commit is contained in:
Yatis 2021-03-14 22:10:12 +01:00
parent 9ef129e788
commit 32e89925b9
26 changed files with 803 additions and 178 deletions

View File

@ -7,6 +7,8 @@
/* define smemfs_*() pirmitive */
#include "fxBoot/fs/smemfs.h"
/* define tsession */
#include <gintrace/tracer.h>
#define HYPERVISOR_BSS __attribute__((section(".hypervisor.bss")))
@ -16,13 +18,13 @@
//--
/* Define the SuperH CPU hardware context */
struct cpuctx {
uint32_t reg[16];
uint32_t gbr;
uint32_t macl;
uint32_t mach;
uint32_t ssr;
uint32_t spc;
uint32_t pr;
uintptr_t reg[16];
uintptr_t gbr;
uintptr_t macl;
uintptr_t mach;
uintptr_t ssr;
uintptr_t spc;
uintptr_t pr;
};
#define HYPERVISOR_STACK_KERNEL_SIZE (2 * 1024)
@ -51,6 +53,10 @@ struct hworld {
struct {
void *start;
size_t size;
struct {
uintptr_t vmin;
uintptr_t vmax;
} elf;
} program;
struct {
void *kernel;
@ -76,6 +82,9 @@ struct hworld {
HYPERVISOR_ENV_GINT = 0,
HYPERVISOR_ENV_CASIO = 1,
} env;
struct {
struct tsession *tracer;
} debug;
} private;
};

View File

@ -65,6 +65,7 @@ extern struct terminal terminal;
//---
extern int terminal_open(void);
extern int terminal_write(const char *format, ...);
extern int terminal_error(const char *format, ...);
extern int terminal_read(void *buffer, size_t nb);
extern int terminal_close(void);

View File

@ -63,8 +63,8 @@ INCLUDE_CG = -I include -I.
# Libraries. Add one -l option for each library you are using, and also
# suitable -L options if you have library files in custom folders. To use
# fxlib, add libfx.a to the project directory and use "-L . -lfx".
LIBS_FX :=
LIBS_CG :=
LIBS_FX := -lgintrace-fx
LIBS_CG := -lgintrace-cg
# Base linker flags for the fxSDK, you usually want to keep these.
LDFLAGS_FX := -T fx9860g.ld -lgint-fx $(LIBS_FX) -lgint-fx -lgcc

View File

@ -11,6 +11,10 @@
#include <gint/std/stdio.h>
#include <gint/gint.h>
#include <gintrace/tracer.h>
#include "./src/hypervisor/internal/elf.h"
/* internal structiure used to handle the hypervisor module */
#define HYP_INFO_WATERMARK (0xdeadbeef)
struct {
@ -19,6 +23,27 @@ struct {
uint32_t installed;
} hypinfo;
//---
// Internal information
//---
/* hyp_get_image(): return the image using its ID */
static struct himage *hyp_get_image(int id)
{
struct himage *img;
int counter;
counter = 0;
img = hypinfo.images;
while (img != NULL) {
if (counter == id)
break;
counter = counter + 1;
img = img->next;
}
return (img);
}
//---
// Module management
//---
@ -42,15 +67,7 @@ static int hyp_img_module(int argc, char **argv)
terminal_write("image ID missing\n");
return (84);
}
int counter = 0;
int id = atoi(argv[3]);
struct himage *img = hypinfo.images;
while (img != NULL) {
if (counter == id)
break;
counter = counter + 1;
img = img->next;
}
struct himage *img = hyp_get_image(atoi(argv[3]));
if (img == NULL) {
terminal_write("image ID invalid\n");
return (84);
@ -60,6 +77,18 @@ static int hyp_img_module(int argc, char **argv)
terminal_write("image successfully loaded\n");
return (0);
}
if (strcmp(argv[2], "dyn") == 0) {
if (argc < 3) {
terminal_write("image ID missing\n");
return (84);
}
struct himage *img = hyp_get_image(atoi(argv[3]));
if (img == NULL) {
terminal_write("image ID invalid\n");
return (84);
}
return (hypervisor_elf_loader_dynamic_check(img->private));
}
error:
terminal_write("\"hyp img\" requires at least 1 argument\n");
@ -75,6 +104,7 @@ error:
/* hyp_os_module(): Handle argument for the os module part */
static int hyp_os_module(int argc, char **argv)
{
if (argc < 2)
goto error;
if (strcmp(argv[2], "ls") == 0) {
@ -100,22 +130,40 @@ static int hyp_os_module(int argc, char **argv)
}
return (0);
}
if (argc < 3) {
terminal_write("OS ID missing\n");
return (84);
}
int counter = 0;
int id = atoi(argv[3]);
struct hworld *world = hypervisor_wswitch_queue_get();
while (world != NULL) {
if (counter == id)
break;
counter = counter + 1;
world = world->private.next;
}
if (world == NULL) {
terminal_write("image ID invalid\n");
return (84);
}
if (strcmp(argv[2], "run") == 0) {
if (argc < 3) {
terminal_write("OS ID missing\n");
//FIXME: indicate that the world is running !
//FIXME: check if the world is already running !
if (hypervisor_wswitch(world) != 0)
return (84);
}
int counter = 0;
int id = atoi(argv[3]);
struct hworld *world = hypervisor_wswitch_queue_get();
while (world != NULL) {
if (counter == id)
break;
counter = counter + 1;
world = world->private.next;
}
if (world == NULL) {
terminal_write("image ID invalid\n");
return (0);
}
if (strcmp(argv[2], "trace") == 0) {
//FIXME: indicate that the world is running !
//FIXME: check if the world is already running !
world->private.debug.tracer =
tracer_create_session((void*)world->context.cpu.spc,
TRACER_DISASM
| TRACER_CONTEXT
| TRACER_HEXDUMP);
if (world->private.debug.tracer == NULL) {
terminal_write("tracer session error\n");
return (84);
}
if (hypervisor_wswitch(world) != 0)

View File

@ -6,7 +6,11 @@
#include <gint/std/string.h>
#include <gint/std/stdlib.h>
#include <gint/bfile.h>
#include <gint/gint.h>
/* world information */
extern void *kernel_env_casio;
extern void *kernel_env_gint;
extern void *gint_switch_to_world(void *buffctx);
/* Define the super block information */
struct smemfs_superblock smemfs_superblock = {
@ -97,7 +101,7 @@ struct smemfs_inode *smemfs_mount(void)
void *root_inode;
/* switch to the Casio's OS */
gint_switch_to_casio();
gint_switch_to_world(kernel_env_casio);
/* Check useless mount */
root_inode = smemfs_superblock.root_inode;
@ -117,7 +121,7 @@ struct smemfs_inode *smemfs_mount(void)
}
/* switch to the Gint kernel */
gint_switch_to_gint();
gint_switch_to_world(kernel_env_gint);
/* Return the sector table to simulate the root inode. */
return (root_inode);

View File

@ -9,6 +9,12 @@
/* external symbols */
extern uint32_t (*cpu_setVBR)(uint32_t vbr, void (*conf_intc)(int), int arg);
/* world information */
extern void *kernel_env_casio;
extern void *kernel_env_gint;
extern void *gint_switch_to_world(void *buffctx);
/* generate_abolute_path(): Generate abolute path
This function will generate the absolute path of a file because Casio's open
@ -36,8 +42,6 @@ static void generate_absolute_path(uint16_t *pathname,
pathname[*pos] = '\0';
}
/* bfile_abstract(): */
/* smemfs_read(): Read primitive */
ssize_t smemfs_pread(struct smemfs_inode *inode,
void *buf, size_t count, off_t pos)
@ -53,7 +57,7 @@ ssize_t smemfs_pread(struct smemfs_inode *inode,
generate_absolute_path(pathname, inode, &handle);
/* Switch from gint to the OS after a short wait */
gint_switch_to_casio();
gint_switch_to_world(kernel_env_casio);
/* Open, read and close the file using Casio's OS syscall */
read = -1;
@ -64,7 +68,7 @@ ssize_t smemfs_pread(struct smemfs_inode *inode,
}
/* Then switch back to gint once the OS finishes working */
gint_switch_to_gint();
gint_switch_to_world(kernel_env_gint);
/* return the number of byte readed */
return (read);

View File

@ -1,6 +1,7 @@
//---
// fxBoot:hypervisor:gint - Gint workaround
//---
#if 0
#include "fxBoot/hypervisor.h"
#include <gint/atomic.h>
@ -34,3 +35,4 @@ void gint_switch(void (*function)(void))
function();
gint_switch_to_gint();
}
#endif

View File

@ -25,6 +25,6 @@ int hypervisor_env_set(struct hworld *world)
default:
return (-2);
}
drivers_context_duplicate(world->context.drivers, env);
drivers_context_duplicate(&world->context.drivers, env);
return (0);
}

View File

@ -8,6 +8,13 @@
#include "fxBoot/fs/smemfs.h"
#include "fxBoot/elf.h"
/* internal gint symbols information structure */
struct dyngint {
const char *name;
const void *addr;
};
extern const struct dyngint gint_reloc[];
//---
// Main API
//---
@ -70,4 +77,6 @@ enum {
extern int hypervisor_elf_loader_reloc_sym(struct hworld *world,
struct smemfs_inode *inode, Elf32_Ehdr *header);
extern int hypervisor_elf_loader_reloc_error(int errnum);
extern int hypervisor_elf_loader_dynamic_check(struct smemfs_inode *inode);
#endif /*__HYPERVISOR_INTERNAL_H__*/

View File

@ -0,0 +1,156 @@
//---
// fxBoot:loader:entry - ELF Loader entry
//---
#include "fxBoot/hypervisor.h"
#include "fxBoot/fs/smemfs.h"
#include "fxBoot/elf.h"
#include "fxBoot/terminal.h"
#include <gint/std/stdlib.h>
#include <gint/std/string.h>
#include "./src/hypervisor/internal/elf.h"
/* elf_dump_section(): Dump one section */
static void *elf_dump_section(struct smemfs_inode *inode, Elf32_Shdr *shdr)
{
void *section;
section = malloc(shdr->sh_size);
if (section == NULL)
return (NULL);
if (smemfs_pread(inode, section, shdr->sh_size, shdr->sh_offset)
!= (ssize_t)shdr->sh_size) {
free(section);
return (NULL);
}
return (section);
}
/* elf_rela_check(): Check rela section */
static void elf_rela_check(struct smemfs_inode *inode, Elf32_Shdr *shdr)
{
Elf32_Rela rela;
Elf32_Word i;
off_t offset;
for (i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i) {
offset = shdr->sh_offset + (i * shdr->sh_entsize);
if (smemfs_pread(inode, &rela, shdr->sh_entsize, offset)
!= (ssize_t)shdr->sh_entsize) {
terminal_write("rela sectio size error\n");
return;
}
terminal_write("%p %p %d %d %d\n", rela.r_offset,
rela.r_info,
ELF32_R_SYM(rela.r_info),
ELF32_R_TYPE(rela.r_info),
rela.r_addend);
}
}
/* hypervisor_elf_loader_dynamic_check(): Display all .dynshr */
int hypervisor_elf_loader_dynamic_check(struct smemfs_inode *inode)
{
Elf32_Ehdr ehdr;
Elf32_Shdr shdr;
Elf32_Shdr dynamichdr;
Elf32_Dyn *dynamic;
char *shstrtab;
char *dynstr;
char *dynsym;
off_t offset;
void **tmp;
int err;
/* Try to get the ELF header information */
err = hypervisor_elf_loader_header_get(inode, &ehdr);
if (err != 0)
return (-2);
/* get ELF section header string table */
offset = ehdr.e_shoff + (ehdr.e_shstrndx * ehdr.e_shentsize);
if (smemfs_pread(inode, &shdr, ehdr.e_shentsize, offset)
!= ehdr.e_shentsize) {
terminal_write("shdr size\n");
return (-1);
}
shstrtab = elf_dump_section(inode, &shdr);
if (shstrtab == NULL) {
terminal_write("cannot get the shstrtab section\n");
return (-2);
}
/* get ELF information */
dynstr = NULL;
dynamic = NULL;
for (int i = 1 ; i < ehdr.e_shnum ; ++i) {
offset = ehdr.e_shoff + (i * ehdr.e_shentsize);
if (smemfs_pread(inode, &shdr, ehdr.e_shentsize, offset)
!= ehdr.e_shentsize) {
terminal_write("section %d size error\n", i);
continue;
}
if (shdr.sh_type == SHT_RELA) {
elf_rela_check(inode, &shdr);
continue;
}
tmp = NULL;
if (strcmp(".dynamic", &shstrtab[shdr.sh_name]) == 0) {
memcpy(&dynamichdr, &shdr, sizeof(Elf32_Shdr));
tmp = (void*)&dynamic;
}
if (strcmp(".dynstr", &shstrtab[shdr.sh_name]) == 0)
tmp = (void*)&dynstr;
if (strcmp(".dynsym", &shstrtab[shdr.sh_name]) == 0)
tmp = (void*)&dynsym;
if (tmp == NULL)
continue;
*tmp = elf_dump_section(inode, &shdr);
if (*tmp == NULL) {
terminal_write("warning: '%s' dump error\n",
&shstrtab[shdr.sh_name]);
}
}
if (dynstr == NULL || dynamic == NULL) {
terminal_write(".dynstr or .dynamic not found\n");
return (-3);
}
#if 0
/* display information */
Elf32_Word i;
terminal_write("%10s %8s Name/Value\n", "TAG", "Type");
for (i = 0; i < dynamichdr.sh_size / dynamichdr.sh_entsize; ++i) {
if (dynamic[i].d_tag == DT_NULL) {
terminal_write("%p %8s %d\n",
dynamic[i].d_tag, "NULL",
dynamic[i].d_un.d_val);
break;
}
if (dynamic[i].d_tag == DT_NEEDED) {
terminal_write("%p %8s %s\n",
dynamic[i].d_tag, "NEEDED",
&dynstr[dynamic[i].d_un.d_val]);
continue;
}
if (dynamic[i].d_tag == DT_STRTAB) {
terminal_write("%p %8s %p\n",
dynamic[i].d_tag, "STRTAB",
dynamic[i].d_un.d_ptr);
continue;
}
if (dynamic[i].d_tag == DT_SYMTAB) {
terminal_write("%x %8s %p\n",
dynamic[i].d_tag, "SYMTAB",
dynamic[i].d_un.d_ptr);
continue;
}
terminal_write("%p %8s %p\n",
dynamic[i].d_tag, type,
dynamic[i].d_un.d_val);
}
terminal_write("dynamic symbols - %d\n", i);
#endif
return (0);
}

View File

@ -19,8 +19,7 @@ int hypervisor_elf_loader(struct hworld *world, struct smemfs_inode *inode)
return (-1);
/* save private information */
terminal_write("hypervisor:\n");
terminal_write("- load the inode \"%s\"\n", inode->name);
terminal_write("- load ELF file \"%s\"\n", inode->name);
world->private.inode = inode;
/* Try to get the ELF header information */
@ -36,17 +35,9 @@ int hypervisor_elf_loader(struct hworld *world, struct smemfs_inode *inode)
return (-3);
/* Relocalise sections / symbols */
terminal_write("- relocalise static symbols\n");
terminal_write("- relocalize symbols\n");
err = hypervisor_elf_loader_reloc_sym(world, inode, &header);
if (err != 0)
return (-4);
#if 0
/* Relocalise Gint symbols */
terminal_write("- relocalise shared symbols\n");
err = hypervisor_elf_loader_reloc_gint(world, inode, &header);
if (err != 0)
return (-5);
#endif
return (0);
}

View File

@ -0,0 +1,42 @@
#include "./src/hypervisor/internal/elf.h"
#include <gint/display.h>
#include <gint/keyboard.h>
const struct dyngint gint_reloc[] = {
/* display symbols */
{.name = "_dclear", .addr = (void*)&dclear},
{.name = "_drect", .addr = (void*)&drect},
{.name = "_drect_border", .addr = (void*)&drect_border},
{.name = "_dpixel", .addr = (void*)&dpixel},
{.name = "_dline", .addr = (void*)&dline},
{.name = "_dhline", .addr = (void*)&dhline},
{.name = "_dvline", .addr = (void*)&dvline},
{.name = "_dfont", .addr = (void*)&dfont},
{.name = "_dsize", .addr = (void*)&dsize},
{.name = "_dtext_opt", .addr = (void*)&dtext_opt},
{.name = "_dtext", .addr = (void*)&dtext},
{.name = "_dprint_opt", .addr = (void*)&dprint_opt},
{.name = "_dprint", .addr = (void*)&dprint},
{.name = "_dimage", .addr = (void*)&dimage},
{.name = "_dsubimage", .addr = (void*)&dsubimage},
{.name = "_dupdate", .addr = (void*)&dupdate},
/* keyboard symbols */
{.name = "_pollevent", .addr = (void*)&pollevent},
{.name = "_waitevent", .addr = (void*)&waitevent},
{.name = "_clearevants", .addr = (void*)&clearevents},
{.name = "_keydown", .addr = (void*)&keydown},
{.name = "_keydown_all", .addr = (void*)&keydown_all},
{.name = "_keydown_any", .addr = (void*)&keydown_any},
{.name = "_getkey", .addr = (void*)&getkey},
{.name = "_getkey_opt", .addr = (void*)&getkey_opt},
{.name = "_getkey_repeat", .addr = (void*)&getkey_repeat},
{.name = "_getkey_repeat_filter",.addr = (void*)&getkey_repeat_filter},
{.name = "_keycode_function", .addr = (void*)&keycode_function},
{.name = "_keycode_digit", .addr = (void*)&keycode_digit},
/* end */
{.name = NULL, .addr = (void*)NULL},
};

View File

@ -53,7 +53,7 @@ int hypervisor_elf_loader_header_get(struct smemfs_inode *inode,
return (hel_header_indent_error);
/* Check ELF type */
if (header->e_type != ET_DYN)
if (header->e_type != ET_DYN && header->e_type != ET_EXEC)
return (hel_header_type_error);
/* Check ELF specifique instruction */

View File

@ -31,13 +31,18 @@ int hypervisor_elf_loader_image_load(struct hworld *world,
struct smemfs_inode *inode, Elf32_Ehdr *header)
{
Elf32_Phdr program;
void *paddress;
uintptr_t paddress;
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;
world->memory.program.size = 0;
while (++i < header->e_phnum) {
offset = header->e_phoff + (i * sizeof(Elf32_Phdr));
@ -45,10 +50,14 @@ int hypervisor_elf_loader_image_load(struct hworld *world,
!= sizeof(Elf32_Phdr)) {
return (hel_image_size_error);
}
if (program.p_type != PT_LOAD)
return (hel_image_type_error);
world->memory.program.size += program.p_memsz;
if (program.p_vaddr < vmin)
vmin = program.p_vaddr;
if (program.p_vaddr + program.p_memsz > vmax)
vmax = program.p_vaddr + program.p_memsz;
}
world->memory.program.size = vmax - vmin;
world->memory.program.elf.vmin = vmin;
world->memory.program.elf.vmax = vmax;
/* Allocate programe memory */
world->memory.program.start = calloc(world->memory.program.size, 1);
@ -59,22 +68,28 @@ int hypervisor_elf_loader_image_load(struct hworld *world,
read each program header, generate the "real" physical address of
the segment then dump data.
Nota that the p_inodesz can be smaller than p_memsz so, we need to
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 < header->e_phnum) {
offset = header->e_phoff + (i * sizeof(Elf32_Phdr));
smemfs_pread(inode, &program, sizeof(Elf32_Phdr), offset);
paddress = program.p_vaddr + world->memory.program.start;
paddress = (uintptr_t)program.p_vaddr - vmin;
paddress += (uintptr_t)world->memory.program.start;
memset(paddress, 0, program.p_memsz);
smemfs_pread(inode, paddress,
memset((void*)paddress, 0x00, program.p_memsz);
smemfs_pread(inode, (void*)paddress,
program.p_filesz, program.p_offset);
}
/* Generate program entry address */
world->context.cpu.spc = (uint32_t)header->e_entry;
world->context.cpu.spc = (uintptr_t)header->e_entry - vmin;
world->context.cpu.spc += (uintptr_t)world->memory.program.start;
terminal_write("- SPC: %p\n", world->context.cpu.spc);
/* Generate other information */
world->context.cpu.ssr = 0x40000000;
//TODO: PR register !
return (hel_image_success);
}

View File

@ -4,33 +4,146 @@
#include "fxBoot/hypervisor.h"
#include "fxBoot/fs/smemfs.h"
#include "fxBoot/elf.h"
#include "fxBoot/terminal.h"
#include <gint/std/stdlib.h>
#include <gint/std/string.h>
#include "./src/hypervisor/internal/elf.h"
//---
// Internal helpers
//---
/* relocinfo: Internal structure used to stoe all ELF information */
struct relocinfo {
Elf32_Ehdr *ehdr;
Elf32_Shdr ehdr_dynamic;
Elf32_Dyn *dynamic;
Elf32_Sym *dynsym;
char *dynstr;
char *shstrtab;
struct smemfs_inode *inode;
};
/* reloc_dump_section(): Dump one section */
static void *reloc_dump_section(struct smemfs_inode *inode, Elf32_Shdr *shdr)
{
void *section;
section = malloc(shdr->sh_size);
if (section == NULL)
return (NULL);
if (smemfs_pread(inode, section, shdr->sh_size, shdr->sh_offset)
!= (ssize_t)shdr->sh_size) {
free(section);
return (NULL);
}
return (section);
}
/* reloc_get_dynamic_info(): Dump all dynamic information */
static int reloc_get_dynamic_info(struct relocinfo *elf)
{
Elf32_Shdr shdr;
off_t offset;
void **tmp;
/* get ELF section header string table */
offset = elf->ehdr->e_shoff;
offset += elf->ehdr->e_shstrndx * elf->ehdr->e_shentsize;
if (smemfs_pread(elf->inode, &shdr, elf->ehdr->e_shentsize, offset)
!= elf->ehdr->e_shentsize) {
return (-1);
}
elf->shstrtab = reloc_dump_section(elf->inode, &shdr);
if (elf->shstrtab == NULL)
return (-2);
/* get ELF information */
elf->dynstr = NULL;
elf->dynamic = NULL;
for (int i = 1 ; i < elf->ehdr->e_shnum ; ++i) {
offset = elf->ehdr->e_shoff + (i * elf->ehdr->e_shentsize);
if (smemfs_pread(elf->inode, &shdr,
elf->ehdr->e_shentsize, offset)
!= elf->ehdr->e_shentsize) {
continue;
}
tmp = NULL;
if (strcmp(".dynamic", &elf->shstrtab[shdr.sh_name]) == 0) {
memcpy(&elf->ehdr_dynamic, &shdr, sizeof(Elf32_Shdr));
tmp = (void*)&elf->dynamic;
}
if (strcmp(".dynstr", &elf->shstrtab[shdr.sh_name]) == 0)
tmp = (void*)&elf->dynstr;
if (strcmp(".dynsym", &elf->shstrtab[shdr.sh_name]) == 0)
tmp = (void*)&elf->dynsym;
if (tmp == NULL)
continue;
*tmp = reloc_dump_section(elf->inode, &shdr);
}
return (0);
}
/* reloc_get_dynsym(): Try to find the dynamic symbol address */
static void *reloc_get_dynsym(struct relocinfo *info, int symid)
{
char *name;
if (info->dynsym == NULL || info->dynstr == NULL)
return (NULL);
//FIXME: check symid validity !
name = &info->dynstr[info->dynsym[symid].st_name];
for (int i = 0; gint_reloc[i].name != NULL; ++i) {
if (strcmp(name, gint_reloc[i].name) != 0)
continue;
terminal_write(" * reloc '%s'\n", name);
return ((void*)gint_reloc[i].addr);
}
terminal_write("unknown '%s' symbols\n", name);
return (NULL);
}
/* reloc_section(): Relocalise section's symbols */
static int reloc_section(struct hworld *world,
struct smemfs_inode *inode, Elf32_Shdr *shdr)
static int reloc_rela(struct hworld *world,
struct relocinfo *info, Elf32_Shdr *shdr)
{
Elf32_Rela rela;
uint32_t *prog;
off_t offset;
void *dyn;
/* List symbols */
if (shdr->sh_size == 0 || shdr->sh_entsize == 0) {
terminal_write("empty section\n");
return (0);
}
prog = (void*)world->memory.program.start;
for (uint32_t i = 0 ; i < shdr->sh_size / shdr->sh_entsize ; ++i) {
/* Get relocatable symbol information */
offset = shdr->sh_offset + (i * shdr->sh_entsize);
if (smemfs_pread(inode, &rela, shdr->sh_entsize, offset)
if (smemfs_pread(info->inode, &rela, shdr->sh_entsize, offset)
!= (ssize_t)shdr->sh_entsize) {
return (hel_reloc_size_error);
}
/* Relocalise the symbol */
prog[rela.r_offset >> 2] +=
(uintptr_t)world->memory.program.start;
if (ELF32_R_TYPE(rela.r_info) == R_SH_RELATIVE) {
offset = rela.r_offset;
offset -= world->memory.program.elf.vmin;
prog[offset >> 2] -= world->memory.program.elf.vmin;
prog[offset >> 2] +=
(uintptr_t)world->memory.program.start;
continue;
}
if (ELF32_R_TYPE(rela.r_info) == R_SH_JMP_SLOT) {
dyn = reloc_get_dynsym(info, ELF32_R_SYM(rela.r_info));
if (dyn == NULL)
return (-1);
offset = rela.r_offset;
offset -= world->memory.program.elf.vmin;
prog[offset >> 2] = (uintptr_t)dyn;
world->private.env = HYPERVISOR_ENV_GINT;
continue;
}
terminal_write("unknown type %x\n", rela.r_info);
return (-1);
}
return (hel_reloc_success);
}
@ -40,21 +153,35 @@ static int reloc_section(struct hworld *world,
//---
/* loader_reloc_sym(): Relocalise all symbols */
int hypervisor_elf_loader_reloc_sym(struct hworld *world,
struct smemfs_inode *inode, Elf32_Ehdr *header)
struct smemfs_inode *inode, Elf32_Ehdr *ehdr)
{
struct relocinfo info;
Elf32_Shdr shdr;
off_t offset;
for (int i = 1 ; i < header->e_shnum ; ++i) {
offset = header->e_shoff + (i * header->e_shentsize);
if (smemfs_pread(inode, &shdr, header->e_shentsize, offset)
!= header->e_shentsize) {
/* get dynamic information */
info.inode = inode;
info.ehdr = ehdr;
if (reloc_get_dynamic_info(&info) != 0)
return (-1);
/* find all reloc section */
//TODO : support SH_REL
//TODO : check if the GOT, PLT sections are relocalized !
for (int i = 1 ; i < ehdr->e_shnum ; ++i) {
offset = ehdr->e_shoff + (i * ehdr->e_shentsize);
if (smemfs_pread(inode, &shdr, ehdr->e_shentsize, offset)
!= ehdr->e_shentsize) {
return (hel_reloc_size_error);
}
if (shdr.sh_type != SHT_RELA)
continue;
if (reloc_section(world, inode, &shdr) != hel_reloc_success)
if (shdr.sh_type == SHT_RELA
&& reloc_rela(world, &info, &shdr) != hel_reloc_success)
return (hel_reloc_error);
if (shdr.sh_type == SHT_REL) {
terminal_write("SHT_REL not yet supported\n");
return (hel_reloc_error);
}
}
return (hel_reloc_success);
}

View File

@ -37,86 +37,139 @@ abi_error:
abi_trapa_reg:
.long 0xff000020
abi_syscall_table:
.long 0x00000000 ! _hypervisor_kernel_world_switch
.long 0x00000000
.long _hypervisor_kernel_world_switch
.long 0x00000000 ! _hypervisor_kernel_schedule
#if 0
/* hypervisor world_switch(): Performs a world switch */
/* hypervisor world_switch(struct hworld *world): Performs a world switch
This hypervisor call will check the world validity then it will save the
current world environment information, install the new world then perform
an world switch. */
_hypervisor_kernel_world_switch:
/* enable exception but block all interruption */
mov.l sr_ws_config, r0
stc sr, r1
or r0, r1
ldc r1, sr
/* check potential error */
stc R4_BANK, r4
tst r4, r4
bt kernel_world_error
mov.l hypervisor_world_current, r5
mov.l @r5, r5
tst r5, r5
bt kernel_world_error
/* switch stack (user -> kernel) */
mov.l r15, @r5
mov.l @(4, r5), r15
/* save the current context */
sts.l pr, @-r15
mov.l r4, @-r15
mov.l r5, @-r15
mov.l drivers_context_save, r0
jsr @r0
mov.l @r4, r4
mov.l @(8, r5), r4
mov.l @r15+, r5
mov.l @r15+, r4
ldc.l @r15+, pr
lds.l @r15+, pr
/* switch stack (kernel -> user) */
mov.l r15, @(4, r5)
mov.l @r5, r15
/* save cpu context */
add #92, r4
mov.l pr, @-r4
stc.l spc, @-r4
stc.l ssr, @-r4
sts.l mach, @-r4
sts.l macl, @-r4
stc.l gbr, @-r4
mov.l r15, @-r4
mov.l r14, @-r4
mov.l r13, @-r4
mov.l r12, @-r4
mov.l r11, @-r4
mov.l r10, @-r4
mov.l r9, @-r4
mov.l r8, @-r4
stc.l R7_BANK, @-r4
stc.l R6_BANK, @-r4
stc.l R5_BANK, @-r4
stc.l R4_BANK, @-r4
stc.l R3_BANK, @-r4
stc.l R2_BANK, @-r4
stc.l R1_BANK, @-r4
stc.l R0_BANK, @-r4
add #100, r5
sts.l pr, @-r5
stc.l spc, @-r5
stc.l ssr, @-r5
sts.l mach, @-r5
sts.l macl, @-r5
stc.l gbr, @-r5
mov.l r15, @-r5
mov.l r14, @-r5
mov.l r13, @-r5
mov.l r12, @-r5
mov.l r11, @-r5
mov.l r10, @-r5
mov.l r9, @-r5
mov.l r8, @-r5
stc.l R7_BANK, @-r5
stc.l R6_BANK, @-r5
stc.l R5_BANK, @-r5
stc.l R4_BANK, @-r5
stc.l R3_BANK, @-r5
stc.l R2_BANK, @-r5
stc.l R1_BANK, @-r5
stc.l R0_BANK, @-r5
/* restore cpu context */
add #4, r5
ldc.l @r5+, R0_BANK
ldc.l @r5+, R1_BANK
ldc.l @r5+, R2_BANK
ldc.l @r5+, R3_BANK
ldc.l @r5+, R4_BANK
ldc.l @r5+, R5_BANK
ldc.l @r5+, R6_BANK
ldc.l @r5+, R7_BANK
mov.l @r5+, r8
mov.l @r5+, r9
mov.l @r5+, r10
mov.l @r5+, r11
mov.l @r5+, r12
mov.l @r5+, r13
mov.l @r5+, r14
mov.l @r5+, r15
ldc.l @r5+, gbr
lds.l @r5+, macl
lds.l @r5+, mach
ldc.l @r5+, ssr
ldc.l @r5+, spc
lds.l @r5+, pr
add #12, r4
ldc.l @r4+, R0_BANK
ldc.l @r4+, R1_BANK
ldc.l @r4+, R2_BANK
ldc.l @r4+, R3_BANK
ldc.l @r4+, R4_BANK
ldc.l @r4+, R5_BANK
ldc.l @r4+, R6_BANK
ldc.l @r4+, R7_BANK
mov.l @r4+, r8
mov.l @r4+, r9
mov.l @r4+, r10
mov.l @r4+, r11
mov.l @r4+, r12
mov.l @r4+, r13
mov.l @r4+, r14
mov.l @r4+, r15
ldc.l @r4+, gbr
lds.l @r4+, macl
lds.l @r4+, mach
ldc.l @r4+, ssr
ldc.l @r4+, spc
lds.l @r4+, pr
/* restore drivers context */
/* TODO */
/* switch stack (user -> kernel) */
add #-100, r4
mov.l r15, @r4
mov.l @(4, r4), r15
/* force install hypervisor */
/* TODO */
/* indicate that the world has changed */
mov.l hypervisor_world_current, r0
mov.l r4, @r0
/* save the current context
Note that the SR register can be restored. So, interruption /
exceptions can occur during this lack of time between JSR and the
resotoration of the SR register. */
stc.l ssr, @-r15
stc.l spc, @-r15
sts.l pr, @-r15
mov.l r4, @-r15
stc.l sr, @-r15
mov.l drivers_context_restore, r0
jsr @r0
mov.l @(8, r4), r4
ldc.l @r15+, sr
mov.l @r15+, r4
lds.l @r15+, pr
ldc.l @r15+, spc
ldc.l @r15+, ssr
/* switch stack (kernel -> user) */
mov.l r15, @(4, r4)
mov.l @r4, r15
/* force hypervisor VBR re-installation, because it possible that the
VBR has been changed during the handler */
mov.l hypervisor_vbr_redirect, r0
mov.l hypervisor_vbr, r1
stc vbr, r2
mov.l r2, @r0
ldc.l @r1+, vbr
/* perform the world switch */
rte
@ -125,4 +178,12 @@ _hypervisor_kernel_world_switch:
kernel_world_error:
rts
mov #-2, r0
#endif
.align 4
sr_ws_config: .long 0x600000f0
!wswitch_debug: .long _wswitch_debug
hypervisor_vbr: .long _hypervisor_vbr
hypervisor_vbr_redirect: .long _hypervisor_vbr_redirect
hypervisor_world_current: .long _hypervisor_world_current
drivers_context_save: .long _drivers_save
drivers_context_restore: .long _drivers_restore

View File

@ -2,6 +2,7 @@
// hypervisor:wsiwtch - hypervisor world switch
//---
#include "fxBoot/hypervisor.h"
#include "fxBoot/terminal.h"
#include <gint/std/stdlib.h>
#include <gint/atomic.h>
@ -10,6 +11,7 @@
/* internal globals information */
HYPERVISOR_BSS void *hypervisor_current_vbr = NULL;
HYPERVISOR_BSS struct hworld *hypervisor_world_queue = NULL;
extern struct hworld *hypervisor_world_current;
extern struct hworld *hypervisor_world;
//---
@ -57,10 +59,10 @@ struct hworld *hypervisor_wswitch_world_alloc(void)
world->stack.user = world->memory.stack.user;
world->stack.user += HYPERVISOR_STACK_USER_SIZE;
world->stack.user = (void*)((uintptr_t)world->stack.user & ~3);
world->context.cpu.reg[15] = (uintptr_t)world->stack.user;
return (world);
}
/* hypervisor_wswitch_create(): Create a new world */
struct hworld *hypervisor_wswitch_create(void)
{
@ -149,7 +151,15 @@ int hypervisor_wswitch(struct hworld *world)
return (-1);
if (world->private.status != HYPERVISOR_STATUS_INIT)
return (-2);
int retval;
hypervisor_install();
//hypervisor_kernel_world_yield(hypervisor_world, world);
return (0);
tracer_set_session(world->private.debug.tracer);
terminal_error("world switch to:\ncurr: %p\nnext: %p\n",
hypervisor_world_current, world);
__asm__ volatile (
"mov %0, r4;"
"trapa #0;"
"mov r0, %0;"
: "=r"(retval) : "r"(world) : "r4", "r0");
return (retval);
}

View File

@ -28,3 +28,25 @@ int terminal_write(const char *format, ...)
dupdate();
return (nb);
}
/* terminal_write() - printf wrapper for the terminal device */
int terminal_error(const char *format, ...)
{
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);
/* display the internal buffer */
dclear(terminal.private.color.bg);
terminal_buffer_display();
dupdate_noint();
return (nb);
}

View File

@ -0,0 +1,7 @@
#! /usr/bin/bash
#non#sh-elf-gcc -nostdlib -m3 -mb -mrenesas -ffreestanding -c test.c -o test.o -DFXCG50
# @note: -mrenesas change the calling convention of varaiodic arguments
sh-elf-gcc -fPIE -nostdlib -m3 -mb -ffreestanding -c test.c -o test.o -DFXCG50
sh-elf-ld -pie test.o -o dyntest -L. -lgint-cg-dyn -T linker.ld

BIN
tests/symboltest/dyntest Executable file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,17 @@
OUTPUT_ARCH(sh4)
OUTPUT_FORMAT(elf32-sh)
ENTRY(_main)
SECTIONS
{
. = SIZEOF_HEADERS;
.text : {
*(.text)
}
.data : {
*(.data)
}
.bss : {
*(.bss)
}
}

14
tests/symboltest/test.c Normal file
View File

@ -0,0 +1,14 @@
#include <gint/display.h>
#include <gint/keyboard.h>
int main(void)
{
while (1) {
dclear(C_WHITE);
dtext(0, 0, C_BLACK, "Relocalized addin :D");
dprint(0, 10, C_RED, "test %d", 10);
dupdate();
getkey();
}
return (0);
}

View File

@ -0,0 +1,87 @@
OUTPUT_FORMAT("elf32-sh", "elf32-sh", "elf32-sh")
OUTPUT_ARCH(sh3)
ENTRY(_main)
/*
** Linker script for user executables.
*/
MEMORY
{
/* virtual memory, read-write segment */
userram (WX) : o = 0x00000000, l = 256k
}
SECTIONS
{
/* Code */
.text : {
*(.text);
*(.text.*);
} > userram
/* Read-only sections */
.rodata : {
/* Read-Only data */
*(.rodata);
*(.rodata.*);
/* Dynamic symbols */
*(.hash)
*(.dynsym)
*(.dynstr)
*(.dynbss)
*(.dynamic)
/* Procedure Linkage Table */
*(.plt)
/* GLobal Offset Table */
*(.got.plt)
*(.got.*)
*(.got)
/* ???? */
*(.rofixup)
} > userram
/* Relocatable sections */
.rela.dyn : {
*(.rela.plt)
*(.rela.got)
*(.rela.got.*)
*(.rela.*)
*(.rela.text)
*(.real.data)
} > userram
/* readable / writable data */
.data ALIGN(4) : {
/* Data sections */
*(.data);
*(.data.*);
/* bss section included to avoid missaligned segment */
*(.bss);
*(.bss.*);
*(COMMON);
} > userram
/* unwanted section */
/DISCARD/ : {
*(.gnu.*)
*(.debug_info)
*(.debug_abbrev)
*(.debug_loc)
*(.debug_aranges)
*(.debug_ranges)
*(.debug_line)
*(.debug_str)
*(.jcr)
*(.eh_frame_hdr)
*(.eh_frame)
*(.comment)
*(.interp)
}
}

BIN
tests/test.elf Executable file

Binary file not shown.

View File

@ -15,73 +15,72 @@ Linker script and memory map
LOAD build/main.o
LOAD build/syscalls.o
.text 0x0000000000000000 0x230
.text 0x0000000000000000 0x220
*(.text)
.text 0x0000000000000000 0x68 build/main.o
.text 0x0000000000000000 0x5c build/main.o
0x0000000000000000 _main
*fill* 0x0000000000000068 0x8
.text 0x0000000000000070 0xe0 build/syscalls.o
0x0000000000000070 _casio_GetKey
0x0000000000000084 _casio_PrintMini
0x00000000000000b4 _casio_Bdisp_AllClr_VRAM
0x00000000000000c4 _casio_Bdisp_PutDisp_DD
0x00000000000000d4 _casio_Bfile_CreateFile
0x00000000000000e4 _casio_Bfile_OpenFile
0x00000000000000f4 _casio_Bfile_CloseFile
0x0000000000000104 _casio_Bfile_WriteFile
0x0000000000000114 _casio_Bfile_ReadFile
0x0000000000000124 _casio_Malloc
0x0000000000000134 _casio_Free
*fill* 0x000000000000005c 0x4
.text 0x0000000000000060 0xe0 build/syscalls.o
0x0000000000000060 _casio_GetKey
0x0000000000000074 _casio_PrintMini
0x00000000000000a4 _casio_Bdisp_AllClr_VRAM
0x00000000000000b4 _casio_Bdisp_PutDisp_DD
0x00000000000000c4 _casio_Bfile_CreateFile
0x00000000000000d4 _casio_Bfile_OpenFile
0x00000000000000e4 _casio_Bfile_CloseFile
0x00000000000000f4 _casio_Bfile_WriteFile
0x0000000000000104 _casio_Bfile_ReadFile
0x0000000000000114 _casio_Malloc
0x0000000000000124 _casio_Free
*(.text.*)
*(.rodata)
.rodata 0x0000000000000150 0x25 build/main.o
.rodata 0x0000000000000140 0x28 build/main.o
*(.rodata.*)
*(.hash)
*fill* 0x0000000000000175 0x3
.hash 0x0000000000000178 0x10 build/main.o
.hash 0x0000000000000168 0x10 build/main.o
*(.dynsym)
.dynsym 0x0000000000000188 0x10 build/main.o
.dynsym 0x0000000000000178 0x10 build/main.o
*(.dynstr)
.dynstr 0x0000000000000198 0x1 build/main.o
.dynstr 0x0000000000000188 0x1 build/main.o
*(.dynbss)
.dynbss 0x0000000000000199 0x0 build/main.o
.dynbss 0x0000000000000189 0x0 build/main.o
*(.dynamic)
*fill* 0x0000000000000199 0x3
.dynamic 0x000000000000019c 0x88 build/main.o
0x000000000000019c _DYNAMIC
*fill* 0x0000000000000189 0x3
.dynamic 0x000000000000018c 0x88 build/main.o
0x000000000000018c _DYNAMIC
*(.plt)
.plt 0x0000000000000224 0x0 build/main.o
.plt 0x0000000000000214 0x0 build/main.o
*(.got.plt)
.got.plt 0x0000000000000224 0xc build/main.o
0x0000000000000224 _GLOBAL_OFFSET_TABLE_
.got.plt 0x0000000000000214 0xc build/main.o
0x0000000000000214 _GLOBAL_OFFSET_TABLE_
*(.got.*)
.got.funcdesc 0x0000000000000230 0x0 build/main.o
.got.funcdesc 0x0000000000000220 0x0 build/main.o
*(.got)
.got 0x0000000000000230 0x0 build/main.o
.got 0x0000000000000220 0x0 build/main.o
*(.rofixup)
.rofixup 0x0000000000000230 0x0 build/main.o
.rofixup 0x0000000000000220 0x0 build/main.o
.rela.dyn 0x0000000000000230 0x48
.rela.dyn 0x0000000000000220 0x48
*(.rela.plt)
.rela.plt 0x0000000000000230 0x0 build/main.o
.rela.plt 0x0000000000000220 0x0 build/main.o
*(.rela.got)
.rela.got 0x0000000000000230 0x0 build/main.o
.rela.got 0x0000000000000220 0x0 build/main.o
*(.rela.got.*)
.rela.got.funcdesc
0x0000000000000230 0x0 build/main.o
0x0000000000000220 0x0 build/main.o
*(.rela.*)
.rela.text 0x0000000000000230 0x48 build/main.o
.rela.text 0x0000000000000220 0x48 build/main.o
*(.rela.text)
*(.real.data)
.data 0x0000000000000278 0x0
.data 0x0000000000000268 0x0
*(.data)
.data 0x0000000000000278 0x0 build/main.o
.data 0x0000000000000278 0x0 build/syscalls.o
.data 0x0000000000000268 0x0 build/main.o
.data 0x0000000000000268 0x0 build/syscalls.o
*(.data.*)
*(.bss)
.bss 0x0000000000000278 0x0 build/main.o
.bss 0x0000000000000278 0x0 build/syscalls.o
.bss 0x0000000000000268 0x0 build/main.o
.bss 0x0000000000000268 0x0 build/syscalls.o
*(.bss.*)
*(COMMON)