Peter Rosin wrote:
> I'm primarily trying to determine what impact this has on my
> MSVC branch...
> 
> Den 2009-01-03 02:39 skrev Charles Wilson:
> *snip*
>> +        *cygwin* | *mingw* | *cegcc* )
> 
> We should strive to have fewer of these in ltmain.m4sh, not more.

Yep. But the problem is, there are really two BIG categories of
platforms: those that support ELF-semantics for shared libraries, and
those that support PE-DLL semantics. The differences between, say, HP
and Linux are in this regard much less significant than the differences
between win32 (cygwin, mingw, msvc, even wince) and any *nixoid. And
vice verse: cygwin and msvc are much more similar *with regards to the
construction of shared libraries* than they are different (even though
the implib/static lib formats are non-interchangeable).

I'm not sure it would be an improvement, exactly, but we could have a
libtool variable $LT_HOST_SUPPORTS_PE_DLL (or a function that takes
$host), and replace many of these
   case $host in
     *cygwin* | *mingw* | *cegcc* ) ... ;;
     everything else ) ... ;;
   esac
occurences with 'if host_supports_pe_dll ; then ... ; else ... ; fi'
Still ugly, but it means you only have to "fix" the case "$host" pattern
in one place.

>> +      func_warn "Using fallback code to determine dllname for $1;
>> consider updating binutils to version 2.20 (2.19.50.20081115), or newer."
> 
> I fail to find that version of binutils in Cygwin setup, so I guess the
> fallback code will get exercised.

Not exactly.  Background: the --identify option is supported only in
CVS. There has not yet been an official binutils release containing that
code. Furthermore, cygwin's official binutils, while based on a CVS
snapshot, is from 20080624.  So, no, if you want it you have to compile
it yourself.  Same for the mingw-provided binutils.

But, func_win32_dllname_for_implib is only ever called if we were unable
to find the .la file for the implib.  Normally, you'd do something like:

  -dlpreopen foo.la

and then, the libfile_$(transliterated implib name) stuff is used, not
func_win32_dllname_for_implib.  You only use that function if somebody did:

  -dlpreopen /path/to/foo.dll.a

(maybe because they had no .la file, or it was not installed by the
system packaging, or whatever).

BTW, I'm assuming that func_win32_import_lib_p() works for msvc, because
you've got the "correct" $file_magic_command for your toolchain
(whatever "correct" means)...

> The comments say that "gcc" adds the
> dll name in .idata$7, and the fallback code makes use of this fact. How
> stable is that?

For gcc dll's, very. Hasn't changed in over a decade. pe-ppc (as opposed
to pe-i386) uses .idata$6; a dlltool compiled for that toolchain
correctly inspects .idata$6. That's why this manual parsing stuff is
just a fallback; it'd be better to use a binary tool. But, for msvc, I
haven't even thought about trying to parse dumpbin output.

Can we (libtool?) provide binary utility programs to go along with msvc
to solve some of these issues?  Furthermore, can we even assume that
binutils progs like objdump and dlltool are available? Or file, for that
matter?

> What happens if you generate an import library late (if
> you only have the dll) with something that is not gcc? 

First, I'm assuming that you're not talking about mixing between
toolchains (e.g. if $CC is gcc, then the libs were generated by gcc/ld.
if $CC is cl, then the libs were generated by cl.exe.)

So, you're talking about completely non-gcc-based toolchains AND you're
dealing with an import library for which you have no .la file. In that
case you're stuck using func_win32_dllname_for_implib.  Now, dlltool
--identify (if you even HAVE dlltool) doesn't work with MSVC lib files
(I just checked). I could see different functions defined for each
toolchain, and then a libtool variable $pedll_dllname_for_implib_cmd
that points to the correct implementation for your toolchain. (mingw and
cygwin and probably cegcc would "point" to my implementation, whatever
it is renamed to).

But remember, this is all a corner case: dlpreopen of a shared library,
when you don't have an .la file. Otherwise, it ought to just work(tm).

> What if you have
> an import library created by e.g. MSVC? Looking at a few import libs in
> the Platform SDK suggests that MSVC uses .idata$6 instead.

Sortof. I see a LOT of .idata$6 entries. Most of them contain symbol
names at offset 2, and offset 0,1 contain a little-endian count. But the
one that has the DLL name starts at offset 0.  How are you supposed to
tell that 'MS' is actually the first two characters of a DLL name, and
not an indication that symbol 'VCR80.dll' is entry number 0x534d in the
symbol list?

Unless "the first member of the archive" is ALWAYS the one that will
specify the DLL, and you look in the .idata$LAST of that member.

I think it would be better NOT to try to generalize this, and instead go
the $LT_pedll_dllname_for_implib_cmd route above. If your msvc port can
use objdump, then the following works (and could be put in the
func_msvc_dllname_for_implib implementation). It's somewhat different
than the existing fallback because in gcc, all .idata$7 except the one
we care about are full of nulls. In msvc, all .idata$6 have data, so we
need to maintain separation between data from different .idata$6 blobs.
But I am assuming that the FIRST archive member that has an .idata&6
section is the one we want:

objdump -s --section '.idata$6' "$1" |
sed '/^Contents of section .idata\$6:/{
  s/.*/====MARK====/
  p
  d
}
/^====MARK====/p
/^.\{43\}/!d
s/^.\{43\}//' |
sed -n '
  /^====MARK====/ b para
  H
  $ b para
  b
  :para
  x
  s/\n//g
  s/^====MARK====//
  s/[\. \t]*$//
  /./p
  ' |
sed -n -e 1p

Note that contra my advice to avoid generizing this, the above script
works for gcc implibs with only a single change: .idata$6 -> .idata$7
(under the same (valid?) assumption: the FIRST archive member with an
.idata$7 member is the one we want).

> To me it
> seems as if the dllname is in the last .idata segment, can't that be
> scripted for a better fallback?

But not every object in the archive has an .idata$7 (or .idata$6). Some
objects only have a few .idata$N sections, and the "last" one is
.idata$4. In other cases, an .idata$7 section is present, but contains
only nulls. (try objdump -s libz.dll.a)

> Hmm, looking at the the --identify patch for binutils, it seems that it
> too simply dumps out .idata$7. That seems to be plain wrong for a whole
> bunch of import libs out there in the wild.

But I can't use gcc or ld to link against those import libs. That's why
the mingw w32api package ships *gcc* format import libraries generated
from .def files. THOSE import libraries DO follow the rules that dlltool
--identify understands.

It's not surprising that a binutils-supplied tool like dlltool is
limited to dealing with the same kinds of files that the binutils linker
generates/can link to.

DLLs (in the C language, at least) are generic for any compiler on the
win32 platform.  But every compiler has its own import (and sometimes
static) library format. In general they are very similar, but not
interchangeable.

However, the improvements suggested by Ralf -- and implemented in this
patch -- should relegate those issues to a dusty back corner.  Do you
really think it is of *primary* importance that somebody be able to
dlpreopen a third-party, non-libtool-generated DLL?  (That functionality
has been broken on cygwin/mingw for several years now and hardly anyone
noticed)  The libfile_$(transliterated implib name) stuff *should* make
things work for dlpreopening libtool-generated DLLs, even for msvc --
once the 'case "$host" in PATTERN's are corrected (or replaced by
something more general).  Eventually, yeah, we can and should fix the
dlpreopen-third-party case for non-gcc...but is it a showstopper?

--
Chuck


Reply via email to