Use AoS for modules instead of SoA

This commit is contained in:
2025-04-18 14:39:09 +03:00
parent dcf863bf26
commit 09d5020494
5 changed files with 70 additions and 91 deletions

View File

@@ -23,17 +23,16 @@ typedef struct {
struct sc_array_memreg memory_regions;
struct sc_array_str enabled_modules;
struct hiFileWatcher *filewatcher;
ModuleInfos *loaded_modules;
HiModuleArray modules;
} HiloadContext;
static HiloadContext context = {0};
// Callback function for dl_iterate_phdr
static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size,
static int gather_module_data_callback(struct dl_phdr_info *info, size_t size,
void *data) {
ModuleInfos *mod_infos = (ModuleInfos *)data;
// '' for executable, fname for rest
const char *modname = info->dlpi_name;
log_info("Processing: '%s'\n", info->dlpi_name);
@@ -41,12 +40,11 @@ static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size,
// Try to get the handle
void *handle = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD);
assert(handle);
mod_infos->count++;
sc_array_add(&mod_infos->handles, handle);
sc_array_add(&mod_infos->addresses, info->dlpi_addr);
HiModuleData module = {0};
module.address = info->dlpi_addr;
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);
log_debugv(" dlpi_tls_data: %p\n", info->dlpi_tls_data);
@@ -57,7 +55,7 @@ static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size,
// Store the full name. Differs from dlpi_name for the executable only,
// afaik
const char *modpath = dl_info.dli_fname;
sc_array_add(&mod_infos->names, strdup(modpath));
module.name = strdup(modpath);
log_debugv("dli_fname: %s\n", dl_info.dli_fname);
log_debugv("dli_sname: %s\n", dl_info.dli_sname);
@@ -69,8 +67,7 @@ static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size,
sc_array_at(&context.enabled_modules, i))) {
// Replace shortform with str pointer from module info
sc_array_at(&context.enabled_modules, i) =
sc_array_last(&mod_infos->names);
sc_array_at(&context.enabled_modules, i) = module.name;
// Add filewatcher
if (!HILOADRES(hi_file_watcher_add(context.filewatcher, modpath,
@@ -82,62 +79,51 @@ static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size,
}
}
} else {
sc_array_add(&mod_infos->names, strdup(modname));
log_error("Couldn't load dlinfo for %s: %s\n",
(sc_array_last(&mod_infos->names)), dlerror());
module.name = strdup(modname);
log_error("Couldn't load dlinfo for %s: %s\n", module.name, dlerror());
}
HiModuleArray *modules = (HiModuleArray *)data;
sc_array_add(modules, module);
return 0; // Continue iteration
}
static void module_infos_free(ModuleInfos *modules) {
static void module_infos_free(HiModuleArray *modules) {
if (!modules)
return;
for (size_t i = 0; i < modules->count; i++) {
// Free char* before clearing the array
const char *n = 0;
sc_array_foreach(&modules->names, n) { free((char *)n); }
sc_array_term(&modules->names);
// Use a destructor for the symbolinfos
hi_free_symbol_info(&(sc_array_at(&modules->symbols, i)));
for (size_t i = 0; i < sc_array_size(modules); i++) {
free((char*)sc_array_at(modules, i).name);
}
sc_array_term(&modules->names);
sc_array_term(&modules->handles);
sc_array_term(&modules->symbols);
free(modules);
}
static ModuleInfos *gather_module_infos(void) {
ModuleInfos *result = NULL;
HiloadResult gather_module_infos(HiModuleArray *modules) {
// Allocate the result structure
result = calloc(1, sizeof(ModuleInfos));
if (!result) {
return NULL;
}
sc_array_init(modules);
// Iterate over all loaded shared objects
if (dl_iterate_phdr(gather_module_infos_callback, result) != 0) {
if (dl_iterate_phdr(gather_module_data_callback, modules) != 0) {
// Error occurred in callback
module_infos_free(result);
return NULL;
module_infos_free(modules);
return HILOAD_FAIL;
}
return result;
return HILOAD_OK;
}
static i32 get_module_index_by_path(const char *path, ModuleInfos *modinfos) {
static HiModuleData *get_module_by_path(const char *path, HiModuleArray *modules) {
for (size_t i = 0; i < modinfos->count; i++) {
const char *name = sc_array_at(&modinfos->names, i);
for (size_t i = 0; i < sc_array_size(modules); i++) {
HiModuleData *module = &sc_array_at(modules, i);
const char *name = module->name;
if (strcmp(name, path) == 0) {
return i;
return module;
}
}
return -1;
return NULL;
}
/**
@@ -145,56 +131,54 @@ static i32 get_module_index_by_path(const char *path, ModuleInfos *modinfos) {
*
* Marks a module dirty if there has been any event.
*/
static void handle_events(struct hiFileWatcher *fw, ModuleInfos *modinfos) {
static void handle_events(struct hiFileWatcher *fw, HiModuleArray *modules) {
hiFileEvent event = hi_file_event_pop(fw);
while (event.type != HI_FILE_NONE) {
log_debug("Event pop: %s %s\n", event.pathname,
hi_file_watch_type_to_str(event.type));
i32 index = get_module_index_by_path(event.pathname, modinfos);
if (index < 0) {
HiModuleData *module = get_module_by_path(event.pathname, modules);
if (!module) {
log_warn("Watched module: %s not found.\n", event.pathname);
} else {
context.loaded_modules->state[index] = HI_MODULE_STATE_DIRTY;
module->state = HI_MODULE_STATE_DIRTY;
}
event = hi_file_event_pop(context.filewatcher);
}
}
static i32 get_string_index(const char *needle,
static const char* find_string_from_array(const char *needle,
const struct sc_array_str *haystack) {
i32 index = -1;
for (size_t i = 0; i < sc_array_size(haystack); i++) {
if (strcmp(needle, sc_array_at(haystack, i)) == 0) {
index = i;
break;
return sc_array_at(haystack, i);
}
}
return index;
return NULL;
}
static HiloadResult reload_dirty_modules(HiloadContext *context) {
HiloadResult ret = HILOAD_OK;
for (u8 i = 0; i < context->loaded_modules->count; i++) {
const char *module_name = sc_array_at(&context->loaded_modules->names, i);
for (u8 i = 0; i < sc_array_size(&context->modules); i++) {
HiModuleData *module = &sc_array_at(&context->modules, i);
// Operate on dirty modules only
if (context->loaded_modules->state[i] == HI_MODULE_STATE_DIRTY) {
if (module->state == HI_MODULE_STATE_DIRTY) {
// Operate only if the module is marked as operatable
i32 module_index =
get_string_index(module_name, &context->enabled_modules);
if (module_index != -1) {
const char *module_name = find_string_from_array(module->name, &context->enabled_modules);
if (module_name) {
log_info("Reloading %s...\n", module_name);
if (moduler_reload(context->loaded_modules, &context->memory_regions,
i) != HILOAD_OK) {
if (moduler_reload(module, &context->memory_regions) != HILOAD_OK) {
ret = HILOAD_FAIL;
log_error("Failed loading: %s\n", module_name);
log_error("Failed loading: %s\n", module->name);
}
log_info("Reloaded\n");
}
}
}
@@ -203,7 +187,7 @@ static HiloadResult reload_dirty_modules(HiloadContext *context) {
HiloadResult hi_reload() {
handle_events(context.filewatcher, context.loaded_modules);
handle_events(context.filewatcher, &context.modules);
reload_dirty_modules(&context);
return HILOAD_OK;
}
@@ -231,23 +215,17 @@ int hi_init(unsigned n, const char **enabled_modules) {
return HILOAD_FAIL;
}
ModuleInfos *infos = gather_module_infos();
if (!infos) {
HiloadResult re = gather_module_infos(&context.modules);
if (re == HILOAD_OK) {
log_error("Failed to gather module infos.\n");
return 1;
}
// Override existing
if (context.loaded_modules) {
module_infos_free(context.loaded_modules);
}
context.loaded_modules = infos;
return 0;
}
void hi_deinit() {
module_infos_free(context.loaded_modules);
module_infos_free(&context.modules);
hi_file_watcher_destroy(context.filewatcher);
log_term();
memset(&context, 0, sizeof(context));

View File

@@ -2,7 +2,7 @@
#include <stdatomic.h>
_Atomic bool hiload_verbose_log = true;
_Atomic bool hiload_verbose_log = false;
void log_set_verbose(bool value) {
atomic_store_explicit(&hiload_verbose_log, value, memory_order_relaxed);

View File

@@ -2,6 +2,7 @@
#define ELF_H_
#include <libelf.h>
#include <gelf.h>
const char *dyn_type_to_str(unsigned type);
const char *segment_type_to_str(unsigned type);

View File

@@ -4,11 +4,12 @@
#include "memory.h"
#include "moduler/elf.h"
#include "types.h"
#include <libelf.h>
HiloadResult moduler_reload(ModuleInfos *modinfos,
const struct sc_array_memreg *const memregs,
int modindex) {
const char *modname = sc_array_at(&modinfos->names, modindex);
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);
@@ -18,9 +19,10 @@ HiloadResult moduler_reload(ModuleInfos *modinfos,
int err = elf_errno();
if (err) {
log_error("%s\n", elf_errmsg(err));
return HILOAD_FAIL;
}
void *module_address = (void *)sc_array_at(&modinfos->addresses, modindex);
void *module_address = (void *)module->address;
size_t phdrnum = 0;
err = elf_getphdrnum(elf, &phdrnum);
@@ -76,7 +78,7 @@ HiloadResult moduler_reload(ModuleInfos *modinfos,
}
++dyn;
}
printf("strtab: %p\n"
log_debugv("\nstrtab: %p\n"
"symtab: %p\n"
"strsz: %zu\n"
"syment: %zu\n"
@@ -94,6 +96,6 @@ HiloadResult moduler_reload(ModuleInfos *modinfos,
}
modinfos->state[modindex] = HI_MODULE_STATE_CLEAN;
module->state = HI_MODULE_STATE_CLEAN;
return HILOAD_OK;
}

View File

@@ -8,24 +8,22 @@
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;
const char *name; // Filename if found
uptr address;
u8 state;
} HiModuleData;
sc_array_def(HiModuleData, module);
typedef struct sc_array_module HiModuleArray;
HiloadResult moduler_reload(HiModuleData *module,
const struct sc_array_memreg *const memregs);
HiloadResult moduler_reload(ModuleInfos *modinfos,
const struct sc_array_memreg *const memregs,
int modindex);
#endif // MODULER_H_