gather information about module.. again
This commit is contained in:
@@ -45,8 +45,10 @@ add_library(hiload SHARED
|
|||||||
src/symbols.c
|
src/symbols.c
|
||||||
src/files.c
|
src/files.c
|
||||||
src/memory.c
|
src/memory.c
|
||||||
src/string/string.c
|
|
||||||
src/logger/logger.c
|
src/logger/logger.c
|
||||||
|
src/moduler/moduler.c
|
||||||
|
src/moduler/elf.c
|
||||||
|
src/string/string.c
|
||||||
src/filewatcher/filewatcher.c
|
src/filewatcher/filewatcher.c
|
||||||
src/filewatcher/filewatch.c
|
src/filewatcher/filewatch.c
|
||||||
|
|
||||||
@@ -61,7 +63,7 @@ target_compile_options(hiload PRIVATE
|
|||||||
$<$<COMPILE_LANGUAGE:C>:-Wno-declaration-after-statement -Wno-padded>
|
$<$<COMPILE_LANGUAGE:C>:-Wno-declaration-after-statement -Wno-padded>
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(hiload dl)
|
target_link_libraries(hiload dl elf)
|
||||||
|
|
||||||
# Specify the public headers location
|
# Specify the public headers location
|
||||||
target_include_directories(hiload PUBLIC
|
target_include_directories(hiload PUBLIC
|
||||||
|
|||||||
28
src/hiload.c
28
src/hiload.c
@@ -5,6 +5,7 @@
|
|||||||
#include "filewatcher/filewatcher.h"
|
#include "filewatcher/filewatcher.h"
|
||||||
#include "logger/logger.h"
|
#include "logger/logger.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "moduler/moduler.h"
|
||||||
#include "string/string.h"
|
#include "string/string.h"
|
||||||
#include "symbols.h"
|
#include "symbols.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@@ -18,22 +19,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
sc_array_def(uptr, uptr);
|
|
||||||
|
|
||||||
enum HiModuleState {
|
|
||||||
HI_MODULE_STATE_CLEAN = 0,
|
|
||||||
HI_MODULE_STATE_DIRTY,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct sc_array_str names; // Array of library names
|
|
||||||
struct sc_array_ptr handles; // Array of library handles
|
|
||||||
struct sc_array_uptr addresses; // Array of library base addresses
|
|
||||||
struct sc_array_syms symbols; // Symbol info for modules
|
|
||||||
u8 state[256]; // Flag for when module needs to be changed
|
|
||||||
size_t count; // Number of modules
|
|
||||||
} ModuleInfos;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct sc_array_memreg memory_regions;
|
struct sc_array_memreg memory_regions;
|
||||||
struct sc_array_str enabled_modules;
|
struct sc_array_str enabled_modules;
|
||||||
@@ -60,7 +45,7 @@ static int gather_module_infos_callback(struct dl_phdr_info *info, size_t size,
|
|||||||
|
|
||||||
sc_array_add(&mod_infos->handles, handle);
|
sc_array_add(&mod_infos->handles, handle);
|
||||||
sc_array_add(&mod_infos->addresses, info->dlpi_addr);
|
sc_array_add(&mod_infos->addresses, info->dlpi_addr);
|
||||||
log_debugv(" size: %u\n", size);
|
log_debugv(" header size: %u\n", size);
|
||||||
log_debugv(" handle: %p\n", sc_array_last(&mod_infos->handles));
|
log_debugv(" handle: %p\n", sc_array_last(&mod_infos->handles));
|
||||||
log_debugv(" dlpi_addr: %p\n", info->dlpi_addr);
|
log_debugv(" dlpi_addr: %p\n", info->dlpi_addr);
|
||||||
log_debugv(" dlpi_tls_modid: %zu\n", info->dlpi_tls_modid);
|
log_debugv(" dlpi_tls_modid: %zu\n", info->dlpi_tls_modid);
|
||||||
@@ -190,12 +175,6 @@ static i32 get_string_index(const char *needle,
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HiloadResult reload_module(ModuleInfos *modinfos, u8 modindex) {
|
|
||||||
|
|
||||||
modinfos->state[modindex] = HI_MODULE_STATE_CLEAN;
|
|
||||||
return HILOAD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HiloadResult reload_dirty_modules(HiloadContext *context) {
|
static HiloadResult reload_dirty_modules(HiloadContext *context) {
|
||||||
|
|
||||||
HiloadResult ret = HILOAD_OK;
|
HiloadResult ret = HILOAD_OK;
|
||||||
@@ -211,7 +190,8 @@ static HiloadResult reload_dirty_modules(HiloadContext *context) {
|
|||||||
if (module_index != -1) {
|
if (module_index != -1) {
|
||||||
log_info("Reloading %s...\n", module_name);
|
log_info("Reloading %s...\n", module_name);
|
||||||
|
|
||||||
if (reload_module(context->loaded_modules, i) != HILOAD_OK) {
|
if (moduler_reload(context->loaded_modules, &context->memory_regions,
|
||||||
|
i) != HILOAD_OK) {
|
||||||
ret = HILOAD_FAIL;
|
ret = HILOAD_FAIL;
|
||||||
log_error("Failed loading: %s\n", module_name);
|
log_error("Failed loading: %s\n", module_name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
|
|
||||||
_Atomic bool hiload_verbose_log = false;
|
_Atomic bool hiload_verbose_log = true;
|
||||||
|
|
||||||
void log_set_verbose(bool value) {
|
void log_set_verbose(bool value) {
|
||||||
atomic_store_explicit(&hiload_verbose_log, value, memory_order_relaxed);
|
atomic_store_explicit(&hiload_verbose_log, value, memory_order_relaxed);
|
||||||
|
|||||||
31
src/memory.c
31
src/memory.c
@@ -9,8 +9,7 @@ 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,
|
HiloadResult memory_find_region(uptr ptr, struct sc_array_memreg *const regions,
|
||||||
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++) {
|
||||||
uptr start = regions->elems[i].region_start;
|
uptr start = regions->elems[i].region_start;
|
||||||
@@ -35,7 +34,7 @@ HiloadResult read_memory_maps_self(struct sc_array_memreg *regions) {
|
|||||||
sc_array_clear(regions);
|
sc_array_clear(regions);
|
||||||
sc_array_init(regions);
|
sc_array_init(regions);
|
||||||
|
|
||||||
char* maps_str = hi_file_to_str_dyn("/proc/self/maps");
|
char *maps_str = hi_file_to_str_dyn("/proc/self/maps");
|
||||||
if (!maps_str)
|
if (!maps_str)
|
||||||
return HILOAD_FAIL;
|
return HILOAD_FAIL;
|
||||||
|
|
||||||
@@ -85,3 +84,29 @@ HiloadResult read_memory_maps_self(struct sc_array_memreg *regions) {
|
|||||||
|
|
||||||
return HILOAD_OK;
|
return HILOAD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryRegionSpan
|
||||||
|
memory_get_module_span(const struct sc_array_memreg *const regions,
|
||||||
|
const char module_name[static 1]) {
|
||||||
|
uptr start = ~0ull;
|
||||||
|
uptr end = 0;
|
||||||
|
for (size_t i = 0; i < sc_array_size(regions); i++) {
|
||||||
|
|
||||||
|
const MemoryRegion *reg = &sc_array_at(regions, i);
|
||||||
|
|
||||||
|
if (reg->pathname && strcmp(reg->pathname, module_name) == 0) {
|
||||||
|
if (reg->region_start < start) {
|
||||||
|
start = reg->region_start;
|
||||||
|
}
|
||||||
|
if (reg->region_end > end) {
|
||||||
|
end = reg->region_end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we passed the module regions
|
||||||
|
if (end > 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(start < ~0ull && end > 0);
|
||||||
|
return (MemoryRegionSpan){.region_start = start, .region_end = end};
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ typedef enum {
|
|||||||
HI_MEMORY_PRIVATE = 1 << 4
|
HI_MEMORY_PRIVATE = 1 << 4
|
||||||
} MemoryPermissions;
|
} MemoryPermissions;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uptr region_start;
|
||||||
|
uptr region_end;
|
||||||
|
} MemoryRegionSpan;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uptr region_start;
|
uptr region_start;
|
||||||
uptr region_end;
|
uptr region_end;
|
||||||
@@ -34,4 +39,7 @@ HiloadResult memory_find_pointer(uptr ptr,
|
|||||||
struct sc_array_memreg *const regions,
|
struct sc_array_memreg *const regions,
|
||||||
size_t *index);
|
size_t *index);
|
||||||
|
|
||||||
|
MemoryRegionSpan memory_get_module_span(const struct sc_array_memreg *const regions,
|
||||||
|
const char module_name[static 1]);
|
||||||
|
|
||||||
#endif // MEMORY_H_
|
#endif // MEMORY_H_
|
||||||
|
|||||||
3
src/moduler/elf.c
Normal file
3
src/moduler/elf.c
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#include "elf.h"
|
||||||
|
|
||||||
|
#include <libelf.h>
|
||||||
84
src/moduler/elf.h
Normal file
84
src/moduler/elf.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#ifndef ELF_H_
|
||||||
|
#define ELF_H_
|
||||||
|
|
||||||
|
#include <libelf.h>
|
||||||
|
|
||||||
|
static inline const char *dyn_type_to_str(unsigned type) {
|
||||||
|
// clang-format off
|
||||||
|
switch (type) {
|
||||||
|
case DT_NULL: return "NULL";
|
||||||
|
case DT_NEEDED: return "NEEDED";
|
||||||
|
case DT_PLTRELSZ: return "PLTRELSZ";
|
||||||
|
case DT_PLTGOT: return "PLTGOT";
|
||||||
|
case DT_HASH: return "HASH";
|
||||||
|
case DT_STRTAB: return "STRTAB";
|
||||||
|
case DT_SYMTAB: return "SYMTAB";
|
||||||
|
case DT_RELA: return "RELA";
|
||||||
|
case DT_RELASZ: return "RELASZ";
|
||||||
|
case DT_RELAENT: return "RELAENT";
|
||||||
|
case DT_STRSZ: return "STRSZ";
|
||||||
|
case DT_SYMENT: return "SYMENT";
|
||||||
|
case DT_INIT: return "INIT";
|
||||||
|
case DT_FINI: return "FINI";
|
||||||
|
case DT_SONAME: return "SONAME";
|
||||||
|
case DT_RPATH: return "RPATH";
|
||||||
|
case DT_SYMBOLIC: return "SYMBOLIC";
|
||||||
|
case DT_REL: return "REL";
|
||||||
|
case DT_RELSZ: return "RELSZ";
|
||||||
|
case DT_RELENT: return "RELENT";
|
||||||
|
case DT_PLTREL: return "PLTREL";
|
||||||
|
case DT_DEBUG: return "DEBUG";
|
||||||
|
case DT_TEXTREL: return "TEXTREL";
|
||||||
|
case DT_JMPREL: return "JMPREL";
|
||||||
|
case DT_BIND_NOW: return "BIND_NOW";
|
||||||
|
case DT_INIT_ARRAY: return "INIT_ARRAY";
|
||||||
|
case DT_FINI_ARRAY: return "FINI_ARRAY";
|
||||||
|
case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ";
|
||||||
|
case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ";
|
||||||
|
case DT_RUNPATH: return "RUNPATH";
|
||||||
|
case DT_FLAGS: return "FLAGS";
|
||||||
|
case DT_PREINIT_ARRAY: return "ENCODING/PREINIT_ARRAY";
|
||||||
|
case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ";
|
||||||
|
case DT_SYMTAB_SHNDX: return "SYMTAB_SHNDX";
|
||||||
|
case DT_RELRSZ: return "RELRSZ";
|
||||||
|
case DT_RELR: return "RELR";
|
||||||
|
case DT_RELRENT: return "RELRENT";
|
||||||
|
case DT_NUM: return "NUM";
|
||||||
|
case DT_LOOS: return "LOOS";
|
||||||
|
case DT_HIOS: return "HIOS";
|
||||||
|
case DT_LOPROC: return "LOPROC";
|
||||||
|
case DT_HIPROC: return "HIPROC";
|
||||||
|
case DT_PROCNUM: return "PROCNUM";
|
||||||
|
default: return "UNKNOWN";
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *segment_type_to_str(unsigned type) {
|
||||||
|
// clang-format off
|
||||||
|
switch (type) {
|
||||||
|
case PT_NULL: return "NULL";
|
||||||
|
case PT_LOAD: return "LOAD";
|
||||||
|
case PT_DYNAMIC: return "DYNAMIC";
|
||||||
|
case PT_INTERP: return "INTERP";
|
||||||
|
case PT_NOTE: return "NOTE";
|
||||||
|
case PT_SHLIB: return "SHLIB";
|
||||||
|
case PT_PHDR: return "PHDR";
|
||||||
|
case PT_TLS: return "TLS";
|
||||||
|
case PT_NUM: return "NUM";
|
||||||
|
case PT_LOOS: return "LOOS";
|
||||||
|
case PT_GNU_EH_FRAME: return "GNU_EH_FRAME";
|
||||||
|
case PT_GNU_STACK: return "GNU_STACK";
|
||||||
|
case PT_GNU_RELRO: return "GNU_RELRO";
|
||||||
|
case PT_GNU_PROPERTY: return "GNU_PROPERTY";
|
||||||
|
case PT_LOSUNW: return "LOSUNW/SUNWBSS";
|
||||||
|
case PT_SUNWSTACK: return "SUNWSTACK";
|
||||||
|
case PT_HIOS: return "HIOS";
|
||||||
|
case PT_LOPROC: return "LOPROC";
|
||||||
|
case PT_HIPROC: return "HIPROC";
|
||||||
|
default: return "UNKNOWN";
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
48
src/moduler/moduler.c
Normal file
48
src/moduler/moduler.c
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#include "moduler.h"
|
||||||
|
|
||||||
|
#include "logger/logger.h"
|
||||||
|
#include "moduler/elf.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
HiloadResult moduler_reload(ModuleInfos *modinfos,
|
||||||
|
const struct sc_array_memreg *const memregs,
|
||||||
|
int modindex) {
|
||||||
|
const char *modname = sc_array_at(&modinfos->names, modindex);
|
||||||
|
MemoryRegionSpan memspan = memory_get_module_span(memregs, modname);
|
||||||
|
log_debugv("Module: %s - [%p, %p]\n", modname, memspan.region_start,
|
||||||
|
memspan.region_end);
|
||||||
|
|
||||||
|
|
||||||
|
Elf *elf = elf_memory((void*)memspan.region_start, memspan.region_end - memspan.region_start);
|
||||||
|
int err = elf_errno();
|
||||||
|
if (err) {
|
||||||
|
log_error("%s\n", elf_errmsg(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
void *module_address = (void*)sc_array_at(&modinfos->addresses, modindex);
|
||||||
|
|
||||||
|
size_t phdrnum = 0;
|
||||||
|
err = elf_getphdrnum(elf, &phdrnum);
|
||||||
|
Elf64_Phdr *phdr = elf64_getphdr(elf);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < phdrnum; ++i) {
|
||||||
|
Elf64_Phdr *p = phdr + i;
|
||||||
|
log_debugv("segment type: %s\n", segment_type_to_str(p->p_type));
|
||||||
|
|
||||||
|
size_t segment_size = p->p_memsz;
|
||||||
|
void *segment_start = module_address + p->p_vaddr;
|
||||||
|
void *segment_end = module_address + p->p_vaddr + segment_size;
|
||||||
|
|
||||||
|
if (p->p_type == PT_DYNAMIC) {
|
||||||
|
Elf64_Dyn *dyn = (Elf64_Dyn*)segment_start;
|
||||||
|
while ((void*)dyn < segment_end) {
|
||||||
|
log_debugv(" dyn type: %s\n", dyn_type_to_str(dyn->d_tag));
|
||||||
|
++dyn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modinfos->state[modindex] = HI_MODULE_STATE_CLEAN;
|
||||||
|
return HILOAD_OK;
|
||||||
|
}
|
||||||
31
src/moduler/moduler.h
Normal file
31
src/moduler/moduler.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef MODULER_H_
|
||||||
|
#define MODULER_H_
|
||||||
|
|
||||||
|
#include "array/array.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "symbols.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
struct HiloadContext;
|
||||||
|
|
||||||
|
sc_array_def(uptr, uptr);
|
||||||
|
|
||||||
|
enum HiModuleState {
|
||||||
|
HI_MODULE_STATE_CLEAN = 0,
|
||||||
|
HI_MODULE_STATE_DIRTY,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct sc_array_str names; // Array of library names
|
||||||
|
struct sc_array_ptr handles; // Array of library handles
|
||||||
|
struct sc_array_uptr addresses; // Array of library base addresses
|
||||||
|
struct sc_array_syms symbols; // Symbol info for modules
|
||||||
|
u8 state[256]; // Flag for when module needs to be changed
|
||||||
|
size_t count; // Number of modules
|
||||||
|
} ModuleInfos;
|
||||||
|
|
||||||
|
HiloadResult moduler_reload(ModuleInfos *modinfos,
|
||||||
|
const struct sc_array_memreg *const memregs,
|
||||||
|
int modindex);
|
||||||
|
|
||||||
|
#endif // MODULER_H_
|
||||||
@@ -4,11 +4,7 @@
|
|||||||
|
|
||||||
void hi_free_symbol_info(SymbolInfos *symbols) {
|
void hi_free_symbol_info(SymbolInfos *symbols) {
|
||||||
for (size_t i = 0; i < symbols->names.size; i++) {
|
for (size_t i = 0; i < symbols->names.size; i++) {
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
|
||||||
free((void *)symbols->names.elems[i]);
|
free((void *)symbols->names.elems[i]);
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_array_term(&symbols->names);
|
sc_array_term(&symbols->names);
|
||||||
|
|||||||
Reference in New Issue
Block a user