Add detection for relative dynamic table addresses
This commit is contained in:
@@ -12,6 +12,14 @@
|
||||
#include <stdlib.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
|
||||
*
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user