use sc_arrays for data
This commit is contained in:
151
src/hiload.c
151
src/hiload.c
@@ -14,11 +14,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char **names; // Array of library names
|
struct sc_array_str names; // Array of library names
|
||||||
void **handles; // Array of library handles
|
struct sc_array_ptr handles; // Array of library handles
|
||||||
SymbolInfos *symbols; // Symbol info for modules
|
struct sc_array_syms symbols; // Symbol info for modules
|
||||||
size_t count; // Number of libraries
|
size_t count; // Number of libraries
|
||||||
size_t capacity; // Allocated capacity
|
|
||||||
} ModuleInfos;
|
} ModuleInfos;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -26,7 +25,6 @@ typedef struct {
|
|||||||
} HiloadContext;
|
} HiloadContext;
|
||||||
|
|
||||||
static HiloadContext context = {0};
|
static HiloadContext context = {0};
|
||||||
|
|
||||||
static ModuleInfos *module_infos = 0;
|
static ModuleInfos *module_infos = 0;
|
||||||
|
|
||||||
// Callback function for dl_iterate_phdr
|
// Callback function for dl_iterate_phdr
|
||||||
@@ -34,50 +32,29 @@ static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size,
|
|||||||
void *data) {
|
void *data) {
|
||||||
|
|
||||||
ModuleInfos *infos = (ModuleInfos *)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));
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the module name
|
// Store the module name
|
||||||
infos->names[infos->count] = strdup(info->dlpi_name);
|
sc_array_add(&infos->names, strdup(info->dlpi_name));
|
||||||
if (!infos->names[infos->count]) {
|
|
||||||
return 1; // Stop iteration on error
|
|
||||||
}
|
|
||||||
|
|
||||||
sc_log_info("Processing: %s\n", info->dlpi_name);
|
sc_log_info("Processing: '%s'\n", info->dlpi_name);
|
||||||
|
|
||||||
// Try to get the handle
|
// Try to get the handle
|
||||||
infos->handles[infos->count] =
|
void *handle = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD);
|
||||||
dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD);
|
sc_array_add(&infos->handles, handle);
|
||||||
|
|
||||||
sc_log_debug(" size: %u\n", size);
|
sc_log_debug(" size: %u\n", size);
|
||||||
sc_log_debug(" handle: %p\n", infos->handles[infos->count]);
|
sc_log_debug(" handle: %p\n", sc_array_last(&infos->handles));
|
||||||
sc_log_debug(" dlpi_addr: %p\n", info->dlpi_addr);
|
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_modid: %zu\n", info->dlpi_tls_modid);
|
||||||
sc_log_debug(" dlpi_tls_data: %p\n", info->dlpi_tls_data);
|
sc_log_debug(" dlpi_tls_data: %p\n", info->dlpi_tls_data);
|
||||||
|
|
||||||
|
|
||||||
if (hi_create_symbol_info(&infos->symbols[infos->count],
|
SymbolInfos symbol_info = {0};
|
||||||
&context.memory_regions, info) != CREATE_SUCCESS) {
|
sc_array_add(&infos->symbols, symbol_info);
|
||||||
fprintf(stderr, "Failed to create symbol info for %s\n",
|
if (hi_create_symbol_info(&(sc_array_last(&infos->symbols)),
|
||||||
infos->names[infos->count]);
|
&context.memory_regions, info) != HILOAD_OK) {
|
||||||
|
sc_log_error("Failed to create symbol info for %s\n",
|
||||||
|
info->dlpi_name);
|
||||||
}
|
}
|
||||||
infos->count++;
|
infos->count++;
|
||||||
return 0; // Continue iteration
|
return 0; // Continue iteration
|
||||||
@@ -88,18 +65,24 @@ static void free_module_infos(ModuleInfos *modules) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (size_t i = 0; i < modules->count; i++) {
|
for (size_t i = 0; i < modules->count; i++) {
|
||||||
if (modules->names[i])
|
// Free char* before clearing the array
|
||||||
free(modules->names[i]);
|
const char *n = 0;
|
||||||
hi_free_symbol_info(&modules->symbols[i]);
|
sc_array_foreach(&modules->names, n) {
|
||||||
|
free((void*)n);
|
||||||
|
}
|
||||||
|
sc_array_term(&modules->names);
|
||||||
|
|
||||||
|
// Use a destructor for the symbolinfos
|
||||||
|
hi_free_symbol_info(&(sc_array_at(&modules->symbols, i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
free(modules->names);
|
sc_array_term(&modules->names);
|
||||||
free(modules->handles);
|
sc_array_term(&modules->handles);
|
||||||
free(modules->symbols);
|
sc_array_term(&modules->symbols);
|
||||||
free(modules);
|
free(modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ModuleInfos *gather_shared_libraries(void) {
|
static ModuleInfos *gather_module_infos(void) {
|
||||||
ModuleInfos *result = NULL;
|
ModuleInfos *result = NULL;
|
||||||
|
|
||||||
// Allocate the result structure
|
// Allocate the result structure
|
||||||
@@ -108,24 +91,7 @@ static ModuleInfos *gather_shared_libraries(void) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initial capacity
|
// Iterate over all loaded shared objects
|
||||||
result->capacity = 16;
|
|
||||||
result->names = calloc(result->capacity, sizeof(char *));
|
|
||||||
result->handles = calloc(result->capacity, sizeof(void *));
|
|
||||||
result->symbols = calloc(result->capacity, sizeof(SymbolInfos));
|
|
||||||
|
|
||||||
if (!result->names || !result->handles || !result->symbols) {
|
|
||||||
if (result->names)
|
|
||||||
free(result->names);
|
|
||||||
if (result->handles)
|
|
||||||
free(result->handles);
|
|
||||||
if (result->symbols)
|
|
||||||
free(result->symbols);
|
|
||||||
free(result);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over all shared objects
|
|
||||||
if (dl_iterate_phdr(gather_module_infos_callback, result) != 0) {
|
if (dl_iterate_phdr(gather_module_infos_callback, result) != 0) {
|
||||||
// Error occurred in callback
|
// Error occurred in callback
|
||||||
free_module_infos(result);
|
free_module_infos(result);
|
||||||
@@ -135,14 +101,6 @@ static ModuleInfos *gather_shared_libraries(void) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reloads a shared library module
|
|
||||||
*
|
|
||||||
* @param modules The ModuleInfos structure containing loaded modules
|
|
||||||
* @param filename The name of the module to reload
|
|
||||||
* @param updated_handle Pointer to store the new handle (can be NULL)
|
|
||||||
* @return ReloadResult indicating success or failure
|
|
||||||
*/
|
|
||||||
static ReloadResult reload_module(ModuleInfos *modules, const char *filename,
|
static ReloadResult reload_module(ModuleInfos *modules, const char *filename,
|
||||||
void **updated_handle) {
|
void **updated_handle) {
|
||||||
if (!modules || !filename) {
|
if (!modules || !filename) {
|
||||||
@@ -155,15 +113,17 @@ static ReloadResult reload_module(ModuleInfos *modules, const char *filename,
|
|||||||
|
|
||||||
for (size_t i = 0; i < modules->count; i++) {
|
for (size_t i = 0; i < modules->count; i++) {
|
||||||
// Check if this is the module we're looking for
|
// Check if this is the module we're looking for
|
||||||
if (modules->names[i] && strcmp(modules->names[i], filename) == 0) {
|
const char *pathname = sc_array_at(&modules->names, i);
|
||||||
|
|
||||||
|
if (pathname && strcmp(pathname, filename) == 0) {
|
||||||
found = 1;
|
found = 1;
|
||||||
index = i;
|
index = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also check if the filename is at the end of the path
|
// Also check if the filename is at the end of the path
|
||||||
if (modules->names[i]) {
|
if (pathname) {
|
||||||
const char *basename = strrchr(modules->names[i], '/');
|
const char *basename = strrchr(pathname, '/');
|
||||||
if (basename && strcmp(basename + 1, filename) == 0) {
|
if (basename && strcmp(basename + 1, filename) == 0) {
|
||||||
found = 1;
|
found = 1;
|
||||||
index = i;
|
index = i;
|
||||||
@@ -177,15 +137,15 @@ static ReloadResult reload_module(ModuleInfos *modules, const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save the full path
|
// Save the full path
|
||||||
char *fullpath = strdup(modules->names[index]);
|
const char *fullpath = sc_array_at(&modules->names, index);
|
||||||
if (!fullpath) {
|
if (!fullpath) {
|
||||||
return HI_RELOAD_OPEN_ERROR;
|
return HI_RELOAD_OPEN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the old handle
|
// Close the old handle
|
||||||
if (modules->handles[index]) {
|
void *handle = sc_array_at(&modules->handles, index);
|
||||||
if (dlclose(modules->handles[index]) != 0) {
|
if (handle) {
|
||||||
free(fullpath);
|
if (dlclose(handle) != 0) {
|
||||||
return HI_RELOAD_CLOSE_ERROR;
|
return HI_RELOAD_CLOSE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,20 +153,18 @@ static ReloadResult reload_module(ModuleInfos *modules, const char *filename,
|
|||||||
// Open the module again with RTLD_NOW
|
// Open the module again with RTLD_NOW
|
||||||
void *new_handle = dlopen(fullpath, RTLD_NOW);
|
void *new_handle = dlopen(fullpath, RTLD_NOW);
|
||||||
if (!new_handle) {
|
if (!new_handle) {
|
||||||
fprintf(stderr, "Error reloading module: %s\n", dlerror());
|
sc_log_error("Error reloading module: %s\n", dlerror());
|
||||||
free(fullpath);
|
|
||||||
return HI_RELOAD_OPEN_ERROR;
|
return HI_RELOAD_OPEN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the handle in our structure
|
// Update the handle in our structure
|
||||||
modules->handles[index] = new_handle;
|
modules->handles.elems[index] = new_handle;
|
||||||
|
|
||||||
// If the caller wants the new handle, provide it
|
// If the caller wants the new handle, provide it
|
||||||
if (updated_handle) {
|
if (updated_handle) {
|
||||||
*updated_handle = new_handle;
|
*updated_handle = new_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fullpath);
|
|
||||||
return HI_RELOAD_SUCCESS;
|
return HI_RELOAD_SUCCESS;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -246,27 +204,29 @@ void hi_print_module_infos() {
|
|||||||
|
|
||||||
const ModuleInfos *modules = module_infos;
|
const ModuleInfos *modules = module_infos;
|
||||||
if (!modules) {
|
if (!modules) {
|
||||||
printf("No module information available.\n");
|
sc_log_error("No module information available.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Found %zu loaded modules:\n\n", modules->count);
|
sc_log_info("Found %zu loaded modules:\n\n", modules->count);
|
||||||
|
|
||||||
for (size_t i = 0; i < modules->count; i++) {
|
for (size_t i = 0; i < modules->count; i++) {
|
||||||
// Get handle information where possible
|
// Get handle information where possible
|
||||||
Dl_info info = {0};
|
Dl_info info = {0};
|
||||||
int has_info = 0;
|
int has_info = 0;
|
||||||
|
|
||||||
printf("%s: %p\n", modules->names[i], modules->handles[i]);
|
sc_log_debug("%s: %p\n", sc_array_at(&modules->names, i), sc_array_at(&modules->handles, i));
|
||||||
if (modules->symbols) {
|
|
||||||
for (int j = 0; j < modules->symbols->names.size; j++) {
|
|
||||||
const void *addr = modules->symbols->addresses.elems[j];
|
const SymbolInfos *symbols = &sc_array_at(&modules->symbols, i);
|
||||||
const char *name = modules->symbols->names.elems[j];
|
for (int j = 0; j < sc_array_size(&symbols->names); j++) {
|
||||||
printf(" %p: %s\n", addr, name);
|
const void *addr = sc_array_at(&symbols->addresses, j);
|
||||||
}
|
const char *name = sc_array_at(&symbols->names, j);
|
||||||
|
sc_log_debug(" %p: %s\n", addr, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
|
sc_log_debug("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,15 +244,20 @@ int hi_init() {
|
|||||||
return HILOAD_FAIL;
|
return HILOAD_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleInfos *infos = gather_shared_libraries();
|
ModuleInfos *infos = gather_module_infos();
|
||||||
if (!infos) {
|
if (!infos) {
|
||||||
fprintf(stderr, "Failed to gather module infos.\n");
|
sc_log_error("Failed to gather module infos.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Override existing
|
||||||
if (module_infos) {
|
if (module_infos) {
|
||||||
free_module_infos(module_infos);
|
free_module_infos(module_infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_infos = infos;
|
module_infos = infos;
|
||||||
|
hi_print_module_infos();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ add_ptr_offset_if_invalid(uptr p, uptr offset,
|
|||||||
* Will clear and free the given SymbolInfo struct. Allocates enough memory to
|
* Will clear and free the given SymbolInfo struct. Allocates enough memory to
|
||||||
* hold found symbols.
|
* hold found symbols.
|
||||||
*/
|
*/
|
||||||
CreateResult hi_create_symbol_info(SymbolInfos *symbols,
|
HiloadResult hi_create_symbol_info(SymbolInfos *symbols,
|
||||||
struct sc_array_memreg *const regions,
|
struct sc_array_memreg *const regions,
|
||||||
struct dl_phdr_info *info) {
|
struct dl_phdr_info *info) {
|
||||||
|
|
||||||
if (!symbols)
|
if (!symbols)
|
||||||
return CREATE_FAILED;
|
return HILOAD_FAIL;
|
||||||
|
|
||||||
hi_free_symbol_info(symbols);
|
hi_free_symbol_info(symbols);
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols,
|
|||||||
if (!strtab || !symtab || strtab_size == 0 || symtab_size == 0) {
|
if (!strtab || !symtab || strtab_size == 0 || symtab_size == 0) {
|
||||||
sc_log_error("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 HILOAD_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over the symbol table
|
// Iterate over the symbol table
|
||||||
@@ -104,7 +104,7 @@ CreateResult hi_create_symbol_info(SymbolInfos *symbols,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CREATE_SUCCESS;
|
return HILOAD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hi_free_symbol_info(SymbolInfos *symbols) {
|
void hi_free_symbol_info(SymbolInfos *symbols) {
|
||||||
|
|||||||
@@ -2,22 +2,24 @@
|
|||||||
#define SYMBOLS_H_
|
#define SYMBOLS_H_
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct sc_array_str names;
|
struct sc_array_str names;
|
||||||
struct sc_array_ptr addresses;
|
struct sc_array_ptr addresses;
|
||||||
} SymbolInfos;
|
} SymbolInfos;
|
||||||
|
|
||||||
typedef enum { CREATE_SUCCESS = 0, CREATE_FAILED } CreateResult;
|
sc_array_def(SymbolInfos, syms);
|
||||||
|
|
||||||
|
|
||||||
struct dl_phdr_info;
|
struct dl_phdr_info;
|
||||||
struct sc_array_memreg;
|
struct sc_array_memreg;
|
||||||
|
HiloadResult hi_create_symbol_info(SymbolInfos *,
|
||||||
CreateResult hi_create_symbol_info(SymbolInfos *,
|
|
||||||
struct sc_array_memreg *const regions,
|
struct sc_array_memreg *const regions,
|
||||||
struct dl_phdr_info *);
|
struct dl_phdr_info *);
|
||||||
void hi_free_symbol_info(SymbolInfos *);
|
void hi_free_symbol_info(SymbolInfos *);
|
||||||
|
|||||||
Reference in New Issue
Block a user