]> git.ipfire.org Git - thirdparty/libtool.git/commitdiff
libtool: add @INIT@ to the preloader, for data imports on Windows
authorPeter Rosin <peda@lysator.liu.se>
Fri, 2 Nov 2012 22:50:43 +0000 (23:50 +0100)
committerPeter Rosin <peda@lysator.liu.se>
Fri, 2 Nov 2012 22:50:43 +0000 (23:50 +0100)
* 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>
NEWS
build-aux/ltmain.in
libltdl/loaders/preopen.c
m4/libtool.m4
tests/demo.at

diff --git a/NEWS b/NEWS
index 081e82f7460aabf5a7a12f6b06e76bb01b2d7381..bb332029ad14c9e19b4ef3e06eb78b2fa6e80dc5 100644 (file)
--- 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:
 
index 6151ee9558cf9c7fbdeef3a0cc783ea63e3fc854..9e790db2f5076705c4824529e44897f94becac18 100644 (file)
@@ -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
index 167008553ffcdd13148593b36ee442d360b549a9..5c1bd55228c995364c1ae2299de8ab63e457fea5 100644 (file)
@@ -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
        {
index e59e0fb641619b3c64e439f8f013ea8612a2c5d9..3cf14e7feb08ce9572fcc3a5cb9d7bdb6729674e 100644 (file)
@@ -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])
index c86e1e91ed95ca18a9721d0ad68adecefff3feb1..eb8a97fd78a53e7dd7cccfb3f62796bc1d604a6a 100644 (file)
@@ -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))