vxBoot/src/loader/elf/header.c

170 lines
4.4 KiB
C

#include "vxBoot/terminal.h"
#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"},
{.id = ld_header_size_error, .strerror = "size error"},
{.id = ld_header_magic_error, .strerror = "magic error"},
{.id = ld_header_class_error, .strerror = "class error"},
{.id = ld_header_indent_error, .strerror = "indent error"},
{.id = ld_header_type_error, .strerror = "type error"},
{.id = ld_header_machine_error, .strerror = "machine error"},
{.id = ld_header_version_error, .strerror = "version error"},
{.id = 0xdeb0cad0, .strerror = NULL},
};
/* loader_header_error(): Display header error information */
int loader_header_error(int const errnum)
{
return (loader_error(header_error_db, "ELF header", errnum));
}
/* loader_header_get(): Get ELF header and check validity */
int loader_header_get(
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);
/* Check magic number */
if (header->e_ident[EI_MAG0] != ELFMAG0
|| header->e_ident[EI_MAG1] != ELFMAG1
|| header->e_ident[EI_MAG2] != ELFMAG2
|| header->e_ident[EI_MAG3] != ELFMAG3) {
return (ld_header_magic_error);
}
/* Check class */
if (header->e_ident[EI_CLASS] != ELFCLASS32)
return (ld_header_class_error);
/* Check data encoding */
if (header->e_ident[EI_DATA] != ELFDATA2MSB)
return (ld_header_indent_error);
/* Check ELF type */
if (header->e_type != ET_DYN && header->e_type != ET_EXEC)
return (ld_header_type_error);
/* Check ELF specifique instruction */
if (header->e_machine != EM_SH)
return (ld_header_machine_error);
/* Check ELF version */
if (header->e_version != EV_CURRENT)
return (ld_header_version_error);
return (ld_header_valid);
}
/* hypervisor_elf_loader_header_check():
Check ELF header validity and dump usefull sections information */
int loader_header_check(struct kernel * const kernel)
{
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);
}