From: Julian Seward Date: Fri, 20 Jan 2006 14:19:25 +0000 (+0000) Subject: More ppc64-only function wrapping hacks: X-Git-Tag: svn/VALGRIND_3_2_3^2~118 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=abb480eac85ed770b73c18f201af0f82148fd703;p=thirdparty%2Fvalgrind.git More ppc64-only function wrapping hacks: - increase size of redirect stack from 8 to 16 elems - augment the _NRADDR pseudo-register with _NRADDR_GPR2, which is the value of R2 at the most recent divert point. This is needed in the ELF ppc64 ABI in order to safely run the function being wrapped. - add pseudo-instruction to read get _NRADDR_GPR2 into _GPR3. - related change: always keep R2 up to date wrt possible memory exceptions (no specific reason, just being conservative) git-svn-id: svn://svn.valgrind.org/vex/trunk@1543 --- diff --git a/VEX/priv/guest-ppc/ghelpers.c b/VEX/priv/guest-ppc/ghelpers.c index a070c91d36..bb3349c32c 100644 --- a/VEX/priv/guest-ppc/ghelpers.c +++ b/VEX/priv/guest-ppc/ghelpers.c @@ -615,6 +615,7 @@ void LibVEX_GuestPPC64_initialise ( /*OUT*/VexGuestPPC64State* vex_state ) vex_state->guest_TILEN = 0; vex_state->guest_NRADDR = 0; + vex_state->guest_NRADDR_GPR2 = 0; vex_state->guest_REDIR_SP = -1; for (i = 0; i < VEX_GUEST_PPC64_REDIR_STACK_SIZE; i++) @@ -671,10 +672,16 @@ Bool guest_ppc32_state_requires_precise_mem_exns ( Int minoff, Bool guest_ppc64_state_requires_precise_mem_exns ( Int minoff, Int maxoff ) { + /* Given that R2 is a Big Deal in the ELF ppc64 ABI, it seems + prudent to be conservative with it, even though thus far there + is no evidence to suggest that it actually needs to be kept up + to date wrt possible exceptions. */ Int lr_min = offsetof(VexGuestPPC64State, guest_LR); Int lr_max = lr_min + 8 - 1; Int r1_min = offsetof(VexGuestPPC64State, guest_GPR1); Int r1_max = r1_min + 8 - 1; + Int r2_min = offsetof(VexGuestPPC64State, guest_GPR2); + Int r2_max = r2_min + 8 - 1; Int cia_min = offsetof(VexGuestPPC64State, guest_CIA); Int cia_max = cia_min + 8 - 1; @@ -690,6 +697,12 @@ Bool guest_ppc64_state_requires_precise_mem_exns ( Int minoff, return True; } + if (maxoff < r2_min || minoff > r2_max) { + /* no overlap with R2 */ + } else { + return True; + } + if (maxoff < cia_min || minoff > cia_max) { /* no overlap with CIA */ } else { @@ -754,7 +767,7 @@ VexGuestLayout /* Describe any sections to be regarded by Memcheck as 'always-defined'. */ - .n_alwaysDefd = 10, + .n_alwaysDefd = 11, .alwaysDefd = { /* 0 */ ALWAYSDEFD64(guest_CIA), @@ -765,8 +778,9 @@ VexGuestLayout /* 5 */ ALWAYSDEFD64(guest_FPROUND), /* 6 */ ALWAYSDEFD64(guest_RESVN), /* 7 */ ALWAYSDEFD64(guest_NRADDR), - /* 8 */ ALWAYSDEFD64(guest_REDIR_SP), - /* 9 */ ALWAYSDEFD64(guest_REDIR_STACK) + /* 8 */ ALWAYSDEFD64(guest_NRADDR_GPR2), + /* 9 */ ALWAYSDEFD64(guest_REDIR_SP), + /* 10 */ ALWAYSDEFD64(guest_REDIR_STACK) } }; diff --git a/VEX/priv/guest-ppc/toIR.c b/VEX/priv/guest-ppc/toIR.c index 5ce26b72a1..567215cc98 100644 --- a/VEX/priv/guest-ppc/toIR.c +++ b/VEX/priv/guest-ppc/toIR.c @@ -109,6 +109,7 @@ 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) 7C421378 (or 2,2,2) %R3 = guest_NRADDR 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 + 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 (64-bit mode only) Any other bytes following the 16-byte preamble are illegal and constitute a failure in instruction decoding. This all assumes @@ -235,6 +236,10 @@ static void* fnptr_to_fnentry( void* f ) #define OFFB_RESVN offsetofPPCGuestState(guest_RESVN) #define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) +/* This only exists in the 64-bit guest state */ +#define OFFB64_NRADDR_GPR2 \ + offsetof(VexGuestPPC64State,guest_NRADDR_GPR2) + /*------------------------------------------------------------*/ /*--- Extract instruction fields --- */ @@ -2248,7 +2253,7 @@ static void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask ) - Non-IEEE Mode */ if (mask & 0xFC) { // Exception Control, Non-IEE mode - VexEmWarn ew = EmWarn_PPC32exns; + VexEmWarn ew = EmWarn_PPCexns; /* If any of the src::exception_control bits are actually set, side-exit to the next insn, reporting the warning, @@ -8465,6 +8470,17 @@ DisResult disInstr_PPC_WRK ( dres.whatNext = Dis_StopHere; goto decode_success; } + else + if (mode64 + && getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { + /* %R3 = guest_NRADDR_GPR2 */ + DIP("r3 = guest_NRADDR_GPR2\n"); + delta += 20; + dres.len = 20; + vassert(ty == Ity_I64); + putIReg(3, IRExpr_Get( OFFB64_NRADDR_GPR2, ty )); + goto decode_success; + } /* We don't know what it is. Set opc1/opc2 so decode_failure can print the insn following the Special-insn preamble. */ theInstr = getUIntBigendianly(code+16); diff --git a/VEX/priv/host-ppc/isel.c b/VEX/priv/host-ppc/isel.c index 66ab534f82..516f3c8136 100644 --- a/VEX/priv/host-ppc/isel.c +++ b/VEX/priv/host-ppc/isel.c @@ -752,7 +752,7 @@ PPCAMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, /* Throw out any cases we don't need. In theory there might be a day where we need to handle others, but not today. */ - if (nElems != 16) + if (nElems != 16 && nElems != 32) vpanic("genGuestArrayOffset(ppc64 host)(1)"); switch (elemSz) { @@ -768,7 +768,7 @@ PPCAMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, /* Compute off into a reg, %off. Then return: addi %tmp, %off, bias (if bias != 0) - andi %tmp, 15 + andi %tmp, nElems-1 sldi %tmp, shift addi %tmp, %tmp, base ... Baseblockptr + %tmp ... diff --git a/VEX/pub/libvex_guest_ppc64.h b/VEX/pub/libvex_guest_ppc64.h index b03db616d3..e2d6b97c10 100644 --- a/VEX/pub/libvex_guest_ppc64.h +++ b/VEX/pub/libvex_guest_ppc64.h @@ -93,7 +93,7 @@ vrsave Non-volatile 32-bit register /*--- Vex's representation of the PPC64 CPU state ---*/ /*---------------------------------------------------------------*/ -#define VEX_GUEST_PPC64_REDIR_STACK_SIZE 16 +#define VEX_GUEST_PPC64_REDIR_STACK_SIZE (16/*entries*/ * 2/*words per entry*/) typedef struct { @@ -257,13 +257,14 @@ typedef Note, this is only set for wrap-style redirects, not for replace-style ones. */ /* 1112 */ ULong guest_NRADDR; + /* 1120 */ ULong guest_NRADDR_GPR2; /* A grows-upwards stack for hidden saves/restores of LR and R2 needed for function interception and wrapping on ppc64-linux. A horrible hack. REDIR_SP points to the highest live entry, and so starts at -1. */ - /* 1120 */ ULong guest_REDIR_SP; - /* 1128 */ ULong guest_REDIR_STACK[VEX_GUEST_PPC64_REDIR_STACK_SIZE]; + /* 1128 */ ULong guest_REDIR_SP; + /* 1136 */ ULong guest_REDIR_STACK[VEX_GUEST_PPC64_REDIR_STACK_SIZE]; /* Padding to make it have an 8-aligned size */ /* UInt padding; */