From c470e0c23c6c79deec943cb6a111b572fc86dbba Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Mon, 20 Nov 2017 11:43:55 +0100 Subject: [PATCH] arm(32)-linux: add support for the TPIDRURW system register. Fixes #386425. --- VEX/priv/guest_arm_helpers.c | 3 +- VEX/priv/guest_arm_toIR.c | 57 ++++++++++++++++++++++++++++++++++++ VEX/pub/libvex_guest_arm.h | 8 +++-- memcheck/mc_machine.c | 1 + 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/VEX/priv/guest_arm_helpers.c b/VEX/priv/guest_arm_helpers.c index 0ef26b6452..8a028736ee 100644 --- a/VEX/priv/guest_arm_helpers.c +++ b/VEX/priv/guest_arm_helpers.c @@ -1334,11 +1334,10 @@ void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state ) vex_state->guest_FPSCR = 0; vex_state->guest_TPIDRURO = 0; + vex_state->guest_TPIDRURW = 0; /* Not in a Thumb IT block. */ vex_state->guest_ITSTATE = 0; - - vex_state->padding1 = 0; } diff --git a/VEX/priv/guest_arm_toIR.c b/VEX/priv/guest_arm_toIR.c index b26393ac8e..26c5174647 100644 --- a/VEX/priv/guest_arm_toIR.c +++ b/VEX/priv/guest_arm_toIR.c @@ -486,6 +486,7 @@ static IRExpr* align4if ( IRExpr* e, Bool b ) #define OFFB_FPSCR offsetof(VexGuestARMState,guest_FPSCR) #define OFFB_TPIDRURO offsetof(VexGuestARMState,guest_TPIDRURO) +#define OFFB_TPIDRURW offsetof(VexGuestARMState,guest_TPIDRURW) #define OFFB_ITSTATE offsetof(VexGuestARMState,guest_ITSTATE) #define OFFB_QFLAG32 offsetof(VexGuestARMState,guest_QFLAG32) #define OFFB_GEFLAG0 offsetof(VexGuestARMState,guest_GEFLAG0) @@ -935,6 +936,7 @@ static void putMiscReg32 ( UInt gsoffset, case OFFB_GEFLAG1: break; case OFFB_GEFLAG2: break; case OFFB_GEFLAG3: break; + case OFFB_TPIDRURW: break; default: vassert(0); /* awaiting more cases */ } vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I32); @@ -18702,6 +18704,35 @@ DisResult disInstr_ARM_WRK ( /* fall through */ } + /* ------------ read/write CP15 TPIDRURW register ----------- */ + /* mcr p15, 0, r0, c13, c0, 2 (r->cr xfer) up to + mcr p15, 0, r14, c13, c0, 2 + + mrc p15, 0, r0, c13, c0, 2 (rc->r xfer) up to + mrc p15, 0, r14, c13, c0, 2 + */ + if (0x0E0D0F50 == (insn & 0x0FFF0FFF)) { // MCR + UInt rS = INSN(15,12); + if (rS <= 14) { + /* skip r15, that's too stupid to handle */ + putMiscReg32(OFFB_TPIDRURW, getIRegA(rS), condT); + DIP("mcr%s p15,0, r%u, c13, c0, 2\n", nCC(INSN_COND), rS); + goto decode_success; + } + /* fall through */ + } + if (0x0E1D0F50 == (insn & 0x0FFF0FFF)) { // MRC + UInt rD = INSN(15,12); + if (rD <= 14) { + /* skip r15, that's too stupid to handle */ + putIRegA(rD, IRExpr_Get(OFFB_TPIDRURW, Ity_I32), + condT, Ijk_Boring); + DIP("mrc%s p15,0, r%u, c13, c0, 2\n", nCC(INSN_COND), rD); + goto decode_success; + } + /* fall through */ + } + /* -------------- read CP15 PMUSRENR register ------------- */ /* mrc p15, 0, r0, c9, c14, 0 up to mrc p15, 0, r14, c9, c14, 0 @@ -23121,6 +23152,32 @@ DisResult disInstr_THUMB_WRK ( /* fall through */ } + /* ------------ read/write CP15 TPIDRURW register ----------- */ + /* mcr p15, 0, r0, c13, c0, 2 (r->cr xfer) up to + mcr p15, 0, r14, c13, c0, 2 + + mrc p15, 0, r0, c13, c0, 2 (rc->r xfer) up to + mrc p15, 0, r14, c13, c0, 2 + */ + if ((INSN0(15,0) == 0xEE0D) && (INSN1(11,0) == 0x0F50)) { + UInt rS = INSN1(15,12); + if (!isBadRegT(rS)) { + putMiscReg32(OFFB_TPIDRURW, getIRegT(rS), condT); + DIP("mcr p15,0, r%u, c13, c0, 2\n", rS); + goto decode_success; + } + /* fall through */ + } + if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F50)) { + UInt rD = INSN1(15,12); + if (!isBadRegT(rD)) { + putIRegT(rD, IRExpr_Get(OFFB_TPIDRURW, Ity_I32), condT); + DIP("mrc p15,0, r%u, c13, c0, 2\n", rD); + goto decode_success; + } + /* fall through */ + } + /* -------------- read CP15 PMUSRENR register ------------- */ /* mrc p15, 0, r0, c9, c14, 0 up to mrc p15, 0, r14, c9, c14, 0 diff --git a/VEX/pub/libvex_guest_arm.h b/VEX/pub/libvex_guest_arm.h index 029441f463..5dbe59c41a 100644 --- a/VEX/pub/libvex_guest_arm.h +++ b/VEX/pub/libvex_guest_arm.h @@ -158,6 +158,11 @@ typedef thread-related syscalls. */ UInt guest_TPIDRURO; + /* TPIDRURW is also apparently used as a thread register, but one + controlled entirely by, and writable from, user space. We model + it as a completely vanilla piece of integer state. */ + UInt guest_TPIDRURW; + /* Representation of the Thumb IT state. ITSTATE is a 32-bit value with 4 8-bit lanes. [7:0] pertain to the next insn to execute, [15:8] for the one after that, etc. The per-insn @@ -192,9 +197,6 @@ typedef to the top 24 bits of ITSTATE being zero. */ UInt guest_ITSTATE; - - /* Padding to make it have an 16-aligned size */ - UInt padding1; } VexGuestARMState; diff --git a/memcheck/mc_machine.c b/memcheck/mc_machine.c index 2f2afada44..d05125a9a8 100644 --- a/memcheck/mc_machine.c +++ b/memcheck/mc_machine.c @@ -873,6 +873,7 @@ static Int get_otrack_shadow_offset_wrk ( Int offset, Int szB ) if (o == GOF(FPSCR) && sz == 4) return -1; if (o == GOF(TPIDRURO) && sz == 4) return -1; + if (o == GOF(TPIDRURW) && sz == 4) return -1; if (o == GOF(ITSTATE) && sz == 4) return -1; /* Accesses to F or D registers */ -- 2.47.2