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_memreg memory_regions;
|
||||||
struct sc_array_str enabled_modules;
|
struct sc_array_str enabled_modules;
|
||||||
struct hiFileWatcher *filewatcher;
|
struct hiFileWatcher *filewatcher;
|
||||||
ModuleInfos *loaded_modules;
|
HiModuleArray modules;
|
||||||
} HiloadContext;
|
} HiloadContext;
|
||||||
|
|
||||||
static HiloadContext context = {0};
|
static HiloadContext context = {0};
|
||||||
|
|
||||||
// Callback function for dl_iterate_phdr
|
// 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) {
|
void *data) {
|
||||||
|
|
||||||
ModuleInfos *mod_infos = (ModuleInfos *)data;
|
// '' for executable, fname for rest
|
||||||
|
|
||||||
const char *modname = info->dlpi_name;
|
const char *modname = info->dlpi_name;
|
||||||
|
|
||||||
log_info("Processing: '%s'\n", 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
|
// Try to get the handle
|
||||||
void *handle = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD);
|
void *handle = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD);
|
||||||
assert(handle);
|
assert(handle);
|
||||||
mod_infos->count++;
|
|
||||||
|
|
||||||
sc_array_add(&mod_infos->handles, handle);
|
HiModuleData module = {0};
|
||||||
sc_array_add(&mod_infos->addresses, info->dlpi_addr);
|
module.address = info->dlpi_addr;
|
||||||
|
|
||||||
log_debugv(" header 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_addr: %p\n", info->dlpi_addr);
|
||||||
log_debugv(" dlpi_tls_modid: %zu\n", info->dlpi_tls_modid);
|
log_debugv(" dlpi_tls_modid: %zu\n", info->dlpi_tls_modid);
|
||||||
log_debugv(" dlpi_tls_data: %p\n", info->dlpi_tls_data);
|
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,
|
// Store the full name. Differs from dlpi_name for the executable only,
|
||||||
// afaik
|
// afaik
|
||||||
const char *modpath = dl_info.dli_fname;
|
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_fname: %s\n", dl_info.dli_fname);
|
||||||
log_debugv("dli_sname: %s\n", dl_info.dli_sname);
|
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))) {
|
sc_array_at(&context.enabled_modules, i))) {
|
||||||
|
|
||||||
// Replace shortform with str pointer from module info
|
// Replace shortform with str pointer from module info
|
||||||
sc_array_at(&context.enabled_modules, i) =
|
sc_array_at(&context.enabled_modules, i) = module.name;
|
||||||
sc_array_last(&mod_infos->names);
|
|
||||||
|
|
||||||
// Add filewatcher
|
// Add filewatcher
|
||||||
if (!HILOADRES(hi_file_watcher_add(context.filewatcher, modpath,
|
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 {
|
} else {
|
||||||
sc_array_add(&mod_infos->names, strdup(modname));
|
module.name = strdup(modname);
|
||||||
log_error("Couldn't load dlinfo for %s: %s\n",
|
log_error("Couldn't load dlinfo for %s: %s\n", module.name, dlerror());
|
||||||
(sc_array_last(&mod_infos->names)), dlerror());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HiModuleArray *modules = (HiModuleArray *)data;
|
||||||
|
sc_array_add(modules, module);
|
||||||
|
|
||||||
return 0; // Continue iteration
|
return 0; // Continue iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
static void module_infos_free(ModuleInfos *modules) {
|
static void module_infos_free(HiModuleArray *modules) {
|
||||||
if (!modules)
|
if (!modules)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (size_t i = 0; i < modules->count; i++) {
|
for (size_t i = 0; i < sc_array_size(modules); i++) {
|
||||||
// Free char* before clearing the array
|
free((char*)sc_array_at(modules, i).name);
|
||||||
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)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_array_term(&modules->names);
|
|
||||||
sc_array_term(&modules->handles);
|
|
||||||
sc_array_term(&modules->symbols);
|
|
||||||
free(modules);
|
free(modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ModuleInfos *gather_module_infos(void) {
|
HiloadResult gather_module_infos(HiModuleArray *modules) {
|
||||||
ModuleInfos *result = NULL;
|
|
||||||
|
|
||||||
// Allocate the result structure
|
sc_array_init(modules);
|
||||||
result = calloc(1, sizeof(ModuleInfos));
|
|
||||||
if (!result) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over all loaded shared objects
|
// 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
|
// Error occurred in callback
|
||||||
module_infos_free(result);
|
module_infos_free(modules);
|
||||||
return NULL;
|
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++) {
|
for (size_t i = 0; i < sc_array_size(modules); i++) {
|
||||||
const char *name = sc_array_at(&modinfos->names, i);
|
HiModuleData *module = &sc_array_at(modules, i);
|
||||||
|
const char *name = module->name;
|
||||||
if (strcmp(name, path) == 0) {
|
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.
|
* 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);
|
hiFileEvent event = hi_file_event_pop(fw);
|
||||||
while (event.type != HI_FILE_NONE) {
|
while (event.type != HI_FILE_NONE) {
|
||||||
log_debug("Event pop: %s – %s\n", event.pathname,
|
log_debug("Event pop: %s – %s\n", event.pathname,
|
||||||
hi_file_watch_type_to_str(event.type));
|
hi_file_watch_type_to_str(event.type));
|
||||||
|
|
||||||
i32 index = get_module_index_by_path(event.pathname, modinfos);
|
HiModuleData *module = get_module_by_path(event.pathname, modules);
|
||||||
if (index < 0) {
|
if (!module) {
|
||||||
log_warn("Watched module: %s not found.\n", event.pathname);
|
log_warn("Watched module: %s not found.\n", event.pathname);
|
||||||
} else {
|
} else {
|
||||||
context.loaded_modules->state[index] = HI_MODULE_STATE_DIRTY;
|
module->state = HI_MODULE_STATE_DIRTY;
|
||||||
}
|
}
|
||||||
event = hi_file_event_pop(context.filewatcher);
|
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) {
|
const struct sc_array_str *haystack) {
|
||||||
i32 index = -1;
|
|
||||||
for (size_t i = 0; i < sc_array_size(haystack); i++) {
|
for (size_t i = 0; i < sc_array_size(haystack); i++) {
|
||||||
if (strcmp(needle, sc_array_at(haystack, i)) == 0) {
|
if (strcmp(needle, sc_array_at(haystack, i)) == 0) {
|
||||||
index = i;
|
return sc_array_at(haystack, i);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return index;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HiloadResult reload_dirty_modules(HiloadContext *context) {
|
static HiloadResult reload_dirty_modules(HiloadContext *context) {
|
||||||
|
|
||||||
HiloadResult ret = HILOAD_OK;
|
HiloadResult ret = HILOAD_OK;
|
||||||
for (u8 i = 0; i < context->loaded_modules->count; i++) {
|
for (u8 i = 0; i < sc_array_size(&context->modules); i++) {
|
||||||
const char *module_name = sc_array_at(&context->loaded_modules->names, i);
|
HiModuleData *module = &sc_array_at(&context->modules, i);
|
||||||
|
|
||||||
// Operate on dirty modules only
|
// 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
|
// Operate only if the module is marked as operatable
|
||||||
i32 module_index =
|
const char *module_name = find_string_from_array(module->name, &context->enabled_modules);
|
||||||
get_string_index(module_name, &context->enabled_modules);
|
if (module_name) {
|
||||||
if (module_index != -1) {
|
|
||||||
log_info("Reloading %s...\n", module_name);
|
log_info("Reloading %s...\n", module_name);
|
||||||
|
|
||||||
if (moduler_reload(context->loaded_modules, &context->memory_regions,
|
if (moduler_reload(module, &context->memory_regions) != HILOAD_OK) {
|
||||||
i) != HILOAD_OK) {
|
|
||||||
ret = HILOAD_FAIL;
|
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() {
|
HiloadResult hi_reload() {
|
||||||
|
|
||||||
handle_events(context.filewatcher, context.loaded_modules);
|
handle_events(context.filewatcher, &context.modules);
|
||||||
reload_dirty_modules(&context);
|
reload_dirty_modules(&context);
|
||||||
return HILOAD_OK;
|
return HILOAD_OK;
|
||||||
}
|
}
|
||||||
@@ -231,23 +215,17 @@ int hi_init(unsigned n, const char **enabled_modules) {
|
|||||||
return HILOAD_FAIL;
|
return HILOAD_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleInfos *infos = gather_module_infos();
|
HiloadResult re = gather_module_infos(&context.modules);
|
||||||
if (!infos) {
|
if (re == HILOAD_OK) {
|
||||||
log_error("Failed to gather module infos.\n");
|
log_error("Failed to gather module infos.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override existing
|
|
||||||
if (context.loaded_modules) {
|
|
||||||
module_infos_free(context.loaded_modules);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.loaded_modules = infos;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hi_deinit() {
|
void hi_deinit() {
|
||||||
module_infos_free(context.loaded_modules);
|
module_infos_free(&context.modules);
|
||||||
hi_file_watcher_destroy(context.filewatcher);
|
hi_file_watcher_destroy(context.filewatcher);
|
||||||
log_term();
|
log_term();
|
||||||
memset(&context, 0, sizeof(context));
|
memset(&context, 0, sizeof(context));
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
_Atomic bool hiload_verbose_log = true;
|
_Atomic bool hiload_verbose_log = false;
|
||||||
|
|
||||||
void log_set_verbose(bool value) {
|
void log_set_verbose(bool value) {
|
||||||
atomic_store_explicit(&hiload_verbose_log, value, memory_order_relaxed);
|
atomic_store_explicit(&hiload_verbose_log, value, memory_order_relaxed);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define ELF_H_
|
#define ELF_H_
|
||||||
|
|
||||||
#include <libelf.h>
|
#include <libelf.h>
|
||||||
|
#include <gelf.h>
|
||||||
|
|
||||||
const char *dyn_type_to_str(unsigned type);
|
const char *dyn_type_to_str(unsigned type);
|
||||||
const char *segment_type_to_str(unsigned type);
|
const char *segment_type_to_str(unsigned type);
|
||||||
|
|||||||
@@ -4,11 +4,12 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "moduler/elf.h"
|
#include "moduler/elf.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include <libelf.h>
|
||||||
|
|
||||||
HiloadResult moduler_reload(ModuleInfos *modinfos,
|
HiloadResult moduler_reload(HiModuleData *module,
|
||||||
const struct sc_array_memreg *const memregs,
|
const struct sc_array_memreg *const memregs) {
|
||||||
int modindex) {
|
|
||||||
const char *modname = sc_array_at(&modinfos->names, modindex);
|
const char *modname = module->name;
|
||||||
MemoryRegionSpan memspan = memory_get_module_span(memregs, modname);
|
MemoryRegionSpan memspan = memory_get_module_span(memregs, modname);
|
||||||
log_debugv("Module: %s - [%p, %p]\n", modname, memspan.region_start,
|
log_debugv("Module: %s - [%p, %p]\n", modname, memspan.region_start,
|
||||||
memspan.region_end);
|
memspan.region_end);
|
||||||
@@ -18,9 +19,10 @@ HiloadResult moduler_reload(ModuleInfos *modinfos,
|
|||||||
int err = elf_errno();
|
int err = elf_errno();
|
||||||
if (err) {
|
if (err) {
|
||||||
log_error("%s\n", elf_errmsg(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;
|
size_t phdrnum = 0;
|
||||||
err = elf_getphdrnum(elf, &phdrnum);
|
err = elf_getphdrnum(elf, &phdrnum);
|
||||||
@@ -76,7 +78,7 @@ HiloadResult moduler_reload(ModuleInfos *modinfos,
|
|||||||
}
|
}
|
||||||
++dyn;
|
++dyn;
|
||||||
}
|
}
|
||||||
printf("strtab: %p\n"
|
log_debugv("\nstrtab: %p\n"
|
||||||
"symtab: %p\n"
|
"symtab: %p\n"
|
||||||
"strsz: %zu\n"
|
"strsz: %zu\n"
|
||||||
"syment: %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;
|
return HILOAD_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,24 +8,22 @@
|
|||||||
|
|
||||||
struct HiloadContext;
|
struct HiloadContext;
|
||||||
|
|
||||||
sc_array_def(uptr, uptr);
|
|
||||||
|
|
||||||
enum HiModuleState {
|
enum HiModuleState {
|
||||||
HI_MODULE_STATE_CLEAN = 0,
|
HI_MODULE_STATE_CLEAN = 0,
|
||||||
HI_MODULE_STATE_DIRTY,
|
HI_MODULE_STATE_DIRTY,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct sc_array_str names; // Array of library names
|
const char *name; // Filename if found
|
||||||
struct sc_array_ptr handles; // Array of library handles
|
uptr address;
|
||||||
struct sc_array_uptr addresses; // Array of library base addresses
|
u8 state;
|
||||||
struct sc_array_syms symbols; // Symbol info for modules
|
} HiModuleData;
|
||||||
u8 state[256]; // Flag for when module needs to be changed
|
sc_array_def(HiModuleData, module);
|
||||||
size_t count; // Number of modules
|
|
||||||
} ModuleInfos;
|
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_
|
#endif // MODULER_H_
|
||||||
|
|||||||
Reference in New Issue
Block a user