]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix 197259 Unsupported arch_prtctl PR_SET_GS option
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Tue, 16 Dec 2014 23:57:51 +0000 (23:57 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Tue, 16 Dec 2014 23:57:51 +0000 (23:57 +0000)
On amd64, We handle GS similar to FS, i.e. consider it is constant.
Note that FS is not always 0 on linux. It looks rather to be constant
in all threads, and is zero in the main thread.
As values for FS and/or GS differs between platforms (linux or darwin),
FS_CONST and GS_CONST are used.

Note that we cannot easily test that the value of GS or FS is the
expected one, as the value might not be set at the begin of execution
but only set after prctl has been executed.

So, we just hope that effectively GS and FS are constant.
Some trials to set GS to other values that the expected
constant value on linux was causing a SEGV.
So, it looks like this is all effectively protected.

In summary: we were counting somewhat on the luck for FS,
we now similarly count on luch for GS

git-svn-id: svn://svn.valgrind.org/vex/trunk@3043

VEX/priv/guest_amd64_helpers.c
VEX/priv/guest_amd64_toIR.c
VEX/priv/main_main.c
VEX/pub/libvex.h
VEX/pub/libvex_guest_amd64.h

index 629e11a2b1bdfc0558a839fa0928a458e93eef7f..15dc8bcb11f312bf67e6d2563bfd0b5a2a8bd841 100644 (file)
@@ -3901,9 +3901,10 @@ void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state )
    vex_state->guest_IDFLAG  = 0;
    vex_state->guest_ACFLAG  = 0;
 
-   /* HACK: represent the offset associated with %fs==0. This
-      assumes that %fs is only ever zero. */
-   vex_state->guest_FS_ZERO = 0;
+   /* HACK: represent the offset associated with a constant %fs. 
+      Typically, on linux, this assumes that %fs is only ever zero (main
+      thread) or 0x63. */
+   vex_state->guest_FS_CONST = 0;
 
    vex_state->guest_RIP = 0;
 
@@ -3945,7 +3946,7 @@ void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state )
 
    vex_state->guest_NRADDR   = 0;
    vex_state->guest_SC_CLASS = 0;
-   vex_state->guest_GS_0x60  = 0;
+   vex_state->guest_GS_CONST = 0;
 
    vex_state->guest_IP_AT_SYSCALL = 0;
    vex_state->pad1 = 0;
@@ -4031,7 +4032,7 @@ VexGuestLayout
                 /*  2 */ ALWAYSDEFD(guest_DFLAG),
                  /*  3 */ ALWAYSDEFD(guest_IDFLAG),
                  /*  4 */ ALWAYSDEFD(guest_RIP),
-                 /*  5 */ ALWAYSDEFD(guest_FS_ZERO),
+                 /*  5 */ ALWAYSDEFD(guest_FS_CONST),
                  /*  6 */ ALWAYSDEFD(guest_FTOP),
                  /*  7 */ ALWAYSDEFD(guest_FPTAG),
                  /*  8 */ ALWAYSDEFD(guest_FPROUND),
index 2d8bd923b3362dd0a333ffd12020d0414fe83ae2..2df860a0dd2717c3c2b0cc056a730abfa2be8757 100644 (file)
@@ -395,8 +395,8 @@ static void unimplemented ( const HChar* str )
 
 #define OFFB_RIP       offsetof(VexGuestAMD64State,guest_RIP)
 
-#define OFFB_FS_ZERO   offsetof(VexGuestAMD64State,guest_FS_ZERO)
-#define OFFB_GS_0x60   offsetof(VexGuestAMD64State,guest_GS_0x60)
+#define OFFB_FS_CONST  offsetof(VexGuestAMD64State,guest_FS_CONST)
+#define OFFB_GS_CONST  offsetof(VexGuestAMD64State,guest_GS_CONST)
 
 #define OFFB_CC_OP     offsetof(VexGuestAMD64State,guest_CC_OP)
 #define OFFB_CC_DEP1   offsetof(VexGuestAMD64State,guest_CC_DEP1)
