Remove hi_ prefixes from internal code. Add documentation.
This commit is contained in:
2733
doc/Doxyfile
Normal file
2733
doc/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
18
src/files.c
18
src/files.c
@@ -11,9 +11,9 @@
|
||||
#define HI_FILE_BUFFER_SIZE 4096
|
||||
#endif
|
||||
|
||||
char *hi_file_to_str_dyn(const char *filename) {
|
||||
char *file_to_str_dyn(const char *filename) {
|
||||
|
||||
char *s = hi_string_from_file_dyn(filename, 0, 0);
|
||||
char *s = hi_str_from_file(filename, 0, 0);
|
||||
if (!s) {
|
||||
sc_log_error("Failed to read file: %s\n", filename);
|
||||
return 0;
|
||||
@@ -21,14 +21,14 @@ char *hi_file_to_str_dyn(const char *filename) {
|
||||
return s;
|
||||
}
|
||||
|
||||
HiFileType hi_file_interpret_as_type(const char *path) {
|
||||
static FileType file_interpret_as_type(const char *path) {
|
||||
const char *pathname_end = path + strlen(path);
|
||||
char last_char = *(pathname_end - 1);
|
||||
bool as_dir = (last_char == '/') || (last_char == '\\');
|
||||
return as_dir ? HI_FILE_TYPE_DIR : HI_FILE_TYPE_FILE;
|
||||
}
|
||||
|
||||
const char *hi_file_name_from_path(const char *path) {
|
||||
const char *file_name_from_path(const char *path) {
|
||||
const char *filename = path;
|
||||
|
||||
// Find the last directory separator
|
||||
@@ -45,7 +45,7 @@ const char *hi_file_name_from_path(const char *path) {
|
||||
return filename;
|
||||
}
|
||||
|
||||
HiResult hi_file_copy(const char *srcname, const char *destination) {
|
||||
HiResult file_copy(const char *srcname, const char *destination) {
|
||||
|
||||
HiResult ret = HI_FAIL;
|
||||
|
||||
@@ -59,10 +59,10 @@ HiResult hi_file_copy(const char *srcname, const char *destination) {
|
||||
|
||||
const char *dstname = destination;
|
||||
|
||||
HiFileType dst_type = hi_file_interpret_as_type(destination);
|
||||
FileType dst_type = file_interpret_as_type(destination);
|
||||
if (dst_type == HI_FILE_TYPE_DIR) {
|
||||
hi_strncat_buf(sizeof(buf), buf, destination,
|
||||
hi_file_name_from_path(srcname));
|
||||
hi_str_concat_buf(sizeof(buf), buf, destination,
|
||||
file_name_from_path(srcname));
|
||||
dstname = buf;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ cleanup:
|
||||
*
|
||||
* TAG: posix
|
||||
*/
|
||||
HiFileType hi_file_type(const char *path) {
|
||||
FileType file_type(const char *path) {
|
||||
struct stat path_stat;
|
||||
int err = stat(path, &path_stat);
|
||||
if (err == -1) {
|
||||
|
||||
13
src/files.h
13
src/files.h
@@ -14,7 +14,7 @@ typedef enum {
|
||||
|
||||
HI_FILE_TYPE_COUNT,
|
||||
HI_FILE_TYPE_NONE,
|
||||
} HiFileType;
|
||||
} FileType;
|
||||
|
||||
/**
|
||||
* Read file dynamically to a string
|
||||
@@ -24,18 +24,19 @@ typedef enum {
|
||||
* the initial memory and a reallocation to match the string size.
|
||||
*/
|
||||
|
||||
char *hi_file_to_str_dyn(const char *filename);
|
||||
char *file_to_str_dyn(const char *filename);
|
||||
|
||||
/**
|
||||
* Copy file \p filename to \p dest
|
||||
*
|
||||
* If \p dest has either '/' or '\' as the last character, it is interpreted as
|
||||
* a directory and the file is copied to the directory with the same filename.
|
||||
* a directory and the file is copied to the directory with the same filename as
|
||||
* the source.
|
||||
*/
|
||||
HiResult hi_file_copy(const char *filename, const char *dest);
|
||||
HiResult file_copy(const char *filename, const char *dest);
|
||||
|
||||
HiFileType hi_file_type(const char *path);
|
||||
FileType file_type(const char *path);
|
||||
|
||||
const char *hi_file_name_from_path(const char *path);
|
||||
const char *file_name_from_path(const char *path);
|
||||
|
||||
#endif // FILES_H_
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
#include <sys/inotify.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* File Watch
|
||||
/**
|
||||
* Used to pass information between some functions
|
||||
*/
|
||||
|
||||
struct WatchMaskParams {
|
||||
u32 file_mask;
|
||||
u32 parent_mask;
|
||||
@@ -46,6 +45,24 @@ static inline struct WatchMaskParams inode_watch_masks_create(u32 flags) {
|
||||
.parent_mask = parent_mask};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return null terminated char array with the parent, or NULL if no path
|
||||
* separator was found.
|
||||
* */
|
||||
static char *get_parent_folder(const char path[static 1]) {
|
||||
const char *last_separator = strrchr(path, '/');
|
||||
if (!last_separator)
|
||||
return NULL;
|
||||
|
||||
// add one for the trailing slash
|
||||
size_t length = last_separator - path + 1;
|
||||
char *parent = calloc(length, sizeof(char));
|
||||
strncpy(parent, path, length);
|
||||
parent[length - 1] = '/';
|
||||
parent[length] = '\0';
|
||||
return parent;
|
||||
}
|
||||
|
||||
static void file_watch_destroy(int fd, FileWatch *fw) {
|
||||
inotify_rm_watch(fd, fw->wd);
|
||||
free((void *)fw->path);
|
||||
@@ -78,8 +95,8 @@ FileWatch *file_watch_find_by_wd(FileWatcherContext *ctx, int wd,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FileWatch *file_watch_find_by_path(FileWatcherContext *ctx,
|
||||
const char *path, size_t *index) {
|
||||
FileWatch *file_watch_find_by_path(FileWatcherContext *ctx, const char *path,
|
||||
size_t *index) {
|
||||
for (size_t i = 0; i < sc_array_size(&ctx->watches); i++) {
|
||||
FileWatch *watch = &sc_array_at(&ctx->watches, i);
|
||||
if (strcmp(watch->path, path) == 0) {
|
||||
@@ -92,26 +109,7 @@ FileWatch *file_watch_find_by_path(FileWatcherContext *ctx,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return null terminated char array with the parent, or NULL if no path
|
||||
* separator was found.
|
||||
* */
|
||||
static char *get_parent_folder(const char path[static 1]) {
|
||||
const char *last_separator = strrchr(path, '/');
|
||||
if (!last_separator)
|
||||
return NULL;
|
||||
|
||||
// add one for the trailing slash
|
||||
size_t length = last_separator - path + 1;
|
||||
char *parent = calloc(length, sizeof(char));
|
||||
strncpy(parent, path, length);
|
||||
parent[length - 1] = '/';
|
||||
parent[length] = '\0';
|
||||
return parent;
|
||||
}
|
||||
|
||||
HiResult file_watch_add(FileWatcherContext *ctx, u32 mask,
|
||||
const char *path) {
|
||||
HiResult file_watch_add(FileWatcherContext *ctx, u32 mask, const char *path) {
|
||||
if (!ctx || ctx->fd == -1) {
|
||||
log_error("Invalid inotify context\n");
|
||||
return HI_FAIL;
|
||||
@@ -167,25 +165,26 @@ HiResult file_watch_add(FileWatcherContext *ctx, u32 mask,
|
||||
}
|
||||
|
||||
HiResult file_watch_remove(FileWatcherContext *ctx, const char *path) {
|
||||
// BUG: Parent watchers are never properly cleared if all children are removed
|
||||
// without removing the parent separately
|
||||
|
||||
size_t i = 0;
|
||||
FileWatch *watch = file_watch_find_by_path(ctx, path, &i);
|
||||
if (watch) {
|
||||
|
||||
// Destroy parent reference. We assume it will only have one.
|
||||
char *parent = get_parent_folder(path);
|
||||
if (parent) {
|
||||
FileWatch *pw = file_watch_find_by_path(ctx, parent, NULL);
|
||||
// Destroy parent reference. Parent should only have one, but lets make
|
||||
// sure.
|
||||
char *parent_name = get_parent_folder(path);
|
||||
if (parent_name) {
|
||||
FileWatch *pw = file_watch_find_by_path(ctx, parent_name, NULL);
|
||||
if (pw) {
|
||||
for (size_t i = 0; i < sc_array_size(&pw->files); i++) {
|
||||
const char *fn = sc_array_at(&pw->files, i);
|
||||
if (fn == watch->path) {
|
||||
sc_array_del(&pw->files, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(parent);
|
||||
free(parent_name);
|
||||
}
|
||||
file_watch_destroy(ctx->fd, watch);
|
||||
sc_array_del(&ctx->watches, i);
|
||||
|
||||
@@ -7,15 +7,40 @@
|
||||
typedef struct FileWatcherContext FileWatcherContext;
|
||||
typedef struct FileWatch FileWatch;
|
||||
|
||||
FileWatch *file_watch_find_by_wd(FileWatcherContext *ctx,
|
||||
int wd, size_t *index);
|
||||
FileWatch *file_watch_find_by_path(FileWatcherContext *ctx,
|
||||
const char *path, size_t *index);
|
||||
/**
|
||||
* Search for a FileWatch matching by watch descriptor.
|
||||
*
|
||||
* @param ctx
|
||||
* @param wd Watch descriptor given by inotipy
|
||||
* @param index Will contain the first occurrance of a matching FileWatch. Can
|
||||
* be null.
|
||||
*/
|
||||
FileWatch *file_watch_find_by_wd(FileWatcherContext *ctx, int wd,
|
||||
size_t *index);
|
||||
/**
|
||||
* Search for a FileWatch in a particular context matching by filepath.
|
||||
* @param ctx
|
||||
* @param path An absolute path for the file searched for
|
||||
* @param index Will contain the first occurrance of a matching FileWatch. Can
|
||||
* be null. */
|
||||
FileWatch *file_watch_find_by_path(FileWatcherContext *ctx, const char *path,
|
||||
size_t *index);
|
||||
|
||||
HiResult file_watch_add(FileWatcherContext *ctx, u32 mask,
|
||||
const char *path);
|
||||
HiResult file_watch_remove(FileWatcherContext *ctx,
|
||||
const char *path);
|
||||
/**
|
||||
* Create FileWatch, start monitoring for changes and generating events.
|
||||
*
|
||||
* Creats a parent FileWatch if it doesn't already exist.
|
||||
*/
|
||||
HiResult file_watch_add(FileWatcherContext *ctx, u32 mask, const char *path);
|
||||
|
||||
/**
|
||||
* Stop a watch, clear all references and free memory
|
||||
*/
|
||||
HiResult file_watch_remove(FileWatcherContext *ctx, const char *path);
|
||||
|
||||
/**
|
||||
* Free memory and clear all watches in this context
|
||||
*/
|
||||
void file_watch_destroy_watches(FileWatcherContext *ctx);
|
||||
|
||||
#endif // FILEWATCH_H_
|
||||
|
||||
@@ -27,8 +27,8 @@ typedef struct sc_array_fwparam VectorWatchParams;
|
||||
* reused, and @a files is a list of files that have this watch as their parent.
|
||||
*/
|
||||
typedef struct FileWatch {
|
||||
i32 wd; // Watch descriptor
|
||||
u32 mask; // watch mask used
|
||||
i32 wd;
|
||||
u32 mask;
|
||||
const char *path; // Owning
|
||||
VectorStr files;
|
||||
} FileWatch;
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
sc_array_def(FileEvent, fwevent);
|
||||
typedef struct sc_array_fwevent VectorFileEvent;
|
||||
|
||||
/**
|
||||
* All context and state required to run a file watcher.
|
||||
*/
|
||||
typedef struct FileWatcher {
|
||||
thrd_t thread;
|
||||
mtx_t mutex;
|
||||
@@ -31,10 +34,10 @@ typedef struct FileWatcher {
|
||||
VectorFileEvent events;
|
||||
} FileWatcher;
|
||||
|
||||
|
||||
/*
|
||||
* Watch Params
|
||||
*/
|
||||
|
||||
static inline WatchParams watch_params_create(const char *path, u32 mask) {
|
||||
return (WatchParams){.path = strdup(path), .mask = mask};
|
||||
}
|
||||
@@ -46,7 +49,7 @@ static inline void watch_params_destroy(WatchParams *params) {
|
||||
static WatchParams *watch_params_find_by_path(const char *path,
|
||||
FileWatcherContext *ctx,
|
||||
size_t *index) {
|
||||
const struct sc_array_fwparam *params = &ctx->params;
|
||||
const VectorWatchParams *params = &ctx->params;
|
||||
for (size_t i = 0; i < sc_array_size(params); ++i) {
|
||||
WatchParams *param = &sc_array_at(params, i);
|
||||
if (strcmp(path, param->path) == 0) {
|
||||
@@ -140,7 +143,7 @@ static FileEvent file_event_create(const struct inotify_event *inevent,
|
||||
return NULL_EVENT;
|
||||
}
|
||||
|
||||
FileEvent hi_file_event_pop(FileWatcher *fw) {
|
||||
FileEvent file_event_pop(FileWatcher *fw) {
|
||||
mtx_lock(&fw->mutex);
|
||||
|
||||
FileEvent e = NULL_EVENT;
|
||||
@@ -178,7 +181,7 @@ static void file_watcher_ctx_destroy(FileWatcherContext *ctx) {
|
||||
// Declare the thread func
|
||||
int file_watcher_watch(void *arg);
|
||||
|
||||
FileWatcher *hi_file_watcher_create() {
|
||||
FileWatcher *file_watcher_create() {
|
||||
|
||||
// Allocate context
|
||||
FileWatcher *fw = malloc(sizeof(FileWatcher));
|
||||
@@ -204,7 +207,7 @@ FileWatcher *hi_file_watcher_create() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HiResult hi_file_watcher_add(FileWatcher *fw, const char *filename, u32 flags) {
|
||||
HiResult file_watcher_add(FileWatcher *fw, const char *filename, u32 flags) {
|
||||
if (!fw) {
|
||||
sc_log_error("Attempted to add file watcher for '%s' with null context\n",
|
||||
filename);
|
||||
@@ -257,19 +260,19 @@ HiResult hi_file_watcher_remove(FileWatcher *fw, const char *filename) {
|
||||
return HI_OK;
|
||||
}
|
||||
|
||||
void hi_file_watcher_notify(FileWatcher *fw) {
|
||||
void file_watcher_notify(FileWatcher *fw) {
|
||||
if (fw && fw->running) {
|
||||
cnd_signal(&fw->cond);
|
||||
}
|
||||
}
|
||||
|
||||
void hi_file_watcher_destroy(FileWatcher *fw) {
|
||||
void file_watcher_destroy(FileWatcher *fw) {
|
||||
if (!fw)
|
||||
return;
|
||||
|
||||
if (fw->running) {
|
||||
fw->running = false;
|
||||
hi_file_watcher_notify(fw);
|
||||
file_watcher_notify(fw);
|
||||
thrd_join(fw->thread, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,9 @@
|
||||
* memory inside the file watcher struct.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *pathname; // Pathname given to a `hi_file_watcher_add` call.
|
||||
// Do not free.
|
||||
/** Path of the file this event is about. Do not free. */
|
||||
const char *pathname;
|
||||
/** Might not be only those given to @a file_watcher_add. */
|
||||
FileWatchType type;
|
||||
} FileEvent;
|
||||
|
||||
@@ -31,44 +32,38 @@ typedef struct FileWatcher FileWatcher;
|
||||
/**
|
||||
* FileEvents is a thread safe list of events.
|
||||
*
|
||||
* It is implemented as a stack, so the events will be popped
|
||||
* in reverse chronological order.
|
||||
* */
|
||||
* Events will be popped mostly in reverse chronological order, but strict
|
||||
* chronology is not guaranteed.
|
||||
*/
|
||||
typedef struct FileEvents FileEvents;
|
||||
|
||||
/**
|
||||
* Create watcher and necessary data to run it.
|
||||
*
|
||||
* Will start the watcher thread immediately.
|
||||
* Starts a new watcher thread immediately.
|
||||
*/
|
||||
FileWatcher *hi_file_watcher_create(void);
|
||||
FileWatcher *file_watcher_create(void);
|
||||
|
||||
/**
|
||||
* Destroy a previously created file watcher context.
|
||||
* Destroy a previously created file watcher.
|
||||
*
|
||||
* Will join the thread and destroy event stack.
|
||||
* Will join the thread and destroy event stack. Any FileEvent still in
|
||||
* existence will contain invalid data after this call.
|
||||
*/
|
||||
void hi_file_watcher_destroy(FileWatcher *context);
|
||||
void file_watcher_destroy(FileWatcher *fw);
|
||||
|
||||
/**
|
||||
* Add a file to the watch list of a file watcher.
|
||||
* Start watching for events on a file.
|
||||
*
|
||||
* @param context Previously created watcher context
|
||||
* @param fw The watcher instance
|
||||
* @param pathname Absolute path to the file or directory
|
||||
* @param flags The events that will be watched for
|
||||
* @param flags The event mask for the events to watch for
|
||||
*/
|
||||
HiResult hi_file_watcher_add(FileWatcher *context,
|
||||
const char *pathname, u32 flags);
|
||||
/**
|
||||
* Can be used to poke file watcher thread to make sure it empties
|
||||
* events before doing something, e.g. for shutting it down.
|
||||
*/
|
||||
void hi_file_watcher_notify(FileWatcher *context);
|
||||
HiResult file_watcher_add(FileWatcher *fw, const char *pathname, u32 flags);
|
||||
|
||||
/**
|
||||
* Pop an event from event stack. Call `hi_file_event_destroy` when done with
|
||||
* it.
|
||||
* Pop an event from event stack.
|
||||
*/
|
||||
FileEvent hi_file_event_pop(FileWatcher *ctx);
|
||||
FileEvent file_event_pop(FileWatcher *ctx);
|
||||
|
||||
#endif // HI_FILEWATCHER_H_
|
||||
|
||||
12
src/hiload.c
12
src/hiload.c
@@ -71,7 +71,7 @@ static int gather_module_data_callback(struct dl_phdr_info *info, size_t size,
|
||||
|
||||
// Mark everything but system and virtual modules as patchable
|
||||
if (module.name[0] == '/') {
|
||||
if (!hi_string_starts_with(module.name, ARRLEN(module_exclude_filter),
|
||||
if (!hi_str_starts_with(module.name, ARRLEN(module_exclude_filter),
|
||||
module_exclude_filter)) {
|
||||
module.info = hi_modinfo_add(module.info, HI_MODULE_STATE_PATCHABLE);
|
||||
}
|
||||
@@ -89,7 +89,7 @@ static int gather_module_data_callback(struct dl_phdr_info *info, size_t size,
|
||||
// Replace shortform with str pointer from module info
|
||||
sc_array_at(&context.enabled_modules, i) = module.name;
|
||||
|
||||
if (!HIOK(hi_file_watcher_add(context.filewatcher, modpath,
|
||||
if (!HIOK(file_watcher_add(context.filewatcher, modpath,
|
||||
HI_FILE_ALL_EVENTS))) {
|
||||
log_error("Failed to set filewatcher for: '%s'\n", modpath);
|
||||
} else {
|
||||
@@ -151,7 +151,7 @@ static ModuleData *get_module_by_path(const char *path,
|
||||
*/
|
||||
static void handle_events(FileWatcher *fw, VectorModuleData *modules) {
|
||||
|
||||
FileEvent event = hi_file_event_pop(fw);
|
||||
FileEvent event = file_event_pop(fw);
|
||||
while (event.type != HI_FILE_NONE) {
|
||||
log_debug("Event pop: %s – %s\n", event.pathname,
|
||||
hi_file_watch_type_to_str(event.type));
|
||||
@@ -162,7 +162,7 @@ static void handle_events(FileWatcher *fw, VectorModuleData *modules) {
|
||||
} else {
|
||||
module->info = hi_modinfo_add(module->info, HI_MODULE_STATE_DIRTY);
|
||||
}
|
||||
event = hi_file_event_pop(context.filewatcher);
|
||||
event = file_event_pop(context.filewatcher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ int hi_init(size_t n, const char **enabled_modules) {
|
||||
log_set_thread_name("Main");
|
||||
|
||||
// Start the filewatcher
|
||||
context.filewatcher = hi_file_watcher_create();
|
||||
context.filewatcher = file_watcher_create();
|
||||
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
const char *module_name = enabled_modules[i];
|
||||
@@ -241,7 +241,7 @@ int hi_init(size_t n, const char **enabled_modules) {
|
||||
|
||||
void hi_deinit() {
|
||||
module_infos_free(&context.modules);
|
||||
hi_file_watcher_destroy(context.filewatcher);
|
||||
file_watcher_destroy(context.filewatcher);
|
||||
log_term();
|
||||
memset(&context, 0, sizeof(context));
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ HiResult memory_find_region(uptr ptr, struct sc_array_memreg *const regions,
|
||||
HiResult read_memory_maps_self(struct sc_array_memreg *regions) {
|
||||
memory_clear_memregs(regions);
|
||||
|
||||
char *maps_str = hi_file_to_str_dyn("/proc/self/maps");
|
||||
char *maps_str = file_to_str_dyn("/proc/self/maps");
|
||||
if (!maps_str)
|
||||
return HI_FAIL;
|
||||
|
||||
|
||||
@@ -135,8 +135,8 @@ static HiResult gather_patchable_symbols(struct sc_array_sym *symbols,
|
||||
}
|
||||
|
||||
void *sym_addr = (void *)((uintptr_t)module_base + sym.st_value);
|
||||
HiSymbolBind binding = symbol_bind_from_efibind(GELF_ST_BIND(sym.st_info));
|
||||
HiSymbolType type = symbol_type_from_efitype(GELF_ST_TYPE(sym.st_info));
|
||||
SymbolBind binding = symbol_bind_from_efibind(GELF_ST_BIND(sym.st_info));
|
||||
SymbolType type = symbol_type_from_efitype(GELF_ST_TYPE(sym.st_info));
|
||||
size_t size = sym.st_size;
|
||||
|
||||
// Gather global symbols and local object symbols. Local functions are
|
||||
@@ -145,7 +145,7 @@ static HiResult gather_patchable_symbols(struct sc_array_sym *symbols,
|
||||
if (binding == HI_SYMBOL_BIND_GLOBAL ||
|
||||
(binding == HI_SYMBOL_BIND_LOCAL &&
|
||||
type == HI_SYMBOL_TYPE_OBJECT)) {
|
||||
HiSymbol hisym = {.name = strdup(name),
|
||||
Symbol hisym = {.name = strdup(name),
|
||||
.size = size,
|
||||
.binding = binding,
|
||||
.type = type,
|
||||
@@ -166,7 +166,7 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HiResult moduler_apply_module_patch(HiSymbols *psymbols,
|
||||
static HiResult moduler_apply_module_patch(VectorSymbol *psymbols,
|
||||
MemoryRegionSpan module_memory) {
|
||||
|
||||
void *module_base = (void *)module_memory.region_start;
|
||||
@@ -246,7 +246,7 @@ static HiResult moduler_apply_module_patch(HiSymbols *psymbols,
|
||||
|
||||
// Check if this is a symbol we want to patch
|
||||
for (size_t j = 0; j < num_symbols; j++) {
|
||||
HiSymbol *sym = &sc_array_at(psymbols, j);
|
||||
Symbol *sym = &sc_array_at(psymbols, j);
|
||||
if (strcmp(sym->name, name) == 0) {
|
||||
sym->got_entry = got_entry;
|
||||
sym->orig_address = *got_entry; // Save the original function
|
||||
@@ -280,7 +280,7 @@ PatchData moduler_create_patch(ModuleData *module) {
|
||||
|
||||
char filename[512];
|
||||
size_t written =
|
||||
hi_strncat_buf(sizeof(filename), filename, module->name, file_append);
|
||||
hi_str_concat_buf(sizeof(filename), filename, module->name, file_append);
|
||||
|
||||
|
||||
if (written == 0) {
|
||||
@@ -288,7 +288,7 @@ PatchData moduler_create_patch(ModuleData *module) {
|
||||
return (PatchData){0};
|
||||
}
|
||||
|
||||
hi_file_copy(module->name, filename);
|
||||
file_copy(module->name, filename);
|
||||
|
||||
PatchData data = {.filename = strdup(filename)};
|
||||
return data;
|
||||
@@ -328,7 +328,7 @@ HiResult moduler_reload(VectorModuleData *modules, ModuleData *module,
|
||||
patch.memreg = memory_get_module_span(memregs, patch.filename);
|
||||
void *patch_base = (void *)patch.memreg.region_start;
|
||||
|
||||
HiSymbols patch_symbols;
|
||||
VectorSymbol patch_symbols;
|
||||
symbol_init_symbols(&patch_symbols);
|
||||
|
||||
HiResult ret =
|
||||
@@ -352,7 +352,7 @@ HiResult moduler_reload(VectorModuleData *modules, ModuleData *module,
|
||||
// If patch is for the same module, also collect local object symbols for
|
||||
// coping those over.
|
||||
|
||||
HiSymbols module_symbols;
|
||||
VectorSymbol module_symbols;
|
||||
symbol_init_symbols(&module_symbols);
|
||||
ret = gather_patchable_symbols(&module_symbols, mod.name,
|
||||
(void *)mod.address);
|
||||
@@ -364,9 +364,9 @@ HiResult moduler_reload(VectorModuleData *modules, ModuleData *module,
|
||||
|
||||
// Copy old data to new data. Breaks with layout changes.
|
||||
for (size_t i = 0; i < sc_array_size(&module_symbols); ++i) {
|
||||
HiSymbol *sym = &sc_array_at(&module_symbols, i);
|
||||
Symbol *sym = &sc_array_at(&module_symbols, i);
|
||||
if (sym->type == HI_SYMBOL_TYPE_OBJECT) {
|
||||
HiSymbol *ps = symbol_find(&patch_symbols, sym);
|
||||
Symbol *ps = symbol_find(&patch_symbols, sym);
|
||||
if (ps) {
|
||||
if (ps->size >= sym->size) {
|
||||
memcpy(ps->address, sym->address, sym->size);
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
size_t hi_strncat_buf(size_t buflen, char buf[buflen], const char *first, const char *second) {
|
||||
if (!buf) return 0;
|
||||
size_t hi_str_concat_buf(size_t buflen, char buf[buflen], const char *first,
|
||||
const char *second) {
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
size_t first_len = strlen(first);
|
||||
size_t second_len = strlen(second);
|
||||
@@ -17,8 +19,8 @@ size_t hi_strncat_buf(size_t buflen, char buf[buflen], const char *first, const
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * first_end = buf + first_len;
|
||||
char * second_end = first_end + second_len;
|
||||
char *first_end = buf + first_len;
|
||||
char *second_end = first_end + second_len;
|
||||
|
||||
strncpy(buf, first, first_end - buf);
|
||||
strncpy(first_end, second, second_end - first_end);
|
||||
@@ -42,7 +44,7 @@ int hi_path_has_filename(const char *path, const char *filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *hi_string_from_file_dyn(const char *filename, size_t *nread,
|
||||
char *hi_str_from_file(const char *filename, size_t *nread,
|
||||
size_t nmax) {
|
||||
|
||||
FILE *f = fopen(filename, "r");
|
||||
@@ -105,11 +107,13 @@ char *hi_string_from_file_dyn(const char *filename, size_t *nread,
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *hi_string_starts_with(const char path[static 1], size_t listn, const char *pathlist[listn]) {
|
||||
const char *hi_str_starts_with(const char path[static 1], size_t listn,
|
||||
const char *pathlist[listn]) {
|
||||
|
||||
if (!pathlist) return path;
|
||||
if (!pathlist)
|
||||
return path;
|
||||
size_t pathlen = strlen(path);
|
||||
for (size_t i=0; i < listn; ++i) {
|
||||
for (size_t i = 0; i < listn; ++i) {
|
||||
size_t len = MIN(strlen(pathlist[i]), pathlen);
|
||||
if (strncmp(path, pathlist[i], len) == 0) {
|
||||
return pathlist[i];
|
||||
|
||||
@@ -6,40 +6,47 @@
|
||||
/**
|
||||
* Concatenate two strings into a buffer.
|
||||
*
|
||||
* If resulting string would be longer than buflen - 1, the resulting string in
|
||||
* \p buf is unchanged.
|
||||
* If resulting string would be longer than @a buflen - 1, the resulting string
|
||||
* in
|
||||
* @a buf is unchanged.
|
||||
*
|
||||
* @param first Null terminated character string
|
||||
* @param second Null terminated character string
|
||||
*/
|
||||
size_t hi_strncat_buf(size_t bufsize, char buf[bufsize], const char *first,
|
||||
const char *second);
|
||||
size_t hi_str_concat_buf(size_t bufsize, char buf[bufsize],
|
||||
const char *first, const char *second);
|
||||
|
||||
/**
|
||||
* @brief Copy file content to a null terminated string, allocating memory while
|
||||
* Copy file content to a null terminated string, allocating memory while
|
||||
* reading.
|
||||
*
|
||||
* This doesn't assume it can read file size, so it allocates memory in chunks
|
||||
* (default 4096 bytes) and keeps reading until 0 bytes is read. If nmax is
|
||||
* non-zero, instead that amount of bytes is allocated and that is read.
|
||||
* Can be used for reading the virtual file system, where the file size isn't
|
||||
* known. If @a nmax is non-zero, that amount of bytes is allocated and read at
|
||||
* once. No more than @a nmax bytes is read in that case.
|
||||
*
|
||||
* In either case, the string is reallocated to match the length before
|
||||
* In all cases, the string is reallocated to match the length before
|
||||
* returning.
|
||||
*
|
||||
* @param filename a complete pathname to the file
|
||||
* @param nread if not null, this will have the total amount bytes read
|
||||
* @param nmax if not 0, this amount of memory in bytes is read and used as
|
||||
* initial allocation
|
||||
*/
|
||||
char *hi_string_from_file_dyn(const char *filename, size_t *nread, size_t nmax);
|
||||
char *hi_str_from_file(const char *filename, size_t *nread,
|
||||
size_t nmax);
|
||||
|
||||
/**
|
||||
* Find if filename exists at the end of path.
|
||||
* Return the first string from @a pathlist that is fully included in @a path.
|
||||
*/
|
||||
const char *hi_str_starts_with(const char path[static 1], size_t listn,
|
||||
const char *pathlist[listn]);
|
||||
|
||||
|
||||
/**
|
||||
* Find if @a filename exists at the end of @a path.
|
||||
*
|
||||
* @return 0 if not found, positive if found
|
||||
*/
|
||||
int hi_path_has_filename(const char *path, const char *filename);
|
||||
|
||||
const char *hi_string_starts_with(const char path[static 1], size_t listn,
|
||||
const char *pathlist[listn]);
|
||||
|
||||
#endif // HI_STRING_H_
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include <elf.h>
|
||||
#include <string.h>
|
||||
|
||||
HiSymbol *symbol_find(HiSymbols *symbols, HiSymbol *symbol) {
|
||||
Symbol *symbol_find(VectorSymbol *symbols, Symbol *symbol) {
|
||||
for (size_t i=0; i < sc_array_size(symbols); ++i) {
|
||||
HiSymbol *s = &sc_array_at(symbols, i);
|
||||
Symbol *s = &sc_array_at(symbols, i);
|
||||
if (strcmp(s->name, symbol->name) == 0) {
|
||||
return s;
|
||||
}
|
||||
@@ -14,7 +14,7 @@ HiSymbol *symbol_find(HiSymbols *symbols, HiSymbol *symbol) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HiSymbolBind symbol_bind_from_efibind(u32 efi_bind) {
|
||||
SymbolBind symbol_bind_from_efibind(u32 efi_bind) {
|
||||
// clang-format off
|
||||
switch (efi_bind) {
|
||||
case STB_LOCAL: return HI_SYMBOL_BIND_LOCAL;
|
||||
@@ -25,7 +25,7 @@ HiSymbolBind symbol_bind_from_efibind(u32 efi_bind) {
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
HiSymbolType symbol_type_from_efitype(u32 efi_type) {
|
||||
SymbolType symbol_type_from_efitype(u32 efi_type) {
|
||||
// clang-format off
|
||||
switch (efi_type) {
|
||||
case STT_NOTYPE: return HI_SYMBOL_TYPE_NOTYPE; /* Symbol type is unspecified */
|
||||
|
||||
@@ -9,7 +9,7 @@ typedef enum {
|
||||
HI_SYMBOL_BIND_LOCAL,
|
||||
HI_SYMBOL_BIND_GLOBAL,
|
||||
HI_SYMBOL_BIND_WEAK,
|
||||
} HiSymbolBind;
|
||||
} SymbolBind;
|
||||
|
||||
typedef enum {
|
||||
HI_SYMBOL_TYPE_NOTYPE,
|
||||
@@ -19,39 +19,41 @@ typedef enum {
|
||||
HI_SYMBOL_TYPE_FILE,
|
||||
HI_SYMBOL_TYPE_COMMON,
|
||||
HI_SYMBOL_TYPE_TLS,
|
||||
} HiSymbolType;
|
||||
} SymbolType;
|
||||
|
||||
typedef struct HiSymbol {
|
||||
typedef struct Symbol {
|
||||
const char *name;
|
||||
HiSymbolBind binding;
|
||||
HiSymbolType type;
|
||||
SymbolBind binding;
|
||||
SymbolType type;
|
||||
size_t size;
|
||||
void *address;
|
||||
void **got_entry;
|
||||
void *orig_address;
|
||||
} HiSymbol;
|
||||
sc_array_def(HiSymbol, sym);
|
||||
typedef struct sc_array_sym HiSymbols;
|
||||
} Symbol;
|
||||
|
||||
static inline void symbol_free(HiSymbol *symbol) { free((char *)symbol->name); }
|
||||
sc_array_def(Symbol, sym);
|
||||
typedef struct sc_array_sym VectorSymbol;
|
||||
|
||||
static inline void symbol_init_symbols(HiSymbols *symbols) {
|
||||
static inline void symbol_free(Symbol *symbol) { free((char *)symbol->name); }
|
||||
|
||||
static inline void symbol_init_symbols(VectorSymbol *symbols) {
|
||||
sc_array_init(symbols);
|
||||
}
|
||||
static inline void symbol_clear_symbols(HiSymbols *symbols) {
|
||||
static inline void symbol_clear_symbols(VectorSymbol *symbols) {
|
||||
for (size_t i = 0; i < sc_array_size(symbols); ++i) {
|
||||
symbol_free(&sc_array_at(symbols, i));
|
||||
}
|
||||
sc_array_clear(symbols);
|
||||
}
|
||||
|
||||
static inline void symbol_term_symbols(HiSymbols *symbols) {
|
||||
static inline void symbol_term_symbols(VectorSymbol *symbols) {
|
||||
symbol_clear_symbols(symbols);
|
||||
sc_array_term(symbols);
|
||||
}
|
||||
|
||||
HiSymbol *symbol_find(HiSymbols *symbols, HiSymbol *symbol);
|
||||
Symbol *symbol_find(VectorSymbol *symbols, Symbol *symbol);
|
||||
|
||||
SymbolBind symbol_bind_from_efibind(u32 efi_bind);
|
||||
SymbolType symbol_type_from_efitype(u32 efi_type);
|
||||
|
||||
HiSymbolBind symbol_bind_from_efibind(u32 efi_bind);
|
||||
HiSymbolType symbol_type_from_efitype(u32 efi_type);
|
||||
#endif // SYMBOLS_H_
|
||||
|
||||
Reference in New Issue
Block a user