Add detection for relative dynamic table addresses
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/memory.c
12
src/memory.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user