@@ -2323,26 +2323,26 @@ static
 IRExpr* handleAddrOverrides ( const VexAbiInfo* vbi, 
                               Prefix pfx, IRExpr* virtual )
 {
+   /* Note that the below are hacks that relies on the assumption
+      that %fs or %gs are constant.
+      Typically, %fs is always 0x63 on linux (in the main thread, it
+      stays at value 0), %gs always 0x60 on Darwin, ... */
    /* --- segment overrides --- */
    if (pfx & PFX_FS) {
-      if (vbi->guest_amd64_assume_fs_is_zero) {
-         /* Note that this is a linux-kernel specific hack that relies
-            on the assumption that %fs is always zero. */
-         /* return virtual + guest_FS_ZERO. */
+      if (vbi->guest_amd64_assume_fs_is_const) {
+         /* return virtual + guest_FS_CONST. */
          virtual = binop(Iop_Add64, virtual,
-                                    IRExpr_Get(OFFB_FS_ZERO, Ity_I64));
+                                    IRExpr_Get(OFFB_FS_CONST, Ity_I64));
       } else {
          unimplemented("amd64 %fs segment override");
       }
    }
 
    if (pfx & PFX_GS) {
-      if (vbi->guest_amd64_assume_gs_is_0x60) {
-         /* Note that this is a darwin-kernel specific hack that relies
-            on the assumption that %gs is always 0x60. */
-         /* return virtual + guest_GS_0x60. */
+      if (vbi->guest_amd64_assume_gs_is_const) {
+         /* return virtual + guest_GS_CONST. */
          virtual = binop(Iop_Add64, virtual,
-                                    IRExpr_Get(OFFB_GS_0x60, Ity_I64));
+                                    IRExpr_Get(OFFB_GS_CONST, Ity_I64));
       } else {
          unimplemented("amd64 %gs segment override");
       }
@@ -31388,11 +31388,11 @@ DisResult disInstr_AMD64_WRK (
 
    /* We have a %fs prefix.  Reject it if there's no evidence in 'vbi'
       that we should accept it. */
-   if ((pfx & PFX_FS) && !vbi->guest_amd64_assume_fs_is_zero)
+   if ((pfx & PFX_FS) && !vbi->guest_amd64_assume_fs_is_const)
       goto decode_failure;
 
    /* Ditto for %gs prefixes. */
-   if ((pfx & PFX_GS) && !vbi->guest_amd64_assume_gs_is_0x60)
+   if ((pfx & PFX_GS) && !vbi->guest_amd64_assume_gs_is_const)
       goto decode_failure;
 
    /* Set up sz. */
index f52a68f23fd2fcef707945ef4d8e2fddb82bfb02..b007fa1c8f06abc6454c3c98155c04cb7e3a5f2a 100644 (file)
@@ -1264,8 +1264,8 @@ void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi )
 {
    vex_bzero(vbi, sizeof(*vbi));
    vbi->guest_stack_redzone_size       = 0;
-   vbi->guest_amd64_assume_fs_is_zero  = False;
-   vbi->guest_amd64_assume_gs_is_0x60  = False;
+   vbi->guest_amd64_assume_fs_is_const = False;
+   vbi->guest_amd64_assume_gs_is_const = False;
    vbi->guest_ppc_zap_RZ_at_blr        = False;
    vbi->guest_ppc_zap_RZ_at_bl         = NULL;
    vbi->host_ppc_calls_use_fndescrs    = False;
index 6da02daf23bf88f1bd29ead5aed1b13e51b6c2c1..1f09de5a0d942338598b1be288b4830f3a7b8a0b 100644 (file)
@@ -316,14 +316,14 @@ void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai );
       guest is amd64-linux                ==> 128
       guest is other                      ==> inapplicable
 
-   guest_amd64_assume_fs_is_zero
+   guest_amd64_assume_fs_is_const
       guest is amd64-linux                ==> True
       guest is amd64-darwin               ==> False
       guest is other                      ==> inapplicable
 
-   guest_amd64_assume_gs_is_0x60
+   guest_amd64_assume_gs_is_const
       guest is amd64-darwin               ==> True
-      guest is amd64-linux                ==> False
+      guest is amd64-linux                ==> True
       guest is other                      ==> inapplicable
 
    guest_ppc_zap_RZ_at_blr
@@ -350,13 +350,13 @@ typedef
 
       /* AMD64 GUESTS only: should we translate %fs-prefixed
          instructions using the assumption that %fs always contains
-         zero? */
-      Bool guest_amd64_assume_fs_is_zero;
+         the same value? (typically zero on linux) */
+      Bool guest_amd64_assume_fs_is_const;
 
       /* AMD64 GUESTS only: should we translate %gs-prefixed
          instructions using the assumption that %gs always contains
-         0x60? */
-      Bool guest_amd64_assume_gs_is_0x60;
+         the same value? (typically 0x60 on darwin)? */
+      Bool guest_amd64_assume_gs_is_const;
 
       /* PPC GUESTS only: should we zap the stack red zone at a 'blr'
          (function return) ? */
index 5920672bf6cf37f42bc86fb33890a8ff7abefffa..787510ee7d3eb2ef158132f3bc66353651c2e6fd 100644 (file)
@@ -90,10 +90,11 @@ typedef
          all the old x87 FPU gunk
          segment registers */
 
-      /* HACK to make tls on amd64-linux work.  %fs only ever seems to
-         hold zero, and so guest_FS_ZERO holds the 64-bit offset
-         associated with a %fs value of zero. */
-      /* 200 */ ULong guest_FS_ZERO;
+      /* HACK to e.g. make tls on amd64-linux work.  %fs only ever seems to
+         hold a constant value (zero on linux main thread, 0x63 in other
+         threads), and so guest_FS_CONST holds
+         the 64-bit offset associated with this constant %fs value. */
+      /* 200 */ ULong guest_FS_CONST;
 
       /* YMM registers.  Note that these must be allocated
          consecutively in order that the SSE4.2 PCMP{E,I}STR{I,M}
@@ -152,11 +153,12 @@ typedef
       /* Used for Darwin syscall dispatching. */
       ULong guest_SC_CLASS;
 
-      /* HACK to make tls on darwin work.  %gs only ever seems to
-         hold 0x60, and so guest_GS_0x60 holds the 64-bit offset
-         associated with a %gs value of 0x60.  (A direct analogue
-         of the %fs-zero hack for amd64-linux). */
-      ULong guest_GS_0x60;
+      /* HACK to make e.g. tls on darwin work, wine on linux work, ...
+         %gs only ever seems to hold a constant value (e.g. 0x60 on darwin,
+         0x6b on linux), and so guest_GS_CONST holds the 64-bit offset
+         associated with this constant %gs value.  (A direct analogue
+         of the %fs-const hack for amd64-linux). */
+      ULong guest_GS_CONST;
 
       /* Needed for Darwin (but mandated for all guest architectures):
          RIP at the last syscall insn (int 0x80/81/82, sysenter,