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_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;
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;
/* 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),
#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)
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");
}
/* 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. */
{
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;
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
/* 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) ? */
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}
/* 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,