Dynamic loading, D all the way (dmd 64bit 2.060/Ubuntu 64bit 12.04/x86_64)
Carl Sturtivant
sturtivant at gmail.com
Mon Aug 20 08:16:42 PDT 2012
>
> I'm not sure I'm following what you exactly have done here but
> in general this is what needs to be done to make dynamic
> libraries properly work in D :
>
> * Initialize module infos (module constructors and similar)
> * Add TLS variables
> * Add exception handling tables
> * Add GC roots
>
> The above four things need to be extracted from the loaded
> dynamic library and it gets loaded and preferably remove them
> as well when the dynamic library gets unloaded. Currently this
> is only extracted from the running executable. This is platform
> dependent but usually it's extracted using bracketed sections
> via extern C variables.
OK, good to know. Any further hints about these, or where I can
look?
What I've done is use the C dynamic loading library (header
dlfcn.h) to manually load a shared object written in D, dload.d,
from a D program (main.d), which then successfully calls
functions in dload.d that are not defined extern(C).
I am attempting a do-it-yourself dynamic loading in D, where I
explicitly do all the administration manually to make it work,
rather than rely upon D to do it automatically. Hence my use of
the C dynamic loading library, which knows nothing of additional
work D must do.
Reason for this approach: the newsgroups indicate that dynamic
loading in D does not work as yet.
What's novel is that I explicitly excluded from the shared object
anything but code generated directly from dload.d:
dmd -c dload.d -m64 -fPIC
ld dload.o -shared -o libdload.so -m elf_x86_64 -E
And I included the whole of libphobos.a in the build of the main
program:
dmd -c main.d -m64
gcc main.o -o main -m64 -Wl,-E -ldl -Wl,--whole-archive -lphobos2
\
-Wl,--no-whole-archive -lcurl -lpthread -lm -lrt
This tactic is in the hope that all parts of D used in the shared
library will find their linkage in the main program when it's
dynamically loaded. (And the -E option passed to the linker in
both cases is to expose all symbols for exactly this purpose.)
Reason for this approach: the newsgroups indicate that D
runtime/phobos (all currently in libphobos.a it seems) does not
initialize properly in a shared library, so I ensure that it's
not present at all, and endeavor to have the shared object
implicitly use the properly working D runtime/phobos in the main
executable.
[And besides, at 64 bits all code in shared libraries apparently
must be position independent, so even if I wanted to link parts
of libphobos.a into the shared library, I couldn't without
recompiling libphobos.a with the -fPIC option!]
This bare-bones-in-the-shared-library approach has worked well in
my toy example. The only thing that apparently doesn't work is if
an exception is thrown from the static initializer 'static
this()' in the shared object. If an exception results from a call
chain initiated by the main program even if thrown from a
function in the shared object, all is well it seems.
Incidentally, I fibbed slightly about the ld command used to link
the shared object. It also contains a trailing
-init=$(shell staticCtor dload.o)
which enables the linker to bind in execution of the static
initializer 'static this()' so that it runs automatically when
the shared library is loaded. staticCtor is a script that
analyzes dload.o to find its name, which is mangled of course.
If anyone can give me any more specific information about what
else I can make happen manually to complete effective linkage at
the D level I'd be grateful. I'm not stopping the investigation
here!
More information about the Digitalmars-d
mailing list