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

157 lines
3.9 KiB
C

//---
// 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);
}