Desperately looking for a work-around to load and unload D shared libraries from C on OSX
bitwise via Digitalmars-d
digitalmars-d at puremagic.com
Wed Sep 16 16:24:26 PDT 2015
On Wednesday, 16 September 2015 at 22:29:46 UTC, ponce wrote:
> Context: On OSX, a C program can load a D shared library but
> once unloaded the next dlopen will crash, jumping into a
> callback that doesn't exist anymore.
>
> I've filed it here:
> https://issues.dlang.org/show_bug.cgi?id=15060
>
>
> It looks like this was known and discussed several times
> already:
> http://forum.dlang.org/post/vixoqmidlbizawbxmsao@forum.dlang.org (2015)
> https://github.com/D-Programming-Language/druntime/pull/228
> (2012)
>
>
> Any idea to work-around this problem would be awesome.
>
> I'm not looking for something correct, future-proof, or pretty.
> Any shit that still stick to the wall will do. Anything!
>
> The only case I need to support is: C host, D shared library,
> with runtime statically linked.
>
> Please help!
I was trying to solve this one myself, but the modifications to
DMD's backend that are needed are out of reach for me right now.
If you're willing to build your own druntime, you may be able to
get by.
If I understand correctly, you want to repeatedly load/unload the
same shared library, correct? I ask because druntime for osx only
supports loading a single image at a time:
https://github.com/D-Programming-Language/druntime/blob/1e25749cd01ad08dc08319a3853fbe86356c3e62/src/rt/sections_osx.d#L26
Anyways, when main() of a D program runs, it calls rt_init() and
rt_term(). If you don't have a D entry point in your program, you
have to retrieve these from your shared lib(which has druntime
statically linked) using dlsym() and call them yourself.
https://github.com/D-Programming-Language/druntime/blob/478b6c5354470bc70e688c45821eea71b766e70d/src/rt/dmain2.d#L158
Now, initSections() and finiSections() are responsible for
setting up the image. If you look at initSections(), the function
"_dyld_register_func_for_add_image" is the one that causes the
crash, because there is no way to remove the callback, which will
reside in your shared lib.
https://github.com/D-Programming-Language/druntime/blob/1e25749cd01ad08dc08319a3853fbe86356c3e62/src/rt/sections_osx.d#L76
So what happens is, when you call
_dyld_register_func_for_add_image, dyld will call your callback
for every shared-library/image(including the main application's
image) that is currently loaded. However, you can skip the
callback and just call "sections_osx_onAddImage" yourself.
You would have to add something like this to sections_osx.d, and
call it instead of adding the callback:
void callOnAddImage()
{
// dladdr() should give you information about the
// shared lib in which the symbol you pass resides.
// Passing the address of this function should work.
Dl_info info;
int ret = dladdr(cast(void*)&callOnAddImage, &info);
assert(ret);
// "dli_fbase" is actually a pointer to
// the mach_header for the shared library.
// once you have the mach_header, you can
// also retrieve the image slide, and finally
// call sections_osx_onAddImage().
mach_header* header = cast(mach_header*)info.dli_fbase;
intptr_t slide = _dyld_get_image_slide(header);
sections_osx_onAddImage(header, slide);
}
Now, if you look at finiSections(), it seems to be incomplete.
There is nothing like sections_osx_onRemoveImage, so you'll have
to complete it to make sure the library is unloaded correctly:
https://github.com/D-Programming-Language/druntime/blob/1e25749cd01ad08dc08319a3853fbe86356c3e62/src/rt/sections_osx.d#L83
You'll may have to make other mods here and there to get this
working correctly, but this is the bulk of it.
Bit
More information about the Digitalmars-d
mailing list