use sc_arrays for data

This commit is contained in:
Kasper Sauramo
2025-03-20 19:00:36 +02:00
parent 32c7d794f1
commit 5bcff694f7
3 changed files with 68 additions and 101 deletions

View File

@@ -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;
} }

View File

@@ -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) {

View File

@@ -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 *);