|
From: <sv...@va...> - 2009-12-29 16:57:43
|
Author: sewardj
Date: 2009-12-29 16:57:28 +0000 (Tue, 29 Dec 2009)
New Revision: 1947
Log:
Add ARM guest-state support for the CP15 TPIDRURO register, which is
used by arm-linux to hold the TLS pointer.
Modified:
branches/ARM/priv/guest_arm_helpers.c
branches/ARM/priv/guest_arm_toIR.c
branches/ARM/pub/libvex_guest_arm.h
Modified: branches/ARM/priv/guest_arm_helpers.c
===================================================================
--- branches/ARM/priv/guest_arm_helpers.c 2009-12-29 14:37:50 UTC (rev 1946)
+++ branches/ARM/priv/guest_arm_helpers.c 2009-12-29 16:57:28 UTC (rev 1947)
@@ -488,6 +488,8 @@
all exns masked, all exn sticky bits cleared). */
vex_state->guest_FPSCR = 0;
+ vex_state->guest_TPIDRURO = 0;
+
/* vex_state->padding1 = 0; */
/* vex_state->padding2 = 0; */
}
@@ -560,7 +562,7 @@
/* Describe any sections to be regarded by Memcheck as
'always-defined'. */
- .n_alwaysDefd = 8,
+ .n_alwaysDefd = 9,
/* flags thunk: OP is always defd, whereas DEP1 and DEP2
have to be tracked. See detailed comment in gdefs.h on
@@ -573,7 +575,8 @@
/* 4 */ ALWAYSDEFD(guest_TISTART),
/* 5 */ ALWAYSDEFD(guest_TILEN),
/* 6 */ ALWAYSDEFD(guest_NRADDR),
- /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL)
+ /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL),
+ /* 8 */ ALWAYSDEFD(guest_TPIDRURO)
}
};
Modified: branches/ARM/priv/guest_arm_toIR.c
===================================================================
--- branches/ARM/priv/guest_arm_toIR.c 2009-12-29 14:37:50 UTC (rev 1946)
+++ branches/ARM/priv/guest_arm_toIR.c 2009-12-29 16:57:28 UTC (rev 1947)
@@ -311,6 +311,7 @@
#define OFFB_D15 offsetof(VexGuestARMState,guest_D15)
#define OFFB_FPSCR offsetof(VexGuestARMState,guest_FPSCR)
+#define OFFB_TPIDRURO offsetof(VexGuestARMState,guest_TPIDRURO)
/* ---------------- Integer registers ---------------- */
@@ -4568,6 +4569,29 @@
}
/* ----------------------------------------------------------- */
+ /* -- ARMv7 instructions -- */
+ /* ----------------------------------------------------------- */
+
+ /* -------------- read CP15 TPIDRURO register ------------- */
+ /* mrc p15, 0, r0, c13, c0, 3 up to
+ mrc p15, 0, r14, c13, c0, 3
+ */
+ /* I don't know whether this is really v7-only. But anyway, we
+ have to support it since arm-linux uses TPIDRURO as a thread
+ state register. */
+ if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) {
+ UInt rD = INSN(15,12);
+ if (rD <= 14) {
+ /* skip r15, that's too stupid to handle */
+ putIReg(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32),
+ condT, Ijk_Boring);
+ DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD);
+ goto decode_success;
+ }
+ /* fall through */
+ }
+
+ /* ----------------------------------------------------------- */
/* -- Undecodable -- */
/* ----------------------------------------------------------- */
Modified: branches/ARM/pub/libvex_guest_arm.h
===================================================================
--- branches/ARM/pub/libvex_guest_arm.h 2009-12-29 14:37:50 UTC (rev 1946)
+++ branches/ARM/pub/libvex_guest_arm.h 2009-12-29 16:57:28 UTC (rev 1947)
@@ -121,6 +121,15 @@
ULong guest_D15;
UInt guest_FPSCR;
+ /* Not a town in Cornwall, but instead the TPIDRURO, on of the
+ Thread ID registers present in CP15 (the system control
+ coprocessor), register set "c13", register 3 (the User
+ Read-only Thread ID Register). arm-linux apparently uses it
+ to hold the TLS pointer for the thread. It's read-only in
+ user space. On Linux it is set in user space by various
+ thread-related syscalls. */
+ UInt guest_TPIDRURO;
+
/* Padding to make it have an 16-aligned size */
/* UInt padding1; */
/* UInt padding2; */
|