fxBoot/src/hypervisor/internal/elf/reloc.c

61 lines
1.5 KiB
C

//---
// fxBoot:loader:entry - ELF Loader entry
//---
#include "fxBoot/hypervisor.h"
#include "fxBoot/fs/smemfs.h"
#include "fxBoot/elf.h"
#include "./src/hypervisor/internal/elf.h"
//---
// Internal helpers
//---
/* reloc_section(): Relocalise section's symbols */
static int reloc_section(struct hworld *world,
struct smemfs_inode *inode, Elf32_Shdr *shdr)
{
Elf32_Rela rela;
uint32_t *prog;
off_t offset;
/* List symbols */
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)
!= (ssize_t)shdr->sh_entsize) {
return (hel_reloc_size_error);
}
/* Relocalise the symbol */
prog[rela.r_offset >> 2] +=
(uintptr_t)world->memory.program.start;
}
return (hel_reloc_success);
}
//---
// Public helpers
//---
/* loader_reloc_sym(): Relocalise all symbols */
int hypervisor_elf_loader_reloc_sym(struct hworld *world,
struct smemfs_inode *inode, Elf32_Ehdr *header)
{
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) {
return (hel_reloc_size_error);
}
if (shdr.sh_type != SHT_RELA)
continue;
if (reloc_section(world, inode, &shdr) != hel_reloc_success)
return (hel_reloc_error);
}
return (hel_reloc_success);
}