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:
parent
9ef129e788
commit
32e89925b9
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
};
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,17 @@
|
|||
OUTPUT_ARCH(sh4)
|
||||
OUTPUT_FORMAT(elf32-sh)
|
||||
ENTRY(_main)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = SIZEOF_HEADERS;
|
||||
.text : {
|
||||
*(.text)
|
||||
}
|
||||
.data : {
|
||||
*(.data)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss)
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue