Use AoS for modules instead of SoA
This commit is contained in:
118
src/hiload.c
118
src/hiload.c
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user