101 lines
3.2 KiB
C
101 lines
3.2 KiB
C
#include "moduler.h"
|
|
|
|
#include "logger/logger.h"
|
|
#include "memory.h"
|
|
#include "moduler/elf.h"
|
|
#include "types.h"
|
|
|
|
HiloadResult moduler_reload(HiModuleData *module,
|
|
const struct sc_array_memreg *const memregs) {
|
|
|
|
const char *modname = module->name;
|
|
MemoryRegionSpan memspan = memory_get_module_span(memregs, modname);
|
|
log_debugv("Module: %s - [%p, %p]\n", modname, memspan.region_start,
|
|
memspan.region_end);
|
|
|
|
Elf *elf = elf_memory((void *)memspan.region_start,
|
|
memspan.region_end - memspan.region_start);
|
|
int err = elf_errno();
|
|
if (err) {
|
|
log_error("%s\n", elf_errmsg(err));
|
|
return HILOAD_FAIL;
|
|
}
|
|
|
|
/* void *new_handle = dlopen(module->name, RTLD_NOW); */
|
|
/* assert(new_handle != module->dlhandle); */
|
|
void *module_address = (void *)module->address;
|
|
|
|
size_t phdrnum = 0;
|
|
err = elf_getphdrnum(elf, &phdrnum);
|
|
Elf64_Phdr *phdr = elf64_getphdr(elf);
|
|
|
|
for (size_t i = 0; i < phdrnum; ++i) {
|
|
Elf64_Phdr *p = phdr + i;
|
|
log_debugv("segment type: %s\n", segment_type_to_str(p->p_type));
|
|
|
|
size_t segment_size = p->p_memsz;
|
|
void *segment_start = module_address + p->p_vaddr;
|
|
void *segment_end = module_address + p->p_vaddr + segment_size;
|
|
|
|
void *strtab = 0;
|
|
void *symtab = 0;
|
|
size_t strsz = 0;
|
|
size_t syment = 0;
|
|
void *rela = 0;
|
|
size_t relasz = 0;
|
|
size_t relaent = 0;
|
|
size_t relacount = 0;
|
|
void *pltgot = 0;
|
|
size_t pltrelsz = 0;
|
|
void *pltrel = 0;
|
|
|
|
if (p->p_type == PT_DYNAMIC) {
|
|
Elf64_Dyn *dyn = (Elf64_Dyn *)segment_start;
|
|
while ((void *)dyn < segment_end) {
|
|
log_debugv(" dyn type: %s\n", dyn_type_to_str(dyn->d_tag));
|
|
|
|
if (dyn->d_tag == DT_STRTAB) {
|
|
strtab = (void *)dyn->d_un.d_ptr;
|
|
} else if (dyn->d_tag == DT_SYMTAB) {
|
|
symtab = (void *)dyn->d_un.d_ptr;
|
|
} else if (dyn->d_tag == DT_STRSZ) {
|
|
strsz = dyn->d_un.d_val;
|
|
} else if (dyn->d_tag == DT_SYMENT) {
|
|
syment = dyn->d_un.d_val;
|
|
} else if (dyn->d_tag == DT_RELA) {
|
|
rela = (void *)dyn->d_un.d_ptr;
|
|
} else if (dyn->d_tag == DT_RELASZ) {
|
|
relasz = dyn->d_un.d_val;
|
|
} else if (dyn->d_tag == DT_RELAENT) {
|
|
relaent = dyn->d_un.d_val;
|
|
} else if (dyn->d_tag == DT_RELACOUNT) {
|
|
relacount = dyn->d_un.d_val;
|
|
} else if (dyn->d_tag == DT_PLTGOT) {
|
|
pltgot = (void *)dyn->d_un.d_ptr;
|
|
} else if (dyn->d_tag == DT_PLTRELSZ) {
|
|
pltrelsz = dyn->d_un.d_val;
|
|
} else if (dyn->d_tag == DT_PLTREL) {
|
|
pltrel = (void *)dyn->d_un.d_val;
|
|
}
|
|
++dyn;
|
|
}
|
|
log_debugv("\nstrtab: %p\n"
|
|
"symtab: %p\n"
|
|
"strsz: %zu\n"
|
|
"syment: %zu\n"
|
|
"rela: %p\n"
|
|
"relasz: %zu\n"
|
|
"relaent: %zu\n"
|
|
"relacount: %zu\n"
|
|
"pltgot: %p\n"
|
|
"pltrelsz: %zu\n"
|
|
"pltrel: %p\n",
|
|
strtab, symtab, strsz, syment, rela, relasz, relaent,
|
|
relacount, pltgot, pltrelsz, pltrel);
|
|
}
|
|
}
|
|
|
|
module->state = HI_MODULE_STATE_CLEAN;
|
|
return HILOAD_OK;
|
|
}
|