summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Rosin <peda@lysator.liu.se>2012-11-02 23:50:43 +0100
committerPeter Rosin <peda@lysator.liu.se>2012-11-02 23:50:43 +0100
commit34fe402efa1e969cf902cf7370e29564c005d508 (patch)
treeb68d63d35641b1b15d7597d65a40e395d37f80e9
parent2ed79f5937f28958b4fdf0b3aeed7330d675d2a1 (diff)
downloadlibtool-34fe402efa1e969cf902cf7370e29564c005d508.tar.gz
libtool: add @INIT@ to the preloader, for data imports on Windows
* m4/libtool.m4 (_LT_CMD_GLOBAL_SYMBOLS) [dumpbin]: Adjust lt_cv_sys_global_symbol_to_cdecl so that it declares imported data symbols as __declspec(dllimport). 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 imported data symbols. Add new lt_cv_sys_global_symbol_to_import which finds imported data symbols if non-empty and export this variable to the libtool script in the global_symbol_to_import variable. Adjust lt_cv_sys_global_symbol_pipe so that data imports can be located. * build-aux/ltmain.in (func_generate_dlsyms): When data imports are present, as indicated by global_symbol_to_import, generate a relocation function lt_syminit that fills in the addresses of data imports at runtime and point to the new function with a new virtual @INIT@ entry in the symbol list. * libltdl/loaders/preopen.c (add_symlist): Look for the virtual @INIT@ symbol (i.e. lt_syminit) and call it. (vm_sym): Step past the @INIT@ symbol, if present. * tests/demo.at (dlmain.c): Call the @INIT@ symbol, if present. * NEWS: Update. Signed-off-by: Peter Rosin <peda@lysator.liu.se>
-rw-r--r--NEWS2
-rw-r--r--build-aux/ltmain.in32
-rw-r--r--libltdl/loaders/preopen.c12
-rw-r--r--m4/libtool.m428
-rw-r--r--tests/demo.at2
5 files changed, 69 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 081e82f7..bb332029 100644
--- a/NEWS
+++ b/NEWS
@@ -60,6 +60,8 @@ NEWS - list of user-visible changes between releases of GNU Libtool
in import libraries using the -headers option of dumpbin. Also fix a
bug in the dumpbin wrapper which could lead to broken symbol listings
in some corner cases.
+ - Use the improved Microsoft dumpbin support to mend preloading of
+ import libraries for Microsoft Visual C/C++.
** Important incompatible changes:
diff --git a/build-aux/ltmain.in b/build-aux/ltmain.in
index 6151ee95..9e790db2 100644
--- a/build-aux/ltmain.in
+++ b/build-aux/ltmain.in
@@ -2798,6 +2798,11 @@ extern \"C\" {
echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
fi
+ func_show_eval '$RM "${nlist}I"'
+ if test -n "$global_symbol_to_import"; then
+ eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I'
+ fi
+
echo >> "$output_objdir/$my_dlsyms" "\
/* The mapping between symbol names and symbols. */
@@ -2806,11 +2811,30 @@ typedef struct {
void *address;
} lt_dlsymlist;
extern LT_DLSYM_CONST lt_dlsymlist
-lt_${my_prefix}_LTX_preloaded_symbols[];
+lt_${my_prefix}_LTX_preloaded_symbols[];\
+"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+static void lt_syminit(void)
+{
+ LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols;
+ for (; symbol->name; ++symbol)
+ {"
+ $SED 's/.*/ if (!strcmp (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms"
+ echo >> "$output_objdir/$my_dlsyms" "\
+ }
+}"
+ fi
+ echo >> "$output_objdir/$my_dlsyms" "\
LT_DLSYM_CONST lt_dlsymlist
lt_${my_prefix}_LTX_preloaded_symbols[] =
-{\
- { \"$my_originator\", (void *) 0 },"
+{ {\"$my_originator\", (void *) 0},"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+ {\"@INIT@\", (void *) &lt_syminit},"
+ fi
case $need_lib_prefix in
no)
@@ -2869,7 +2893,7 @@ static const void *lt_preloaded_setup() {
func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
# Clean up the generated files.
- func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+ func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"'
# Transform the symbol file into the correct name.
symfileobj=$output_objdir/${my_outputname}S.$objext
diff --git a/libltdl/loaders/preopen.c b/libltdl/loaders/preopen.c
index 16700855..5c1bd552 100644
--- a/libltdl/loaders/preopen.c
+++ b/libltdl/loaders/preopen.c
@@ -210,6 +210,11 @@ vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
{
lt_dlsymlist *symbol = (lt_dlsymlist*) module;
+ if (symbol[1].name && STREQ (symbol[1].name, "@INIT@"))
+ {
+ symbol++; /* Skip optional init entry. */
+ }
+
symbol +=2; /* Skip header (originator then libname). */
while (symbol->name)
@@ -273,6 +278,13 @@ add_symlist (const lt_dlsymlist *symlist)
tmp->symlist = symlist;
tmp->next = preloaded_symlists;
preloaded_symlists = tmp;
+
+ if (symlist[1].name && STREQ (symlist[1].name, "@INIT@"))
+ {
+ void (*init_symlist)(void);
+ *(void **)(&init_symlist) = symlist[1].address;
+ (*init_symlist)();
+ }
}
else
{
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index e59e0fb6..3cf14e7f 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -3649,21 +3649,41 @@ case `$NM -V 2>&1` in
symcode='[[ABCDGIRSTW]]' ;;
esac
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Gets list of data symbols to import.
+ lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+ # Adjust the below global symbol transforms to fixup imported variables.
+ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
+ lt_c_name_lib_hook="\
+ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
+ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
+else
+ # Disable hooks by default.
+ lt_cv_sys_global_symbol_to_import=
+ lt_cdecl_hook=
+ lt_c_name_hook=
+ lt_c_name_lib_hook=
+fi
+
# Transform an extracted symbol line into a proper C declaration.
# Some systems (esp. on ia64) link data and code symbols differently,
# so use this general approach.
lt_cv_sys_global_symbol_to_cdecl="sed -n"\
+$lt_cdecl_hook\
" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
# Transform an extracted symbol line into symbol name and symbol address
lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
+$lt_c_name_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
# Transform an extracted symbol line into symbol name with lib prefix and
# symbol address.
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+$lt_c_name_lib_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'"
@@ -3684,8 +3704,8 @@ for ac_symprfx in "" "_"; do
# Write the raw and C identifiers.
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
- # Fake it for dumpbin and say T for any non-static function
- # and D for any global variable.
+ # Fake it for dumpbin and say T for any non-static function,
+ # D for any global variable and I for any imported variable.
# Also find C++ and __fastcall symbols from MSVC++,
# which start with @ or ?.
lt_cv_sys_global_symbol_pipe="$AWK ['"\
@@ -3694,7 +3714,7 @@ for ac_symprfx in "" "_"; do
" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
-" /^ *Type *: data/{print \"D\",si,substr(si,length(prfx))};"\
+" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
" \$ 0!~/External *\|/{next};"\
" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
" {if(hide[section]) next};"\
@@ -3841,6 +3861,8 @@ _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
[Take the output of nm and produce a listing of raw symbols and C names])
_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
[Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
+ [Transform the output of nm into a list of symbols to manually relocate])
_LT_DECL([global_symbol_to_c_name_address],
[lt_cv_sys_global_symbol_to_c_name_address], [1],
[Transform the output of nm in a C name address pair])
diff --git a/tests/demo.at b/tests/demo.at
index c86e1e91..eb8a97fd 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))
+ ((void(*)())s->address)();
if (STREQ ("hello", name))
phello = (int(*)())s->address;
else if (STREQ ("foo", name))