Create a new patch file for each patch and close old handle

This stopped a few misbehaviours
This commit is contained in:
2025-04-30 23:44:10 +03:00
parent 7d2ac662d0
commit 466aac142c
5 changed files with 63 additions and 25 deletions

View File

@@ -19,8 +19,15 @@
#include <stdalign.h> #include <stdalign.h>
#include <stdbool.h> #include <stdbool.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
typedef struct {
const char *filename;
void *dlhandle;
MemoryRegionSpan memreg;
} PatchData;
static void *adjust_if_relative(void *ptr, void *module_base) { static void *adjust_if_relative(void *ptr, void *module_base) {
uptr p = (uptr)ptr; uptr p = (uptr)ptr;
if (p && (p < (uptr)module_base)) { if (p && (p < (uptr)module_base)) {
@@ -131,8 +138,8 @@ static HiloadResult gather_patchable_symbols(struct sc_array_sym *symbols,
} }
void *sym_addr = (void *)((uintptr_t)module_base + sym.st_value); void *sym_addr = (void *)((uintptr_t)module_base + sym.st_value);
HiSymbolBind binding = symbol_bind_from_efi(GELF_ST_BIND(sym.st_info)); HiSymbolBind binding = symbol_bind_from_efibind(GELF_ST_BIND(sym.st_info));
HiSymbolType type = symbol_type_from_efi(GELF_ST_TYPE(sym.st_info)); HiSymbolType type = symbol_type_from_efitype(GELF_ST_TYPE(sym.st_info));
size_t size = sym.st_size; size_t size = sym.st_size;
// Gather global symbols and local object symbols. Local functions are // Gather global symbols and local object symbols. Local functions are
@@ -268,6 +275,36 @@ static HiloadResult moduler_apply_module_patch(HiSymbols *psymbols,
return HILOAD_OK; return HILOAD_OK;
} }
PatchData moduler_create_patch(HiModuleData *module) {
time_t now = time(NULL);
struct tm *t = localtime(&now);
if (t == NULL) {
return (PatchData){0};
}
char file_append[32];
if (strftime(file_append, sizeof(file_append), ".%Y%m%d%H%M%S.patch", t) == 0) {
log_error("Failed to create patch filename.\n");
return (PatchData){0};
}
char filename[512];
size_t written =
hi_strncat_buf(sizeof(filename), filename, module->name, file_append);
if (written == 0) {
log_error("Failed to concat %s and %s\n", module->name, ".patch");
return (PatchData){0};
}
hi_file_copy(module->name, filename);
PatchData data = {.filename = strdup(filename)};
return data;
}
HiloadResult moduler_reload(HiModuleArray *modules, HiModuleData *module, HiloadResult moduler_reload(HiModuleArray *modules, HiModuleData *module,
struct sc_array_memreg *memregs) { struct sc_array_memreg *memregs) {
@@ -279,40 +316,36 @@ HiloadResult moduler_reload(HiModuleArray *modules, HiModuleData *module,
return HILOAD_OK; return HILOAD_OK;
} }
dlerror(); // clear old errors PatchData patch = moduler_create_patch(module);
char patch_filename[512]; if (!patch.filename) {
size_t written = hi_strncat_buf(sizeof(patch_filename), patch_filename, log_error("Couldn't create patch for %s\n", module->name);
module->name, ".patch");
if (written == 0) {
log_error("Failed to concat %s and %s\n", module->name, ".patch");
return HILOAD_FAIL; return HILOAD_FAIL;
} }
hi_file_copy(module->name, patch_filename);
// Load patch // Load patch
log_debug("Opening: %s\n", patch_filename); dlerror(); // clear any previous errors
void *new_handle = dlopen(patch_filename, RTLD_LAZY); log_debug("Opening: %s\n", patch.filename);
void *new_handle = dlopen(patch.filename, RTLD_LAZY);
if (!new_handle) { if (!new_handle) {
log_error("Couldn't load: %s\n", dlerror()); log_error("Couldn't load: %s\n", dlerror());
module->info = hi_modinfo_clear(module->info, HI_MODULE_STATE_DIRTY); module->info = hi_modinfo_clear(module->info, HI_MODULE_STATE_DIRTY);
return HILOAD_FAIL; return HILOAD_FAIL;
} }
patch.dlhandle = new_handle;
// refresh cache // refresh cache
read_memory_maps_self(memregs); read_memory_maps_self(memregs);
MemoryRegionSpan patch_memory = patch.memreg = memory_get_module_span(memregs, patch.filename);
memory_get_module_span(memregs, patch_filename); void *patch_base = (void *)patch.memreg.region_start;
void *patch_base = (void *)patch_memory.region_start;
HiSymbols patch_symbols; HiSymbols patch_symbols;
symbol_init_symbols(&patch_symbols); symbol_init_symbols(&patch_symbols);
HiloadResult ret = HiloadResult ret =
gather_patchable_symbols(&patch_symbols, patch_filename, patch_base); gather_patchable_symbols(&patch_symbols, patch.filename, patch_base);
if (!HIOK(ret)) { if (!HIOK(ret)) {
log_error("Failed to gather symbols for %s\n", patch_filename); log_error("Failed to gather symbols for %s\n", patch.filename);
return HILOAD_FAIL; return HILOAD_FAIL;
} }
@@ -327,7 +360,7 @@ HiloadResult moduler_reload(HiModuleArray *modules, HiModuleData *module,
// If patch is for the same module, also collect local object symbols for // If patch is for the same module, also collect local object symbols for
// coping those over // coping those over
if (strncmp(mod.name, patch_filename, strlen(mod.name)) == 0) { if (strncmp(mod.name, patch.filename, strlen(mod.name)) == 0) {
HiSymbols module_symbols; HiSymbols module_symbols;
symbol_init_symbols(&module_symbols); symbol_init_symbols(&module_symbols);
@@ -360,7 +393,11 @@ HiloadResult moduler_reload(HiModuleArray *modules, HiModuleData *module,
module->info = hi_modinfo_clear(module->info, HI_MODULE_STATE_DIRTY); module->info = hi_modinfo_clear(module->info, HI_MODULE_STATE_DIRTY);
} }
free((char*)patch.filename);
symbol_term_symbols(&patch_symbols); symbol_term_symbols(&patch_symbols);
dlclose(module->dlhandle);
module->dlhandle = patch.dlhandle;
return HILOAD_OK; return HILOAD_OK;
} }

View File

@@ -15,7 +15,7 @@ HiSymbol *symbol_find(HiSymbols *symbols, HiSymbol *symbol) {
return NULL; return NULL;
} }
HiSymbolBind symbol_bind_from_efi(u32 efi_bind) { HiSymbolBind symbol_bind_from_efibind(u32 efi_bind) {
// clang-format off // clang-format off
switch (efi_bind) { switch (efi_bind) {
case STB_LOCAL: return HI_SYMBOL_BIND_LOCAL; case STB_LOCAL: return HI_SYMBOL_BIND_LOCAL;
@@ -26,7 +26,7 @@ HiSymbolBind symbol_bind_from_efi(u32 efi_bind) {
return ~0u; return ~0u;
} }
HiSymbolType symbol_type_from_efi(u32 efi_type) { HiSymbolType symbol_type_from_efitype(u32 efi_type) {
// clang-format off // clang-format off
switch (efi_type) { switch (efi_type) {
case STT_NOTYPE: return HI_SYMBOL_TYPE_NOTYPE; /* Symbol type is unspecified */ case STT_NOTYPE: return HI_SYMBOL_TYPE_NOTYPE; /* Symbol type is unspecified */

View File

@@ -52,6 +52,6 @@ static inline void symbol_term_symbols(HiSymbols *symbols) {
HiSymbol *symbol_find(HiSymbols *symbols, HiSymbol *symbol); HiSymbol *symbol_find(HiSymbols *symbols, HiSymbol *symbol);
HiSymbolBind symbol_bind_from_efi(u32 efi_bind); HiSymbolBind symbol_bind_from_efibind(u32 efi_bind);
HiSymbolType symbol_type_from_efi(u32 efi_type); HiSymbolType symbol_type_from_efitype(u32 efi_type);
#endif // SYMBOLS_H_ #endif // SYMBOLS_H_

View File

@@ -18,7 +18,7 @@ int main(int argc, char *argv[]) {
while (modified != 0) { while (modified != 0) {
modified = minimal_lib::getNewValue(5); modified = minimal_lib::getNewValue(5);
printf("getNewValue(5): %d\n", modified); printf("getNewValue: %d\n", modified);
std::this_thread::sleep_for(std::chrono::seconds(1)); std::this_thread::sleep_for(std::chrono::seconds(1));
printf("otherValue: %d\n", minimal_lib::otherValue++); printf("otherValue: %d\n", minimal_lib::otherValue++);

View File

@@ -1,10 +1,11 @@
#include "minimal_lib.h" #include "minimal_lib.h"
#include <cstdio>
namespace minimal_lib { namespace minimal_lib {
int getNewValue(int x) { int getNewValue(int x) {
static int value = 0; static int value = 0;
value = value + 5; value = value + x;
return value; return value;
} }