libtool-patches
[Top][All Lists]
Advanced

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

Re: [PATCH] [cygwin|mingw] fix dlpreopen with --disable-static


From: Charles Wilson
Subject: Re: [PATCH] [cygwin|mingw] fix dlpreopen with --disable-static
Date: Fri, 02 Jan 2009 18:55:10 -0500
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.19) Gecko/20081209 Thunderbird/2.0.0.19 Mnenhy/0.7.5.666

* libltdl/config/ltmain.m4sh (func_dlltool_identify): New function.
(func_win32_dllname_for_implib): New function.
(func_mode_link) [cygwin|mingw]: Use linklib (that is,
import lib) as dlpreopen file, rather than DLL.
(func_generate_dlsyms) [cygwin|mingw]: Use
func_win32_dllname_for_implib to extract DLL name from
import library. Also, properly extract dlsyms from the
import library.
* libltdl/m4/libtool.m4 (_LT_LINKER_SHLIBS) [cygwin|mingw][C++]:
Set exclude_expsyms correctly for $host. Simplify regular
expression in export_symbols_cmds.
(_LT_LINKER_SHLIBS) [cygwin|mingw|pw32][C]: Set exclude_expsyms
correctly for $host. Enable export_symbols_cmds to identify
DATA exports by _nm_ prefix.
---

This is a revised -- but obsoleted -- version of a patch first
posted here:
http://lists.gnu.org/archive/html/libtool-patches/2008-11/msg00019.html
in response to a bug first posted here:
http://lists.gnu.org/archive/html/bug-libtool/2008-05/msg00054.html


This version of the patch corrects all issues raised in that thread and
is updated to current master -- except for two issues:

1)
This idiom
  eval '$ECHO ": $name " >> "$nlist"'
  eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
is still used, rather than
  $ECHO ": $name " >> "$nlist"
  eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
because, while "extra" evals are bad, the idiom predated this patch, and
 should be cleaned up -- if it needs to be -- in a separate patch.

2)
At the end of the thread, Ralf had a suggestion for "saving" the name of
the la file associated with each import library in the dlpreopen list.
This avoids the need for func_win32_dllname_for_implib(), except when
there IS no la file. I've implemented a version of that idea, but not
here. The new implmentation completely obsoletes (but incorporates large
parts of) this patch.

So why post this one? For completeness, and to terminate the originating
thread. I'll start a new thread with the new patch.

=====

 libltdl/config/ltmain.m4sh |  148
+++++++++++++++++++++++++++++++++++++++++---
 libltdl/m4/libtool.m4      |    8 ++-
 2 files changed, 145 insertions(+), 11 deletions(-)

diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh
index 20ca07b..c7d0dc0 100644
--- a/libltdl/config/ltmain.m4sh
+++ b/libltdl/config/ltmain.m4sh
@@ -2001,10 +2001,36 @@ extern \"C\" {
          func_verbose "extracting global C symbols from \`$dlprefile'"
          func_basename "$dlprefile"
          name="$func_basename_result"
-         $opt_dry_run || {
-           eval '$ECHO ": $name " >> "$nlist"'
-           eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
-         }
+         case $host in
+           *cygwin | *mingw* )
+             # if an import library, we need to obtain dlname
+             if func_win32_import_lib_p "$dlprefile"; then
+               func_win32_dllname_for_implib "$dlprefile"
+               dllname=$func_win32_dllname_for_implib_result
+               $opt_dry_run || {
+                 if test -n "$dllname" ; then
+                   eval '$ECHO ": $dllname " >> "$nlist"'
+                 else
+                   func_warning "Could not compute DLL name from $name"
+                   eval '$ECHO ": $name " >> "$nlist"'
+                 fi
+                 eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe |
+                   $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> 
'$nlist'"
+               }
+             else
+               $opt_dry_run || {
+                 eval '$ECHO ": $name " >> "$nlist"'
+                 eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >>
'$nlist'"
+               }
+             fi
+             ;;
+            * )
+             $opt_dry_run || {
+               eval '$ECHO ": $name " >> "$nlist"'
+               eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >>
'$nlist'"
+               }
+             ;;
+          esac
        done

        $opt_dry_run || {
@@ -2208,6 +2234,99 @@ func_win32_libid ()
   $ECHO "$win32_libid_type"
 }

