libtool-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 3/3] libtool: add @INIT@ to the preloader, for data imports on Wi


From: Peter Rosin
Subject: [PATCH 3/3] libtool: add @INIT@ to the preloader, for data imports on Windows
Date: Sat, 3 Nov 2012 00:42:16 +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 <address@hidden>
---
 NEWS                      |    2 ++
 build-aux/ltmain.in       |   32 ++++++++++++++++++++++++++++----
 libltdl/loaders/preopen.c |   12 ++++++++++++
 m4/libtool.m4             |   28 +++++++++++++++++++++++++---
 tests/demo.at             |    2 ++
 5 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index 081e82f..bb33202 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 6151ee9..9e790db 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" "\
+  {\"@address@hidden", (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 1670085..5c1bd55 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 e59e0fb..3cf14e7 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 c86e1e9..eb8a97f 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))
-- 
1.7.9




reply via email to

[Prev in Thread] Current Thread [Next in Thread]