On Wednesday, 16 September 2015 at 23:24:29 UTC, bitwise wrote:

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.

I'd prefer a solution that works with existing compilers, but maybe building a custom LDC is possible if I figure it out.

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


In practive I've found that the D shared libraries I produce can be dlopen/dlclose any number of times, simultaneous too. Using both LDC and DMD, don't know why it works. The thing that doesn't work is the C host program dlopen'ing the shared library, dlclose it, then dlopen another shared library written in C.


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.

I don't control the host program. My shared libs do have an entrypoint, from which I call Runtime.initialize().

I can also use LDC global constructor/destructor to call Runtime.initialize / Runtime.terminate, but it doesn't work any better because of the callback.




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

Thanks for your answer. This is really helpful, though I don't understand the first thing about what images, headers and sections are in this context.


Reply via email to