about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/box64context.c44
-rw-r--r--src/core.c5
-rw-r--r--src/elfs/elfloader.c29
-rw-r--r--src/emu/x64emu.c22
-rw-r--r--src/emu/x64emu_private.h7
-rw-r--r--src/emu/x64run0f.c5
-rw-r--r--src/emu/x64tls.c71
-rw-r--r--src/include/box64context.h5
-rw-r--r--src/include/debug.h1
-rw-r--r--src/include/elfloader.h7
-rw-r--r--src/include/os.h4
-rw-r--r--src/include/x64tls.h2
-rw-r--r--src/libtools/threads.c3
-rwxr-xr-xsrc/libtools/threads32.c2
-rw-r--r--src/os/os_linux.c25
-rw-r--r--src/os/os_wine.c4
-rw-r--r--src/wrapped/wrappedldlinux.c4
-rw-r--r--src/wrapped/wrappedldlinux_private.h2
-rwxr-xr-xsrc/wrapped32/wrappedldlinux.c4
19 files changed, 133 insertions, 113 deletions
diff --git a/src/box64context.c b/src/box64context.c
index 444a76a8..cbc92283 100644
--- a/src/box64context.c
+++ b/src/box64context.c
@@ -72,17 +72,6 @@ int getrand(int maxval)
 
 }
 
-void free_tlsdatasize(void* p)
-{
-    if(!p)
-        return;
-    tlsdatasize_t *data = (tlsdatasize_t*)p;
-    actual_free(data->ptr);
-    actual_free(p);
-    if(my_context)
-        pthread_setspecific(my_context->tlskey, NULL);
-}
-
 void x64Syscall(x64emu_t *emu);
 void x86Syscall(x64emu_t *emu);
 
@@ -217,28 +206,25 @@ box64context_t *NewBox64Context(int argc)
     init_mutexes(context);
     pthread_atfork(NULL, NULL, atfork_child_box64context);
 
-    pthread_key_create(&context->tlskey, free_tlsdatasize);
-
-
     for (int i=0; i<8; ++i) context->canary[i] = 1 +  getrand(255);
     context->canary[getrand(4)] = 0;
     printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x28, value:%08X\n", *(uint32_t*)context->canary);
 
     // init segments
     for(int i=0; i<16; i++) {
-        context->segtls[i].limit = (uintptr_t)-1LL;
+        context->seggdt[i].limit = (uintptr_t)-1LL;
     }
-    context->segtls[10].key_init = 0;    // 0x53 selector
-    context->segtls[10].present = 1;
-    context->segtls[8].key_init = 0;    // 0x43 selector
-    context->segtls[8].present = 1;
-    context->segtls[6].key_init = 0;    // 0x33 selector
-    context->segtls[6].present = 1;
-    context->segtls[5].key_init = 0;    // 0x2b selector
-    context->segtls[5].present = 1;
-    context->segtls[4].key_init = 0;    // 0x23 selector
-    context->segtls[4].present = 1;
-    context->segtls[4].is32bits = 1;
+    // 0x53 selector
+    context->seggdt[10].present = 1;
+    // 0x43 selector
+    context->seggdt[8].present = 1;
+    // 0x33 selector
+    context->seggdt[6].present = 1;
+    // 0x2b selector
+    context->seggdt[5].present = 1;
+    // 0x23 selector
+    context->seggdt[4].present = 1;
+    context->seggdt[4].is32bits = 1;
 
     context->globdata = NewMapSymbols();
     context->uniques = NewMapSymbols();
@@ -330,12 +316,6 @@ void FreeBox64Context(box64context_t** context)
         box_free(ctx->stack_clone);
 
 
-    void* ptr;
-    if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
-        free_tlsdatasize(ptr);
-    }
-    pthread_key_delete(ctx->tlskey);
-
     if(ctx->tlsdata)
         box_free(ctx->tlsdata);
 
