Preloading import libraries with MSVC

2012-11-02 Thread Peter Rosin
Hi!

As discussed earlier[1], there are problems with preloading import
libraries when using Microsoft Visual C/C++. This series is a
polished version of the previously posted rough cut. However, the
first two patches are largely unrelated to the topic, but they
help visualize what the meat in the third patch is all about. So,
I guess they are related after all, which is why I posted them
as a series. :-)

This version will not create an @INIT@ symbol in the preloader
table unless one is neaded, i.e. an actual data import item
is needed to trigger the creation of the lt_syminit function
and the fake @INIT@ symbol providing its address.

Also, the "cost" in preopen.c is neglectable, as the loops from
the proof of concept first draft are gone.

With:

.../configure \
CC="`pwd`/build-aux/compile cl -nologo" \
CFLAGS="-MD -Zi -EHsc" \
CXX="`pwd`/build-aux/compile cl -nologo" \
CXXFLAGS="-MD -Zi -EHsc" \
NM="dumpbin -symbols -headers" \
LD=link \
STRIP=: \
AR="`pwd`/build-aux/ar-lib lib" \
RANLIB=: \
F77=no FC=no GCJ=no

from MSYS with Microsoft Visual C/C++ 2010 on $PATH, I get:

## - ##
## Test results. ##
## - ##

139 tests behaved as expected.
29 tests were skipped.

So, all failures are fixed. The testsuite is also clean on Cygwin
and MinGW (which makes me confident that the added special caseing
doesn't mess up systems that don't make use of them).

Is it unintrusive enough? Ok to push?

(confession: I did a few last minute trivial changes just before
posting which (drumroll) shouldn't affect things. Anyway, the testsuite
is part way through with thouse changes and the patch has been somewhat
exercised so it is looking good, but I will naturally post a followup
if anything untoward surfaces)

Cheers,
Peter

[1] http://lists.gnu.org/archive/html/libtool-patches/2012-10/msg00055.html



[PATCH 2/3] libtool: unify the global symbol transformations

2012-11-02 Thread Peter Rosin
Since it is safe for $lt_cv_sys_global_symbol_to_cdecl to match
with a simple /^T .* .*$/ type expression, it is ok for the other
transformations as well.  At least if you require at least one
$symcode at the start of the line, so that the just generated output
doesn't match the next sed expression.

* m4/libtool.m4 (_LT_CMD_GLOBAL_SYMBOLS): Unify the matching expressions
in the sed programs that transform the extracted symbol lines.

Signed-off-by: Peter Rosin 
---
 m4/libtool.m4 |   14 +++---
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 79a4222..e59e0fb 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -3654,19 +3654,19 @@ esac
 # so use this general approach.
 lt_cv_sys_global_symbol_to_cdecl="sed -n"\
 " -e 's/^T .* \(.*\)$/extern int \1();/p'"\
-" -e 's/^$symcode* .* \(.*\)$/extern char \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"\
-" -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p'"\
-" -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"
+" -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"\
-" -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p'"\
-" -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"\
-" -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+" -e 's/^: \(.*\) .*$/  {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/  {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/  {\"lib\1\", (void *) \&\1},/p'"
 
 # Handle CRLF in mingw tool chain
 opt_cr=
@@ -3771,7 +3771,7 @@ lt__PROGRAM__LTX_preloaded_symbols[[]] =
 {
   { "@PROGRAM@", (void *) 0 },
 _LT_EOF
- $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) 
\&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ $SED "s/^$symcode$symcode* .* \(.*\)$/  {\"\1\", (void *) \&\1},/" < 
"$nlist" | $GREP -v main >> conftest.$ac_ext
  cat <<\_LT_EOF >> conftest.$ac_ext
   {0, (void *) 0}
 };
-- 
1.7.9




[PATCH 1/3] libtool: break up long lines

2012-11-02 Thread Peter Rosin
* m4/libtool.m4 (_LT_CMD_GLOBAL_SYMBOLS): Break up long lines when
assigning the sed scripts that transform the extracted symbol lines.

Signed-off-by: Peter Rosin 
---
 m4/libtool.m4 |   16 +---
 1 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 37f7d7c..79a4222 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -3652,11 +3652,21 @@ esac
 # 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 -e 's/^T .* \(.*\)$/extern int 
\1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+lt_cv_sys_global_symbol_to_cdecl="sed -n"\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$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 -e 's/^: \([[^ ]]*\)[[ ]]*$/ 
 {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  
{\"\2\", (void *) \&\2},/p'"
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ 
]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) 
\(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) 
\([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
+" -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p'"\
+" -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/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"\
+" -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p'"\
+" -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"\
+" -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
 
 # Handle CRLF in mingw tool chain
 opt_cr=
-- 
1.7.9




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

2012-11-02 Thread Peter Rosin
* 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 
---
 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" "\
+  {\"@INIT@\", (void *) <_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 **)