diff --git a/linux_load_time/build.sh b/linux_load_time/build.sh new file mode 100644 index 0000000..3e659a8 --- /dev/null +++ b/linux_load_time/build.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Path setup +src=$PWD +cd .. +mkdir -p build +cd build + + +#### THE ARRANGEMENT OF THIS BUILD #### +# The "base layer" must be built and shared by all dynamic components. +# In this example the the base layer is linked via load-time linking with the other modules. +# The "plugin" is loaded at run-time. + + +# Build the base layer as a .so +gcc -fvisibility=hidden -fPIC -shared $src/linux_base.c -o linux_base.so + + +# Build the executable; provide the base layer's load-time linking data via linux_base.so +gcc -fvisibility=hidden $src/linux_main.c linux_base.so -o linux_main -Wl,-rpath,\$ORIGIN/ + + +# Build the plugin as a .so; provide the base layer's load-time linking data via linux_base.so +gcc -fvisibility=hidden -fPIC -shared $src/linux_plugin.c linux_base.so -o linux_plugin.so -Wl,-rpath,\$ORIGIN/ + diff --git a/linux_load_time/linux_base.c b/linux_load_time/linux_base.c new file mode 100644 index 0000000..45059fb --- /dev/null +++ b/linux_load_time/linux_base.c @@ -0,0 +1,11 @@ +// declare base_func; mark it as an exported symbol +__attribute__ ((visibility ("default"))) void base_func(void); + +// define base_func +#include +int x = 0; +__attribute__ ((visibility ("default"))) void +base_func(void){ + printf("x = %d\n", x); + x += 1; +} diff --git a/linux_load_time/linux_main.c b/linux_load_time/linux_main.c new file mode 100644 index 0000000..e2095fc --- /dev/null +++ b/linux_load_time/linux_main.c @@ -0,0 +1,38 @@ +// declare base_func; no mark -> load-time imported symbol +void base_func(void); + + +// setup plugin_func as a function pointer so that it can be linked at run time +typedef void PLUGIN_Func(void); +PLUGIN_Func *plugin_func = 0; + + +// need to include for dlopen and dlsym +#include + +// helper macro for dlsym that handles the casting of function pointers +#define GET_PROC(var,mod,name) *((void**)(&(var))) = dlsym((mod),(name)) + + +int main(){ + + // functions linked by load-time linking can be called directly without further setup + base_func(); + + + // to call a function with run-time linking, we must manually load and link it + void *module = dlopen("./linux_plugin.so", RTLD_NOW); + if (module != 0){ + GET_PROC(plugin_func, module, "plugin_func"); + } + + + // calls to plugin_func only work after the "plugin" loaded successfully + if (plugin_func != 0){ + plugin_func(); + } + + + // demonstration: the data structures contained in the 'base' are not duplicated in each binary + base_func(); +} diff --git a/linux_load_time/linux_plugin.c b/linux_load_time/linux_plugin.c new file mode 100644 index 0000000..2a34763 --- /dev/null +++ b/linux_load_time/linux_plugin.c @@ -0,0 +1,17 @@ +// declare base_func; no mark -> load-time imported symbol +void base_func(void); + +// declare base_func; mark it as an exported symbol +__attribute__ ((visibility ("default"))) void plugin_func(void); + +// define plugin_func +#include +__attribute__ ((visibility ("default"))) void +plugin_func(void){ + printf("provided by plugin: {\n"); + printf(" "); + base_func(); + printf(" "); + base_func(); + printf("}\n"); +} diff --git a/win32_load_time/build.bat b/win32_load_time/build.bat index d7e5898..2bfbb0a 100644 --- a/win32_load_time/build.bat +++ b/win32_load_time/build.bat @@ -1,12 +1,14 @@ @echo off -SET src=%cd% +REM: Path setup +SET src=%cd% cd .. if not exist "build\" mkdir build cd build -REM: ## The arrangement of this build ## + +REM: ### THE ARRANGEMENT OF THIS BUILD ### REM: The "base layer" must be built and shared by all dynamic components. REM: In this example the the base layer is linked via load-time linking with the other modules. REM: The "plugin" is loaded at run-time.