diff --git a/src/core.c b/src/core.c
index 20a6df56..14d0c26a 100644
--- a/src/core.c
+++ b/src/core.c
@@ -67,6 +67,7 @@ int box64_zoom = 0;
 int box64_steam = 0;
 int box64_steamcmd = 0;
 int box64_musl = 0;
+int box64_nolibs = 0;
 char* box64_custom_gstreamer = NULL;
 int box64_tcmalloc_minimal = 0;
 uintptr_t fmod_smc_start = 0;
@@ -1322,6 +1323,8 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
         my_context->orig_argc = argc;
         my_context->orig_argv = (char**)argv;
     }
+    box64_nolibs = (NeededLibs(elf_header)==0);
+    if(box64_nolibs) printf_log(LOG_INFO, "Warning, box64 is not really compatible with staticaly linked binaries. Expect crash!\n");
     box64_isglibc234 = GetNeededVersionForLib(elf_header, "libc.so.6", "GLIBC_2.34");
     if(box64_isglibc234)
         printf_log(LOG_DEBUG, "Program linked with GLIBC 2.34+\n");
@@ -1405,7 +1408,7 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
     setupTraceInit();
     RunDeferredElfInit(emu);
     // update TLS of main elf
-    RefreshElfTLS(elf_header);
+    RefreshElfTLS(elf_header, emu);
     // do some special case check, _IO_2_1_stderr_ and friends, that are setup by libc, but it's already done here, so need to do a copy
     ResetSpecialCaseMainElf(elf_header);
     // init...
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 7cc6b490..2c860cac 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -1133,14 +1133,14 @@ int ElfCheckIfUseTCMallocMinimal(elfheader_t* h)
     return 0;
 }
 
