This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [ANNOUNCEMENT] New experimental package: gcc4-4.3.0-1


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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]