|
From: <sv...@va...> - 2009-03-19 22:21:49
|
Author: sewardj
Date: 2009-03-19 22:21:40 +0000 (Thu, 19 Mar 2009)
New Revision: 1886
Log:
In order to make it possible for Valgrind to restart client syscalls
that have been interrupted by signals, on Darwin, generalise an idea
which first emerged in the guest ppc32/64 stuff, in order to solve the
same problem on AIX.
Idea is: make all guests have a pseudo-register "IP_AT_SYSCALL", which
records the address of the most recently executed system call
instruction. Then, to back up the guest over the most recent syscall,
simply make its program counter equal to this value. This idea
already existing in the for ppc32/64 guests, but the register was
called "CIA_AT_SC".
Currently is not set in guest-amd64.
This commit will break the Valgrind svn trunk (temporarily).
Modified:
trunk/priv/guest-amd64/ghelpers.c
trunk/priv/guest-ppc/ghelpers.c
trunk/priv/guest-ppc/toIR.c
trunk/priv/guest-x86/ghelpers.c
trunk/priv/guest-x86/toIR.c
trunk/pub/libvex.h
trunk/pub/libvex_guest_amd64.h
trunk/pub/libvex_guest_ppc32.h
trunk/pub/libvex_guest_ppc64.h
trunk/pub/libvex_guest_x86.h
trunk/pub/libvex_ir.h
Modified: trunk/priv/guest-amd64/ghelpers.c
===================================================================
--- trunk/priv/guest-amd64/ghelpers.c 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/priv/guest-amd64/ghelpers.c 2009-03-19 22:21:40 UTC (rev 1886)
@@ -2315,6 +2315,7 @@
vex_state->guest_SC_CLASS = 0;
vex_state->guest_GS_0x60 = 0;
+ vex_state->guest_IP_AT_SYSCALL = 0;
vex_state->padding = 0;
}
@@ -2383,7 +2384,7 @@
/* Describe any sections to be regarded by Memcheck as
'always-defined'. */
- .n_alwaysDefd = 14,
+ .n_alwaysDefd = 16,
/* flags thunk: OP and NDEP are always defd, whereas DEP1
and DEP2 have to be tracked. See detailed comment in
@@ -2410,7 +2411,9 @@
/* 10 */ ALWAYSDEFD(guest_EMWARN),
/* 11 */ ALWAYSDEFD(guest_SSEROUND),
/* 12 */ ALWAYSDEFD(guest_TISTART),
- /* 13 */ ALWAYSDEFD(guest_TILEN)
+ /* 13 */ ALWAYSDEFD(guest_TILEN),
+ /* 14 */ ALWAYSDEFD(guest_SC_CLASS),
+ /* 15 */ ALWAYSDEFD(guest_IP_AT_SYSCALL)
}
};
Modified: trunk/priv/guest-ppc/ghelpers.c
===================================================================
--- trunk/priv/guest-ppc/ghelpers.c 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/priv/guest-ppc/ghelpers.c 2009-03-19 22:21:40 UTC (rev 1886)
@@ -489,7 +489,7 @@
for (i = 0; i < VEX_GUEST_PPC32_REDIR_STACK_SIZE; i++)
vex_state->guest_REDIR_STACK[i] = 0;
- vex_state->guest_CIA_AT_SC = 0;
+ vex_state->guest_IP_AT_SYSCALL = 0;
vex_state->guest_SPRG3_RO = 0;
}
@@ -648,7 +648,7 @@
for (i = 0; i < VEX_GUEST_PPC64_REDIR_STACK_SIZE; i++)
vex_state->guest_REDIR_STACK[i] = 0;
- vex_state->guest_CIA_AT_SC = 0;
+ vex_state->guest_IP_AT_SYSCALL = 0;
vex_state->guest_SPRG3_RO = 0;
}
@@ -781,7 +781,7 @@
/* 8 */ ALWAYSDEFD32(guest_NRADDR_GPR2),
/* 9 */ ALWAYSDEFD32(guest_REDIR_SP),
/* 10 */ ALWAYSDEFD32(guest_REDIR_STACK),
- /* 11 */ ALWAYSDEFD32(guest_CIA_AT_SC)
+ /* 11 */ ALWAYSDEFD32(guest_IP_AT_SYSCALL)
}
};
@@ -823,7 +823,7 @@
/* 8 */ ALWAYSDEFD64(guest_NRADDR_GPR2),
/* 9 */ ALWAYSDEFD64(guest_REDIR_SP),
/* 10 */ ALWAYSDEFD64(guest_REDIR_STACK),
- /* 11 */ ALWAYSDEFD64(guest_CIA_AT_SC)
+ /* 11 */ ALWAYSDEFD64(guest_IP_AT_SYSCALL)
}
};
Modified: trunk/priv/guest-ppc/toIR.c
===================================================================
--- trunk/priv/guest-ppc/toIR.c 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/priv/guest-ppc/toIR.c 2009-03-19 22:21:40 UTC (rev 1886)
@@ -218,7 +218,7 @@
offsetof(VexGuestPPC32State, _x))
#define OFFB_CIA offsetofPPCGuestState(guest_CIA)
-#define OFFB_CIA_AT_SC offsetofPPCGuestState(guest_CIA_AT_SC)
+#define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
#define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO)
#define OFFB_LR offsetofPPCGuestState(guest_LR)
#define OFFB_CTR offsetofPPCGuestState(guest_CTR)
@@ -327,7 +327,7 @@
PPC_GST_TISTART,// For icbi: start of area to invalidate
PPC_GST_TILEN, // For icbi: length of area to invalidate
PPC_GST_RESVN, // For lwarx/stwcx.
- PPC_GST_CIA_AT_SC, // the CIA of the most recently executed SC insn
+ PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
PPC_GST_SPRG3_RO, // SPRG3
PPC_GST_MAX
} PPC_GST;
@@ -2208,9 +2208,9 @@
IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
vassert( reg < PPC_GST_MAX );
switch (reg) {
- case PPC_GST_CIA_AT_SC:
+ case PPC_GST_IP_AT_SYSCALL:
vassert( ty_src == ty );
- stmt( IRStmt_Put( OFFB_CIA_AT_SC, src ) );
+ stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
break;
case PPC_GST_CIA:
vassert( ty_src == ty );
@@ -4776,10 +4776,10 @@
// sc (System Call, PPC32 p504)
DIP("sc\n");
- /* Copy CIA into the CIA_AT_SC pseudo-register, so that on AIX
+ /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
Valgrind can back the guest up to this instruction if it needs
to restart the syscall. */
- putGST( PPC_GST_CIA_AT_SC, getGST( PPC_GST_CIA ) );
+ putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
/* It's important that all ArchRegs carry their up-to-date value
at this point. So we declare an end-of-block here, which
Modified: trunk/priv/guest-x86/ghelpers.c
===================================================================
--- trunk/priv/guest-x86/ghelpers.c 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/priv/guest-x86/ghelpers.c 2009-03-19 22:21:40 UTC (rev 1886)
@@ -2635,6 +2635,11 @@
vex_state->guest_NRADDR = 0;
vex_state->guest_SC_CLASS = 0;
+ vex_state->guest_IP_AT_SYSCALL = 0;
+
+ vex_state->padding1 = 0;
+ vex_state->padding2 = 0;
+ vex_state->padding3 = 0;
}
@@ -2702,7 +2707,7 @@
/* Describe any sections to be regarded by Memcheck as
'always-defined'. */
- .n_alwaysDefd = 22,
+ .n_alwaysDefd = 24,
/* flags thunk: OP and NDEP are always defd, whereas DEP1
and DEP2 have to be tracked. See detailed comment in
@@ -2729,7 +2734,9 @@
/* 18 */ ALWAYSDEFD(guest_EMWARN),
/* 19 */ ALWAYSDEFD(guest_SSEROUND),
/* 20 */ ALWAYSDEFD(guest_TISTART),
- /* 21 */ ALWAYSDEFD(guest_TILEN)
+ /* 21 */ ALWAYSDEFD(guest_TILEN),
+ /* 22 */ ALWAYSDEFD(guest_SC_CLASS),
+ /* 23 */ ALWAYSDEFD(guest_IP_AT_SYSCALL)
}
};
Modified: trunk/priv/guest-x86/toIR.c
===================================================================
--- trunk/priv/guest-x86/toIR.c 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/priv/guest-x86/toIR.c 2009-03-19 22:21:40 UTC (rev 1886)
@@ -254,7 +254,9 @@
#define OFFB_TILEN offsetof(VexGuestX86State,guest_TILEN)
#define OFFB_NRADDR offsetof(VexGuestX86State,guest_NRADDR)
+#define OFFB_IP_AT_SYSCALL offsetof(VexGuestX86State,guest_IP_AT_SYSCALL)
+
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
/*--- x86 insn stream. ---*/
@@ -12592,20 +12594,28 @@
}
/* Handle int $0x80 (linux syscalls), int $0x81 and $0x82
- (darwin syscalls). */
+ (darwin syscalls). As part of this, note where we are, so we
+ can back up the guest to this point if the syscall needs to
+ be restarted. */
if (d32 == 0x80) {
+ stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
+ mkU32(guest_EIP_curr_instr) ) );
jmp_lit(Ijk_Sys_int128,((Addr32)guest_EIP_bbstart)+delta);
dres.whatNext = Dis_StopHere;
DIP("int $0x80\n");
break;
}
if (d32 == 0x81) {
+ stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
+ mkU32(guest_EIP_curr_instr) ) );
jmp_lit(Ijk_Sys_int129,((Addr32)guest_EIP_bbstart)+delta);
dres.whatNext = Dis_StopHere;
DIP("int $0x81\n");
break;
}
if (d32 == 0x82) {
+ stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
+ mkU32(guest_EIP_curr_instr) ) );
jmp_lit(Ijk_Sys_int130,((Addr32)guest_EIP_bbstart)+delta);
dres.whatNext = Dis_StopHere;
DIP("int $0x82\n");
@@ -14275,7 +14285,12 @@
before resuming execution. If that doesn't happen, the
thread will jump to address zero, which is probably
fatal.
- */
+ */
+
+ /* Note where we are, so we can back up the guest to this
+ point if the syscall needs to be restarted. */
+ stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL,
+ mkU32(guest_EIP_curr_instr) ) );
jmp_lit(Ijk_Sys_sysenter, 0/*bogus next EIP value*/);
dres.whatNext = Dis_StopHere;
DIP("sysenter");
Modified: trunk/pub/libvex.h
===================================================================
--- trunk/pub/libvex.h 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/pub/libvex.h 2009-03-19 22:21:40 UTC (rev 1886)
@@ -329,7 +329,7 @@
/* The max number of guest state chunks which we can describe as
always defined (for the benefit of Memcheck). */
-#define VEXGLO_N_ALWAYSDEFD 22
+#define VEXGLO_N_ALWAYSDEFD 24
typedef
struct {
Modified: trunk/pub/libvex_guest_amd64.h
===================================================================
--- trunk/pub/libvex_guest_amd64.h 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/pub/libvex_guest_amd64.h 2009-03-19 22:21:40 UTC (rev 1886)
@@ -161,6 +161,12 @@
of the %fs-zero hack for amd64-linux). */
ULong guest_GS_0x60;
+ /* Needed for Darwin (but mandated for all guest architectures):
+ RIP at the last syscall insn (int 0x80/81/82, sysenter,
+ syscall). Used when backing up to restart a syscall that has
+ been interrupted by a signal. */
+ ULong guest_IP_AT_SYSCALL;
+
/* Padding to make it have an 16-aligned size */
ULong padding;
}
Modified: trunk/pub/libvex_guest_ppc32.h
===================================================================
--- trunk/pub/libvex_guest_ppc32.h 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/pub/libvex_guest_ppc32.h 2009-03-19 22:21:40 UTC (rev 1886)
@@ -228,9 +228,10 @@
/* 964 */ UInt guest_REDIR_SP;
/* 968 */ UInt guest_REDIR_STACK[VEX_GUEST_PPC32_REDIR_STACK_SIZE];
- /* Needed for AIX: CIA at the last SC insn. Used when backing up
- to restart a syscall that has been interrupted by a signal. */
- /* ??? */ UInt guest_CIA_AT_SC;
+ /* Needed for AIX (but mandated for all guest architectures):
+ CIA at the last SC insn. Used when backing up to restart a
+ syscall that has been interrupted by a signal. */
+ /* ??? */ UInt guest_IP_AT_SYSCALL;
/* SPRG3, which AIUI is readonly in user space. Needed for
threading on AIX. */
Modified: trunk/pub/libvex_guest_ppc64.h
===================================================================
--- trunk/pub/libvex_guest_ppc64.h 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/pub/libvex_guest_ppc64.h 2009-03-19 22:21:40 UTC (rev 1886)
@@ -271,7 +271,7 @@
/* Needed for AIX: CIA at the last SC insn. Used when backing up
to restart a syscall that has been interrupted by a signal. */
- /* 1392 */ ULong guest_CIA_AT_SC;
+ /* 1392 */ ULong guest_IP_AT_SYSCALL;
/* SPRG3, which AIUI is readonly in user space. Needed for
threading on AIX. */
Modified: trunk/pub/libvex_guest_x86.h
===================================================================
--- trunk/pub/libvex_guest_x86.h 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/pub/libvex_guest_x86.h 2009-03-19 22:21:40 UTC (rev 1886)
@@ -223,8 +223,16 @@
/* Used for Darwin syscall dispatching. */
UInt guest_SC_CLASS;
+ /* Needed for Darwin (but mandated for all guest architectures):
+ EIP at the last syscall insn (int 0x80/81/82, sysenter,
+ syscall). Used when backing up to restart a syscall that has
+ been interrupted by a signal. */
+ UInt guest_IP_AT_SYSCALL;
+
/* Padding to make it have an 16-aligned size */
- /* UInt padding; */
+ UInt padding1;
+ UInt padding2;
+ UInt padding3;
}
VexGuestX86State;
Modified: trunk/pub/libvex_ir.h
===================================================================
--- trunk/pub/libvex_ir.h 2009-03-02 09:57:11 UTC (rev 1885)
+++ trunk/pub/libvex_ir.h 2009-03-19 22:21:40 UTC (rev 1886)
@@ -1196,6 +1196,13 @@
In the case of Ijk_EmFail, the exit is fatal (Vex-generated code
cannot continue) and so the jump destination can be anything.
+
+ Re Ijk_Sys_ (syscall jumps): the guest state must have a
+ pseudo-register guest_IP_AT_SYSCALL, which is the size of a guest
+ word. Front ends should set this to be the IP at the most recently
+ executed kernel-entering (system call) instruction. This makes it
+ very much easier (viz, actually possible at all) to back up the
+ guest to restart a syscall that has been interrupted by a signal.
*/
typedef
enum {
|