redirect: Make it easier to define new bindings

We add some new helpers to make it simpler to define a vtable and
populate it with some symbol binding helper functions.

Signed-off-by: Ikey Doherty <ikey@solus-project.com>
This commit is contained in:
Ikey Doherty
2017-10-24 00:33:55 +01:00
parent a89de2bb58
commit e2325befba
+58 -24
View File
@@ -28,6 +28,14 @@
#include "profile.h"
#include "redirect.h"
#define _STRINGIFY(x) #x
#define SYMBOL_BINDING(l, x) \
{ \
.handle = &lsi_table.handles.l, .name = _STRINGIFY(x), \
.func = (void **)(&lsi_table.x), .func_size = sizeof(lsi_table.x) \
}
/**
* Whether we've initialised yet or not.
*/
@@ -67,6 +75,16 @@ typedef struct LsiRedirectTable {
} handles;
} LsiRedirectTable;
/**
* Easy mapping to make it quick and easy to add new function overrides
*/
typedef struct LsiSymbolBinding {
void **handle;
char *name;
void **func;
size_t func_size;
} LsiSymbolBinding;
/**
* Our redirect instance, stack only.
*/
@@ -77,6 +95,15 @@ static LsiRedirectTable lsi_table = { 0 };
*/
static LsiRedirectProfile *lsi_profile = NULL;
/**
* Our current set of libc bindings. This sets up the LsiRedirectTable with
* all of our needed dlsym() functions from libc.so.6.
*/
static LsiSymbolBinding lsi_libc_bindings[] = {
SYMBOL_BINDING(libc, open),
SYMBOL_BINDING(libc, fopen64),
};
/**
* We'll only perform teardown code if the process doesn't `abort()` or `_exit()`
*/
@@ -98,6 +125,28 @@ __attribute__((destructor)) static void lsi_redirect_shutdown(void)
}
}
/**
* Internal helper to perform the symbol binding
*/
static bool lsi_redirect_bind_function(void *handle, const char *name, void **out_func,
size_t func_size)
{
void *symbol_lookup = NULL;
char *dl_error = NULL;
/* Safely look up the symbol */
symbol_lookup = dlsym(handle, name);
dl_error = dlerror();
if (dl_error || !symbol_lookup) {
fprintf(stderr, "Failed to bind '%s': %s\n", name, dl_error);
return false;
}
/* Have the symbol correctly, copy it to make it usable */
memcpy(out_func, &symbol_lookup, func_size);
return true;
}
/**
* Responsible for setting up the vfunc redirect table so that we're able to
* get `open` and such working before we've hit the constructor, and ensure
@@ -105,9 +154,6 @@ __attribute__((destructor)) static void lsi_redirect_shutdown(void)
*/
static void lsi_redirect_init_tables(void)
{
void *symbol_lookup = NULL;
char *dl_error = NULL;
if (lsi_init) {
return;
}
@@ -123,29 +169,17 @@ static void lsi_redirect_init_tables(void)
goto failed;
}
/* Safely look up the symbol */
symbol_lookup = dlsym(lsi_table.handles.libc, "open");
dl_error = dlerror();
if (dl_error || !symbol_lookup) {
fprintf(stderr, "Failed to bind 'open': %s\n", dl_error);
goto failed;
/* Hook up all necessary symbol binding */
for (size_t i = 0; i < ARRAY_SIZE(lsi_libc_bindings); i++) {
LsiSymbolBinding *binding = &lsi_libc_bindings[i];
if (!lsi_redirect_bind_function(*(binding->handle),
binding->name,
binding->func,
binding->func_size)) {
goto failed;
}
}
/* Have the symbol correctly, copy it to make it usable */
memcpy(&lsi_table.open, &symbol_lookup, sizeof(lsi_table.open));
symbol_lookup = NULL;
/* Safely look up the fopen64 symbol */
symbol_lookup = dlsym(lsi_table.handles.libc, "fopen64");
dl_error = dlerror();
if (dl_error || !symbol_lookup) {
fprintf(stderr, "Failed to bind 'fopen64': %s\n", dl_error);
goto failed;
}
/* Have the symbol correctly, copy it to make it usable */
memcpy(&lsi_table.fopen64, &symbol_lookup, sizeof(lsi_table.fopen64));
/* We might not get an unload, so chain onto atexit */
atexit(lsi_redirect_shutdown);
return;