diff --git a/src/hiload.c b/src/hiload.c index 3397161..890319f 100644 --- a/src/hiload.c +++ b/src/hiload.c @@ -1,6 +1,7 @@ #include "hiload/hiload.h" #include "logger.h" +#include "logger/sc_log.h" #include "memory.h" #include "symbols.h" #include "types.h" @@ -31,24 +32,27 @@ static ModuleInfos *module_infos = 0; // Callback function for dl_iterate_phdr static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size, void *data) { + ModuleInfos *infos = (ModuleInfos *)data; + { + // Resize arrays if needed + if (infos->count >= infos->capacity) { + infos->capacity *= 2; + char **new_names = + realloc(infos->names, infos->capacity * sizeof(char *)); + void **new_handles = + realloc(infos->handles, infos->capacity * sizeof(void *)); + SymbolInfos *new_symbols = + realloc(infos->symbols, infos->capacity * sizeof(SymbolInfos)); - // Resize arrays if needed - if (infos->count >= infos->capacity) { - infos->capacity *= 2; - char **new_names = realloc(infos->names, infos->capacity * sizeof(char *)); - void **new_handles = - realloc(infos->handles, infos->capacity * sizeof(void *)); - SymbolInfos *new_symbols = - realloc(infos->symbols, infos->capacity * sizeof(SymbolInfos)); + if (!new_names || !new_handles || !new_symbols) { + return 1; // Stop iteration on error + } - if (!new_names || !new_handles || !new_symbols) { - return 1; // Stop iteration on error + infos->names = new_names; + infos->handles = new_handles; + infos->symbols = new_symbols; } - - infos->names = new_names; - infos->handles = new_handles; - infos->symbols = new_symbols; } // Store the module name @@ -57,12 +61,21 @@ static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size, return 1; // Stop iteration on error } + sc_log_info("Processing: %s\n", info->dlpi_name); + // Try to get the handle infos->handles[infos->count] = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD); - if (hi_create_symbol_info(&infos->symbols[infos->count], info) != - CREATE_SUCCESS) { + sc_log_debug(" size: %u\n", size); + sc_log_debug(" handle: %p\n", infos->handles[infos->count]); + sc_log_debug(" dlpi_addr: %p\n", info->dlpi_addr); + sc_log_debug(" dlpi_tls_modid: %zu\n", info->dlpi_tls_modid); + sc_log_debug(" dlpi_tls_data: %p\n", info->dlpi_tls_data); + + + if (hi_create_symbol_info(&infos->symbols[infos->count], + &context.memory_regions, info) != CREATE_SUCCESS) { fprintf(stderr, "Failed to create symbol info for %s\n", infos->names[infos->count]); } @@ -266,7 +279,6 @@ int hi_init() { } sc_log_set_level("DEBUG"); - if (read_memory_maps_self(&context.memory_regions) != HILOAD_OK) { sc_log_error("Could not populate program memory maps.\n"); return HILOAD_FAIL; diff --git a/src/memory.c b/src/memory.c index 00585d2..d8a8e87 100644 --- a/src/memory.c +++ b/src/memory.c @@ -1,9 +1,29 @@ #include "memory.h" +#include "array/sc_array.h" #include "files.h" #include "logger.h" #include "types.h" +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, + 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) { + *index = i; + return HILOAD_OK; + } + } + } + + return HILOAD_FAIL; +} + HiloadResult read_memory_maps_self(struct sc_array_memreg *regions) { str memory_str = str_null; diff --git a/src/memory.h b/src/memory.h index 0c14d36..aa70690 100644 --- a/src/memory.h +++ b/src/memory.h @@ -31,4 +31,7 @@ sc_array_def(MemoryRegion, memreg); /* A pointer that can be used to place the memory regions into. Clears regions before use, but uses the same buffer. */ HiloadResult read_memory_maps_self(struct sc_array_memreg *regions); +/* Return index the pointer is found in */ +HiloadResult memory_find_pointer(uptr ptr, struct sc_array_memreg* const regions, size_t *index); + #endif // MEMORY_H_ diff --git a/src/symbols.c b/src/symbols.c index f81ef42..68a8110 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -1,5 +1,9 @@ #include "symbols.h" +#include "logger.h" +#include "memory.h" +#include "types.h" + #include #include #include @@ -15,6 +19,7 @@ * hold found symbols. */ CreateResult hi_create_symbol_info(SymbolInfos *symbols, + struct sc_array_memreg *const regions, struct dl_phdr_info *info) { if (!symbols) @@ -29,15 +34,15 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols, if (phdr->p_type != PT_DYNAMIC) continue; - printf("Dynamic Header:\n"); - printf("p_type: %u\n", phdr->p_type); - printf("p_flags: %u\n", phdr->p_flags); - printf("p_offset: %#06lx\n", phdr->p_offset); - printf("p_vaddr: %#06lx\n", phdr->p_vaddr); - printf("p_paddr: %#06lx\n", phdr->p_paddr); - printf("p_filesz: %zu\n", phdr->p_filesz); - printf("p_memsz: %zu\n", phdr->p_memsz); - printf("p_align: %zu\n", phdr->p_align); + sc_log_debug("Dynamic Header:\n"); + sc_log_debug("p_type: %u\n", phdr->p_type); + sc_log_debug("p_flags: %u\n", phdr->p_flags); + sc_log_debug("p_offset: %#06lx\n", phdr->p_offset); + sc_log_debug("p_vaddr: %#06lx\n", phdr->p_vaddr); + sc_log_debug("p_paddr: %#06lx\n", phdr->p_paddr); + sc_log_debug("p_filesz: %zu\n", phdr->p_filesz); + sc_log_debug("p_memsz: %zu\n", phdr->p_memsz); + sc_log_debug("p_align: %zu\n", phdr->p_align); const ElfW(Dyn) *dyn = (const ElfW(Dyn) *)(info->dlpi_addr + phdr->p_vaddr); const char *strtab = NULL; @@ -45,14 +50,25 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols, size_t symtab_size = 0; size_t strtab_size = 0; - // Parse the dynamic table + uptr off = info->dlpi_addr; + // Parse the dynamic table for (; dyn->d_tag != DT_NULL; dyn++) { + if (dyn->d_tag == DT_STRTAB) { - strtab = (const char *)(dyn->d_un.d_ptr); + uptr p = dyn->d_un.d_ptr; + if (!memory_find_pointer(p, regions, NULL)) + p += off; + strtab = (const char *)p; + } else if (dyn->d_tag == DT_STRSZ) { strtab_size = dyn->d_un.d_val; + } else if (dyn->d_tag == DT_SYMTAB) { - symtab = (const ElfW(Sym) *)(dyn->d_un.d_ptr); + uptr p = dyn->d_un.d_ptr; + if (!memory_find_pointer(p, regions, NULL)) + p += off; + symtab = (const ElfW(Sym) *)(p); + } else if (dyn->d_tag == DT_SYMENT) { symtab_size = dyn->d_un.d_val; } @@ -65,7 +81,7 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols, return CREATE_FAILED; } - symbols->capacity = symtab_size / sizeof(ElfW(Sym)); + symbols->capacity = symtab_size / sizeof(char); symbols->names = calloc(symbols->capacity, sizeof(char *)); if (!symbols->names) { diff --git a/src/symbols.h b/src/symbols.h index 5236b15..899c7cf 100644 --- a/src/symbols.h +++ b/src/symbols.h @@ -1,6 +1,7 @@ #ifndef SYMBOLS_H_ #define SYMBOLS_H_ +#include "memory.h" #include #include #include @@ -15,8 +16,11 @@ typedef struct { typedef enum { CREATE_SUCCESS = 0, CREATE_FAILED } CreateResult; struct dl_phdr_info; +struct sc_array_memreg; -CreateResult hi_create_symbol_info(SymbolInfos *, struct dl_phdr_info *); +CreateResult hi_create_symbol_info(SymbolInfos *, + struct sc_array_memreg *const regions, + struct dl_phdr_info *); void hi_free_symbol_info(SymbolInfos *); #endif // SYMBOLS_H_