+# func_dlltool_identify
+# Determine if $DLLTOOL supports the --identify option
+func_dlltool_identify ()
+{
+  $opt_debug
+  if test -z "$func_dlltool_identify_result"; then
+    case `$DLLTOOL --help` in
+    *--identify*) func_dlltool_identify_result=: ;;
+    *) func_dlltool_identify_result=false ;;
+    esac
+  fi
+  $func_dlltool_identify_result
+}
+
+# func_win32_dllname_for_implib implib
+# Obtain the name of the DLL associated with the
+# specified import library. Result is available
+# in $func_win32_dllname_for_implib_result.
+#
+func_win32_dllname_for_implib ()
+{
+  $opt_debug
+  func_win32_dllname_for_implib_result=""
+
+  if func_dlltool_identify ; then
+    func_win32_dllname_for_implib_result=`$DLLTOOL --identify "$1"
2>/dev/null`
+    # if this fails, the fallback code is unlikely to succeed, so
+    # we don't bother...
+  else
+    # use fallback dlltool does not have the --identify option.
+    # make sure argument is actually an import library
+    if func_win32_import_lib_p "$1"; then
+      func_warning "Using fallback code to determine dllname for $1;
consider updating binutils to version 2.20 (2.19.50.20081115), or newer."
+      # gcc puts dllname in the .idata$7 section of ONE member
+      # of the import library -- but the name of that member is
+      # random. No other member contains an .idata$7 section.
+      # So, use objdump to print the contents. We get something
+      # like the following (blank lines elided):
+      #
+      #  |In archive /usr/lib/libncurses++.dll.a:
+      #  |d000253.o:     file format pe-i386
+      #  |Contents of section .idata$7:
+      #  | 0000 6379676e 63757273 65732b2b 2d382e64  cygncurses++-8.d
+      #  | 0010 6c6c0000                             ll..____________
+      #  |d000006.o:     file format pe-i386
+      #  |d000252.o:     file format pe-i386
+      #  |Contents of section .idata$7:
+      #  | 0000 00000000                             ....____________
+      #
+      # where '_' represents a space character. So, we delete all
+      # lines that have less than 43 characters, and chomp the
+      # first 43 characters of the remaining lines. This gives us
+      #
+      #  |cygncurses++-8.d
+      #  |ll..____________
+      #  |....____________
+      #
+      # We are not guaranteed that the name we want is first. So,
+      # remove all newlines, then remove all sequences of two
+      # or more . characters, then remove all sequences of two
+      # or more whitespace characters. Finally, remove leading and
+      # trailing whitespace. This would be simpler if we could
+      # assume that the dllname does not contain whitespace, but we
+      # DO assume the dllname doesn't contain *multiple* adjacent
+      # whitespace, nor *multiple* adjacent . characters.
+
+      func_win32_dllname_for_implib_result=`$OBJDUMP -s --section
'.idata$7' "$1" |
+        $SED '/^[^      ]*\.o:/{
+           s/.*//
+           p
+           d
+         }
+         /^.\{43\}/!d
+         s/^.\{43\}//' |
+        $SED -n '
+         :more
+         N
+         /\n$/b work
+         $!b more
+         :work
+         s/\n//g
+         s/\.\.\.*//g
+         s/[      ][      ][      ]*//g; s/^[     ]*//; s/[       ]*$//
+         /./{
+           p
+           q
+         }
+         '`
+    fi
+  fi
+}
+
+


 # func_extract_an_archive dir oldlib
@@ -5180,11 +5299,24 @@ func_mode_link ()
            # that they are being used correctly in the link pass.
            test -z "$libdir" && \
                dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
-         # Otherwise, use the dlname, so that lt_dlopen finds it.
-         elif test -n "$dlname"; then
-           newdlprefiles="$newdlprefiles $dir/$dlname"
+         # Otherwise, use the dlname, so that lt_dlopen finds it --
+         # except on mingw|cygwin, where we must use the import library
+         # for symbol extraction. Therefore, on those platforms, the name
+         # needed by lt_dlopen is extracted from the import library via
+         # func_win32_dllname_for_implib.
          else
-           newdlprefiles="$newdlprefiles $dir/$linklib"
+           case "$host" in
+             *cygwin* | *mingw* )
+               newdlprefiles="$newdlprefiles $dir/$linklib"
+                ;;
+             * )
+               if test -n "$dlname"; then
+                 newdlprefiles="$newdlprefiles $dir/$dlname"
+               else
+                 newdlprefiles="$newdlprefiles $dir/$linklib"
+               fi
+                ;;
+           esac
          fi
        fi # $pass = dlpreopen

diff --git a/libltdl/m4/libtool.m4 b/libltdl/m4/libtool.m4
index b7b566d..ee4b106 100644
--- a/libltdl/m4/libtool.m4
+++ b/libltdl/m4/libtool.m4
@@ -4108,6 +4108,7 @@ m4_require([_LT_TAG_COMPILER])dnl
 AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared
libraries])
 m4_if([$1], [CXX], [
   _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience |
$global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(exclude_expsyms,
$1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
   case $host_os in
   aix[[4-9]]*)
     # If we're using GNU nm, then we don't want the "-C" option.
@@ -4122,13 +4123,13 @@ m4_if([$1], [CXX], [
     _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
   ;;
   cygwin* | mingw* | cegcc*)
-    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience |
$global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^
]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^
]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq >
$export_symbols'
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience |
$global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^
]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[
]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+    _LT_TAGVAR(exclude_expsyms,
$1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
   ;;
   *)
     _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience |
$global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
   ;;
   esac
-  _LT_TAGVAR(exclude_expsyms,
$1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
 ], [
   runpath_var=
   _LT_TAGVAR(allow_undefined_flag, $1)=
@@ -4267,7 +4268,8 @@ _LT_EOF
       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
       _LT_TAGVAR(always_export_symbols, $1)=no
       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
-      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience |
$global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^
]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort
| uniq > $export_symbols'
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience |
$global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^
]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[
]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms,
$1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']

       if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs
$compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base
-Xlinker --out-implib -Xlinker $lib'
-- 
1.6.0.4






reply via email to

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