|
|
|
@@ -16,11 +16,11 @@
|
|
|
|
#include <gelf.h>
|
|
|
|
#include <gelf.h>
|
|
|
|
#include <libelf.h>
|
|
|
|
#include <libelf.h>
|
|
|
|
#include <link.h>
|
|
|
|
#include <link.h>
|
|
|
|
|
|
|
|
#include <stdalign.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
@@ -119,7 +119,9 @@ static HiloadResult gather_patchable_symbols(struct sc_array_sym *symbols,
|
|
|
|
|
|
|
|
|
|
|
|
// Assumption: Only symbols with size are defined here, and those
|
|
|
|
// Assumption: Only symbols with size are defined here, and those
|
|
|
|
// without are safely ignored. Linker will handle them.
|
|
|
|
// without are safely ignored. Linker will handle them.
|
|
|
|
if (sym.st_size == 0) {
|
|
|
|
// Assumption: completed.0 seems to be size 1 and appears locally, lets
|
|
|
|
|
|
|
|
// assume its useless
|
|
|
|
|
|
|
|
if (sym.st_size <= 1) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -160,7 +162,7 @@ cleanup:
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static HiloadResult moduler_apply_module_patch(HiSymbols *psymbols, HiSymbols *msymbols,
|
|
|
|
static HiloadResult moduler_apply_module_patch(HiSymbols *psymbols,
|
|
|
|
MemoryRegionSpan module_memory) {
|
|
|
|
MemoryRegionSpan module_memory) {
|
|
|
|
|
|
|
|
|
|
|
|
void *module_base = (void *)module_memory.region_start;
|
|
|
|
void *module_base = (void *)module_memory.region_start;
|
|
|
|
@@ -255,29 +257,13 @@ static HiloadResult moduler_apply_module_patch(HiSymbols *psymbols, HiSymbols *m
|
|
|
|
|
|
|
|
|
|
|
|
*got_entry = sym->address;
|
|
|
|
*got_entry = sym->address;
|
|
|
|
log_debug("Found GOT entry for '%s' at %p (points to %p)\n", name,
|
|
|
|
log_debug("Found GOT entry for '%s' at %p (points to %p)\n", name,
|
|
|
|
got_entry, *got_entry);
|
|
|
|
got_entry, *got_entry);
|
|
|
|
|
|
|
|
|
|
|
|
found_count++;
|
|
|
|
found_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Copy old data to new data. Breaks with layout changes.
|
|
|
|
|
|
|
|
for (size_t i = 0; i < sc_array_size(msymbols); ++i) {
|
|
|
|
|
|
|
|
HiSymbol *sym = &sc_array_at(msymbols, i);
|
|
|
|
|
|
|
|
if (sym->type == HI_SYMBOL_TYPE_OBJECT) {
|
|
|
|
|
|
|
|
HiSymbol *ps = symbol_find(psymbols, sym);
|
|
|
|
|
|
|
|
if (ps) {
|
|
|
|
|
|
|
|
if (ps->size >= sym->size) {
|
|
|
|
|
|
|
|
memcpy(ps->address, sym->address, sym->size);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
memcpy(ps->address, sym->address, ps->size);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
log_debug("Copied data for symbol: %s\n", sym->name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elf_end(elf);
|
|
|
|
elf_end(elf);
|
|
|
|
return HILOAD_OK;
|
|
|
|
return HILOAD_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -295,8 +281,8 @@ HiloadResult moduler_reload(HiModuleArray *modules, HiModuleData *module,
|
|
|
|
|
|
|
|
|
|
|
|
dlerror(); // clear old errors
|
|
|
|
dlerror(); // clear old errors
|
|
|
|
char patch_filename[512];
|
|
|
|
char patch_filename[512];
|
|
|
|
size_t written =
|
|
|
|
size_t written = hi_strncat_buf(sizeof(patch_filename), patch_filename,
|
|
|
|
hi_strncat_buf(sizeof(patch_filename), patch_filename, module->name, ".patch");
|
|
|
|
module->name, ".patch");
|
|
|
|
if (written == 0) {
|
|
|
|
if (written == 0) {
|
|
|
|
log_error("Failed to concat %s and %s\n", module->name, ".patch");
|
|
|
|
log_error("Failed to concat %s and %s\n", module->name, ".patch");
|
|
|
|
return HILOAD_FAIL;
|
|
|
|
return HILOAD_FAIL;
|
|
|
|
@@ -313,16 +299,18 @@ HiloadResult moduler_reload(HiModuleArray *modules, HiModuleData *module,
|
|
|
|
return HILOAD_FAIL;
|
|
|
|
return HILOAD_FAIL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// refresh before using
|
|
|
|
// refresh cache
|
|
|
|
read_memory_maps_self(memregs);
|
|
|
|
read_memory_maps_self(memregs);
|
|
|
|
|
|
|
|
|
|
|
|
MemoryRegionSpan patch_memory = memory_get_module_span(memregs, patch_filename);
|
|
|
|
MemoryRegionSpan patch_memory =
|
|
|
|
|
|
|
|
memory_get_module_span(memregs, patch_filename);
|
|
|
|
void *patch_base = (void *)patch_memory.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 = gather_patchable_symbols(&patch_symbols, patch_filename, patch_base);
|
|
|
|
HiloadResult ret =
|
|
|
|
|
|
|
|
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;
|
|
|
|
@@ -334,19 +322,42 @@ HiloadResult moduler_reload(HiModuleArray *modules, HiModuleData *module,
|
|
|
|
if (!hi_modinfo_has(mod.info, HI_MODULE_STATE_PATCHABLE))
|
|
|
|
if (!hi_modinfo_has(mod.info, HI_MODULE_STATE_PATCHABLE))
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
HiSymbols module_symbols;
|
|
|
|
|
|
|
|
symbol_init_symbols(&module_symbols);
|
|
|
|
|
|
|
|
ret = gather_patchable_symbols(&module_symbols, mod.name, (void*)mod.address);
|
|
|
|
|
|
|
|
if (!HIOK(ret)) {
|
|
|
|
|
|
|
|
log_error("Failed to gather symbols for %s\n", mod.name);
|
|
|
|
|
|
|
|
symbol_term_symbols(&module_symbols);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
MemoryRegionSpan module_memory = memory_get_module_span(memregs, mod.name);
|
|
|
|
MemoryRegionSpan module_memory = memory_get_module_span(memregs, mod.name);
|
|
|
|
moduler_apply_module_patch(&patch_symbols, &module_symbols, module_memory);
|
|
|
|
moduler_apply_module_patch(&patch_symbols, module_memory);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If patch is for the same module, also collect local object symbols for
|
|
|
|
|
|
|
|
// coping those over
|
|
|
|
|
|
|
|
if (strncmp(mod.name, patch_filename, strlen(mod.name)) == 0) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HiSymbols module_symbols;
|
|
|
|
|
|
|
|
symbol_init_symbols(&module_symbols);
|
|
|
|
|
|
|
|
ret = gather_patchable_symbols(&module_symbols, mod.name,
|
|
|
|
|
|
|
|
(void *)mod.address);
|
|
|
|
|
|
|
|
if (!HIOK(ret)) {
|
|
|
|
|
|
|
|
log_error("Failed to gather symbols for %s\n", mod.name);
|
|
|
|
|
|
|
|
symbol_term_symbols(&module_symbols);
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Copy old data to new data. Breaks with layout changes.
|
|
|
|
|
|
|
|
for (size_t i = 0; i < sc_array_size(&module_symbols); ++i) {
|
|
|
|
|
|
|
|
HiSymbol *sym = &sc_array_at(&module_symbols, i);
|
|
|
|
|
|
|
|
if (sym->type == HI_SYMBOL_TYPE_OBJECT) {
|
|
|
|
|
|
|
|
HiSymbol *ps = symbol_find(&patch_symbols, sym);
|
|
|
|
|
|
|
|
if (ps) {
|
|
|
|
|
|
|
|
if (ps->size >= sym->size) {
|
|
|
|
|
|
|
|
memcpy(ps->address, sym->address, sym->size);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
memcpy(ps->address, sym->address, ps->size);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
log_debug("Copied data for symbol: %s\n", sym->name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
symbol_term_symbols(&module_symbols);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
module->info = hi_modinfo_clear(module->info, HI_MODULE_STATE_DIRTY);
|
|
|
|
module->info = hi_modinfo_clear(module->info, HI_MODULE_STATE_DIRTY);
|
|
|
|
symbol_term_symbols(&module_symbols);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
symbol_term_symbols(&patch_symbols);
|
|
|
|
symbol_term_symbols(&patch_symbols);
|
|
|
|
|