PERFORCE change 176894 for review

Attilio Rao attilio at FreeBSD.org
Wed Apr 14 14:30:11 UTC 2010


http://p4web.freebsd.org/@@176894?ac=10

Change 176894 by attilio at attilio_pavilion on 2010/04/14 14:30:04

	Fix TLS handling within i386 by passing a correct LDT location for
	any thread rather than using always the same one.
	Submitted by:	stass

Affected files ...

.. //depot/projects/valgrind/coregrind/m_syswrap/syswrap-x86-freebsd.c#17 edit

Differences ...

==== //depot/projects/valgrind/coregrind/m_syswrap/syswrap-x86-freebsd.c#17 (text+ko) ====

@@ -409,10 +409,10 @@
 }
 #endif
 
-
-static SysRes sys_set_thread_area ( ThreadId tid, Int idx, void* base )
+static SysRes sys_set_thread_area ( ThreadId tid, Int *idxptr, void *base)
 {
    VexGuestX86SegDescr* gdt;
+   Int idx;
 
    vg_assert(8 == sizeof(VexGuestX86SegDescr));
    vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
@@ -425,12 +425,31 @@
       VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
    }
 
+   idx = *idxptr;
+   if (idx == -1) {
+      /* Find and use the first free entry.  Don't allocate entry
+         zero, because the hardware will never do that, and apparently
+         doing so confuses some code (perhaps stuff running on
+         Wine). */
+      for (idx = 1; idx < VEX_GUEST_X86_GDT_NENT; idx++) {
+         if (gdt[idx].LdtEnt.Words.word1 == 0
+             && gdt[idx].LdtEnt.Words.word2 == 0)
+            break;
+      }
+
+      if (idx == VEX_GUEST_X86_GDT_NENT)
+         return VG_(mk_SysRes_Error)( VKI_ESRCH );
+   } else if (idx < 0 || idx == 0 || idx >= VEX_GUEST_X86_GDT_NENT) {
+      /* Similarly, reject attempts to use GDT[0]. */
+      return VG_(mk_SysRes_Error)( VKI_EINVAL );
+   }
+
    translate_to_hw_format(base, &gdt[idx]);
 
+   *idxptr = idx;
    return VG_(mk_SysRes_Success)( 0 );
 }
 
-
 static SysRes sys_get_thread_area ( ThreadId tid, Int idx, void ** basep )
 {
    VexGuestX86SegDescr* gdt;
@@ -532,6 +551,7 @@
    SysRes       res;
    vki_sigset_t blockall, savedmask;
    struct vki_thr_param tp;
+   Int idx = -1;
    Addr stk;
 
    PRINT("thr_new ( %#lx, %ld )",ARG1,ARG2);
@@ -596,8 +616,8 @@
 
    if (debug)
       VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base);
-   sys_set_thread_area( ctid, 2, tp.tls_base );
-   ctst->arch.vex.guest_GS = (2 << 3) | 3;	/* GSEL(GUGS_SEL, SEL_UPL) */
+   sys_set_thread_area( ctid, &idx, tp.tls_base );
+   ctst->arch.vex.guest_GS = (idx << 3) | 3;   /* GSEL(GUGS_SEL, SEL_UPL) */
    tp.tls_base = 0;	/* Don't have the kernel do it too */
 
    /* start the thread with everything blocked */
@@ -908,6 +928,7 @@
 PRE(sys_sysarch)
 {
    ThreadState *tst;
+   Int idx;
    void **p;
 
    PRINT("sys_sysarch ( %ld, %#lx )", ARG1, ARG2);
@@ -921,9 +942,10 @@
       /* On FreeBSD, the syscall loads the %gs selector for us, so do it now. */
       tst = VG_(get_ThreadState)(tid);
       p = (void**)ARG2;
-      tst->arch.vex.guest_GS = (2 << 3) | 3;	/* GSEL(GUGS_SEL, SEL_UPL) */
+      tst->arch.vex.guest_GS = (1 << 3) | 3;   /* GSEL(GUGS_SEL, SEL_UPL) */
       /* "do" the syscall ourselves; the kernel never sees it */
-      SET_STATUS_from_SysRes( sys_set_thread_area( tid, 2, *p ) );
+      idx = 1;
+      SET_STATUS_from_SysRes( sys_set_thread_area( tid, &idx, *p ) );
 
       break;
    case VKI_I386_GET_GSBASE:


More information about the p4-projects mailing list