delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2008/09/15/23:43:02

X-Recipient: archive-cygwin AT delorie DOT com
X-Spam-Check-By: sourceware.org
Message-ID: <48CF2B17.21790B70@dessent.net>
Date: Mon, 15 Sep 2008 20:42:16 -0700
From: Brian Dessent <brian AT dessent DOT net>
X-Mailer: Mozilla 4.79 [en] (Windows NT 5.0; U)
MIME-Version: 1.0
To: cygwin AT cygwin DOT com
Subject: Re: [ANNOUNCEMENT] New experimental package: gcc4-4.3.0-1
References: <announce.001001c91336$91e70d10$9601a8c0 AT CAM DOT ARTIMI DOT COM> <48C8FE4D DOT 1090103 AT users DOT sourceforge DOT net> <013401c9140b$22b569c0$9601a8c0 AT CAM DOT ARTIMI DOT COM> <48CA2107 DOT FE8D0CB2 AT dessent DOT net> <01cb01c914db$53d34d80$9601a8c0 AT CAM DOT ARTIMI DOT COM> <48CAFDD9 DOT 641C423A AT dessent DOT net> <48CD71CC DOT 3060704 AT users DOT sourceforge DOT net> <48CDFA0D DOT D5CC3883 AT dessent DOT net> <002101c91779$0f9e8b20$9601a8c0 AT CAM DOT ARTIMI DOT COM>
X-IsSubscribed: yes
Reply-To: cygwin AT cygwin DOT com
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com

Dave Korn wrote:

>   Yep, that's more-or-less what I was referring to by "stunk thubbery" ;-)

With one important difference: the plan you outlined relies on the .exe
exporting the function that overrides the copy in the dll.  This is
somewhat controversial (IMHO) in that it requires adorning the function
with __declspec(dllexport) (or -Wl,--export-all-symbols or using a .def
file) and it is not typical to export from an executable.  If at all
possible I'd like to avoid this.

The current special casing for malloc/free doesn't require exporting,
because the names of the overriding symbols are available to the linker
at the time the executable is linked (i.e. the statically linked crt
startup code), and so it can choose at that time which copy to resolve.

The problem with this is that, contrary to what I outlined previously,
it cannot be done dynamically; the linker must see a reference to the
symbol, i.e. "foo = &malloc;".  But this can be solved as you hinted by
adding a static stub to the import library.  The issue about breaking
direct-to-DLL linking is not a problem in my opinion, because in the
Cygwin distro we always use import libraries because they provide the
"ABI name indirection" that lets e.g. -lintl link to cygintl-8.dll
without having to specify it as -lintl-8.  There are other situations
where an import library is required, such as when you are trying to link
to stdcall calling convention functions that aren't decorated.  So this
would just be another case where using an import library is required,
and it would be of essentially zero burden to the distro as it exists
today because we always ship and import lib anyway.

So, we teach the linker that when creating an import library for a DLL,
if it sees a weak function exported it should emit a small static stub
in the import library that takes the address of that function.  We can
add a runtime support function to receive that address, let's call it
_pei386_add_overridable() just for the sake of argument.  It could be a
static CRT function like the runtime pseudo reloc helper function
_pei386_runtime_relocator() which also gets statically linked into every
app, or it could be in libgcc, or Cygwin.  I'd prefer the static CRT
option, just because it is universal, standalone, and safe; and there's
a precedent for doing it that way with the runtime pseudo reloc helper. 
The downside of this is that it will require apps to be linked with a
newer (presumbaly 1.7 only) version of Cygwin to pick up the new
libcygwin.a which contains these static bits.

Anyway, so the linker puts a stub that looks like this in the import
library of the DLL it is linking:

_pei386_weakhelper_<uniquestring>()
{
  _pei386_add_overridable ("malloc", &malloc);
}

Where malloc is the symbol that was marked weak in the DLL it's
linking.  The <uniquestring> is just something to make sure no two of
these collide but is also unique in that it can be keyed to the function
name.  Maybe it's just the function name alone, I dunno.

Next we need something to cause these stubs to get included into the
link when linking an executable against such an import library.  So we
make the linker keep a running tab of symbols in the executable that it
has resolved with an import library for which there exists a
_pei386_weakhelper_<uniquestring>() stub for that symbol.  At the end of
the link it synthesizes a function that calls each of the stubs, and
adds that synthetic object into the link:

_pei386_weakhelper()
{
  _pei386_weakhelper_for_sym1();
  _pei386_weakhelper_for_sym2();
  ...
}

Next we add a call to _pei386_weakhelper() in the Cygwin CRT startup so
that that synthetic object and all stubs get pulled into the final
link.  We also write an implementation of _pei386_add_overridable() that
just maintains a list of pairs of (function name, pointer).

At this point we have achieved the feat that we have at runtime a
dynamic list of all overridable functions by name and pointer, without
ever touching the export tables or requiring they be exported at all. 
The other half of this version of the plan would be identical to yours,
i.e. add indirection on the DLL side to get the function's address at
runtime.  Preferably this would be in a sort of PLT-like manner where
the overhead of looking up a symbol's address by name only happens the
first time and thereafter it's just an indirect jump through a slot.

Brian

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019