December 08, 2015
I’m looking in to if I can get to DMD output native TLS on OS X. I’m trying to output a reference to a symbol (not sure if that’s the correct terminology) using the “dtxoff” function that matches Clang. The code I have looks like this:

const char *tlvInitName = concat(s->Sident, strlen(s->Sident), "$tlv$init", 9);
Symbol* tlvInit = symbol_name(tlvInitName, SCstatic, type_fake(TYnfunc));
tlvInit->Sdt = NULL;
tlvInit->Sseg = MachObj::getsegment("__thread_data", "__DATA", 2, S_THREAD_LOCAL_REGULAR);
Initializer_toDt(vd->_init, &tlvInit->Sdt);
outdata(tlvInit);

Symbol* tlvBootstrap = symbol_name("__tlv_bootstrap", SCglobal, type_fake(TYnfunc));

dtxoff(&s->Sdt, tlvBootstrap, 0, TYnptr);
dtsize_t(&s->Sdt, 0);
dtxoff(&s->Sdt, tlvInit, 0, TYnptr);

I’ve added my code here [1]. The problem is the “tlvInit” symbol. With the code like above it will output the “__thread_vars” section like this:

Contents of (__DATA,__thread_vars) section
00000000000000cc      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000000000000dc      c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000000000000ec      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000000000000fc	      c4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000000000010c      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000000000011c      c8 00 00 00 00 00 00 00

And with another view:

Section __thread_vars {
  0x10 0 3 0 X86_64_RELOC_UNSIGNED 0 __thread_data
  0x30 0 3 0 X86_64_RELOC_UNSIGNED 0 __thread_data
  0x50 0 3 0 X86_64_RELOC_UNSIGNED 0 __thread_data
  0x40 0 3 1 X86_64_RELOC_UNSIGNED 0 __tlv_bootstrap
  0x20 0 3 1 X86_64_RELOC_UNSIGNED 0 __tlv_bootstrap
  0x0 0 3 1 X86_64_RELOC_UNSIGNED 0 __tlv_bootstrap
}

The dump from Clang for the corresponding code looks like this:

Contents of (__DATA,__thread_vars) section
000000000000007c	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000000000008c	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000000000009c	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000000000000ac	00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000000000000bc	00 00 00 00 00 00 00 00

And:

Section __thread_vars {
  0x40 0 3 1 X86_64_RELOC_UNSIGNED 0 _bar3$tlv$init
  0x30 0 3 1 X86_64_RELOC_UNSIGNED 0 __tlv_bootstrap
  0x28 0 3 1 X86_64_RELOC_UNSIGNED 0 _bar2$tlv$init
  0x18 0 3 1 X86_64_RELOC_UNSIGNED 0 __tlv_bootstrap
  0x10 0 3 1 X86_64_RELOC_UNSIGNED 0 _bar$tlv$init
  0x0 0 3 1 X86_64_RELOC_UNSIGNED 0 __tlv_bootstrap
}

I’ve tried various ways of solving this but I don’t really understand how “dtxoff” function (and similar functions) work. If I create a new symbol with the same name as in “tlvInitName” without any data (like for “tlvBootstrap”) it looks correct in the  “__thread_vars” section but DMD has outputted duplicated symbols (for the "_bar$tlv$init" symbols) in the symbol table, one which is undefined, which will cause a linker error.

Any ideas?

[1] https://github.com/D-Programming-Language/dmd/blob/master/src/toobj.c#L950

-- 
/Jacob Carlborg


_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals
December 13, 2015
> On 8 dec 2015, at 22:20, Jacob Carlborg via dmd-internals <dmd-internals@puremagic.com> wrote:
> 
> I’m looking in to if I can get to DMD output native TLS on OS X. I’m trying to output a reference to a symbol (not sure if that’s the correct terminology) using the “dtxoff” function that matches Clang. The code I have looks like this:
> 
> const char *tlvInitName = concat(s->Sident, strlen(s->Sident), "$tlv$init", 9);
> Symbol* tlvInit = symbol_name(tlvInitName, SCstatic, type_fake(TYnfunc));
> tlvInit->Sdt = NULL;
> tlvInit->Sseg = MachObj::getsegment("__thread_data", "__DATA", 2, S_THREAD_LOCAL_REGULAR);
> Initializer_toDt(vd->_init, &tlvInit->Sdt);
> outdata(tlvInit);
> 
> Symbol* tlvBootstrap = symbol_name("__tlv_bootstrap", SCglobal, type_fake(TYnfunc));
> 
> dtxoff(&s->Sdt, tlvBootstrap, 0, TYnptr);
> dtsize_t(&s->Sdt, 0);
> dtxoff(&s->Sdt, tlvInit, 0, TYnptr);

I managed to solve the problem by changing the class of the “tlvInit” symbol to “export” after outputting it.

tlvInit->Sclass = SCextern;

-- 
/Jacob Carlborg


_______________________________________________
dmd-internals mailing list
dmd-internals@puremagic.com
http://lists.puremagic.com/mailman/listinfo/dmd-internals