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