From 32c7d794f17e27716803920881d61e2328923fbc Mon Sep 17 00:00:00 2001 From: Kasper Sauramo Date: Thu, 20 Mar 2025 11:55:09 +0200 Subject: [PATCH] Add detection for relative dynamic table addresses --- src/hiload.c | 6 +++--- src/memory.c | 14 +++++++------ src/symbols.c | 57 ++++++++++++++++++++------------------------------- src/symbols.h | 7 +++---- 4 files changed, 36 insertions(+), 48 deletions(-) diff --git a/src/hiload.c b/src/hiload.c index 890319f..a3bf3d2 100644 --- a/src/hiload.c +++ b/src/hiload.c @@ -259,9 +259,9 @@ void hi_print_module_infos() { printf("%s: %p\n", modules->names[i], modules->handles[i]); if (modules->symbols) { - for (int j = 0; j < modules->symbols->count; j++) { - const void *addr = modules->symbols->addresses[j]; - const char *name = modules->symbols->names[j]; + for (int j = 0; j < modules->symbols->names.size; j++) { + const void *addr = modules->symbols->addresses.elems[j]; + const char *name = modules->symbols->names.elems[j]; printf(" %p: %s\n", addr, name); } } diff --git a/src/memory.c b/src/memory.c index d8a8e87..49f444e 100644 --- a/src/memory.c +++ b/src/memory.c @@ -9,15 +9,17 @@ static inline int ptr_in_range(uptr ptr, uptr start, uptr end) { return ptr >= start && ptr <= end; } -HiloadResult memory_find_pointer(uptr ptr, struct sc_array_memreg* const regions, +HiloadResult memory_find_pointer(uptr ptr, + struct sc_array_memreg *const regions, size_t *index) { for (size_t i = 0; i < sc_array_size(regions); i++) { - if (ptr_in_range(ptr, regions->elems[i].region_start, - regions->elems[i].region_end)) { - if (index) { + uptr start = regions->elems[i].region_start; + uptr end = regions->elems[i].region_end; + if (ptr_in_range(ptr, start, end)) { + if (index) *index = i; - return HILOAD_OK; - } + sc_log_debug("Pointer match (%p) found in index: %u, range: %p - %p\n", ptr, i, start, end); + return HILOAD_OK; } } diff --git a/src/symbols.c b/src/symbols.c index 68a8110..39bb5cd 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -12,6 +12,14 @@ #include #include +static inline uptr +add_ptr_offset_if_invalid(uptr p, uptr offset, + struct sc_array_memreg *const regions) { + if (memory_find_pointer(p, regions, NULL) != HILOAD_OK) + return p + offset; + return p; +} + /** * Gathers and populates symbols, given a dynamic module info * @@ -51,13 +59,14 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols, size_t strtab_size = 0; uptr off = info->dlpi_addr; - // Parse the dynamic table + // Parse the dynamic table. Add offset if address is not in executable memory. + // NOTE: Haven't found a better way to differentiate with items that have + // relative address, and items that don't. for (; dyn->d_tag != DT_NULL; dyn++) { if (dyn->d_tag == DT_STRTAB) { uptr p = dyn->d_un.d_ptr; - if (!memory_find_pointer(p, regions, NULL)) - p += off; + p = add_ptr_offset_if_invalid(p, off, regions); strtab = (const char *)p; } else if (dyn->d_tag == DT_STRSZ) { @@ -65,8 +74,7 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols, } else if (dyn->d_tag == DT_SYMTAB) { uptr p = dyn->d_un.d_ptr; - if (!memory_find_pointer(p, regions, NULL)) - p += off; + p = add_ptr_offset_if_invalid(p, off, regions); symtab = (const ElfW(Sym) *)(p); } else if (dyn->d_tag == DT_SYMENT) { @@ -76,25 +84,11 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols, // Ensure we found the symbol and string tables if (!strtab || !symtab || strtab_size == 0 || symtab_size == 0) { - fprintf(stderr, "Failed to find symbol or string table in %s\n", + sc_log_error("Failed to find symbol or string table in %s\n", info->dlpi_name); return CREATE_FAILED; } - symbols->capacity = symtab_size / sizeof(char); - - symbols->names = calloc(symbols->capacity, sizeof(char *)); - if (!symbols->names) { - fprintf(stderr, "Failed to allocate memory for symbol names.\n"); - return CREATE_FAILED; - } - - symbols->addresses = calloc(symbols->capacity, sizeof(void *)); - if (!symbols->addresses) { - fprintf(stderr, "Failed to allocate memory for symbol addresses.\n"); - return CREATE_FAILED; - } - // Iterate over the symbol table for (const ElfW(Sym) *sym = symtab; (const char *)sym < (const char *)symtab + symtab_size; sym++) { @@ -103,15 +97,9 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols, const char *name = strdup(&strtab[sym->st_name]); void *address = (void *)(info->dlpi_addr + sym->st_value); - // Store the symbol information in the struct of arrays - if (symbols->count < symbols->capacity) { - symbols->names[symbols->count] = (char *)name; - symbols->addresses[symbols->count] = address; - symbols->count++; - } else { - fprintf(stderr, "Symbol table capacity exceeded!\n"); - return CREATE_FAILED; - } + // Store the symbol information in the arrays + sc_array_add(&symbols->names, name); + sc_array_add(&symbols->addresses, address); } } } @@ -120,11 +108,10 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols, } void hi_free_symbol_info(SymbolInfos *symbols) { - for (size_t i = 0; i < symbols->count; i++) { - free(symbols->names[i]); + for (size_t i = 0; i < symbols->names.size; i++) { + free((void *)symbols->names.elems[i]); } - free(symbols->names); - free(symbols->addresses); - symbols->count = 0; - symbols->capacity = 0; + + sc_array_term(&symbols->names); + sc_array_term(&symbols->addresses); } diff --git a/src/symbols.h b/src/symbols.h index 899c7cf..29dd567 100644 --- a/src/symbols.h +++ b/src/symbols.h @@ -2,15 +2,14 @@ #define SYMBOLS_H_ #include "memory.h" + #include #include #include typedef struct { - char **names; - void **addresses; - size_t count; - size_t capacity; + struct sc_array_str names; + struct sc_array_ptr addresses; } SymbolInfos; typedef enum { CREATE_SUCCESS = 0, CREATE_FAILED } CreateResult;