Binutils README
by Chuck Wilson
Updated on 20010924

This document is just a place to keep track of various issues
related to the '--enable-auto-import' feature of recent
(20010802 and newer) binutils on cygwin.  It is based on 
the /usr/doc/Cygwin/binutils-20010802-1.README distributed 
within cygwin's binutils-20010802-1.tar.gz package.

TOC:
  BUGS/TODO (Auto-import)
    0. default status of --enable-auto-import
    1. FIXED. internal implementation details (pe_data_import_dll)
    2. FIXED. memory leak
    3. Danny Smith's esoteric bug report
    4. Ralf Habacker's --export-whole-archive problem
  KNOWN ISSUES (Auto-import)
    0. What does "variable '<var>' can't be auto-imported" mean?
    1. Can't link client with old DLL using --enable-auto-import.
    2. Can't link client with Microsoft DLL using --enable-auto-import.
----------------------------------------------------

BUGS/TODO (Auto-import):
------------------------
0. make --enable-auto-export the default (uncomment line 176
   in pe.em).  The cygwin package now does this, but it
   has not yet been submitted/accepted into the official
   GNU binutils.  We'll give this another month to simmer
   before that.

1. FIXED. make pe_data_import_dll static?
   No, used in both pe.em and pe-dll.c.  In fact, it is
   necessary to do it this way, if we want ld to build
   properly for all pe targets (esp. multi-pe-target 
   builds).  Nick Clifton came up with a way to do this
   -- but it still requires that pe_data_import_dll be
   defined/used in pe.em as well as declared/used in 
   pe-dll.c.  See 
   http://sources.redhat.com/ml/binutils/2001-09/msg00429.html
   as well as the enclosing thread.

2. FIXED. Ralf's bug report.
   See http://sources.redhat.com/ml/binutils/2001-06/msg00742.html
   synopsis: segfaults when xmalloc returns 0.  Caused by
   running out of heap space due to memory leak (which Ralf has
   pinpointed).  

3. Danny Smith reports an esoteric problem:
   "I am still having some (sorry, one very specific) problem
   with C++ and auto-import.  It is with cerr, cin, cout in
   the STLport of the SGI iostream lib.  These are initialised
   before main.  When building dll with auto-export and using
   auto-import to link (no dllimport attributes), I get
   successful link, but runtime failure of app at initialisation
   (before main). When building dll with --export-all, but
   marking DATA with dllimport when compiling client, I get
   successful link and run."
	
4. Ralf's "--export-whole-archive" problem with static libs:
   http://sources.redhat.com/ml/cygwin/2001-07/msg01198.html
   Question: how do you distinguish, automagically, between
   static libs that *shouldn't* be exported, and static
   "convenience" libs that *should* be exported?  I think
   this "problem" should be addressed at a higher level --
   for a particular package: Makefile.am?  Perhaps improvements
   to the already-experimental robert-collins-libtool?  Ralf's
   suggestion of "--export-whole-archive" and "--no-whole-archive"
   has possibilities, but it's really orthogonal to the question:
   "Does auto-import work".  (e.g. it's another feature, not an
   improvement to THIS feature).  Another possibility is to
   extend the new table-based symbol exclusion list
   (pe-dll.c(auto-export)) so that you can add patterns to those
   tables from the command line.  --exclude-symbols-from-library,
   --exclude-symbols-from-object, --exclude-symbol-with-prefix,
   --exclude-symbol-wiht-suffix  (there already is an
   --exclude-symbols option).

   But again, this is a *different* problem, not specifically a
   problem with auto-import itself.

KNOWN ISSUES (Auto-import)
--------------------------
These behaviors are not bugs.  It's just "the way things are".

