Ralf Wildenhues wrote:

> > * Windows (cygwin/mingw)
> > As i understand the issue (I am not very familiar with this) you can't
> > have unresolved references in a plugin back to the GCC executable. I.e.
> > Building GCC with -rdynamic will not work on this platform. Do we move
> > most of the GCC implementation into a "library/DLL" having a "stub"
> > main() that just calls the library implementation. Then both the
> > application AND the plugins can link with this library/DLL in a way that
> > will work on Windows.
> > Or are we going for the quick solution of using -rdynamic and not
> > supporting this platform (Not my preferred option)?
> 
> AFAIK you can fix w32 issues with DEF files.

Well, that is another way to do it.  You don't have to use a .def file
or __declspec(dllexport) markup, you can also use
-Wl,--export-all-symbols which doesn't require any source code
modifications.

But there is another more sinister problem on PE hosts with having the
plugin link to symbols from the executable: this hard codes the name of
the executable in the plugin, as essentially the executable is now a
library to which the plugin is linked.  Obviously this is a deal-breaker
because the plugin needs to be loadable from cc1, cc1plus, f951, etc.
unless you want to link a separate copy of the plugin for each language.

An alternative is to have the plugin resolve the symbols in the
executable at runtime, using the moral equivalent of dlsym.  This also
makes linking the plugin a lot easier because you don't have to worry
about resolving the executable's symbols at link-time (which you would
otherwise have to do with an import library for the executable.) 
However, this makes life more difficult for the writer of the plugin as
they have to deal with all those function pointers.  It is possible to
ameliorate this with macros that set up each function pointer to a
wrapper that looks up the actual function the first time it's called and
then sets the pointer to that address, essentially a poor-man's PLT. 
But with this method you still have to maintain a list of every
functions/variable used in order to instantiate a copy of the wrapper
macro for it.

Moving the compiler itself into a shared library of course avoids all of
the above, but I'm not sure I understand how this would work w.r.t. the
different language backends.  Would the shared library just contain
everything, and somehow just determine its behavior based on whether it
was loaded by cc1 or cc1plus or f951 etc.  Or would there be a separate
shared library for each?  (Which would really be useless and not solve
anything for PE hosts because it would be back to requiring a number of
copies of the plugin, one for each language backend.)

Is it really that far fetched to have the plugin not directly access
anything from the executable's symbol table but instead be passed a
structure that contains a defined set of interfaces and callbacks?  By
using this strategy you also insulate the plugin from the gcc internals,
such that you can define this struct in a separate header that goes in
the plugin SDK, without requiring that the SDK drags in a bunch of
internal crap from the build directory.  With judicious use of callbacks
you can even achieve some degree of plugin binary compatibility.  For
example you have gcc provide function pointers for
getters/setters/walkers/enumerators for internal structures in this
struct that is passed to the plugin.  The plugin is then insulated from
internal representation changes since the callback lives in gcc too and
gets rebuilt when the internal representation changes.

Now, I understand that maintaining a stable binary API for plugins is
probably not the number one priority, i.e. past discussions have
concluded that this is too much work and pain to maintain.  And maybe
that's true.  But I'm just suggesting that you can in fact kill two
birds with one stone here: insulate the plugin from internal
representation details *and* overcome portability problems with non-ELF
hosts.  

Brian

Reply via email to