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