Add detection for relative dynamic table addresses

This commit is contained in:
Kasper Sauramo
2025-03-20 11:55:09 +02:00
parent 1f10b3b821
commit 32c7d794f1
4 changed files with 36 additions and 48 deletions

View File

@@ -259,9 +259,9 @@ void hi_print_module_infos() {
printf("%s: %p\n", modules->names[i], modules->handles[i]); printf("%s: %p\n", modules->names[i], modules->handles[i]);
if (modules->symbols) { if (modules->symbols) {
for (int j = 0; j < modules->symbols->count; j++) { for (int j = 0; j < modules->symbols->names.size; j++) {
const void *addr = modules->symbols->addresses[j]; const void *addr = modules->symbols->addresses.elems[j];
const char *name = modules->symbols->names[j]; const char *name = modules->symbols->names.elems[j];
printf(" %p: %s\n", addr, name); printf(" %p: %s\n", addr, name);
} }
} }

View File

@@ -9,17 +9,19 @@ static inline int ptr_in_range(uptr ptr, uptr start, uptr end) {
return ptr >= start && ptr <= 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) { size_t *index) {
for (size_t i = 0; i < sc_array_size(regions); i++) { for (size_t i = 0; i < sc_array_size(regions); i++) {
if (ptr_in_range(ptr, regions->elems[i].region_start, uptr start = regions->elems[i].region_start;
regions->elems[i].region_end)) { uptr end = regions->elems[i].region_end;
if (index) { if (ptr_in_range(ptr, start, end)) {
if (index)
*index = i; *index = i;
sc_log_debug("Pointer match (%p) found in index: %u, range: %p - %p\n", ptr, i, start, end);
return HILOAD_OK; return HILOAD_OK;
} }
} }
}
return HILOAD_FAIL; return HILOAD_FAIL;
} }

View File

@@ -12,6 +12,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
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 * 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; size_t strtab_size = 0;
uptr off = info->dlpi_addr; 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++) { for (; dyn->d_tag != DT_NULL; dyn++) {
if (dyn->d_tag == DT_STRTAB) { if (dyn->d_tag == DT_STRTAB) {
uptr p = dyn->d_un.d_ptr; uptr p = dyn->d_un.d_ptr;
if (!memory_find_pointer(p, regions, NULL)) p = add_ptr_offset_if_invalid(p, off, regions);
p += off;
strtab = (const char *)p; strtab = (const char *)p;
} else if (dyn->d_tag == DT_STRSZ) { } 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) { } else if (dyn->d_tag == DT_SYMTAB) {
uptr p = dyn->d_un.d_ptr; uptr p = dyn->d_un.d_ptr;
if (!memory_find_pointer(p, regions, NULL)) p = add_ptr_offset_if_invalid(p, off, regions);
p += off;
symtab = (const ElfW(Sym) *)(p); symtab = (const ElfW(Sym) *)(p);
} else if (dyn->d_tag == DT_SYMENT) { } 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 // Ensure we found the symbol and string tables
if (!strtab || !symtab || strtab_size == 0 || symtab_size == 0) { 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); info->dlpi_name);
return CREATE_FAILED; 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 // Iterate over the symbol table
for (const ElfW(Sym) *sym = symtab; for (const ElfW(Sym) *sym = symtab;
(const char *)sym < (const char *)symtab + symtab_size; sym++) { (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]); const char *name = strdup(&strtab[sym->st_name]);
void *address = (void *)(info->dlpi_addr + sym->st_value); void *address = (void *)(info->dlpi_addr + sym->st_value);
// Store the symbol information in the struct of arrays // Store the symbol information in the arrays
if (symbols->count < symbols->capacity) { sc_array_add(&symbols->names, name);
symbols->names[symbols->count] = (char *)name; sc_array_add(&symbols->addresses, address);
symbols->addresses[symbols->count] = address;
symbols->count++;
} else {
fprintf(stderr, "Symbol table capacity exceeded!\n");
return CREATE_FAILED;
}
} }
} }
} }
@@ -120,11 +108,10 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols,
} }
void hi_free_symbol_info(SymbolInfos *symbols) { void hi_free_symbol_info(SymbolInfos *symbols) {
for (size_t i = 0; i < symbols->count; i++) { for (size_t i = 0; i < symbols->names.size; i++) {
free(symbols->names[i]); free((void *)symbols->names.elems[i]);
} }
free(symbols->names);
free(symbols->addresses); sc_array_term(&symbols->names);
symbols->count = 0; sc_array_term(&symbols->addresses);
symbols->capacity = 0;
} }

View File

@@ -2,15 +2,14 @@
#define SYMBOLS_H_ #define SYMBOLS_H_
#include "memory.h" #include "memory.h"
#include <link.h> #include <link.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
typedef struct { typedef struct {
char **names; struct sc_array_str names;
void **addresses; struct sc_array_ptr addresses;
size_t count;
size_t capacity;
} SymbolInfos; } SymbolInfos;
typedef enum { CREATE_SUCCESS = 0, CREATE_FAILED } CreateResult; typedef enum { CREATE_SUCCESS = 0, CREATE_FAILED } CreateResult;