Shared library in D on Linux

Timo Westkämper" <timo.westkamper at gmail.com> Timo Westkämper" <timo.westkamper at gmail.com>
Mon Apr 9 13:44:33 PDT 2012


On Monday, 9 April 2012 at 20:31:44 UTC, Timo Westkämper wrote:
> On Monday, 9 April 2012 at 19:59:18 UTC, Iain Buclaw wrote:
>> On 9 April 2012 20:37,  <"Timo Westkämper\"
>> <timo.westkamper at gmail.com>"@puremagic.com> wrote:
>>> On Monday, 9 April 2012 at 15:14:45 UTC, Ellery Newcomer 
>>> wrote:
>>>>
>>>> Well, if you're really hankering for a shared lib, try ldc. 
>>>> I have gotten
>>>> it to compile working shared libs in the past.
>>>>
>>>> On 04/09/2012 01:24 AM, "Timo Westkämper" 
>>>> <timo.westkamper at gmail.com>"
>>>> wrote:
>>>>>
>>>>> On Sunday, 8 April 2012 at 17:59:28 UTC, Timo Westkämper 
>>>>> wrote:
>>>>>>
>>>>>> Does someone know why the lib (.a) packaging instead of 
>>>>>> objects (.o)
>>>>>> works better in this case?
>>>>>
>>>>>
>>>>> Didn't work after all with -lib. I mixed up outputs.
>>>
>>>
>>> Thanks, I might switch to ldc, if dmd and gdc fail here.
>>>
>>> I found this tls.S script in the druntime sources 
>>> (src/rt/tls.S). Do you
>>> think it could be included in the library to make tls 
>>> initialization work?
>>>
>>> #if linux
>>>
>>> /* The memory between the addresses of _tlsstart and _tlsend 
>>> is the storage
>>> for
>>>  * thread-local data in D 2.0.  Both of these rely on the 
>>> default linker
>>> script
>>>  * of:
>>>  *      .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
>>>  *      .tbss  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) 
>>> *(.tcommon) }
>>>  * to group the sections in that order.
>>>  *
>>>  * Sadly, this does not work because ld orders .tdata after 
>>> .tdata.*,
>>> despite
>>>  * what the linker script says.
>>>  */
>>>
>>> .file "tls.S"
>>>
>>> .globl _tlsstart
>>>    .section .tdata,"awT", at progbits
>>>    .align 4
>>>    .type   _tlsstart, @object
>>>    .size   _tlsstart, 4
>>> _tlsstart:
>>>    .long   3
>>>
>>> .globl _tlsend
>>>    .section .tcommon,"awT", at nobits
>>>    .align 4
>>>    .type   _tlsend, @object
>>>    .size   _tlsend, 4
>>> _tlsend:
>>>    .zero   4
>>>
>>> #endif
>>>
>>>
>>
>> That assembly file does nothing for shared library support.  I 
>> have
>> been meaning to finish up a solution to help support shared 
>> libs,
>> would mean more deviation from the dmd compiler's runtime 
>> library, but
>> that's fine.
>
> Ok. Good to know. Here is what I came up with for now.
>
> I have not yet much knowledge of DMD internals so I just played 
> around with declarations:
>
> import std.stdio;
>
> // FIXME
> __gshared extern(C) void* __data_start;
>
> // FIXME tls marks
> extern(C) int _tlsstart;
> extern(C) int _tlsend;
>
> // FIXME exception handling markers
> extern(C) void _deh_beg() { }
> extern(C) void _deh_end() { }
>
> // hooks for init and term
> extern (C) void rt_init();
> extern (C) void rt_term();
>
> extern (C) void hiD() {
>   rt_init();
>   writeln("hi from D lib");
>   rt_term();
> }
>
> //void main();
>
> /*extern(C) {
>
>   void _init() {
>     rt_init();
>   }
>
>   void _fini() {
>     rt_term();
>   }
>
> }*/
>
>
> For some reasons, the _init and _fini parts don't yet work 
> properly.
>
> And here the part of the Makefile that created the library:
>
>   dmd -c -g test.d -fPIC
>   ld -shared -o libtest.so test.o -lrt -lphobos2 -lpthread
>
> This mostly reflects Jacob Carlborg's comment in the beginning 
> of what features are still missing
>
> * Proper initialization of TLS data
> * Setting up exception handling tables
> * Setting up module info

I just figured out this alternative approach which works as well:

import std.stdio;

// FIXME
__gshared extern(C) void* __data_start;

// hooks for init and term
extern (C) void rt_init();
extern (C) void rt_term();

extern (C) void hiD() {
   rt_init();
   writeln("hi from D lib");
   rt_term();
}

void main() {}


The declaration of the main method adds the tls and deh parts.



More information about the Digitalmars-d mailing list