From 54b9ec74044010b6677a95b9499352e4067c1609 Mon Sep 17 00:00:00 2001 From: Kasper Date: Mon, 14 Apr 2025 00:56:41 +0300 Subject: [PATCH] gather information about module.. again --- CMakeLists.txt | 6 ++-- src/hiload.c | 28 +++------------ src/logger/logger.c | 2 +- src/memory.c | 33 ++++++++++++++--- src/memory.h | 8 +++++ src/moduler/elf.c | 3 ++ src/moduler/elf.h | 84 +++++++++++++++++++++++++++++++++++++++++++ src/moduler/moduler.c | 48 +++++++++++++++++++++++++ src/moduler/moduler.h | 31 ++++++++++++++++ src/symbols.c | 4 --- 10 files changed, 212 insertions(+), 35 deletions(-) create mode 100644 src/moduler/elf.c create mode 100644 src/moduler/elf.h create mode 100644 src/moduler/moduler.c create mode 100644 src/moduler/moduler.h diff --git a/CMakeLists.txt b/CMakeLists.txt index db1a3d4..c146dd0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,8 +45,10 @@ add_library(hiload SHARED src/symbols.c src/files.c src/memory.c - src/string/string.c src/logger/logger.c + src/moduler/moduler.c + src/moduler/elf.c + src/string/string.c src/filewatcher/filewatcher.c src/filewatcher/filewatch.c @@ -61,7 +63,7 @@ target_compile_options(hiload PRIVATE $<$:-Wno-declaration-after-statement -Wno-padded> ) -target_link_libraries(hiload dl) +target_link_libraries(hiload dl elf) # Specify the public headers location target_include_directories(hiload PUBLIC diff --git a/src/hiload.c b/src/hiload.c index 5396484..bb802b5 100644 --- a/src/hiload.c +++ b/src/hiload.c @@ -5,6 +5,7 @@ #include "filewatcher/filewatcher.h" #include "logger/logger.h" #include "memory.h" +#include "moduler/moduler.h" #include "string/string.h" #include "symbols.h" #include "types.h" @@ -18,22 +19,6 @@ #include #include -sc_array_def(uptr, uptr); - -enum HiModuleState { - HI_MODULE_STATE_CLEAN = 0, - HI_MODULE_STATE_DIRTY, -}; - -typedef struct { - struct sc_array_str names; // Array of library names - struct sc_array_ptr handles; // Array of library handles - struct sc_array_uptr addresses; // Array of library base addresses - struct sc_array_syms symbols; // Symbol info for modules - u8 state[256]; // Flag for when module needs to be changed - size_t count; // Number of modules -} ModuleInfos; - typedef struct { struct sc_array_memreg memory_regions; struct sc_array_str enabled_modules; @@ -60,7 +45,7 @@ static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size, sc_array_add(&mod_infos->handles, handle); sc_array_add(&mod_infos->addresses, info->dlpi_addr); - log_debugv(" size: %u\n", size); + log_debugv(" header size: %u\n", size); log_debugv(" handle: %p\n", sc_array_last(&mod_infos->handles)); log_debugv(" dlpi_addr: %p\n", info->dlpi_addr); log_debugv(" dlpi_tls_modid: %zu\n", info->dlpi_tls_modid); @@ -190,12 +175,6 @@ static i32 get_string_index(const char *needle, return index; } -static HiloadResult reload_module(ModuleInfos *modinfos, u8 modindex) { - - modinfos->state[modindex] = HI_MODULE_STATE_CLEAN; - return HILOAD_OK; -} - static HiloadResult reload_dirty_modules(HiloadContext *context) { HiloadResult ret = HILOAD_OK; @@ -211,7 +190,8 @@ static HiloadResult reload_dirty_modules(HiloadContext *context) { if (module_index != -1) { log_info("Reloading %s...\n", module_name); - if (reload_module(context->loaded_modules, i) != HILOAD_OK) { + if (moduler_reload(context->loaded_modules, &context->memory_regions, + i) != HILOAD_OK) { ret = HILOAD_FAIL; log_error("Failed loading: %s\n", module_name); } diff --git a/src/logger/logger.c b/src/logger/logger.c index 2f90021..6ad72bf 100644 --- a/src/logger/logger.c +++ b/src/logger/logger.c @@ -2,7 +2,7 @@ #include -_Atomic bool hiload_verbose_log = false; +_Atomic bool hiload_verbose_log = true; void log_set_verbose(bool value) { atomic_store_explicit(&hiload_verbose_log, value, memory_order_relaxed); diff --git a/src/memory.c b/src/memory.c index 532f053..c1a4809 100644 --- a/src/memory.c +++ b/src/memory.c @@ -9,9 +9,8 @@ static inline int ptr_in_range(uptr ptr, uptr start, uptr end) { return ptr >= start && ptr <= end; } -HiloadResult memory_find_pointer(uptr ptr, - struct sc_array_memreg *const regions, - size_t *index) { +HiloadResult memory_find_region(uptr ptr, struct sc_array_memreg *const regions, + size_t *index) { for (size_t i = 0; i < sc_array_size(regions); i++) { uptr start = regions->elems[i].region_start; // we assume a sorted region by start address, so we can do a quick discard @@ -35,7 +34,7 @@ HiloadResult read_memory_maps_self(struct sc_array_memreg *regions) { sc_array_clear(regions); sc_array_init(regions); - char* maps_str = hi_file_to_str_dyn("/proc/self/maps"); + char *maps_str = hi_file_to_str_dyn("/proc/self/maps"); if (!maps_str) return HILOAD_FAIL; @@ -85,3 +84,29 @@ HiloadResult read_memory_maps_self(struct sc_array_memreg *regions) { return HILOAD_OK; } + +MemoryRegionSpan +memory_get_module_span(const struct sc_array_memreg *const regions, + const char module_name[static 1]) { + uptr start = ~0ull; + uptr end = 0; + for (size_t i = 0; i < sc_array_size(regions); i++) { + + const MemoryRegion *reg = &sc_array_at(regions, i); + + if (reg->pathname && strcmp(reg->pathname, module_name) == 0) { + if (reg->region_start < start) { + start = reg->region_start; + } + if (reg->region_end > end) { + end = reg->region_end; + } + } else { + // we passed the module regions + if (end > 0) break; + } + } + + assert(start < ~0ull && end > 0); + return (MemoryRegionSpan){.region_start = start, .region_end = end}; +} diff --git a/src/memory.h b/src/memory.h index 4406430..bf4a042 100644 --- a/src/memory.h +++ b/src/memory.h @@ -14,6 +14,11 @@ typedef enum { HI_MEMORY_PRIVATE = 1 << 4 } MemoryPermissions; +typedef struct { + uptr region_start; + uptr region_end; +} MemoryRegionSpan; + typedef struct { uptr region_start; uptr region_end; @@ -34,4 +39,7 @@ HiloadResult memory_find_pointer(uptr ptr, struct sc_array_memreg *const regions, size_t *index); +MemoryRegionSpan memory_get_module_span(const struct sc_array_memreg *const regions, + const char module_name[static 1]); + #endif // MEMORY_H_ diff --git a/src/moduler/elf.c b/src/moduler/elf.c new file mode 100644 index 0000000..edc3a4e --- /dev/null +++ b/src/moduler/elf.c @@ -0,0 +1,3 @@ +#include "elf.h" + +#include diff --git a/src/moduler/elf.h b/src/moduler/elf.h new file mode 100644 index 0000000..63b83eb --- /dev/null +++ b/src/moduler/elf.h @@ -0,0 +1,84 @@ +#ifndef ELF_H_ +#define ELF_H_ + +#include + +static inline const char *dyn_type_to_str(unsigned type) { + // 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"; + default: return "UNKNOWN"; + } + // clang-format on +} + +static inline const char *segment_type_to_str(unsigned type) { + // 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"; + default: return "UNKNOWN"; + } + // clang-format on +} + +#endif diff --git a/src/moduler/moduler.c b/src/moduler/moduler.c new file mode 100644 index 0000000..a2332c2 --- /dev/null +++ b/src/moduler/moduler.c @@ -0,0 +1,48 @@ +#include "moduler.h" + +#include "logger/logger.h" +#include "moduler/elf.h" +#include "memory.h" +#include "types.h" + +HiloadResult moduler_reload(ModuleInfos *modinfos, + const struct sc_array_memreg *const memregs, + int modindex) { + const char *modname = sc_array_at(&modinfos->names, modindex); + 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)); + } + + void *module_address = (void*)sc_array_at(&modinfos->addresses, modindex); + + 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; + + 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)); + ++dyn; + } + } + } + + modinfos->state[modindex] = HI_MODULE_STATE_CLEAN; + return HILOAD_OK; +} diff --git a/src/moduler/moduler.h b/src/moduler/moduler.h new file mode 100644 index 0000000..be491dc --- /dev/null +++ b/src/moduler/moduler.h @@ -0,0 +1,31 @@ +#ifndef MODULER_H_ +#define MODULER_H_ + +#include "array/array.h" +#include "memory.h" +#include "symbols.h" +#include "types.h" + +struct HiloadContext; + +sc_array_def(uptr, uptr); + +enum HiModuleState { + HI_MODULE_STATE_CLEAN = 0, + HI_MODULE_STATE_DIRTY, +}; + +typedef struct { + struct sc_array_str names; // Array of library names + struct sc_array_ptr handles; // Array of library handles + struct sc_array_uptr addresses; // Array of library base addresses + struct sc_array_syms symbols; // Symbol info for modules + u8 state[256]; // Flag for when module needs to be changed + size_t count; // Number of modules +} ModuleInfos; + +HiloadResult moduler_reload(ModuleInfos *modinfos, + const struct sc_array_memreg *const memregs, + int modindex); + +#endif // MODULER_H_ diff --git a/src/symbols.c b/src/symbols.c index 70d6780..957bddf 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -4,11 +4,7 @@ void hi_free_symbol_info(SymbolInfos *symbols) { for (size_t i = 0; i < symbols->names.size; i++) { - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" free((void *)symbols->names.elems[i]); -#pragma GCC diagnostic pop } sc_array_term(&symbols->names);