More loader code, not finished yet.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15318 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
9ab7bf1d5b
commit
4532dd9243
|
@ -36,6 +36,16 @@
|
||||||
/* Module local definitions. */
|
/* Module local definitions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/* Relevant section types.*/
|
||||||
|
#define SHT_PROGBITS 1U
|
||||||
|
#define SHT_REL 9U
|
||||||
|
|
||||||
|
/* Relevant section flags.*/
|
||||||
|
#define SHF_WRITE (1U << 0)
|
||||||
|
#define SHF_ALLOC (1U << 1)
|
||||||
|
#define SHF_EXECINSTR (1U << 2)
|
||||||
|
#define SHF_INFO_LINK (1U << 6)
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Module exported variables. */
|
/* Module exported variables. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -56,6 +66,7 @@ typedef struct elf_load_context {
|
||||||
uint16_t shnum;
|
uint16_t shnum;
|
||||||
vfs_offset_t shoff;
|
vfs_offset_t shoff;
|
||||||
vfs_offset_t stringsoff;
|
vfs_offset_t stringsoff;
|
||||||
|
uint64_t loaded;
|
||||||
} elf_load_context_t;
|
} elf_load_context_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,12 +106,65 @@ typedef struct {
|
||||||
/* Module local variables. */
|
/* Module local variables. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Module local functions. */
|
/* Module local functions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static msg_t read_section_name(elf_load_context_t *ctxp,
|
||||||
|
elf32_section_header_t *shp,
|
||||||
|
char *buf, size_t buflen) {
|
||||||
|
msg_t ret;
|
||||||
|
|
||||||
|
if (shp->sh_name == 0U) {
|
||||||
|
*buf = '\0';
|
||||||
|
return CH_RET_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vfsSetFilePosition(ctxp->fnp,
|
||||||
|
ctxp->stringsoff + (vfs_offset_t)shp->sh_name,
|
||||||
|
VFS_SEEK_SET);
|
||||||
|
CH_RETURN_ON_ERROR(ret);
|
||||||
|
ret = vfsReadFile(ctxp->fnp, (void *)buf, buflen);
|
||||||
|
CH_RETURN_ON_ERROR(ret);
|
||||||
|
|
||||||
|
return CH_RET_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static msg_t read_section_header(elf_load_context_t *ctxp,
|
||||||
|
elf32_section_header_t *shp,
|
||||||
|
unsigned index) {
|
||||||
|
msg_t ret;
|
||||||
|
|
||||||
|
ret = vfsSetFilePosition(ctxp->fnp,
|
||||||
|
ctxp->shoff + ((vfs_offset_t)index *
|
||||||
|
(vfs_offset_t)sizeof (elf32_section_header_t)),
|
||||||
|
VFS_SEEK_SET);
|
||||||
|
CH_RETURN_ON_ERROR(ret);
|
||||||
|
return vfsReadFile(ctxp->fnp, (void *)shp, sizeof (elf32_section_header_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
static msg_t load_section(elf_load_context_t *ctxp,
|
||||||
|
elf32_section_header_t *shp) {
|
||||||
|
|
||||||
|
(void)ctxp;
|
||||||
|
(void)shp;
|
||||||
|
|
||||||
|
return CH_RET_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static msg_t reloc_section(elf_load_context_t *ctxp,
|
||||||
|
elf32_section_header_t *shp) {
|
||||||
|
|
||||||
|
(void)ctxp;
|
||||||
|
(void)shp;
|
||||||
|
|
||||||
|
return CH_RET_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static msg_t init_elf_context(elf_load_context_t *ctxp,
|
static msg_t init_elf_context(elf_load_context_t *ctxp,
|
||||||
|
elf32_section_header_t *shp,
|
||||||
vfs_file_node_c *fnp,
|
vfs_file_node_c *fnp,
|
||||||
memory_area_t *map) {
|
memory_area_t *map) {
|
||||||
static uint8_t elf32_header[16] = {
|
static uint8_t elf32_header[16] = {
|
||||||
|
@ -108,9 +172,10 @@ static msg_t init_elf_context(elf_load_context_t *ctxp,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
elf32_header_t h;
|
elf32_header_t h;
|
||||||
elf32_section_header_t sh;
|
|
||||||
msg_t ret;
|
msg_t ret;
|
||||||
|
|
||||||
|
memset((void *)ctxp, 0, sizeof (elf_load_context_t));
|
||||||
|
|
||||||
/* Initializing the fixed part of the context.*/
|
/* Initializing the fixed part of the context.*/
|
||||||
ctxp->fnp = fnp;
|
ctxp->fnp = fnp;
|
||||||
ctxp->map = map;
|
ctxp->map = map;
|
||||||
|
@ -129,20 +194,14 @@ static msg_t init_elf_context(elf_load_context_t *ctxp,
|
||||||
|
|
||||||
/* TODO more consistency checks.*/
|
/* TODO more consistency checks.*/
|
||||||
|
|
||||||
/* Reading the header of the section containing the section names.*/
|
|
||||||
ret = vfsSetFilePosition(ctxp->fnp,
|
|
||||||
(vfs_offset_t)(h.e_shoff +
|
|
||||||
(h.e_shstrndx * sizeof (elf32_section_header_t))),
|
|
||||||
VFS_SEEK_SET);
|
|
||||||
CH_RETURN_ON_ERROR(ret);
|
|
||||||
ret = vfsReadFile(ctxp->fnp, (void *)&sh, sizeof (elf32_section_header_t));
|
|
||||||
CH_RETURN_ON_ERROR(ret);
|
|
||||||
|
|
||||||
/* Storing info required later.*/
|
/* Storing info required later.*/
|
||||||
ctxp->entry = h.e_entry;
|
ctxp->entry = h.e_entry;
|
||||||
ctxp->shnum = h.e_shnum;
|
ctxp->shnum = h.e_shnum;
|
||||||
ctxp->shoff = (vfs_offset_t)h.e_shoff;
|
ctxp->shoff = (vfs_offset_t)h.e_shoff;
|
||||||
ctxp->stringsoff = (vfs_offset_t)sh.sh_offset;
|
|
||||||
|
/* Reading the header of the section containing the section names.*/
|
||||||
|
ret = read_section_header(ctxp, shp, (unsigned)h.e_shstrndx);
|
||||||
|
ctxp->stringsoff = (vfs_offset_t)shp->sh_offset;
|
||||||
|
|
||||||
return CH_RET_SUCCESS;
|
return CH_RET_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -151,23 +210,88 @@ static msg_t init_elf_context(elf_load_context_t *ctxp,
|
||||||
/* Module exported functions. */
|
/* Module exported functions. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
msg_t sbElfLoad(vfs_driver_c *drvp, const char *path, memory_area_t *map) {
|
msg_t sbElfLoad(vfs_file_node_c *fnp, memory_area_t *map) {
|
||||||
|
elf_load_context_t ctx;
|
||||||
|
elf32_section_header_t sh;
|
||||||
|
unsigned i;
|
||||||
|
msg_t ret;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = init_elf_context(&ctx, &sh, fnp, map);
|
||||||
|
CH_BREAK_ON_ERROR(ret);
|
||||||
|
|
||||||
|
/* Iterating through sections.*/
|
||||||
|
for (i = 0U; i < (unsigned)ctx.shnum; i++) {
|
||||||
|
// char name[8];
|
||||||
|
|
||||||
|
ret = read_section_header(&ctx, &sh, i);
|
||||||
|
CH_BREAK_ON_ERROR(ret);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
ret = read_section_name(&ctx, &sh, name, sizeof name);
|
||||||
|
CH_BREAK_ON_ERROR(ret);
|
||||||
|
|
||||||
|
/* Handling the various sections.*/
|
||||||
|
if (strcmp(name, ".text") == (size_t)0) {
|
||||||
|
ret = load_section(&ctx, &sh, i);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, ".rodata") == (size_t)0) {
|
||||||
|
ret = load_section(&ctx, &sh, i);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, ".data") == (size_t)0) {
|
||||||
|
ret = load_section(&ctx, &sh, i);
|
||||||
|
}
|
||||||
|
else if (strcmp(name, ".bss") == (size_t)0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Sections to be loaded.*/
|
||||||
|
if ((sh.sh_type == SHT_PROGBITS) && ((sh.sh_flags & SHF_ALLOC) != 0U)) {
|
||||||
|
|
||||||
|
/* Loading sections with index greater than 63 is not supported.*/
|
||||||
|
if (i >= 64U) {
|
||||||
|
return CH_RET_ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = load_section(&ctx, &sh);
|
||||||
|
CH_RETURN_ON_ERROR(ret);
|
||||||
|
|
||||||
|
ctx.loaded |= (1ULL << i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections to be relocated, must refer to a loaded section.*/
|
||||||
|
if ((sh.sh_type == SHT_REL) &&
|
||||||
|
((sh.sh_flags & SHF_INFO_LINK) != 0U) &&
|
||||||
|
((ctx.loaded & (1ULL << sh.sh_info)) != 0ULL)) {
|
||||||
|
|
||||||
|
ret = reloc_section(&ctx, &sh);
|
||||||
|
CH_RETURN_ON_ERROR(ret);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (false);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_t sbElfLoadFile(vfs_driver_c *drvp, const char *path, memory_area_t *map) {
|
||||||
vfs_file_node_c *fnp;
|
vfs_file_node_c *fnp;
|
||||||
msg_t ret;
|
msg_t ret;
|
||||||
elf_load_context_t ctx;
|
|
||||||
|
|
||||||
ret = vfsDrvOpenFile(drvp, path, VO_RDONLY, &fnp);
|
ret = vfsDrvOpenFile(drvp, path, VO_RDONLY, &fnp);
|
||||||
CH_RETURN_ON_ERROR(ret);
|
CH_RETURN_ON_ERROR(ret);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = init_elf_context(&ctx, fnp, map);
|
ret = sbElfLoad(fnp, map);
|
||||||
CH_BREAK_ON_ERROR(ret);
|
CH_BREAK_ON_ERROR(ret);
|
||||||
|
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
vfsClose((vfs_node_c *)fnp);
|
vfsClose((vfs_node_c *)fnp);
|
||||||
|
|
||||||
return CH_RET_SUCCESS;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SB_CFG_ENABLE_VFS == TRUE */
|
#endif /* SB_CFG_ENABLE_VFS == TRUE */
|
||||||
|
|
|
@ -57,7 +57,8 @@
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
msg_t sbElfLoad(vfs_driver_c *drvp, const char *path, memory_area_t *map);
|
msg_t sbElfLoad(vfs_file_node_c *fnp, memory_area_t *map);
|
||||||
|
msg_t sbElfLoadFile(vfs_driver_c *drvp, const char *path, memory_area_t *map);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue