#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"
/* 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)
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;
}
#include "libvex.h"
#include "main_util.h"
+#include "main_globals.h"
#include "guest_generic_bb_to_IR.h"
#include "guest_arm_defs.h"
/* 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)
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;
}
#include "libvex.h"
#include "main_util.h"
+#include "main_globals.h"
#include "guest_generic_bb_to_IR.h"
#include "guest_mips_defs.h"
/* 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)
{
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;
}
#include "libvex.h"
#include "main_util.h"
+#include "main_globals.h"
#include "guest_generic_bb_to_IR.h"
#include "guest_ppc_defs.h"
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 )
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;
}
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;
}
#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"
/* 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)
{
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;
}
#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"
/* 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)
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;
}
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.
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
}
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. */
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])
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();
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];
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) {
(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 );
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 );
/* 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_<arch>_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
points.
VexRegUpdAllregsAtEachInsn : all registers up to date at each instruction. */
-typedef enum { VexRegUpdUnwindregsAtMemAccess,
+typedef enum { VexRegUpdSpAtMemAccess,
+ VexRegUpdUnwindregsAtMemAccess,
VexRegUpdAllregsAtMemAccess,
VexRegUpdAllregsAtEachInsn } VexRegisterUpdates;