|
From: <sv...@va...> - 2006-10-03 20:02:33
|
Author: sewardj
Date: 2006-10-03 21:02:29 +0100 (Tue, 03 Oct 2006)
New Revision: 6149
Log:
Generalise the machinery developed for function intercepts/wrapping
ppc64-linux, in which we have to deal with the big extra complexity
resulting from TOC pointers. This generalises it to work in 32-bit
mode too.
Add helpers to deal with AIX stack redzones.
Track VG_(am_find_nsegment) constness change and other minor=20
changes to the m_aspacemgr interface.
(All platforms): use the new VexMiscInfo structure to tell VEX about
host and guest ABI conventions.
This module could do with further tidying up and documentation.
Modified:
branches/AIX5/coregrind/m_translate.c
Modified: branches/AIX5/coregrind/m_translate.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/AIX5/coregrind/m_translate.c 2006-10-03 19:53:02 UTC (rev 61=
48)
+++ branches/AIX5/coregrind/m_translate.c 2006-10-03 20:02:29 UTC (rev 61=
49)
@@ -30,6 +30,7 @@
*/
=20
#include "pub_core_basics.h"
+#include "pub_core_vki.h"
#include "pub_core_aspacemgr.h"
=20
#include "pub_core_machine.h" // VG_(fnptr_to_fnentry)
@@ -53,7 +54,7 @@
// VG_(run_a_noredir_translation__return_=
point)
=20
#include "pub_core_threadstate.h" // VexGuestArchState
-#include "pub_core_trampoline.h" // VG_(ppc64_linux_magic_redirect_ret=
urn_stub)
+#include "pub_core_trampoline.h" // VG_(ppctoc_magic_redirect_return_s=
tub)
=20
=20
/*------------------------------------------------------------*/
@@ -473,7 +474,9 @@
=20
/* Vex dumps the final code in here. Then we can copy it off
wherever we like. */
-#define N_TMPBUF 20000
+/* 60000: should agree with assertion in VG_(add_to_transtab) in
+ m_transtab.c. */
+#define N_TMPBUF 60000
static UChar tmpbuf[N_TMPBUF];
=20
=20
@@ -503,7 +506,7 @@
/* Look for reasons to disallow making translations from the given
segment. */
=20
-static Bool translations_allowable_from_seg ( NSegment* seg )
+static Bool translations_allowable_from_seg ( NSegment const* seg )
{
# if defined(VGA_x86)
Bool allowR =3D True;
@@ -519,7 +522,7 @@
/* Is a self-check required for a translation of a guest address
inside segment SEG when requested by thread TID ? */
=20
-static Bool self_check_required ( NSegment* seg, ThreadId tid )
+static Bool self_check_required ( NSegment const* seg, ThreadId tid )
{
switch (VG_(clo_smc_check)) {
case Vg_SmcNone: return False;
@@ -547,7 +550,7 @@
static Bool chase_into_ok ( void* closureV, Addr64 addr64 )
{
Addr addr =3D (Addr)addr64;
- NSegment* seg =3D VG_(am_find_nsegment)(addr);
+ NSegment const* seg =3D VG_(am_find_nsegment)(addr);
VgCallbackClosure* closure =3D (VgCallbackClosure*)closureV;
=20
/* Work through a list of possibilities why we might not want to
@@ -565,9 +568,12 @@
if (addr !=3D VG_(redir_do_lookup)(addr, NULL))
goto dontchase;
=20
-# if defined(VGP_ppc64_linux)
- /* This needs to be at the start of its own block. Don't chase. */
- if (addr64 =3D=3D (Addr64)&VG_(ppc64_linux_magic_redirect_return_stub=
))
+# if defined(VG_PLAT_USES_PPCTOC)
+ /* This needs to be at the start of its own block. Don't chase. Re
+ ULong_to_Ptr, be careful to ensure we only compare 32 bits on a
+ 32-bit target.*/
+ if (ULong_to_Ptr(addr64)
+ =3D=3D (void*)&VG_(ppctoc_magic_redirect_return_stub))
goto dontchase;
# endif
=20
@@ -583,36 +589,76 @@
}
=20
=20
-/* --------------- ppc64-linux specific helpers --------------- */
+/* --------------- helpers for with-TOC platforms --------------- */
=20
+/* NOTE: with-TOC platforms are: ppc64-linux, ppc32-aix5, ppc64-aix5. */
+
static IRExpr* mkU64 ( ULong n ) {
return IRExpr_Const(IRConst_U64(n));
}
static IRExpr* mkU32 ( UInt n ) {
return IRExpr_Const(IRConst_U32(n));
}
-#if defined(VGP_ppc64_linux)
+
+#if defined(VG_PLAT_USES_PPCTOC)
static IRExpr* mkU8 ( UChar n ) {
return IRExpr_Const(IRConst_U8(n));
}
+static IRExpr* narrowTo32 ( IRTypeEnv* tyenv, IRExpr* e ) {
+ if (typeOfIRExpr(tyenv, e) =3D=3D Ity_I32) {
+ return e;
+ } else {
+ vg_assert(typeOfIRExpr(tyenv, e) =3D=3D Ity_I64);
+ return IRExpr_Unop(Iop_64to32, e);
+ }
+}
=20
+/* Generate code to push word-typed expression 'e' onto this thread's
+ redir stack, checking for stack overflow and generating code to
+ bomb out if so. */
+
static void gen_PUSH ( IRBB* bb, IRExpr* e )
{
- Int stack_size =3D VEX_GUEST_PPC64_REDIR_STACK_SIZE;
- Int offB_REDIR_SP =3D offsetof(VexGuestPPC64State,guest_REDIR_SP);
- Int offB_REDIR_STACK =3D offsetof(VexGuestPPC64State,guest_REDIR_STAC=
K);
- Int offB_EMWARN =3D offsetof(VexGuestPPC64State,guest_EMWARN);
+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
+ Int stack_size =3D VEX_GUEST_PPC64_REDIR_STACK_SIZE;
+ Int offB_REDIR_SP =3D offsetof(VexGuestPPC64State,guest_REDIR_S=
P);
+ Int offB_REDIR_STACK =3D offsetof(VexGuestPPC64State,guest_REDIR_S=
TACK);
+ Int offB_EMWARN =3D offsetof(VexGuestPPC64State,guest_EMWARN)=
;
+ Bool is64 =3D True;
+ IRType ty_Word =3D Ity_I64;
+ IROp op_CmpNE =3D Iop_CmpNE64;
+ IROp op_Sar =3D Iop_Sar64;
+ IROp op_Sub =3D Iop_Sub64;
+ IROp op_Add =3D Iop_Add64;
+ IRExpr*(*mkU)(ULong) =3D mkU64;
+ vg_assert(VG_WORDSIZE =3D=3D 8);
+# else
+ Int stack_size =3D VEX_GUEST_PPC32_REDIR_STACK_SIZE;
+ Int offB_REDIR_SP =3D offsetof(VexGuestPPC32State,guest_REDIR_S=
P);
+ Int offB_REDIR_STACK =3D offsetof(VexGuestPPC32State,guest_REDIR_S=
TACK);
+ Int offB_EMWARN =3D offsetof(VexGuestPPC32State,guest_EMWARN)=
;
+ Bool is64 =3D False;
+ IRType ty_Word =3D Ity_I32;
+ IROp op_CmpNE =3D Iop_CmpNE32;
+ IROp op_Sar =3D Iop_Sar32;
+ IROp op_Sub =3D Iop_Sub32;
+ IROp op_Add =3D Iop_Add32;
+ IRExpr*(*mkU)(UInt) =3D mkU32;
+ vg_assert(VG_WORDSIZE =3D=3D 4);
+# endif
=20
- IRArray* descr =3D mkIRArray( offB_REDIR_STACK, Ity_I64, stack_size )=
;
- IRTemp t1 =3D newIRTemp( bb->tyenv, Ity_I64 );
- IRExpr* one =3D mkU64(1);
+ IRArray* descr =3D mkIRArray( offB_REDIR_STACK, ty_Word, stack_size )=
;
+ IRTemp t1 =3D newIRTemp( bb->tyenv, ty_Word );
+ IRExpr* one =3D mkU(1);
=20
+ vg_assert(typeOfIRExpr(bb->tyenv, e) =3D=3D ty_Word);
+
/* t1 =3D guest_REDIR_SP + 1 */
addStmtToIRBB(
bb,=20
IRStmt_Tmp(
t1,=20
- IRExpr_Binop(Iop_Add64, IRExpr_Get( offB_REDIR_SP, Ity_I64 ), o=
ne)
+ IRExpr_Binop(op_Add, IRExpr_Get( offB_REDIR_SP, ty_Word ), one)
)
);
=20
@@ -629,16 +675,16 @@
bb,
IRStmt_Exit(
IRExpr_Binop(
- Iop_CmpNE64,
+ op_CmpNE,
IRExpr_Binop(
- Iop_Sar64,
- IRExpr_Binop(Iop_Sub64,mkU64(stack_size-1),IRExpr_Tmp(t1)=
),
- mkU8(63)
+ op_Sar,
+ IRExpr_Binop(op_Sub,mkU(stack_size-1),IRExpr_Tmp(t1)),
+ mkU8(8 * VG_WORDSIZE - 1)
),
- mkU64(0)
+ mkU(0)
),
Ijk_EmFail,
- IRConst_U64(0)
+ is64 ? IRConst_U64(0) : IRConst_U32(0)
)
);
=20
@@ -646,28 +692,53 @@
addStmtToIRBB(bb, IRStmt_Put(offB_REDIR_SP, IRExpr_Tmp(t1)));
=20
/* guest_REDIR_STACK[t1+0] =3D e */
+ /* PutI/GetI have I32-typed indexes regardless of guest word size */
addStmtToIRBB(
bb,=20
- IRStmt_PutI(descr, IRExpr_Unop(Iop_64to32,IRExpr_Tmp(t1)), 0, e)
+ IRStmt_PutI(descr, narrowTo32(bb->tyenv,IRExpr_Tmp(t1)), 0, e)
);
}
=20
+
+/* Generate code to pop a word-sized value from this thread's redir
+ stack, binding it to a new temporary, which is returned. As with
+ gen_PUSH, an overflow check is also performed. */
+
static IRTemp gen_POP ( IRBB* bb )
{
- Int stack_size =3D VEX_GUEST_PPC64_REDIR_STACK_SIZE;
- Int offB_REDIR_SP =3D offsetof(VexGuestPPC64State,guest_REDIR_SP);
- Int offB_REDIR_STACK =3D offsetof(VexGuestPPC64State,guest_REDIR_STAC=
K);
- Int offB_EMWARN =3D offsetof(VexGuestPPC64State,guest_EMWARN);
+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
+ Int stack_size =3D VEX_GUEST_PPC64_REDIR_STACK_SIZE;
+ Int offB_REDIR_SP =3D offsetof(VexGuestPPC64State,guest_REDIR_S=
P);
+ Int offB_REDIR_STACK =3D offsetof(VexGuestPPC64State,guest_REDIR_S=
TACK);
+ Int offB_EMWARN =3D offsetof(VexGuestPPC64State,guest_EMWARN)=
;
+ Bool is64 =3D True;
+ IRType ty_Word =3D Ity_I64;
+ IROp op_CmpNE =3D Iop_CmpNE64;
+ IROp op_Sar =3D Iop_Sar64;
+ IROp op_Sub =3D Iop_Sub64;
+ IRExpr*(*mkU)(ULong) =3D mkU64;
+# else
+ Int stack_size =3D VEX_GUEST_PPC32_REDIR_STACK_SIZE;
+ Int offB_REDIR_SP =3D offsetof(VexGuestPPC32State,guest_REDIR_S=
P);
+ Int offB_REDIR_STACK =3D offsetof(VexGuestPPC32State,guest_REDIR_S=
TACK);
+ Int offB_EMWARN =3D offsetof(VexGuestPPC32State,guest_EMWARN)=
;
+ Bool is64 =3D False;
+ IRType ty_Word =3D Ity_I32;
+ IROp op_CmpNE =3D Iop_CmpNE32;
+ IROp op_Sar =3D Iop_Sar32;
+ IROp op_Sub =3D Iop_Sub32;
+ IRExpr*(*mkU)(UInt) =3D mkU32;
+# endif
=20
- IRArray* descr =3D mkIRArray( offB_REDIR_STACK, Ity_I64, stack_size )=
;
- IRTemp t1 =3D newIRTemp( bb->tyenv, Ity_I64 );
- IRTemp res =3D newIRTemp( bb->tyenv, Ity_I64 );
- IRExpr* one =3D mkU64(1);
+ IRArray* descr =3D mkIRArray( offB_REDIR_STACK, ty_Word, stack_size )=
;
+ IRTemp t1 =3D newIRTemp( bb->tyenv, ty_Word );
+ IRTemp res =3D newIRTemp( bb->tyenv, ty_Word );
+ IRExpr* one =3D mkU(1);
=20
/* t1 =3D guest_REDIR_SP */
addStmtToIRBB(
bb,=20
- IRStmt_Tmp( t1, IRExpr_Get( offB_REDIR_SP, Ity_I64 ) )
+ IRStmt_Tmp( t1, IRExpr_Get( offB_REDIR_SP, ty_Word ) )
);
=20
/* Bomb out if t1 < 0. Same comments as gen_PUSH apply. */
@@ -679,54 +750,77 @@
bb,
IRStmt_Exit(
IRExpr_Binop(
- Iop_CmpNE64,
+ op_CmpNE,
IRExpr_Binop(
- Iop_Sar64,
+ op_Sar,
IRExpr_Tmp(t1),
- mkU8(63)
+ mkU8(8 * VG_WORDSIZE - 1)
),
- mkU64(0)
+ mkU(0)
),
Ijk_EmFail,
- IRConst_U64(0)
+ is64 ? IRConst_U64(0) : IRConst_U32(0)
)
);
=20
/* res =3D guest_REDIR_STACK[t1+0] */
+ /* PutI/GetI have I32-typed indexes regardless of guest word size */
addStmtToIRBB(
bb,
IRStmt_Tmp(
res,=20
- IRExpr_GetI(descr, IRExpr_Unop(Iop_64to32,IRExpr_Tmp(t1)), 0)
+ IRExpr_GetI(descr, narrowTo32(bb->tyenv,IRExpr_Tmp(t1)), 0)
)
);
=20
/* guest_REDIR_SP =3D t1-1 */
addStmtToIRBB(
bb,=20
- IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(Iop_Sub64, IRExpr_Tmp(t1), =
one))
+ IRStmt_Put(offB_REDIR_SP, IRExpr_Binop(op_Sub, IRExpr_Tmp(t1), one=
))
);
=20
return res;
}
=20
+/* Generate code to push LR and R2 onto this thread's redir stack,
+ then set R2 to the new value (which is the TOC pointer to be used
+ for the duration of the replacement function, as determined by
+ m_debuginfo), and set LR to the magic return stub, so we get to
+ intercept the return and restore R2 and L2 to the values saved
+ here. */
+
static void gen_push_and_set_LR_R2 ( IRBB* bb, Addr64 new_R2_value )
{
- Addr64 bogus_RA =3D (Addr64)&VG_(ppc64_linux_magic_redirect_return_st=
ub);
- Int offB_GPR2 =3D offsetof(VexGuestPPC64State,guest_GPR2);
- Int offB_LR =3D offsetof(VexGuestPPC64State,guest_LR);
+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
+ Addr64 bogus_RA =3D (Addr64)&VG_(ppctoc_magic_redirect_return_stub);
+ Int offB_GPR2 =3D offsetof(VexGuestPPC64State,guest_GPR2);
+ Int offB_LR =3D offsetof(VexGuestPPC64State,guest_LR);
gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I64) );
gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I64) );
addStmtToIRBB( bb, IRStmt_Put( offB_LR, mkU64( bogus_RA )) );
addStmtToIRBB( bb, IRStmt_Put( offB_GPR2, mkU64( new_R2_value )) );
+
+# elif defined(VGP_ppc32_aix5)
+ Addr32 bogus_RA =3D (Addr32)&VG_(ppctoc_magic_redirect_return_stub);
+ Int offB_GPR2 =3D offsetof(VexGuestPPC32State,guest_GPR2);
+ Int offB_LR =3D offsetof(VexGuestPPC32State,guest_LR);
+ gen_PUSH( bb, IRExpr_Get(offB_LR, Ity_I32) );
+ gen_PUSH( bb, IRExpr_Get(offB_GPR2, Ity_I32) );
+ addStmtToIRBB( bb, IRStmt_Put( offB_LR, mkU32( bogus_RA )) );
+ addStmtToIRBB( bb, IRStmt_Put( offB_GPR2, mkU32( new_R2_value )) );
+
+# else
+# error Platform is not TOC-afflicted, fortunately
+# endif
}
=20
static void gen_pop_R2_LR_then_bLR ( IRBB* bb )
{
- Int offB_GPR2 =3D offsetof(VexGuestPPC64State,guest_GPR2);
- Int offB_LR =3D offsetof(VexGuestPPC64State,guest_LR);
- IRTemp old_R2 =3D newIRTemp( bb->tyenv, Ity_I64 );
- IRTemp old_LR =3D newIRTemp( bb->tyenv, Ity_I64 );
+# if defined(VGP_ppc64_linux) || defined(VGP_ppc64_aix5)
+ Int offB_GPR2 =3D offsetof(VexGuestPPC64State,guest_GPR2);
+ Int offB_LR =3D offsetof(VexGuestPPC64State,guest_LR);
+ IRTemp old_R2 =3D newIRTemp( bb->tyenv, Ity_I64 );
+ IRTemp old_LR =3D newIRTemp( bb->tyenv, Ity_I64 );
/* Restore R2 */
old_R2 =3D gen_POP( bb );
addStmtToIRBB( bb, IRStmt_Put( offB_GPR2, IRExpr_Tmp(old_R2)) );
@@ -736,13 +830,36 @@
/* Branch to LR */
/* re boring, we arrived here precisely because a wrapped fn did a
blr (hence Ijk_Ret); so we should just mark this jump as Boring,
- else one _Call will have resulted in to _Rets. */
+ else one _Call will have resulted in two _Rets. */
bb->jumpkind =3D Ijk_Boring;
bb->next =3D IRExpr_Binop(Iop_And64, IRExpr_Tmp(old_LR), mkU64(~(3ULL=
)));
+
+# elif defined(VGP_ppc32_aix5)
+ Int offB_GPR2 =3D offsetof(VexGuestPPC32State,guest_GPR2);
+ Int offB_LR =3D offsetof(VexGuestPPC32State,guest_LR);
+ IRTemp old_R2 =3D newIRTemp( bb->tyenv, Ity_I32 );
+ IRTemp old_LR =3D newIRTemp( bb->tyenv, Ity_I32 );
+ /* Restore R2 */
+ old_R2 =3D gen_POP( bb );
+ addStmtToIRBB( bb, IRStmt_Put( offB_GPR2, IRExpr_Tmp(old_R2)) );
+ /* Restore LR */
+ old_LR =3D gen_POP( bb );
+ addStmtToIRBB( bb, IRStmt_Put( offB_LR, IRExpr_Tmp(old_LR)) );
+
+ /* Branch to LR */
+ /* re boring, we arrived here precisely because a wrapped fn did a
+ blr (hence Ijk_Ret); so we should just mark this jump as Boring,
+ else one _Call will have resulted in two _Rets. */
+ bb->jumpkind =3D Ijk_Boring;
+ bb->next =3D IRExpr_Binop(Iop_And32, IRExpr_Tmp(old_LR), mkU32(~3));
+
+# else
+# error Platform is not TOC-afflicted, fortunately
+# endif
}
=20
static
-Bool mk_preamble__ppc64_magic_return_stub ( void* closureV, IRBB* bb )
+Bool mk_preamble__ppctoc_magic_return_stub ( void* closureV, IRBB* bb )
{
VgCallbackClosure* closure =3D (VgCallbackClosure*)closureV;
/* Since we're creating the entire IRBB right here, give it a
@@ -761,21 +878,22 @@
}
#endif
=20
-/* --------------- END ppc64-linux specific helpers --------------- */
+/* --------------- END helpers for with-TOC platforms --------------- */
=20
-/* This is an the IR preamble generators used for replacement
+
+/* This is the IR preamble generators used for replacement
functions. It adds code to set the guest_NRADDR{_GPR2} to zero
(technically not necessary, but facilitates detecting mixups in
which a replacement function has been erroneously declared using
VG_REPLACE_FUNCTION_Z{U,Z} when instead it should have been written
using VG_WRAP_FUNCTION_Z{U,Z}).
=20
- On ppc64-linux the follow hacks are also done: LR and R2 are pushed
- onto a hidden stack, sets R2 to the correct value for the
- replacement function, and sets LR to point at the magic return-stub
- address. Setting LR causes the return of the wrapped/redirected
- function to lead to our magic return stub, which restores LR and R2
- from said stack and returns for real.
+ On with-TOC platforms the follow hacks are also done: LR and R2 are
+ pushed onto a hidden stack, R2 is set to the correct value for the
+ replacement function, and LR is set to point at the magic
+ return-stub address. Setting LR causes the return of the
+ wrapped/redirected function to lead to our magic return stub, which
+ restores LR and R2 from said stack and returns for real.
=20
VG_(get_StackTrace2) understands that the LR value may point to the
return stub address, and that in that case it can get the real LR
@@ -786,6 +904,7 @@
Int nraddr_szB
=3D sizeof(((VexGuestArchState*)0)->guest_NRADDR);
vg_assert(nraddr_szB =3D=3D 4 || nraddr_szB =3D=3D 8);
+ vg_assert(nraddr_szB =3D=3D VG_WORDSIZE);
addStmtToIRBB(=20
bb,
IRStmt_Put(=20
@@ -793,13 +912,13 @@
nraddr_szB =3D=3D 8 ? mkU64(0) : mkU32(0)
)
);
-# if defined(VGP_ppc64_linux)
+# if defined(VG_PLAT_USES_PPCTOC)
{ VgCallbackClosure* closure =3D (VgCallbackClosure*)closureV;
addStmtToIRBB(
bb,
IRStmt_Put(
offsetof(VexGuestArchState,guest_NRADDR_GPR2),
- mkU64(0)
+ VG_WORDSIZE=3D=3D8 ? mkU64(0) : mkU32(0)
)
);
gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
@@ -811,7 +930,7 @@
/* Ditto, except set guest_NRADDR to nraddr (the un-redirected guest
address). This is needed for function wrapping - so the wrapper
can read _NRADDR and find the address of the function being
- wrapped. */
+ wrapped. On toc-afflicted platforms we must also snarf r2. */
static=20
Bool mk_preamble__set_NRADDR_to_nraddr ( void* closureV, IRBB* bb )
{
@@ -819,6 +938,7 @@
Int nraddr_szB
=3D sizeof(((VexGuestArchState*)0)->guest_NRADDR);
vg_assert(nraddr_szB =3D=3D 4 || nraddr_szB =3D=3D 8);
+ vg_assert(nraddr_szB =3D=3D VG_WORDSIZE);
addStmtToIRBB(=20
bb,
IRStmt_Put(=20
@@ -828,13 +948,14 @@
: IRExpr_Const(IRConst_U32( (UInt)closure->nraddr ))
)
);
-# if defined(VGP_ppc64_linux)
+# if defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
+ || defined(VGP_ppc64_aix5)
addStmtToIRBB(=20
bb,
IRStmt_Put(=20
offsetof(VexGuestArchState,guest_NRADDR_GPR2),
IRExpr_Get(offsetof(VexGuestArchState,guest_GPR2),=20
- Ity_I64)
+ VG_WORDSIZE=3D=3D8 ? Ity_I64 : Ity_I32)
)
);
gen_push_and_set_LR_R2 ( bb, VG_(get_tocptr)( closure->readdr ) );
@@ -842,7 +963,56 @@
return False;
}
=20
+/* --- Helpers to do with PPC related stack redzones. --- */
=20
+__attribute__((unused))
+static Bool const_True ( Addr64 guest_addr )
+{
+ return True;
+}
+
+__attribute__((unused))
+static Bool bl_RZ_zap_ok_for_AIX ( Addr64 bl_target )
+{
+ /* paranoia */
+ if (sizeof(void*) =3D=3D 4)
+ bl_target &=3D 0xFFFFFFFFULL;
+
+ /* don't zap the redzone for calls to millicode. */
+ if (bl_target < 0x10000ULL)
+ return False;
+
+ /* don't zap the redzone for calls to .$SAVEF14 .. .$SAVEF31.
+ First we need to be reasonably sure we won't segfault by looking
+ at the branch target. */
+ { NSegment const*const seg =3D VG_(am_find_nsegment)( (Addr)bl_target=
);
+ if (seg && seg->hasR) {
+ switch ( *(UInt*)(Addr)bl_target ) {
+ case 0xd9c1ff70: /* stfd f14,-144(r1) */
+ case 0xd9e1ff78: /* stfd f15,-136(r1) */
+ case 0xda01ff80: /* stfd f16,-128(r1) */
+ case 0xda21ff88: /* stfd f17,-120(r1) */
+ case 0xda41ff90: /* stfd f18,-112(r1) */
+ case 0xda61ff98: /* stfd f19,-104(r1) */
+ case 0xda81ffa0: /* stfd f20,-96(r1) */
+ case 0xdaa1ffa8: /* stfd f21,-88(r1) */
+ case 0xdac1ffb0: /* stfd f22,-80(r1) */
+ case 0xdae1ffb8: /* stfd f23,-72(r1) */
+ case 0xdb01ffc0: /* stfd f24,-64(r1) */
+ case 0xdb21ffc8: /* stfd f25,-56(r1) */
+ case 0xdb41ffd0: /* stfd f26,-48(r1) */
+ case 0xdb61ffd8: /* stfd f27,-40(r1) */
+ case 0xdb81ffe0: /* stfd f28,-32(r1) */
+ case 0xdba1ffe8: /* stfd f29,-24(r1) */
+ case 0xdbc1fff0: /* stfd f30,-16(r1) */
+ case 0xdbe1fff8: /* stfd f31,-8(r1) */
+ return False;
+ }
+ }
+ }
+ return True;
+}
+
/* --------------- main translation function --------------- */
=20
/* Note: see comments at top of m_redir.c for the Big Picture on how
@@ -885,10 +1055,10 @@
Int tmpbuf_used, verbosity, i;
Bool notrace_until_done, do_self_check;
UInt notrace_until_limit =3D 0;
- NSegment* seg;
Bool (*preamble_fn)(void*,IRBB*);
VexArch vex_arch;
VexArchInfo vex_archinfo;
+ VexMiscInfo vex_miscinfo;
VexGuestExtents vge;
VexTranslateArgs vta;
VexTranslateResult tres;
@@ -970,9 +1140,13 @@
=20
/* Are we allowed to translate here? */
=20
- seg =3D VG_(am_find_nsegment)(addr);
+ { /* BEGIN new scope specially for 'seg' */
+ NSegment const*const seg =3D VG_(am_find_nsegment)(addr);
=20
if (!translations_allowable_from_seg(seg)) {
+ if (VG_(clo_trace_signals))
+ VG_(message)(Vg_DebugMsg, "translations not allowed here "
+ "- throwing SEGV");
/* U R busted, sonny. Place your hands on your head and step
away from the orig_addr. */
/* Code address is bad - deliver a signal instead */
@@ -1009,8 +1183,10 @@
else=20
if (kind =3D=3D T_Redir_Wrap)
preamble_fn =3D mk_preamble__set_NRADDR_to_nraddr;
-# if defined(VGP_ppc64_linux)
- if (nraddr =3D=3D (Addr64)&VG_(ppc64_linux_magic_redirect_return_stub=
)) {
+
+# if defined(VG_PLAT_USES_PPCTOC)
+ if (ULong_to_Ptr(nraddr)
+ =3D=3D (void*)&VG_(ppctoc_magic_redirect_return_stub)) {
/* If entering the special return stub, this means a wrapped or
redirected function is returning. Make this translation one
which restores R2 and LR from the thread's hidden redir
@@ -1018,8 +1194,8 @@
really causing the function to return. */
vg_assert(kind =3D=3D T_Normal);
vg_assert(nraddr =3D=3D addr);
- preamble_fn =3D mk_preamble__ppc64_magic_return_stub;
- }
+ preamble_fn =3D mk_preamble__ppctoc_magic_return_stub;
+ }
# endif
=20
/* ------ Actually do the translation. ------ */
@@ -1029,6 +1205,29 @@
/* Get the CPU info established at startup. */
VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
=20
+ /* Set up 'misc info' structure with stuff Vex needs to know about
+ the guest and host ABIs. */
+
+ LibVEX_default_VexMiscInfo( &vex_miscinfo );
+ vex_miscinfo.guest_stack_redzone_size =3D VG_STACK_REDZONE_SZB;
+
+# if defined(VGP_ppc32_linux)
+ vex_miscinfo.guest_ppc_zap_RZ_at_blr =3D False;
+ vex_miscinfo.guest_ppc_zap_RZ_at_bl =3D NULL;
+ vex_miscinfo.host_ppc32_regalign_int64_args =3D True;
+# endif
+# if defined(VGP_ppc64_linux)
+ vex_miscinfo.guest_ppc_zap_RZ_at_blr =3D True;
+ vex_miscinfo.guest_ppc_zap_RZ_at_bl =3D const_True;
+ vex_miscinfo.host_ppc_calls_use_fndescrs =3D True;
+# endif
+# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ vex_miscinfo.guest_ppc_zap_RZ_at_blr =3D False;
+ vex_miscinfo.guest_ppc_zap_RZ_at_bl =3D bl_RZ_zap_ok_for_AIX;
+ vex_miscinfo.guest_ppc_sc_continues_at_LR =3D True;
+ vex_miscinfo.host_ppc_calls_use_fndescrs =3D True;
+# endif
+
/* Set up closure args. */
closure.tid =3D tid;
closure.nraddr =3D nraddr;
@@ -1039,6 +1238,7 @@
vta.archinfo_guest =3D vex_archinfo;
vta.arch_host =3D vex_arch;
vta.archinfo_host =3D vex_archinfo;
+ vta.miscinfo_both =3D vex_miscinfo;
vta.guest_bytes =3D (UChar*)ULong_to_Ptr(addr);
vta.guest_bytes_addr =3D (Addr64)addr;
vta.callback_opaque =3D (void*)&closure;
@@ -1105,13 +1305,15 @@
should already point to it. */
=20
vg_assert( vge.base[0] =3D=3D (Addr64)addr );
- if (seg->kind =3D=3D SkFileC || seg->kind =3D=3D SkAnonC)
- seg->hasT =3D True; /* has cached code */
+ /* set 'translations taken from this segment' flag */
+ VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
+ } /* END new scope specially for 'seg' */
=20
for (i =3D 1; i < vge.n_used; i++) {
- seg =3D VG_(am_find_nsegment)( vge.base[i] );
- if (seg->kind =3D=3D SkFileC || seg->kind =3D=3D SkAnonC)
- seg->hasT =3D True; /* has cached code */
+ NSegment const*const seg=20
+ =3D VG_(am_find_nsegment)( vge.base[i] );
+ /* set 'translations taken from this segment' flag */
+ VG_(am_set_segment_hasT_if_SkFileC_or_SkAnonC)( (NSegment*)seg );
}
=20
/* Copy data at trans_addr into the translation cache. */
|