Showing with 29 additions and 1 deletion.
  1. +29 −1 src/rt/sections_linux.d
30 changes: 29 additions & 1 deletion src/rt/sections_linux.d
Original file line number Diff line number Diff line change
Expand Up @@ -820,12 +820,40 @@ struct tls_index

extern(C) void* __tls_get_addr(tls_index* ti);

/* The dynamic thread vector (DTV) pointers may point 0x8000 past the start of
* each TLS block. This is at least true for PowerPC and Mips platforms.
* See: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/powerpc/dl-tls.h;h=f7cf6f96ebfb505abfd2f02be0ad0e833107c0cd;hb=HEAD#l34
* https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/mips/dl-tls.h;h=93a6dc050cb144b9f68b96fb3199c60f5b1fcd18;hb=HEAD#l32
*/
version(X86)
enum TLS_DTV_OFFSET = 0x;
else version(X86_64)
enum TLS_DTV_OFFSET = 0x;
else version(ARM)
enum TLS_DTV_OFFSET = 0x;
else version(AArch64)
enum TLS_DTV_OFFSET = 0x;
else version(SPARC)
enum TLS_DTV_OFFSET = 0x;
else version(SPARC64)
enum TLS_DTV_OFFSET = 0x;
else version(PPC)
enum TLS_DTV_OFFSET = 0x8000;
else version(PPC64)
enum TLS_DTV_OFFSET = 0x8000;
else version(MIPS)
enum TLS_DTV_OFFSET = 0x8000;
else version(MIPS64)
enum TLS_DTV_OFFSET = 0x8000;
else
static assert( false, "Platform not supported." );

void[] getTLSRange(size_t mod, size_t sz)
{
if (mod == 0)
return null;

// base offset
auto ti = tls_index(mod, 0);
return __tls_get_addr(&ti)[0 .. sz];
return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz];
}