diff --git a/src/moduler/elf.c b/src/moduler/elf.c index 82a9156..7fa4c83 100644 --- a/src/moduler/elf.c +++ b/src/moduler/elf.c @@ -1,112 +1,218 @@ #include "elf.h" +#include "logger/logger.h" +#include "types.h" + +#include +#include +#include + +void *hi_elf_load_module(const char *filename) { + int fd = open(filename, O_RDONLY); + + Elf *elf = elf_begin(fd, ELF_C_READ, NULL); + + Elf_Kind modkind = elf_kind(elf); + log_debug("kind: %u\n", modkind); + + uptr modbase = elf_getbase(elf); + + close(fd); + return (void*)modbase; +} + +void hi_elf_print_module_from_memory(void *address, size_t size) { + Elf *elf = elf_memory(address, size); + + int err = elf_errno(); + if (err) { + log_error("%s\n", elf_errmsg(err)); + return; + } + + 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 = address + p->p_vaddr; + void *segment_end = 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); + } + } +} + +#define TYPE_TO_STR(type) \ + case (type): \ + return #type const char *dyn_type_to_str(unsigned type) { - // clang-format off + // clang-format off switch (type) { - case DT_NULL: return "NULL"; - case DT_NEEDED: return "NEEDED"; - case DT_PLTRELSZ: return "PLTRELSZ"; - case DT_PLTGOT: return "PLTGOT"; - case DT_HASH: return "HASH"; - case DT_STRTAB: return "STRTAB"; - case DT_SYMTAB: return "SYMTAB"; - case DT_RELA: return "RELA"; - case DT_RELASZ: return "RELASZ"; - case DT_RELAENT: return "RELAENT"; - case DT_STRSZ: return "STRSZ"; - case DT_SYMENT: return "SYMENT"; - case DT_INIT: return "INIT"; - case DT_FINI: return "FINI"; - case DT_SONAME: return "SONAME"; - case DT_RPATH: return "RPATH"; - case DT_SYMBOLIC: return "SYMBOLIC"; - case DT_REL: return "REL"; - case DT_RELSZ: return "RELSZ"; - case DT_RELENT: return "RELENT"; - case DT_PLTREL: return "PLTREL"; - case DT_DEBUG: return "DEBUG"; - case DT_TEXTREL: return "TEXTREL"; - case DT_JMPREL: return "JMPREL"; - case DT_BIND_NOW: return "BIND_NOW"; - case DT_INIT_ARRAY: return "INIT_ARRAY"; - case DT_FINI_ARRAY: return "FINI_ARRAY"; - case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ"; - case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ"; - case DT_RUNPATH: return "RUNPATH"; - case DT_FLAGS: return "FLAGS"; - case DT_PREINIT_ARRAY: return "ENCODING/PREINIT_ARRAY"; - case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ"; - case DT_SYMTAB_SHNDX: return "SYMTAB_SHNDX"; - case DT_RELRSZ: return "RELRSZ"; - case DT_RELR: return "RELR"; - case DT_RELRENT: return "RELRENT"; - case DT_NUM: return "NUM"; - case DT_LOOS: return "LOOS"; - case DT_HIOS: return "HIOS"; - case DT_LOPROC: return "LOPROC"; - case DT_HIPROC: return "HIPROC"; - case DT_PROCNUM: return "PROCNUM"; - case DT_VALRNGLO: return "VALRNGLO"; - case DT_GNU_PRELINKED: return "GNU_PRELINKED"; - case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ"; - case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ"; - case DT_CHECKSUM: return "CHECKSUM"; - case DT_PLTPADSZ: return "PLTPADSZ"; - case DT_MOVEENT: return "MOVEENT"; - case DT_MOVESZ: return "MOVESZ"; - case DT_FEATURE_1: return "FEATURE_1"; - case DT_POSFLAG_1: return "POSFLAG_1"; - case DT_SYMINSZ: return "SYMINSZ"; - case DT_SYMINENT: return "SYMINENT/VALRNGHI"; - case DT_ADDRRNGLO: return "ADDRRNGLO"; - case DT_GNU_HASH: return "GNU_HASH"; - case DT_TLSDESC_PLT: return "TLSDESC_PLT"; - case DT_TLSDESC_GOT: return "TLSDESC_GOT"; - case DT_GNU_CONFLICT: return "GNU_CONFLICT"; - case DT_GNU_LIBLIST: return "GNU_LIBLIST"; - case DT_CONFIG: return "CONFIG"; - case DT_DEPAUDIT: return "DEPAUDIT"; - case DT_AUDIT: return "AUDIT"; - case DT_PLTPAD: return "PLTPAD"; - case DT_MOVETAB: return "MOVETAB"; - case DT_SYMINFO: return "SYMINFO/ADDRRNGHI"; - case DT_VERSYM: return "VERSYM"; - case DT_RELACOUNT: return "RELACOUNT"; - case DT_RELCOUNT: return "RELCOUNT"; - case DT_FLAGS_1: return "FLAGS_1"; - case DT_VERDEF: return "VERDEF"; - case DT_VERDEFNUM: return "VERDEFNUM"; - case DT_VERNEED: return "VERNEED"; - case DT_VERNEEDNUM: return "VERNEEDNUM"; + TYPE_TO_STR(DT_NULL); + TYPE_TO_STR(DT_NEEDED); + TYPE_TO_STR(DT_PLTRELSZ); + TYPE_TO_STR(DT_PLTGOT); + TYPE_TO_STR(DT_HASH); + TYPE_TO_STR(DT_STRTAB); + TYPE_TO_STR(DT_SYMTAB); + TYPE_TO_STR(DT_RELA); + TYPE_TO_STR(DT_RELASZ); + TYPE_TO_STR(DT_RELAENT); + TYPE_TO_STR(DT_STRSZ); + TYPE_TO_STR(DT_SYMENT); + TYPE_TO_STR(DT_INIT); + TYPE_TO_STR(DT_FINI); + TYPE_TO_STR(DT_SONAME); + TYPE_TO_STR(DT_RPATH); + TYPE_TO_STR(DT_SYMBOLIC); + TYPE_TO_STR(DT_REL); + TYPE_TO_STR(DT_RELSZ); + TYPE_TO_STR(DT_RELENT); + TYPE_TO_STR(DT_PLTREL); + TYPE_TO_STR(DT_DEBUG); + TYPE_TO_STR(DT_TEXTREL); + TYPE_TO_STR(DT_JMPREL); + TYPE_TO_STR(DT_BIND_NOW); + TYPE_TO_STR(DT_INIT_ARRAY); + TYPE_TO_STR(DT_FINI_ARRAY); + TYPE_TO_STR(DT_INIT_ARRAYSZ); + TYPE_TO_STR(DT_FINI_ARRAYSZ); + TYPE_TO_STR(DT_RUNPATH); + TYPE_TO_STR(DT_FLAGS); + TYPE_TO_STR(DT_PREINIT_ARRAY); + TYPE_TO_STR(DT_PREINIT_ARRAYSZ); + TYPE_TO_STR(DT_SYMTAB_SHNDX); + TYPE_TO_STR(DT_RELRSZ); + TYPE_TO_STR(DT_RELR); + TYPE_TO_STR(DT_RELRENT); + TYPE_TO_STR(DT_NUM); + TYPE_TO_STR(DT_LOOS); + TYPE_TO_STR(DT_HIOS); + TYPE_TO_STR(DT_LOPROC); + TYPE_TO_STR(DT_HIPROC); + TYPE_TO_STR(DT_PROCNUM); + TYPE_TO_STR(DT_VALRNGLO); + TYPE_TO_STR(DT_GNU_PRELINKED); + TYPE_TO_STR(DT_GNU_CONFLICTSZ); + TYPE_TO_STR(DT_GNU_LIBLISTSZ); + TYPE_TO_STR(DT_CHECKSUM); + TYPE_TO_STR(DT_PLTPADSZ); + TYPE_TO_STR(DT_MOVEENT); + TYPE_TO_STR(DT_MOVESZ); + TYPE_TO_STR(DT_FEATURE_1); + TYPE_TO_STR(DT_POSFLAG_1); + TYPE_TO_STR(DT_SYMINSZ); + TYPE_TO_STR(DT_SYMINENT); + TYPE_TO_STR(DT_ADDRRNGLO); + TYPE_TO_STR(DT_GNU_HASH); + TYPE_TO_STR(DT_TLSDESC_PLT); + TYPE_TO_STR(DT_TLSDESC_GOT); + TYPE_TO_STR(DT_GNU_CONFLICT); + TYPE_TO_STR(DT_GNU_LIBLIST); + TYPE_TO_STR(DT_CONFIG); + TYPE_TO_STR(DT_DEPAUDIT); + TYPE_TO_STR(DT_AUDIT); + TYPE_TO_STR(DT_PLTPAD); + TYPE_TO_STR(DT_MOVETAB); + TYPE_TO_STR(DT_SYMINFO); + TYPE_TO_STR(DT_VERSYM); + TYPE_TO_STR(DT_RELACOUNT); + TYPE_TO_STR(DT_RELCOUNT); + TYPE_TO_STR(DT_FLAGS_1); + TYPE_TO_STR(DT_VERDEF); + TYPE_TO_STR(DT_VERDEFNUM); + TYPE_TO_STR(DT_VERNEED); + TYPE_TO_STR(DT_VERNEEDNUM); default: return "UNKNOWN"; } - // clang-format on + // clang-format on } const char *segment_type_to_str(unsigned type) { - // clang-format off + // clang-format off switch (type) { - case PT_NULL: return "NULL"; - case PT_LOAD: return "LOAD"; - case PT_DYNAMIC: return "DYNAMIC"; - case PT_INTERP: return "INTERP"; - case PT_NOTE: return "NOTE"; - case PT_SHLIB: return "SHLIB"; - case PT_PHDR: return "PHDR"; - case PT_TLS: return "TLS"; - case PT_NUM: return "NUM"; - case PT_LOOS: return "LOOS"; - case PT_GNU_EH_FRAME: return "GNU_EH_FRAME"; - case PT_GNU_STACK: return "GNU_STACK"; - case PT_GNU_RELRO: return "GNU_RELRO"; - case PT_GNU_PROPERTY: return "GNU_PROPERTY"; - case PT_LOSUNW: return "LOSUNW/SUNWBSS"; - case PT_SUNWSTACK: return "SUNWSTACK"; - case PT_HIOS: return "HIOS"; - case PT_LOPROC: return "LOPROC"; - case PT_HIPROC: return "HIPROC"; + TYPE_TO_STR(PT_NULL); + TYPE_TO_STR(PT_LOAD); + TYPE_TO_STR(PT_DYNAMIC); + TYPE_TO_STR(PT_INTERP); + TYPE_TO_STR(PT_NOTE); + TYPE_TO_STR(PT_SHLIB); + TYPE_TO_STR(PT_PHDR); + TYPE_TO_STR(PT_TLS); + TYPE_TO_STR(PT_NUM); + TYPE_TO_STR(PT_LOOS); + TYPE_TO_STR(PT_GNU_EH_FRAME); + TYPE_TO_STR(PT_GNU_STACK); + TYPE_TO_STR(PT_GNU_RELRO); + TYPE_TO_STR(PT_GNU_PROPERTY); + TYPE_TO_STR(PT_LOSUNW); + TYPE_TO_STR(PT_SUNWSTACK); + TYPE_TO_STR(PT_HIOS); + TYPE_TO_STR(PT_LOPROC); + TYPE_TO_STR(PT_HIPROC); default: return "UNKNOWN"; } - // clang-format on + // clang-format on } + +#undef TYPE_TO_STR diff --git a/src/moduler/elf.h b/src/moduler/elf.h index 9af8937..34e5b72 100644 --- a/src/moduler/elf.h +++ b/src/moduler/elf.h @@ -4,6 +4,9 @@ #include #include +void *hi_elf_load_module(const char* filename); +void hi_elf_print_module_from_memory(void *address, size_t size); + const char *dyn_type_to_str(unsigned type); const char *segment_type_to_str(unsigned type); diff --git a/src/moduler/moduler.c b/src/moduler/moduler.c index 031618d..9a12008 100644 --- a/src/moduler/moduler.c +++ b/src/moduler/moduler.c @@ -5,95 +5,17 @@ #include "moduler/elf.h" #include "types.h" +#include + 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, + MemoryRegionSpan memspan = memory_get_module_span(memregs, module->name); + log_debugv("Module: %s - [%p, %p]\n", module->name, 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); - } - } + void *address = hi_elf_load_module(module->name); + log_debug("modaddress: %p\n", address); module->state = HI_MODULE_STATE_CLEAN; return HILOAD_OK; diff --git a/test/manual/minimal.cpp b/test/manual/minimal.cpp index 8417994..f2f23c0 100644 --- a/test/manual/minimal.cpp +++ b/test/manual/minimal.cpp @@ -17,15 +17,8 @@ int main(int argc, char *argv[]) { int modified = -1; while (modified != 0) { - // printf("==========================\n"); - // printf("main address: %p\n", main); - // printf("minimal_lib::getNewValue address: %p\n", minimal_lib::getNewValue); - // printf("minimal_lib::otherValue address: %p\n", &minimal_lib::otherValue); - // printf("==========================\n"); - // printf(""); - modified = minimal_lib::getNewValue(5); - printf("getModified(5): %d\n", modified); + printf("getNewValue(5): %d\n", modified); std::this_thread::sleep_for(std::chrono::seconds(1)); printf("otherValue: %d\n", minimal_lib::otherValue++);