On 24/02/2013 15:13, Ben Davis wrote:
I'm hitting more problems getting my DLL to start up, but I'll post
about those separately later if necessary.
That's weird. Whatever further problem I thought I was hitting, I'm not
hitting it any more. I'll put it down to user error on my part. :)
Yay! GDC built my DLL and it works!
I'll post here a summary of what I had to do, in case it helps anyone
else who wants to build a DLL with GDC. Also in case you want to fix the
bugs I'm posting a workaround for. I get the feeling you guys are
already too busy, but it's here if you want it. :)
So, to summarise - in order for 32-bit DLLs to work, you need to:
- Not use the 20130108 release because of the 32-bit TLS bug;
- Replace dll.d and threadaux.d (both in core/sys/windows, containing
D-style asm) with versions that contain GCC-style asm instead (my
versions below). Because the user's DllMain is responsible for calling
down into these, it's easy to declare one's own copies with the fixes
applied, and call those instead. I put mine in a subdirectory (does D
call those packages?) called 'gdcdll', and then imported them instead of
the Windows ones. (They're Boost-licensed so it looks as if this is OK
no matter what end-user licence your own code has. I'll put my changes
under Boost too; why not? So you guys can use them.)
Here are all the specific changes I made for MinGW, along with the old
(DMD) versions. You'll find the 'else' parts already in the source.
In dll.d somewhere near the top - I think this change already exists
somewhere but the only place I found it was in a .di file somewhere:
version (MinGW)
{
extern __gshared void* _tls_start;
extern __gshared void* _tls_end;
extern __gshared void* __xl_a;
alias _tls_start _tlsstart;
alias _tls_end _tlsend;
alias __xl_a _tls_callbacks_a;
}
else
{
extern __gshared void* _tlsstart;
extern __gshared void* _tlsend;
extern __gshared void* _tls_callbacks_a;
}
extern __gshared int _tls_index; //This is unchanged
Further down in dll.d:
void** peb;
version (MinGW) {
asm
{
".intel_syntax noprefix\n"
"mov EAX,FS:[0x30]\n"
".att_syntax noprefix\n"
:"=a"(peb);
}
}
else {
asm
{
mov EAX,FS:[0x30];
mov peb, EAX;
}
}
Somewhere in the middle of threadaux.d:
version(MinGW)
{
void** teb;
asm
{
".intel_syntax noprefix\n"
"mov EAX,FS:[0x18]\n"
"ret\n"
".att_syntax noprefix\n"
:"=a"(teb);
}
return teb;
}
else version(Win32)
{
asm
{
naked;
mov EAX,FS:[0x18];
ret;
}
}
else version(Win64)
{ snip }