digitalmars.D - osx shared libraries.
- bitwise (27/27) Jun 06 2015 I'm trying to fix shared libraries for OSX. I've updated sections_osx.d ...
- bitwise (12/15) Jun 06 2015 One thought that just occurred to me would be to require that D dynamic ...
- Walter Bright (5/21) Jun 06 2015 Martin Nowak is the author of most of the OSX DLL support, but he seems ...
- bitwise (41/73) Jun 15 2015 Right. I was wondering what he was doing there...Just learned what COMDA...
- bitwise (6/8) Jun 15 2015 It actually appears that __attribute__((visibility("hidden")) is redunda...
- bitwise (9/11) Jun 16 2015 derp.. no it's not. Its the fact they were marked static in the C code
- Jacob Carlborg (8/12) Jun 16 2015 Why don't you just do what Martin did for Linux, or is that what you
- bitwise (16/26) Jun 16 2015 Heh... trying ;)
- Jacob Carlborg (9/23) Jun 16 2015 Obj::staticctor does not seem to be used for setting up the runtime.
- bitwise (19/21) Jun 17 2015 I realize that, but I was thinking that I could just generate a DllMain ...
- David Nadlinger (8/18) Jun 16 2015 I can help you with codegen questions if you want to try LDC. The
- bitwise (19/22) Jun 16 2015 I actually tried to compile my library with LDC a week or two ago, and g...
- David Nadlinger (8/13) Jun 16 2015 Well, this is the old LDC-specific implementation for all
- bitwise (14/25) Jun 17 2015 The llvm codegen is certainly easier on the eyes ;)
- Andrei Alexandrescu (4/7) Jun 06 2015 Where would an approach based on static shared this() and ~this fall
- Walter Bright (2/8) Jun 06 2015 The druntime must be initialized before those are called.
- Jacob Carlborg (8/25) Jun 06 2015 For Linux (and FreeBSD I think) the compiler already generates a
I'm trying to fix shared libraries for OSX. I've updated sections_osx.d to support multiple images, however, the method of notifying druntime when to load/unload images needs to be fixed. Currently, the following method is used to register a callback for when images are loaded, which, based on the last conversation on this topic, is a no-go. Basically, the problem is that there is no way of unregistering the callbacks. https://github.com/D-Programming-Language/druntime/blob/master/src/rt/sections_osx.d#L76 So the solution is to add __attribute__((constructor/destructor)) calls to all D binaries on OSX to initialize the images. The code looks like this: http://dpaste.com/0SF46B6 So my question is, what is the best way to get this code into the binary? I suppose the code could be pre-compiled into an object file and linked by dmd during compilation, but adding external dependencies to dmd seems like a bad idea. I would say DMD could generate this code, but where would it go? I don't think it would be right to add the __constructors__ to a random *.o produced by the compiler, because people will expect *.o files to behave like *.o files. On the other hand, if the __constructors__ were to be added by dmd at link-time, and someone used a linker other than dmd, it would not add in the __constructor__ code, and thus generate a defective dylib. This is a complicated problem with many things to consider, so I'm not exactly sure where to go from here. Any ideas on this would be much appreciated. Thanks, Bit
Jun 06 2015
On Sat, 06 Jun 2015 14:52:11 -0400, bitwise <bitwise.pvt gmail.com> wrote:Any ideas on this would be much appreciated. Thanks, BitOne thought that just occurred to me would be to require that D dynamic libraries contain a main entry point, like DllMain on Windows. This seems like the only real/reliable option. The coder would have to explicitly give dmd a module in which to place the constructor/destructor code for images, the same way that dmd adds a C-main in the file where D-main is found. Enforcing this in the future would be a breaking change, but not a dangerous one. It would be a simple link-time error which was easy to fix. Also, requiring all D binaries to have some kind of entry point would alleviate the need to ever call Runtime.initialize() explicitly. Bit
Jun 06 2015
On 6/6/2015 12:09 PM, bitwise wrote:On Sat, 06 Jun 2015 14:52:11 -0400, bitwise <bitwise.pvt gmail.com> wrote:Martin Nowak is the author of most of the OSX DLL support, but he seems to not be around lately. I'd rather have a dynamic library entry point than put a constructor/destructor call into every object file.Any ideas on this would be much appreciated. Thanks, BitOne thought that just occurred to me would be to require that D dynamic libraries contain a main entry point, like DllMain on Windows. This seems like the only real/reliable option. The coder would have to explicitly give dmd a module in which to place the constructor/destructor code for images, the same way that dmd adds a C-main in the file where D-main is found. Enforcing this in the future would be a breaking change, but not a dangerous one. It would be a simple link-time error which was easy to fix. Also, requiring all D binaries to have some kind of entry point would alleviate the need to ever call Runtime.initialize() explicitly. Bit
Jun 06 2015
On Sat, 06 Jun 2015 16:04:33 -0400, Walter Bright <newshound2 digitalmars.com> wrote:On 6/6/2015 12:09 PM, bitwise wrote:Right. I was wondering what he was doing there...Just learned what COMDAT is ;) It's starting to look like reworking druntime was the easy part. I've got druntime built as a shared library now, and my main project, which thus far is an app/graphics/game engine, is working nicely. Of course, all this goes out the window with a C-Host app... unless people knew to link the shared druntime with their C host app, which doesn't sound intuitive. I like the idea of a dll entry point though. I suppose it could look something like this: enum Reason { processAttach, processDetach, threadAttach, threadDetatch } bool main(void *handle, Reason reason) { return true; } For windows, we could simply hijack DllMain(). As for the OSX, we could use an entry point stub like this, with the rest of the code in druntime: // dladdr(&symbol) gets us the mach_image* void _osx_image_init(void *symbol); void _osx_image_term(void *symbol); __attribute__((visibility("hidden"), constructor)) static void _image_init() { _osx_image_init((void*)&_image_init); } __attribute__((visibility("hidden"), destructor)) static void _image_term(){ _osx_image_term((void*)&_image_term); } I would like to do the above stub in D, but I haven't found a way to specify visibility or section of the function yet. I would rather not do what Martin has done, outputting the entire thing in asm, as that would take me a very long time to get right. Anyways, onward! Thanks BitOn Sat, 06 Jun 2015 14:52:11 -0400, bitwise <bitwise.pvt gmail.com> wrote:Martin Nowak is the author of most of the OSX DLL support, but he seems to not be around lately. I'd rather have a dynamic library entry point than put a constructor/destructor call into every object file.Any ideas on this would be much appreciated. Thanks, BitOne thought that just occurred to me would be to require that D dynamic libraries contain a main entry point, like DllMain on Windows. This seems like the only real/reliable option. The coder would have to explicitly give dmd a module in which to place the constructor/destructor code for images, the same way that dmd adds a C-main in the file where D-main is found. Enforcing this in the future would be a breaking change, but not a dangerous one. It would be a simple link-time error which was easy to fix. Also, requiring all D binaries to have some kind of entry point would alleviate the need to ever call Runtime.initialize() explicitly. Bit
Jun 15 2015
On Mon, 15 Jun 2015 23:26:18 -0400, bitwise <bitwise.pvt gmail.com> wrote:I would like to do the above stub in D, but I haven't found a way to specify visibility or section of the function yet.It actually appears that __attribute__((visibility("hidden")) is redundant and making it a constructor already hides it. So if I can get a D function to go to the "__mod_init_func" section instead, I should be set. Bit
Jun 15 2015
On Mon, 15 Jun 2015 23:56:14 -0400, bitwise <bitwise.pvt gmail.com> wrote:It actually appears that __attribute__((visibility("hidden")) is redundant and making it a constructor already hides it.derp.. no it's not. Its the fact they were marked static in the C code that made them hidden. If anyone is willing to point me in the right direction here, it would be much appreciated ;) Looking at Martin's github, it doesn't appear that he's back in business yet. Thanks, Bit
Jun 16 2015
On 2015-06-16 16:56, bitwise wrote:If anyone is willing to point me in the right direction here, it would be much appreciated ;) Looking at Martin's github, it doesn't appear that he's back in business yet.Why don't you just do what Martin did for Linux, or is that what you would like to avoid? The code was a bit more than I first thought it would be. You could try doing the same for OS X and see what happens :). Just replace the segments and section names with the appropriate OS X names and similar stuff. -- /Jacob Carlborg
Jun 16 2015
On Tue, 16 Jun 2015 15:50:32 -0400, Jacob Carlborg <doob me.com> wrote:On 2015-06-16 16:56, bitwise wrote:Heh... trying ;) Here, there seems to be a function to put things in ctors/dtors, but it looks like it was copy pasted from the Elf code: https://github.com/D-Programming-Language/dmd/blob/c718790165c3124c61e510d8352b9cb9d8ae0198/src/backend/machobj.c#L1532 I've rewritten the first line as follows, but still working on what I need to do to actually put the function in there. IDXSEC seg = s->Sseg = MachObj::getsegment("__mod_init_func", "__DATA", 2, S_MOD_INIT_FUNC_POINTERS); I think the S_COALESCED flag could be added to the above to allow a definition in every obj file like Martin's approach, but I would rather have an explicit DllMain and put the init code in that one obj file. It seems more intuitive to me. So if I get Obj::staticctor and Obj::staticdtor working on osx, that's half the problem solved... I think. BitIf anyone is willing to point me in the right direction here, it would be much appreciated ;) Looking at Martin's github, it doesn't appear that he's back in business yet.Why don't you just do what Martin did for Linux, or is that what you would like to avoid? The code was a bit more than I first thought it would be. You could try doing the same for OS X and see what happens :). Just replace the segments and section names with the appropriate OS X names and similar stuff.
Jun 16 2015
On 2015-06-17 01:19, bitwise wrote:Heh... trying ;) Here, there seems to be a function to put things in ctors/dtors, but it looks like it was copy pasted from the Elf code: https://github.com/D-Programming-Language/dmd/blob/c718790165c3124c61e510d8352b9cb9d8ae0198/src/backend/machobj.c#L1532 I've rewritten the first line as follows, but still working on what I need to do to actually put the function in there. IDXSEC seg = s->Sseg = MachObj::getsegment("__mod_init_func", "__DATA", 2, S_MOD_INIT_FUNC_POINTERS); I think the S_COALESCED flag could be added to the above to allow a definition in every obj file like Martin's approach, but I would rather have an explicit DllMain and put the init code in that one obj file. It seems more intuitive to me. So if I get Obj::staticctor and Obj::staticdtor working on osx, that's half the problem solved... I think.Obj::staticctor does not seem to be used for setting up the runtime. This is the code that generates the runtime initialization [1], I believe, at least it calls "_d_dso_registry". There's a lot more code there than I first hoped. [1] https://github.com/D-Programming-Language/dmd/blob/c718790165c3124c61e510d8352b9cb9d8ae0198/src/backend/elfobj.c#L3183 -- /Jacob Carlborg
Jun 16 2015
On Wed, 17 Jun 2015 02:21:31 -0400, Jacob Carlborg <doob me.com> wrote:Obj::staticctor does not seem to be used for setting up the runtime.I realize that, but I was thinking that I could just generate a DllMain in D code[1], and then output it as a special case[2] as is done with regular D main: [1] https://github.com/D-Programming-Language/dmd/blob/c718790165c3124c61e510d8352b9cb9d8ae0198/src/mars.c#L228 [2] https://github.com/D-Programming-Language/dmd/blob/c718790165c3124c61e510d8352b9cb9d8ae0198/src/mars.c#L1669 For the second step though, I could also call staticctor/staticdtor or something.. still workin on it ;)There's a lot more code there than I first hoped.Yeah... Writing out assembly as byte codes like that is a little too much for me. I think I can get by with the above solution. I'm still having trouble finding where functions are exported though. Every instance of export_symbol() seems to be check first with isExport(), except all symbols are exported by default on OSX.... but from where? https://github.com/D-Programming-Language/dmd/blob/c718790165c3124c61e510d8352b9cb9d8ae0198/src/toobj.c#L572 It seems like it could be in either out.c or machobj.c, but I still haven't found it. Bit
Jun 17 2015
On Tuesday, 16 June 2015 at 14:56:35 UTC, bitwise wrote:On Mon, 15 Jun 2015 23:56:14 -0400, bitwise <bitwise.pvt gmail.com> wrote:I can help you with codegen questions if you want to try LDC. The implementation I did there for Linux was based on Martin's work (but I contributed fixes to a couple of the shared problems and made it work with --gc-sections). You'll have to drop down to the compiler level to influence the visibility in either case, though. - DavidIt actually appears that __attribute__((visibility("hidden")) is redundant and making it a constructor already hides it.derp.. no it's not. Its the fact they were marked static in the C code that made them hidden. If anyone is willing to point me in the right direction here, it would be much appreciated ;) Looking at Martin's github, it doesn't appear that he's back in business yet.
Jun 16 2015
On Tue, 16 Jun 2015 17:45:52 -0400, David Nadlinger <code klickverbot.at> wrote:I can help you with codegen questions if you want to try LDC.I actually tried to compile my library with LDC a week or two ago, and got ICEd. I would like to try LDC, so I'll probably give it a go next release. It looks like the runtime for LDC would need some work too though. In particular, it doesn't seem to support dynamic loading: https://github.com/ldc-developers/druntime/blob/ldc/src/rt/sections_ldc.d#L379You'll have to drop down to the compiler level to influence the visibility in either case, though.Yeah... I'm still trying to figure out how dmd exports, and decides when to export, functions. In Martin's code, it looks like he's manually outputting assembly as bytecodes, but I was hoping for a simpler solution. Ideally, I would like to copy this approach: https://github.com/D-Programming-Language/dmd/blob/c718790165c3124c61e510d8352b9cb9d8ae0198/src/mars.c#L228 Then, add some special cases to put the generated function into the right section and ensure the symbols are not exported. Anyways, your Dconf presentation was helpful to explain a few things, so thanks for that =D Bit
Jun 16 2015
On Tuesday, 16 June 2015 at 23:52:26 UTC, bitwise wrote:I would like to try LDC, so I'll probably give it a go next release. It looks like the runtime for LDC would need some work too though. In particular, it doesn't seem to support dynamic loading: https://github.com/ldc-developers/druntime/blob/ldc/src/rt/sections_ldc.d#L379Well, this is the old LDC-specific implementation for all platforms that have not been converted to the new scheme yet. You'd probably want to base your implementation on sections_linux, which we use on Linux. The code that emits the global constructors/destructors is here: https://github.com/ldc-developers/ldc/blob/33befca6d72fe267ee8e4179ba670513993e2eb7/gen/module.cpp#L348-L546 - David
Jun 16 2015
On Tue, 16 Jun 2015 20:07:03 -0400, David Nadlinger <code klickverbot.at> wrote:On Tuesday, 16 June 2015 at 23:52:26 UTC, bitwise wrote:The llvm codegen is certainly easier on the eyes ;) When I started porting my library though, I fumbled around with a bunch of compilers and build commands trying to get D/C++ interop to work right. xcode's default compiler seems to work nicely with dmd, so I went with that. Other combinations where giving me strange linker errors. As far as the runtime code, I understand most of what's going on, but I'm still confused about the purpose of ThreadDSO, and what these are for: pinLoadedLibraries() unpinLoadedLibraries() inheritLoadedLibraries() cleanupLoadedLibraries() BitI would like to try LDC, so I'll probably give it a go next release. It looks like the runtime for LDC would need some work too though. In particular, it doesn't seem to support dynamic loading: https://github.com/ldc-developers/druntime/blob/ldc/src/rt/sections_ldc.d#L379Well, this is the old LDC-specific implementation for all platforms that have not been converted to the new scheme yet. You'd probably want to base your implementation on sections_linux, which we use on Linux. The code that emits the global constructors/destructors is here: https://github.com/ldc-developers/ldc/blob/33befca6d72fe267ee8e4179ba670513993e2eb7/gen/module.cpp#L348-L546 - David
Jun 17 2015
On 6/6/15 11:52 AM, bitwise wrote:The code looks like this: http://dpaste.com/0SF46B6 So my question is, what is the best way to get this code into the binary?Where would an approach based on static shared this() and ~this fall short? Those would get called when the library is loaded, unless you actually need to implement exactly that :o). -- Andrei
Jun 06 2015
On 6/6/2015 12:47 PM, Andrei Alexandrescu wrote:On 6/6/15 11:52 AM, bitwise wrote:The druntime must be initialized before those are called.The code looks like this: http://dpaste.com/0SF46B6 So my question is, what is the best way to get this code into the binary?Where would an approach based on static shared this() and ~this fall short?
Jun 06 2015
On 2015-06-06 20:52, bitwise wrote:I'm trying to fix shared libraries for OSX. I've updated sections_osx.d to support multiple images, however, the method of notifying druntime when to load/unload images needs to be fixed. Currently, the following method is used to register a callback for when images are loaded, which, based on the last conversation on this topic, is a no-go. Basically, the problem is that there is no way of unregistering the callbacks. https://github.com/D-Programming-Language/druntime/blob/master/src/rt/sections_osx.d#L76 So the solution is to add __attribute__((constructor/destructor)) calls to all D binaries on OSX to initialize the images. The code looks like this: http://dpaste.com/0SF46B6 So my question is, what is the best way to get this code into the binary? I suppose the code could be pre-compiled into an object file and linked by dmd during compilation, but adding external dependencies to dmd seems like a bad idea. I would say DMD could generate this code, but where would it go?For Linux (and FreeBSD I think) the compiler already generates a __attribute__((constructor)) function which calls _d_dso_registry [1]. Modify the compiler to do the same thing for OS X. [1] https://github.com/D-Programming-Language/druntime/blob/master/src/rt/sections_elf_shared.d#L321 -- /Jacob Carlborg
Jun 06 2015