[Issue 15060] Can't load a D shared library first, then load a C shared library

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Sun Sep 27 21:50:09 PDT 2015


https://issues.dlang.org/show_bug.cgi?id=15060

bitwise <nicolas.jinchereau at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |nicolas.jinchereau at gmail.co
                   |                            |m

--- Comment #6 from bitwise <nicolas.jinchereau at gmail.com> ---
For reference:

dyld's source:

http://www.opensource.apple.com/source/dyld/
http://www.opensource.apple.com/source/dyld/dyld-353.2.3/

The callbacks being discussed:
'_dyld_register_func_for_add_image'
'_dyld_register_func_for_remove_image'
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dyld.3.html
https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/MachOReference/index.html

'dyld_register_image_state_change_handler'
couldn't find docs, but declaration/definition are here:
http://www.opensource.apple.com/source/dyld/dyld-353.2.3/include/mach-o/dyld_priv.h
http://www.opensource.apple.com/source/dyld/dyld-353.2.3/src/dyldAPIs.cpp

Finally, I don't see any callback API which allows you to unregister the
"library loaded" callback, so I think that adding init/fini calls is the
solution.

Now, when the library is loaded, and init/fini are called, we need a way to get
the mach_header* for the library which is loading. 'dladdr' can do this. It's
documented that the 'dli_fbase' member of dl_info is a (mach_header*). So a
private symbol can be added to the files along with the init/fini calls...or I
suppose you could use the address of the init/fini calls themselves.. and pass
the symbol to dladdr.

https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/MachOReference/index.html#//apple_ref/c/func/dladdr

The other piece of information that you need is the vmaddr_slide value. Right
now, '_dyld_get_image_slide' is listed in 'dyld_priv.h'. If it turns out that
_dyld_get_image_slide is a private API or something, and not allowed in the
Apple Store, we can use plan B, which is to just iterate the mach_images and
vmaddr_slides in lockstep until a match is found using these APIs:

uint32_t _dyld_image_count()
const struct mach_header* _dyld_get_image_header(uint32_t image_index)
intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index)

These three are APIs are here:
https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/MachOReference/index.html

'_dyld_get_image_slide' can be found here:
http://www.opensource.apple.com/source/dyld/dyld-353.2.3/include/mach-o/dyld_priv.h


Last time I looked, it seemed like this is more complicated than what you've
done for ELF. I think manually injecting this code in the backend as ASM would
be very difficult. I would(if I knew how) instead try to add some pragmas to
DMD to help out, so that init/fini could just be written in D. Then, DMD's
front end could inject the needed code.

For example, LDC already has these, so maybe DMD could too:

pragma(LDC_global_crt_ctor, 1024)
pragma(LDC_global_crt_dtor, 1024)
http://wiki.dlang.org/LDC-specific_language_changes

I think one more could make symbols private(GCC has something like this)
pragma(visibility, hidden)

Since public symbols are merged even between shared libraries on OSX, init/fini
and whatever symbol is passed to dladdr would have to be private/hidden.

Maybe one final pragma to make the symbols COMDAT.

--


More information about the Digitalmars-d-bugs mailing list