From: Philippe Waroquiers Date: Tue, 14 Aug 2012 22:29:01 +0000 (+0000) Subject: VEX part Implement --vex-iropt-register-updates=sp-at-mem-access X-Git-Tag: svn/VALGRIND_3_9_0^2~293 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5d8f3584365e6f54a04265df025ae13b9305aac0;p=thirdparty%2Fvalgrind.git VEX part Implement --vex-iropt-register-updates=sp-at-mem-access git-svn-id: svn://svn.valgrind.org/vex/trunk@2468 --- diff --git a/VEX/priv/guest_amd64_helpers.c b/VEX/priv/guest_amd64_helpers.c index 7e67d73f18..467702a311 100644 --- a/VEX/priv/guest_amd64_helpers.c +++ b/VEX/priv/guest_amd64_helpers.c @@ -40,6 +40,7 @@ #include "libvex.h" #include "main_util.h" +#include "main_globals.h" #include "guest_generic_bb_to_IR.h" #include "guest_amd64_defs.h" #include "guest_generic_x87.h" @@ -3716,11 +3717,13 @@ void LibVEX_GuestAMD64_initialise ( /*OUT*/VexGuestAMD64State* vex_state ) /* Figure out if any part of the guest state contained in minoff .. maxoff requires precise memory exceptions. If in doubt return - True (but this is generates significantly slower code). + True (but this generates significantly slower code). By default we enforce precise exns for guest %RSP, %RBP and %RIP only. These are the minimum needed to extract correct stack backtraces from amd64 code. + + Only %RSP is needed in mode VexRegUpdSpAtMemAccess. */ Bool guest_amd64_state_requires_precise_mem_exns ( Int minoff, Int maxoff) @@ -3732,14 +3735,16 @@ Bool guest_amd64_state_requires_precise_mem_exns ( Int minoff, Int rip_min = offsetof(VexGuestAMD64State, guest_RIP); Int rip_max = rip_min + 8 - 1; - if (maxoff < rbp_min || minoff > rbp_max) { - /* no overlap with rbp */ + if (maxoff < rsp_min || minoff > rsp_max) { + /* no overlap with rsp */ + if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess) + return False; // We only need to check stack pointer. } else { return True; } - if (maxoff < rsp_min || minoff > rsp_max) { - /* no overlap with rsp */ + if (maxoff < rbp_min || minoff > rbp_max) { + /* no overlap with rbp */ } else { return True; } diff --git a/VEX/priv/guest_arm_helpers.c b/VEX/priv/guest_arm_helpers.c index d31e64a232..5fc42c72ab 100644 --- a/VEX/priv/guest_arm_helpers.c +++ b/VEX/priv/guest_arm_helpers.c @@ -35,6 +35,7 @@ #include "libvex.h" #include "main_util.h" +#include "main_globals.h" #include "guest_generic_bb_to_IR.h" #include "guest_arm_defs.h" @@ -1043,9 +1044,12 @@ void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state ) /* Figure out if any part of the guest state contained in minoff .. maxoff requires precise memory exceptions. If in doubt return - True (but this is generates significantly slower code). + True (but this generates significantly slower code). - We enforce precise exns for guest R13(sp), R15T(pc). + We enforce precise exns for guest R13(sp), R15T(pc), R7, R11. + + + Only R13(sp) is needed in mode VexRegUpdSpAtMemAccess. */ Bool guest_arm_state_requires_precise_mem_exns ( Int minoff, Int maxoff) @@ -1057,6 +1061,8 @@ Bool guest_arm_state_requires_precise_mem_exns ( Int minoff, if (maxoff < sp_min || minoff > sp_max) { /* no overlap with sp */ + if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess) + return False; // We only need to check stack pointer. } else { return True; } diff --git a/VEX/priv/guest_mips_helpers.c b/VEX/priv/guest_mips_helpers.c index d992b9cd36..6951ea7161 100644 --- a/VEX/priv/guest_mips_helpers.c +++ b/VEX/priv/guest_mips_helpers.c @@ -35,6 +35,7 @@ #include "libvex.h" #include "main_util.h" +#include "main_globals.h" #include "guest_generic_bb_to_IR.h" #include "guest_mips_defs.h" @@ -160,9 +161,11 @@ void LibVEX_GuestMIPS32_initialise( /*OUT*/ VexGuestMIPS32State * vex_state) /* Figure out if any part of the guest state contained in minoff .. maxoff requires precise memory exceptions. If in doubt return - True (but this is generates significantly slower code). + True (but this generates significantly slower code). We enforce precise exns for guest SP, PC. + + Only SP is needed in mode VexRegUpdSpAtMemAccess. */ Bool guest_mips32_state_requires_precise_mem_exns(Int minoff, Int maxoff) { @@ -173,6 +176,8 @@ Bool guest_mips32_state_requires_precise_mem_exns(Int minoff, Int maxoff) if (maxoff < sp_min || minoff > sp_max) { /* no overlap with sp */ + if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess) + return False; // We only need to check stack pointer. } else { return True; } diff --git a/VEX/priv/guest_ppc_helpers.c b/VEX/priv/guest_ppc_helpers.c index 6ffb1eabfd..d945602a30 100644 --- a/VEX/priv/guest_ppc_helpers.c +++ b/VEX/priv/guest_ppc_helpers.c @@ -41,6 +41,7 @@ #include "libvex.h" #include "main_util.h" +#include "main_globals.h" #include "guest_generic_bb_to_IR.h" #include "guest_ppc_defs.h" @@ -696,6 +697,8 @@ void LibVEX_GuestPPC64_initialise ( /*OUT*/VexGuestPPC64State* vex_state ) minimum needed to extract correct stack backtraces from ppc code. [[NB: not sure if keeping LR up to date is actually necessary.]] + + Only R1 is needed in mode VexRegUpdSpAtMemAccess. */ Bool guest_ppc32_state_requires_precise_mem_exns ( Int minoff, Int maxoff ) @@ -707,14 +710,16 @@ Bool guest_ppc32_state_requires_precise_mem_exns ( Int minoff, Int cia_min = offsetof(VexGuestPPC32State, guest_CIA); Int cia_max = cia_min + 4 - 1; - if (maxoff < lr_min || minoff > lr_max) { - /* no overlap with LR */ + if (maxoff < r1_min || minoff > r1_max) { + /* no overlap with R1 */ + if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess) + return False; // We only need to check stack pointer. } else { return True; } - if (maxoff < r1_min || minoff > r1_max) { - /* no overlap with R1 */ + if (maxoff < lr_min || minoff > lr_max) { + /* no overlap with LR */ } else { return True; } @@ -744,14 +749,16 @@ Bool guest_ppc64_state_requires_precise_mem_exns ( Int minoff, Int cia_min = offsetof(VexGuestPPC64State, guest_CIA); Int cia_max = cia_min + 8 - 1; - if (maxoff < lr_min || minoff > lr_max) { - /* no overlap with LR */ + if (maxoff < r1_min || minoff > r1_max) { + /* no overlap with R1 */ + if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess) + return False; // We only need to check stack pointer. } else { return True; } - if (maxoff < r1_min || minoff > r1_max) { - /* no overlap with R1 */ + if (maxoff < lr_min || minoff > lr_max) { + /* no overlap with LR */ } else { return True; } diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c index 08deb64d71..ad726f7011 100644 --- a/VEX/priv/guest_s390_helpers.c +++ b/VEX/priv/guest_s390_helpers.c @@ -38,6 +38,7 @@ #include "libvex_s390x_common.h" #include "main_util.h" +#include "main_globals.h" #include "guest_generic_bb_to_IR.h" #include "guest_s390_defs.h" @@ -148,7 +149,7 @@ LibVEX_GuestS390X_initialise(VexGuestS390XState *state) /* Figure out if any part of the guest state contained in minoff .. maxoff requires precise memory exceptions. If in doubt return - True (but this is generates significantly slower code). */ + True (but this generates significantly slower code). */ Bool guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff) { @@ -161,14 +162,16 @@ guest_s390x_state_requires_precise_mem_exns(Int minoff, Int maxoff) Int ia_min = S390X_GUEST_OFFSET(guest_IA); Int ia_max = ia_min + 8 - 1; - if (maxoff < lr_min || minoff > lr_max) { - /* No overlap with LR */ + if (maxoff < sp_min || minoff > sp_max) { + /* No overlap with SP */ + if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess) + return False; // We only need to check stack pointer. } else { return True; } - if (maxoff < sp_min || minoff > sp_max) { - /* No overlap with SP */ + if (maxoff < lr_min || minoff > lr_max) { + /* No overlap with LR */ } else { return True; } diff --git a/VEX/priv/guest_x86_helpers.c b/VEX/priv/guest_x86_helpers.c index 62c9dd1afb..df9c72d649 100644 --- a/VEX/priv/guest_x86_helpers.c +++ b/VEX/priv/guest_x86_helpers.c @@ -40,6 +40,7 @@ #include "libvex.h" #include "main_util.h" +#include "main_globals.h" #include "guest_generic_bb_to_IR.h" #include "guest_x86_defs.h" #include "guest_generic_x87.h" @@ -2739,11 +2740,13 @@ void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state ) /* Figure out if any part of the guest state contained in minoff .. maxoff requires precise memory exceptions. If in doubt return - True (but this is generates significantly slower code). + True (but this generates significantly slower code). By default we enforce precise exns for guest %ESP, %EBP and %EIP only. These are the minimum needed to extract correct stack backtraces from x86 code. + + Only %ESP is needed in mode VexRegUpdSpAtMemAccess. */ Bool guest_x86_state_requires_precise_mem_exns ( Int minoff, Int maxoff) @@ -2755,14 +2758,16 @@ Bool guest_x86_state_requires_precise_mem_exns ( Int minoff, Int eip_min = offsetof(VexGuestX86State, guest_EIP); Int eip_max = eip_min + 4 - 1; - if (maxoff < ebp_min || minoff > ebp_max) { - /* no overlap with ebp */ + if (maxoff < esp_min || minoff > esp_max) { + /* no overlap with esp */ + if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess) + return False; // We only need to check stack pointer. } else { return True; } - if (maxoff < esp_min || minoff > esp_max) { - /* no overlap with esp */ + if (maxoff < ebp_min || minoff > ebp_max) { + /* no overlap with ebp */ } else { return True; } diff --git a/VEX/priv/ir_opt.c b/VEX/priv/ir_opt.c index 6d93b632ca..206f80cf93 100644 --- a/VEX/priv/ir_opt.c +++ b/VEX/priv/ir_opt.c @@ -69,6 +69,13 @@ not marked as being read or modified by the helper cannot be assumed to be up-to-date at the point where the helper is called. + * If iropt_register_updates == VexRegUpdSpAtMemAccess : + The guest state is only up to date only as explained above + (i.e. at SB exits and as specified by dirty helper call). + Also, the stack pointer register is up to date at memory + exception points (as this is needed for the stack extension + logic in m_signals.c). + * If iropt_register_updates == VexRegUpdUnwindregsAtMemAccess : Immediately prior to any load or store, those parts of the guest state marked as requiring precise exceptions will be up to date. @@ -76,11 +83,11 @@ not marked as requiring precise exceptions cannot be assumed to be up-to-date at the point of the load/store. - If iropt_register_updates == VexRegUpdAllregsAtMemAccess: + * If iropt_register_updates == VexRegUpdAllregsAtMemAccess: Same as minimal, but all the guest state is up to date at memory exception points. - If iropt_register_updates == VexRegUpdAllregsAtEachInsn : + * If iropt_register_updates == VexRegUpdAllregsAtEachInsn : Guest state is up to date at each instruction. The relative order of loads and stores (including loads/stores of @@ -778,7 +785,7 @@ static void handle_gets_Stmt ( } if (memRW) { - /* This statement accesses memory. So we need to dump all parts + /* This statement accesses memory. So we might need to dump all parts of the environment corresponding to guest state that may not be reordered with respect to memory references. That means at least the stack pointer. */ @@ -789,6 +796,12 @@ static void handle_gets_Stmt ( for (j = 0; j < env->used; j++) env->inuse[j] = False; break; + case VexRegUpdSpAtMemAccess: + /* We need to dump the stack pointer + (needed for stack extension in m_signals.c). + preciseMemExnsFn will use vex_control.iropt_register_updates + to verify only the sp is to be checked. */ + /* fallthrough */ case VexRegUpdUnwindregsAtMemAccess: for (j = 0; j < env->used; j++) { if (!env->inuse[j]) @@ -837,9 +850,7 @@ static void redundant_put_removal_BB ( IRStmt* st; UInt key = 0; /* keep gcc -O happy */ - vassert - (vex_control.iropt_register_updates == VexRegUpdUnwindregsAtMemAccess - || vex_control.iropt_register_updates == VexRegUpdAllregsAtMemAccess); + vassert(vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn); HashHW* env = newHHW(); @@ -3958,9 +3969,7 @@ void do_redundant_PutI_elimination ( IRSB* bb ) Bool delete; IRStmt *st, *stj; - vassert - (vex_control.iropt_register_updates == VexRegUpdUnwindregsAtMemAccess - || vex_control.iropt_register_updates == VexRegUpdAllregsAtMemAccess); + vassert(vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn); for (i = 0; i < bb->stmts_used; i++) { st = bb->stmts[i]; @@ -5201,7 +5210,7 @@ IRSB* cheap_transformations ( ppIRSB(bb); } - if (vex_control.iropt_register_updates != VexRegUpdAllregsAtEachInsn) { + if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) { redundant_put_removal_BB ( bb, preciseMemExnsFn ); } if (iropt_verbose) { @@ -5241,7 +5250,7 @@ IRSB* expensive_transformations( IRSB* bb ) (void)do_cse_BB( bb ); collapse_AddSub_chains_BB( bb ); do_redundant_GetI_elimination( bb ); - if (vex_control.iropt_register_updates != VexRegUpdAllregsAtEachInsn) { + if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) { do_redundant_PutI_elimination( bb ); } do_deadcode_BB( bb ); @@ -5392,7 +5401,7 @@ IRSB* do_iropt_BB( work extra hard to get rid of it. */ bb = cprop_BB(bb); bb = spec_helpers_BB ( bb, specHelper ); - if (vex_control.iropt_register_updates != VexRegUpdAllregsAtEachInsn) { + if (vex_control.iropt_register_updates < VexRegUpdAllregsAtEachInsn) { redundant_put_removal_BB ( bb, preciseMemExnsFn ); } do_cse_BB( bb ); diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index 9d7fcb092c..a66a399801 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -311,6 +311,10 @@ void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi ); /* VexRegisterUpdates specifies when to ensure that the guest state is up to date. + VexRegUpdSpAtMemAccess : all registers are updated at superblock + exits, SP is up to date at memory exception points. The SP is described + by the arch specific functions guest__state_requires_precise_mem_exns. + VexRegUpdUnwindregsAtMemAccess : registers needed to make a stack trace are up to date at memory exception points. Typically, these are PC/SP/FP. The minimal registers are described by the arch specific functions @@ -320,7 +324,8 @@ void LibVEX_default_VexAbiInfo ( /*OUT*/VexAbiInfo* vbi ); points. VexRegUpdAllregsAtEachInsn : all registers up to date at each instruction. */ -typedef enum { VexRegUpdUnwindregsAtMemAccess, +typedef enum { VexRegUpdSpAtMemAccess, + VexRegUpdUnwindregsAtMemAccess, VexRegUpdAllregsAtMemAccess, VexRegUpdAllregsAtEachInsn } VexRegisterUpdates;