0. I get the following error message when I try to link:
  "variable '<var>' can't be auto-imported. Please read the
  documentation for ld's `--enable-auto-import' for details."

     This message occurs when some (sub)expression accesses an address
     ultimately given by the sum of two constants (Win32 import tables
     only allow one).  Instances where this may occur include accesses
     to member fields of struct variables imported from a DLL, as well
     as using a constant index into an array variable imported from a
     DLL.  Any multiword variable (arrays, structs, long long, etc) may
     trigger this error condition.  However, regardless of the exact
     data type of the offending exported variable, ld will always
     detect it, issue the warning, and exit.

     There are several ways to address this difficulty, regardless of
     the data type of the exported variable:
   
  See 'info ld', Invocation::Options::--enable-auto-import for ideas
  on how to deal with this problem (most often, you need to change
  your DLL's code, and your client application's code).

  Just to be clear, this "problem" is not limited to just arrays 
  and struct variables exported from a DLL.  Any multi-word data 
  type *could* exhibit the problem -- but ld will catch them, and
  report the problem with the message quoted above.  Regardless of
  the exact data type of the exported variable that triggers the 
  message, whether array or struct or long long or..., the 
  workarounds presented in the ld.info documentation will solve
  the problem for you.

1. Situation:
      DLL: built using an "old" version of ld.  Has
           __declspec(dllexport) decorators.
      client: New client, does not use __declspec(dllimport)

    Q: Why can't I link this client with this DLL? I'm using the
    --enable-auto-import option...

    A: Because the DLL doesn't export the correct thunking items
    to allow this.  Face it, if your library headers (which
    declare function foo or variable baz) do not match the DLL,
    then you're going to have problems -- whether the discrepancy
    is "int foo()" vs. "char foo()" or "extern int foo()" vs.
    "extern __declspec(dllimport) foo()".  Clients and libs should
    AGREE on definitions!

    Ordinarily, you shouldn't have to worry about this -- if a
    library's header was munged to support DLL's the "old way" --
    that is, with appropriate defines so that __declspec(dllexport),
    __declspec(dllimport), and "" all work properly -- then they
    will continue to work.  Just read that package's documentation.

    Note also that even the "old" ld could do auto-import/export --
    if the DLL in question (a) used a functional-only interface, no
    data exports, (b) no overzealous porter (like me, csw) sprinkled
    __declspec()'s around -- THEN you could build a client app
    without __declspec's, too.  However, this ONLY works for DLL's
    written in C.  Why?  Because there aint no such animal as a C++
    dll with a functional-only interface.  C++ *has* to export data.
    Classes ARE data.

2. Situation:
      DLL: a standard, microsoft system DLL.  Generated an import
           library using dlltool, or used the import libs provided
           in the w32api package
      client: New client, accessing exported items in that DLL
           but doesn't declare them with __declspec(dllimport).

    Q: Why can't I link this client?  I'm using the
    --enable-auto-import option...

    A: Because the DLL doesn't export the correct thunking items
    to allow this -- it's an MS DLL!  This is really the same
    question as #1.  However, at least with open-source DLL's,
    it's possible (if not likely) that these old DLLs may, at
    some point in the future, be recompiled to support
    auto-import.  However, I'll give you dollars to donuts that
    MS DLL's will never support it. (Note that you CAN auto-import
    *functions* from MS DLL's -- you've been able to do that for
    several years.  It's the DATA exports that are troublesome.)

    So, you can cheat (use auto-import, be lazy with __declspec()
    on DATA items, etc)  IF and ONLY IF the dll was built by a new
    ld.  Since the official Microsoft dll's will never be built
    that way, you'll aways be stuck with these windows-isms.

    In other words, you need to "follow the __declspec rules" to
    link with MS dlls and with "old-style" dlls that were built
    with an "old" ld.  Most of the time, you won't need to worry
    about this; library maintainers and "platform distributors"
    (like the main cygwin team, or the main w32api team, will
    insure that the headers you include will use the __declspec
    decorators when necessary.  All you have to do is make sure
    to #define the appropriate flags (if any) like -DZLIB_STATIC
    on cygwin-zlib.

    Unfortunately, there will never be a replacement for reading
    the distribution documentation (or package documentation).