-void RefreshElfTLS(elfheader_t* h)
+void RefreshElfTLS(elfheader_t* h, x64emu_t* emu)
 {
     if(h->tlsfilesize) {
         char* dest = (char*)(my_context->tlsdata+my_context->tlssize+h->tlsbase);
         printf_dump(LOG_DEBUG, "Refreshing main TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlsfilesize);
         memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
-        if (pthread_getspecific(my_context->tlskey)) {
-            tlsdatasize_t* ptr = getTLSData(my_context);
+        if (emu->tlsdata) {
+            tlsdatasize_t* ptr = getTLSData(emu);
             // refresh in tlsdata too
             dest = (char*)(ptr->data+h->tlsbase);
             printf_dump(LOG_DEBUG, "Refreshing active TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlssize-h->tlsfilesize);
@@ -1166,7 +1166,7 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
     memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
     uintptr_t p = h->initentry + h->delta;
     // Refresh no-file part of TLS in case default value changed
-    RefreshElfTLS(h);
+    RefreshElfTLS(h, emu);
     // check if in deferredInit
     if(my_context->deferredInit) {
         if(my_context->deferredInitSz==my_context->deferredInitCap) {
@@ -1438,9 +1438,9 @@ int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, int v
     return 0;
 }
 
-void* GetDTatOffset(box64context_t* context, unsigned long int index, unsigned long int offset)
+void* GetDTatOffset(x64emu_t* emu, unsigned long int index, unsigned long int offset)
 {
-    return (void*)((char*)GetTLSPointer(context, context->elfs[index])+offset);
+    return (void*)((char*)GetTLSPointer(emu, emu->context->elfs[index])+offset);
 }
 
 int32_t GetTLSBase(elfheader_t* h)
@@ -1453,11 +1453,11 @@ uint32_t GetTLSSize(elfheader_t* h)
     return h?h->tlssize:0;
 }
 
-void* GetTLSPointer(box64context_t* context, elfheader_t* h)
+void* GetTLSPointer(x64emu_t* emu, elfheader_t* h)
 {
     if(!h || !h->tlssize)
         return NULL;
-    tlsdatasize_t* ptr = getTLSData(context);
+    tlsdatasize_t* ptr = getTLSData(emu);
     return ptr->data+h->tlsbase;
 }
 
@@ -1776,6 +1776,19 @@ int ElfGetSymTabStartEnd(elfheader_t* head, uintptr_t *offs, uintptr_t *end, con
     return box64_is32bits?ElfGetSymTabStartEnd32(head, offs, end, symname):ElfGetSymTabStartEnd64(head, offs, end, symname);
 }
 
+int NeededLibs(elfheader_t* h)
+{
+    if(!h) return 0;
+    int cnt = 0;
+    // count the number of needed libs, and also grab soname
+    for (size_t i=0; i<h->numDynamic; ++i) {
+        int tag = box64_is32bits?h->Dynamic._32[i].d_tag:h->Dynamic._64[i].d_tag;
+        if(tag==DT_NEEDED)
+            ++cnt;
+    }
+    return cnt;
+}
+
 typedef struct search_symbol_s{
     const char* name;
     void*       addr;
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index e32ce693..f4fa700b 100644
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -80,6 +80,11 @@ static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t s
         emu->segs[_FS] = 0x43;
         emu->segs[_GS] = default_gs;
     }
+    // init segments
+    for(int i=0; i<16; i++) {
+        emu->segldt[i].limit = (uintptr_t)-1LL;
+    }
+    memcpy(emu->seggdt, context->seggdt, sizeof(emu->seggdt));
     // setup fpu regs
     reset_fpu(emu);
     emu->mxcsr.x32 = 0x1f80;
@@ -149,6 +154,10 @@ static void internalFreeX64(x64emu_t* emu)
         actual_free(emu->res_state_32);
     emu->res_state_32 = NULL;
     #endif
+    if(emu->tlsdata) {
+        free_tlsdatasize(emu->tlsdata);
+        emu->tlsdata = NULL;
+    }
 }
 
 EXPORTDYN
@@ -186,6 +195,8 @@ void CloneEmu(x64emu_t *newemu, const x64emu_t* emu)
     newemu->old_ip = emu->old_ip;
     memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
     memset(newemu->segs_serial, 0, sizeof(newemu->segs_serial));
+    memcpy(newemu->seggdt, emu->seggdt, sizeof(newemu->seggdt));
+    memcpy(newemu->segldt, emu->segldt, sizeof(newemu->segldt));
     memcpy(newemu->x87, emu->x87, sizeof(emu->x87));
     memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
     memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
@@ -1585,10 +1596,19 @@ void UpdateFlags(x64emu_t* emu)
     RESET_FLAGS(emu);
 }
 
+void free_tlsdatasize(void* p)
+{
+    if(!p)
+        return;
+    tlsdatasize_t *data = (tlsdatasize_t*)p;
+    actual_free(data->ptr);
+    actual_free(p);
+}
+
 uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg)
 {
     if (emu->segs_serial[seg] != emu->context->sel_serial) {
-        emu->segs_offs[seg] = (uintptr_t)GetSegmentBase(emu->segs[seg]);
+        emu->segs_offs[seg] = (uintptr_t)GetSegmentBase(emu, emu->segs[seg]);
         emu->segs_serial[seg] = emu->context->sel_serial;
     }
     return emu->segs_offs[seg];
diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h
index aba2b3ed..bd76c047 100644
--- a/src/emu/x64emu_private.h
+++ b/src/emu/x64emu_private.h
@@ -3,8 +3,8 @@
 
 #include "regs.h"
 #include "os.h"
+#include "box64context.h"
 
-typedef struct box64context_s box64context_t;
 typedef struct x64_ucontext_s x64_ucontext_t;
 #ifdef BOX32
 typedef struct i386_ucontext_s i386_ucontext_t;
@@ -127,6 +127,11 @@ typedef struct x64emu_s {
     #ifdef _WIN32
     uint64_t    win64_teb;
     #endif
+    // local selector handling
+    base_segment_t  segldt[16];
+    base_segment_t  seggdt[16];  // hacky
+    tlsdatasize_t  *tlsdata;
+    // other informations
     int         type;       // EMUTYPE_xxx define
     #ifdef BOX32
     int         libc_err;   // copy of errno from libc
diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c
index aff7419e..caba2238 100644
--- a/src/emu/x64run0f.c
+++ b/src/emu/x64run0f.c
@@ -168,10 +168,11 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
             GETGD;

             CHECK_FLAGS(emu);

             tmp8u = ED->word[0]>>3;

-            if (tmp8u>0x10 || !my_context->segtls[tmp8u].present) {

+            tmp8s = !!(ED->word[0]&2);

+            if (tmp8u>0x10 || !tmp8s?emu->segldt[tmp8u].present:my_context->seggdt[tmp8u].present) {

                 CLEAR_FLAG(F_ZF);

             } else {

-                GD->dword[0] = my_context->segtls[tmp8u].limit;

+                GD->dword[0] = tmp8s?emu->segldt[tmp8u].limit:my_context->seggdt[tmp8u].limit;

                 SET_FLAG(F_ZF);

             }

             break;

diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c
index 4c17dda8..80aef6ae 100644
--- a/src/emu/x64tls.c
+++ b/src/emu/x64tls.c
@@ -62,7 +62,7 @@ uint32_t my_set_thread_area_32(x64emu_t* emu, thread_area_32_t* td)
     if(idx==-1) {
         // find a free one
         for (int i=9; i<15 && idx==-1; ++i)
-            if(!my_context->segtls[i].present)
+            if(!my_context->seggdt[i].present)
                 idx=i;
         if(idx==-1) {
             errno = ESRCH;
@@ -75,7 +75,7 @@ uint32_t my_set_thread_area_32(x64emu_t* emu, thread_area_32_t* td)
         return (uint32_t)-1;
     }
     if(isempty) {
-        memset(&my_context->segtls[td->entry_number], 0, sizeof(base_segment_t));
+        memset(&my_context->seggdt[td->entry_number], 0, sizeof(base_segment_t));
         return 0;
     }
     if((idx<9 || idx>15)) {
@@ -83,17 +83,17 @@ uint32_t my_set_thread_area_32(x64emu_t* emu, thread_area_32_t* td)
         return (uint32_t)-1;
     }
 
-    my_context->segtls[idx].base = td->base_addr;
-    my_context->segtls[idx].limit = td->limit;
-    my_context->segtls[idx].present = 1;
-    my_context->segtls[idx].is32bits = 1;
-    if(!my_context->segtls[idx].key_init) {
-        pthread_key_create(&my_context->segtls[idx].key, NULL);
-        my_context->segtls[idx].key_init = 1;
+    my_context->seggdt[idx].base = td->base_addr;
+    my_context->seggdt[idx].limit = td->limit;
+    my_context->seggdt[idx].present = 1;
+    my_context->seggdt[idx].is32bits = 1;
+    if(idx>5) {
+        emu->seggdt[idx].base = td->base_addr;
+        emu->seggdt[idx].limit = td->limit;
+        emu->seggdt[idx].present = 1;
+        emu->seggdt[idx].is32bits = 1;
     }
 
-    pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
-
     ResetSegmentsCache(emu);
 
     return 0;
@@ -124,15 +124,9 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
 
     if(box64_is32bits) {
         emu->segs_serial[_GS] = 0;
-        my_context->segtls[idx].base = td->base_addr;
-        my_context->segtls[idx].limit = td->limit;
-        my_context->segtls[idx].present = 1;
-        if(idx>8 && !my_context->segtls[idx].key_init) {
-            pthread_key_create(&my_context->segtls[idx].key, NULL);
-            my_context->segtls[idx].key_init = 1;
-        }
-        if(my_context->segtls[idx].key_init)
-            pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
+        emu->segldt[idx].base = td->base_addr;
+        emu->segldt[idx].limit = td->limit;
+        emu->segldt[idx].present = 1;
     }
 
     ResetSegmentsCache(emu);
@@ -172,21 +166,21 @@ int my_arch_prctl(x64emu_t *emu, int code, void* addr)
     errno = 0;
     switch(code) {
         case ARCH_GET_GS:
-            *(void**)addr = GetSegmentBase(emu->segs[_GS]);
+            *(void**)addr = GetSegmentBase(emu, emu->segs[_GS]);
             return 0;
         case ARCH_GET_FS:
-            *(void**)addr = GetSegmentBase(emu->segs[_FS]);
+            *(void**)addr = GetSegmentBase(emu, emu->segs[_FS]);
             return 0;
         case ARCH_SET_FS:
         case ARCH_SET_GS:
             seg=(code==ARCH_SET_FS)?_FS:_GS;
             int idx = -1;
             // search if it's a TLS base
-            if(GetSeg43Base()==addr)
+            if(GetSeg43Base(emu)==addr)
                 idx = 0x43>>3;
             // Is this search only occurs when seg==0?
             for (int i=9; i<15 && idx==-1; ++i)
-                if(my_context->segtls[i].present && my_context->segtls[i].base==(uintptr_t)addr)
+                if(my_context->seggdt[i].present && my_context->seggdt[i].base==(uintptr_t)addr)
                     idx=i;
             // found...
             if(idx!=-1) {
@@ -204,15 +198,14 @@ int my_arch_prctl(x64emu_t *emu, int code, void* addr)
                 return -1;
             }
             emu->segs_serial[seg] = 0;
-            my_context->segtls[idx].base = (uintptr_t)addr;
-            my_context->segtls[idx].limit = 0;
-            my_context->segtls[idx].present = 1;
-            if(idx>8 && !my_context->segtls[idx].key_init) {
-                pthread_key_create(&my_context->segtls[idx].key, NULL);
-                my_context->segtls[idx].key_init = 1;
+            my_context->seggdt[idx].base = (uintptr_t)addr;
+            my_context->seggdt[idx].limit = 0;
+            my_context->seggdt[idx].present = 1;
+            if(idx>5) {
+                emu->seggdt[idx].base = (uintptr_t)addr;
+                emu->seggdt[idx].limit = 0;
+                emu->seggdt[idx].present = 1;
             }
-            if(my_context->segtls[idx].key_init)
-                pthread_setspecific(my_context->segtls[idx].key, addr);
             ResetSegmentsCache(emu);
             return 0;
         case ARCH_GET_XCOMP_SUPP:
@@ -234,7 +227,7 @@ int my_arch_prctl(x64emu_t *emu, int code, void* addr)
 /*
  tls record should looks like:
  void*      tcb             0x00
- void*      dtv             0x08
+ void*      dts             0x08
  void*      self            0x10
  int        multiple        0x18
  int        gscope          0x1c
@@ -274,7 +267,6 @@ static tlsdatasize_t* setupTLSData(box64context_t* context)
     data->tlssize = context->tlssize;
     data->ptr = ptr_oversized;
     data->n_elfs = context->elfsize;
-    pthread_setspecific(context->tlskey, data);
     #ifdef BOX32
     if(box64_is32bits) {
         // copy canary...
@@ -364,14 +356,15 @@ static void* resizeTLSData(box64context_t *context, void* oldptr)
         }
 }
 
-tlsdatasize_t* getTLSData(box64context_t *context)
+tlsdatasize_t* getTLSData(x64emu_t* emu)
 {
     tlsdatasize_t* ptr = NULL;
     if(!ptr)
-        if ((ptr = (tlsdatasize_t*)pthread_getspecific(context->tlskey)) == NULL) {
-            ptr = (tlsdatasize_t*)fillTLSData(context);
+        if ((ptr = emu->tlsdata) == NULL) {
+            ptr = (tlsdatasize_t*)fillTLSData(emu->context);
         }
-    if(ptr->tlssize != context->tlssize)
-        ptr = (tlsdatasize_t*)resizeTLSData(context, ptr);
+    if(ptr->tlssize != emu->context->tlssize)
+        ptr = (tlsdatasize_t*)resizeTLSData(emu->context, ptr);
+    emu->tlsdata = ptr;
     return ptr;
 }
\ No newline at end of file
diff --git a/src/include/box64context.h b/src/include/box64context.h
index 910b0e8a..419599c6 100644
--- a/src/include/box64context.h
+++ b/src/include/box64context.h
@@ -88,10 +88,8 @@ void add1libref_neededlib(needed_libs_t* needed, library_t* lib);
 typedef struct base_segment_s {
     uintptr_t       base;
     uint64_t        limit;
-    pthread_key_t   key;
     uint8_t         present;
     uint8_t         is32bits;
-    uint8_t         key_init;
 } base_segment_t;
 
 typedef struct box64context_s {
@@ -202,10 +200,9 @@ typedef struct box64context_s {
     int                 deferredInitSz;
     int                 deferredInitCap;
 
-    pthread_key_t       tlskey;     // then tls key to have actual tlsdata
     void*               tlsdata;    // the initial global tlsdata
     int64_t             tlssize;    // wanted size of tlsdata
-    base_segment_t      segtls[16];
+    base_segment_t      seggdt[16];
 
     uintptr_t           *auxval_start;
 
diff --git a/src/include/debug.h b/src/include/debug.h
index 2c7e1a62..556c7e37 100644
--- a/src/include/debug.h
+++ b/src/include/debug.h
@@ -15,6 +15,7 @@ extern int box64_rdtsc;
 extern uint8_t box64_rdtsc_shift;
 extern int box64_is32bits;
 extern int box64_isAddressSpace32;
+extern int box64_nolibs;
 #ifdef DYNAREC
 extern cpu_ext_t cpuext;
 #endif
diff --git a/src/include/elfloader.h b/src/include/elfloader.h
index 56a0571e..c2cc529d 100644
--- a/src/include/elfloader.h
+++ b/src/include/elfloader.h
@@ -51,10 +51,11 @@ void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign);
 uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
 uintptr_t GetLastByte(elfheader_t* h);
 void AddSymbols(lib_t *maplib, elfheader_t* h);
+int NeededLibs(elfheader_t* h);
 int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, int deepbind, box64context_t *box64, x64emu_t* emu);
 uintptr_t GetElfInit(elfheader_t* h);
 uintptr_t GetElfFini(elfheader_t* h);
-void RefreshElfTLS(elfheader_t* h);
+void RefreshElfTLS(elfheader_t* h, x64emu_t* emu);
 void RunElfInit(elfheader_t* h, x64emu_t *emu);
 void RunElfFini(elfheader_t* h, x64emu_t *emu);
 void RunDeferredElfInit(x64emu_t *emu);
@@ -67,8 +68,8 @@ elfheader_t* FindElfAddress(box64context_t *context, uintptr_t addr);
 const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint64_t* sz);
 int32_t GetTLSBase(elfheader_t* h);
 uint32_t GetTLSSize(elfheader_t* h);
-void* GetTLSPointer(box64context_t* context, elfheader_t* h);
-void* GetDTatOffset(box64context_t* context, unsigned long int index, unsigned long int offset);
+void* GetTLSPointer(x64emu_t* emu, elfheader_t* h);
+void* GetDTatOffset(x64emu_t* emu, unsigned long int index, unsigned long int offset);
 void ResetSpecialCaseMainElf(elfheader_t* h);
 void CreateMemorymapFile(box64context_t* context, int fd);
 void* GetDynamicSection(elfheader_t* h);
diff --git a/src/include/os.h b/src/include/os.h
index fc778928..60be6195 100644
--- a/src/include/os.h
+++ b/src/include/os.h
@@ -45,8 +45,8 @@ int SchedYield(void);
 void EmuX64Syscall(void* emu);
 void EmuX86Syscall(void* emu);
 
-void* GetSeg43Base();
-void* GetSegmentBase(uint32_t desc);
+void* GetSeg43Base(void* emu);
+void* GetSegmentBase(void* emu, uint32_t desc);
 
 // These functions only applies to Linux --------------------------
 int IsBridgeSignature(char s, char c);
diff --git a/src/include/x64tls.h b/src/include/x64tls.h
index e8eefd31..112cc59a 100644
--- a/src/include/x64tls.h
+++ b/src/include/x64tls.h
@@ -7,7 +7,7 @@ typedef struct thread_area_32_s thread_area_32_t;
 uint32_t my_set_thread_area_32(x64emu_t* emu, thread_area_32_t* td);
 uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size);
 
-tlsdatasize_t* getTLSData(box64context_t* context);
+tlsdatasize_t* getTLSData(x64emu_t* emu);
 
 int my_arch_prctl(x64emu_t *emu, int code, void* addr);
 
diff --git a/src/libtools/threads.c b/src/libtools/threads.c
index 6fd7ffe6..1076b3e2 100644
--- a/src/libtools/threads.c
+++ b/src/libtools/threads.c
@@ -24,6 +24,7 @@
 #include "x64trace.h"
 #include "bridge.h"
 #include "myalign.h"
+#include "x64tls.h"
 #ifdef DYNAREC
 #include "dynablock.h"
 #include "dynarec/native_lock.h"
@@ -215,6 +216,7 @@ x64emu_t* thread_get_emu()
 			setProtection_stack((uintptr_t)stack, stacksize, PROT_READ|PROT_WRITE);
 		x64emu_t *emu = NewX64Emu(my_context, my_context->exit_bridge, (uintptr_t)stack, stacksize, 1);
 		SetupX64Emu(emu, NULL);
+		getTLSData(emu);
 		thread_set_emu(emu);
 		return emu;
 	}
@@ -248,6 +250,7 @@ static void* pthread_routine(void* p)
 	et->emu->type = EMUTYPE_MAIN;
 	// setup callstack and run...
 	x64emu_t* emu = et->emu;
+	getTLSData(emu);
 	ResetSegmentsCache(emu);
 	Push64(emu, 0);	// PUSH 0 (backtrace marker: return address is 0)
 	Push64(emu, 0);	// PUSH BP
diff --git a/src/libtools/threads32.c b/src/libtools/threads32.c
index ce5a4579..4d614b93 100755
--- a/src/libtools/threads32.c
+++ b/src/libtools/threads32.c
@@ -27,6 +27,7 @@
 #include "x64trace.h"
 #include "bridge.h"
 #include "threads32.h"
+#include "x64tls.h"
 #ifdef DYNAREC
 #include "dynablock.h"
 #endif
@@ -112,6 +113,7 @@ static void* pthread_routine(void* p)
 	et->hself = to_hash(et->self);
 	// setup callstack and run...
 	x64emu_t* emu = et->emu;
+	getTLSData(emu);
 	Push_32(emu, 0);	// PUSH 0 (backtrace marker: return address is 0)
 	Push_32(emu, 0);	// PUSH BP
 	R_EBP = R_ESP;	// MOV BP, SP
diff --git a/src/os/os_linux.c b/src/os/os_linux.c
index 235d43ee..17ba33cc 100644
--- a/src/os/os_linux.c
+++ b/src/os/os_linux.c
@@ -22,6 +22,7 @@
 #include "debug.h"
 #include "x64tls.h"
 #include "librarian.h"
+#include "emu/x64emu_private.h"
 
 int GetTID(void)
 {
@@ -65,33 +66,33 @@ void EmuX86Syscall(void* emu)
 
 extern int box64_is32bits;
 
-void* GetSeg43Base()
+void* GetSeg43Base(void* emu)
 {
-    tlsdatasize_t* ptr = getTLSData(my_context);
+    tlsdatasize_t* ptr = getTLSData((x64emu_t*)emu);
     return ptr->data;
 }
 
-void* GetSegmentBase(uint32_t desc)
+void* GetSegmentBase(void* emu, uint32_t desc)
 {
     if (!desc) {
         printf_log(LOG_NONE, "Warning, accessing segment NULL\n");
         return NULL;
     }
     int base = desc >> 3;
-    if (!box64_is32bits && base == 0x8 && !my_context->segtls[base].key_init)
-        return GetSeg43Base();
-    if (box64_is32bits && (base == 0x6))
-        return GetSeg43Base();
+    int is_ldt = !!(desc&4);
+    base_segment_t* segs = is_ldt?((x64emu_t*)emu)->segldt:((base>5)?((x64emu_t*)emu)->seggdt:my_context->seggdt);
+    if(!box64_nolibs) {
+        if (!box64_is32bits && (base == 0x8) )
+            return GetSeg43Base((x64emu_t*)emu);
+        if (box64_is32bits && (base == 0x6))
+            return GetSeg43Base((x64emu_t*)emu);
+        }
     if (base > 15) {
         printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x or unset\n", desc);
         return NULL;
     }
-    if (my_context->segtls[base].key_init) {
-        void* ptr = pthread_getspecific(my_context->segtls[base].key);
-        return ptr;
-    }
 
-    void* ptr = (void*)my_context->segtls[base].base;
+    void* ptr = (void*)segs[base].base;
     return ptr;
 }
 
diff --git a/src/os/os_wine.c b/src/os/os_wine.c
index edae6e07..4693295d 100644
--- a/src/os/os_wine.c
+++ b/src/os/os_wine.c
@@ -30,12 +30,12 @@ int IsBridgeSignature(char s, char c)
     return FALSE;
 }
 
-void* GetSeg43Base()
+void* GetSeg43Base(void* emu)
 {
     return NULL;
 }
 
-void* GetSegmentBase(uint32_t desc)
+void* GetSegmentBase(void* emu, uint32_t desc)
 {
     printf_log(LOG_NONE, "GetSegmentBase does not apply to Wine dlls\n");
     return NULL;
diff --git a/src/wrapped/wrappedldlinux.c b/src/wrapped/wrappedldlinux.c
index cd2ee420..acb69a8d 100644
--- a/src/wrapped/wrappedldlinux.c
+++ b/src/wrapped/wrappedldlinux.c
@@ -21,10 +21,10 @@ typedef struct my_tls_s {
     unsigned long int   o;
 } my_tls_t;
 
-EXPORT void* my___tls_get_addr(void* p)
+EXPORT void* my___tls_get_addr(x64emu_t* emu, void* p)
 {
     my_tls_t *t = (my_tls_t*)p;
-    tlsdatasize_t* ptr = getTLSData(my_context);
+    tlsdatasize_t* ptr = getTLSData(emu);
     return ptr->data+GetTLSBase(my_context->elfs[t->i])+t->o;
 }
 
diff --git a/src/wrapped/wrappedldlinux_private.h b/src/wrapped/wrappedldlinux_private.h
index bbfe723c..6e2b6fe5 100644
--- a/src/wrapped/wrappedldlinux_private.h
+++ b/src/wrapped/wrappedldlinux_private.h
@@ -27,4 +27,4 @@ DATA(_rtld_global, sizeof(void*))
 DATA(_rtld_global_ro, sizeof(void*))
 #endif
 DATA(__stack_chk_guard, sizeof(void*))
-GOM(__tls_get_addr, pFp)    //%NoE
+GOM(__tls_get_addr, pFEp)
diff --git a/src/wrapped32/wrappedldlinux.c b/src/wrapped32/wrappedldlinux.c
index b83e3559..bb138d52 100755
--- a/src/wrapped32/wrappedldlinux.c
+++ b/src/wrapped32/wrappedldlinux.c
@@ -23,14 +23,14 @@ typedef struct __attribute__((packed, aligned(4))) my32_tls_s {
 EXPORT void* my32___tls_get_addr(x64emu_t* emu, void* p)
 {
     my32_tls_t *t = (my32_tls_t*)p;
-    return GetDTatOffset(emu->context, t->i, t->o);
+    return GetDTatOffset(emu, t->i, t->o);
 }
 
 EXPORT void* my32____tls_get_addr(x64emu_t* emu)
 {
     // the GNU version (with 3 '_') use register for the parameter!
     my32_tls_t *t = (my32_tls_t*)from_ptrv(R_EAX);
-    return GetDTatOffset(emu->context, t->i, t->o);
+    return GetDTatOffset(emu, t->i, t->o);
 }
 
 EXPORT ptr_t my32___libc_stack_end;