>From 3e840b158f7a9949457273ec070f35ab03b04ade Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Fri, 19 Oct 2012 22:49:56 +0200 Subject: [PATCH] libtool: add @INIT@ to the preloader, for data imports on Windows * build-aux/ltmain.in (func_generate_dlsyms) [MSVC]: Mark all data symbols __declspec(dllimport) and handle static libraries and import libraries equivalently. Generate a relocation function lt_syminit that fills in the addresses of data items and point it out with a new virtual @INIT@ entry in the symbol list. * m4/libtool.m4 (_LT_CMD_GLOBAL_SYMBOLS) [MSVC]: Adjust lt_cv_sys_global_symbol_to_c_name_address and lt_cv_sys_global_symbol_to_c_name_address_lib_prefix so that they fill in "(void*) 0" for data symbols which need to be relocated at runtime by the above lt_syminit. * libltdl/loaders/preopen.c (add_symlist): Look up the virtual @INIT@ symbol (i.e. lt_syminit) and call it if non-zero. (vm_sym, lt_dlpreload_open): Step past the @INIT@ symbol. * tests/demo.at (dlmain.c): Call the @INIT@ symbol if non-zero. --- build-aux/ltmain.in | 26 +++++++++++++++++++++++--- libltdl/loaders/preopen.c | 22 ++++++++++++++++++++-- m4/libtool.m4 | 2 ++ tests/demo.at | 2 ++ 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/build-aux/ltmain.in b/build-aux/ltmain.in index ed4a4b1..a153df0 100644 --- a/build-aux/ltmain.in +++ b/build-aux/ltmain.in @@ -2659,6 +2659,11 @@ extern \"C\" { #else # define LT_DLSYM_CONST const #endif +#if defined _WIN32 && defined _MSC_VER +#define LT_DLSYM_DATA extern __declspec(dllimport) +#else +#define LT_DLSYM_DATA extern +#endif /* External symbol declarations for the compiler. */\ " @@ -2793,7 +2798,7 @@ extern \"C\" { fi if test -f "$nlist"S; then - eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + eval "$global_symbol_to_cdecl"' < "$nlist"S' | $SED 's/^extern char /LT_DLSYM_DATA char /' >> "$output_objdir/$my_dlsyms" else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi @@ -2807,10 +2812,25 @@ typedef struct { } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; +static void lt_syminit(void) +{ +#if defined _WIN32 && defined _MSC_VER + LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; + for (; symbol->name; ++symbol) + {\ +" + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S' | $SED -n 's/extern char \([^;]*\).*/if (!strcmp (symbol->name, \"\1\")) symbol->address = (void *) \&\1;/p' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + } +#endif +} LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = -{\ - { \"$my_originator\", (void *) 0 }," +{ {\"$my_originator\", (void *) 0}, + {\"@address@hidden", (void *) <_syminit}," case $need_lib_prefix in no) diff --git a/libltdl/loaders/preopen.c b/libltdl/loaders/preopen.c index 1670085..432f552 100644 --- a/libltdl/loaders/preopen.c +++ b/libltdl/loaders/preopen.c @@ -210,7 +210,7 @@ vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name) { lt_dlsymlist *symbol = (lt_dlsymlist*) module; - symbol +=2; /* Skip header (originator then libname). */ + symbol +=3; /* Skip header (originator, init then libname). */ while (symbol->name) { @@ -270,9 +270,25 @@ add_symlist (const lt_dlsymlist *symlist) if (tmp) { + const lt_dlsymlist *symbol; + tmp->symlist = symlist; tmp->next = preloaded_symlists; preloaded_symlists = tmp; + + for (symbol = symlist; symbol->name; ++symbol) + { + if (STREQ (symbol->name, "@INIT@")) + { + if (symbol->address) + { + void (*init_symlist)(void); + *(void **)(&init_symlist) = symbol->address; + init_symlist(); + } + break; + } + } } else { @@ -345,7 +361,9 @@ lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func) ++found; /* ...load the symbols per source compilation unit: - (we preincrement the index to skip over the originator entry) */ + (we increment the index once to skip over the originator entry + and then preincrement to also skip the init entry) */ + ++idx; while ((symbol = &list->symlist[++idx])->name != 0) { if ((symbol->address == 0) diff --git a/m4/libtool.m4 b/m4/libtool.m4 index c85a85f..a7c3f4f 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -3674,6 +3674,8 @@ for ac_symprfx in "" "_"; do # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^T \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^D \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) 0},/p'" + lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^T \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^T \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p' -e 's/^D \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) 0},/p' -e 's/^T \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) 0},/p'" # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, diff --git a/tests/demo.at b/tests/demo.at index b3d2532..1c4e91e 100644 --- a/tests/demo.at +++ b/tests/demo.at @@ -295,6 +295,8 @@ int main () if (s->address) { const char *name = s->name; printf ("found symbol: %s\n", name); + if (STREQ ("@INIT@", name) && s->address) + ((void(*)())s->address)(); if (STREQ ("hello", name)) phello = (int(*)())s->address; else if (STREQ ("foo", name)) -- 1.7.9