MethodDesc* AsMethodDesc(size_t addr);
static SLOT getTargetOfCall(SLOT instrPtr, PCONTEXT regs, SLOT*nextInstr);
+bool isCallToStopForGCJitHelper(SLOT instrPtr);
#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
static void replaceSafePointInstructionWithGcStressInstr(UINT32 safePointOffset, LPVOID codeStart);
static bool replaceInterruptibleRangesWithGcStressInstr (UINT32 startOffset, UINT32 stopOffset, LPVOID codeStart);
if (instrLen == 2)
*((WORD*)instrPtr) = INTERRUPT_INSTR;
else
- *((DWORD*)instrPtr) = INTERRUPT_INSTR_32;
+ {
+ // Do not replace with gcstress interrupt instruction at call to JIT_RareDisableHelper
+ if(!isCallToStopForGCJitHelper(instrPtr))
+ *((DWORD*)instrPtr) = INTERRUPT_INSTR_32;
+ }
instrPtr += instrLen;
#elif defined(_TARGET_ARM64_)
*((DWORD*)instrPtr) != INTERRUPT_INSTR_CALL &&
*((DWORD*)instrPtr) != INTERRUPT_INSTR_PROTECT_RET);
}
-
- *((DWORD*)instrPtr) = INTERRUPT_INSTR;
+
+ // Do not replace with gcstress interrupt instruction at call to JIT_RareDisableHelper
+ if(!isCallToStopForGCJitHelper(instrPtr))
+ *((DWORD*)instrPtr) = INTERRUPT_INSTR;
instrPtr += 4;
#endif
}
#endif
+// Is this a call instruction to JIT_RareDisableHelper()
+// We cannot insert GCStress instruction at this call
+// For arm64 & arm (R2R) call to jithelpers happens via a stub.
+// For other architectures call does not happen via stub.
+// For other architecures we can get the target directly by calling getTargetOfCall().
+// This is not the case for arm64/arm so need to decode the stub
+// instruction to find the actual jithelper target.
+// For other architecture we detect call to JIT_RareDisableHelper
+// in function OnGcCoverageInterrupt() since getTargetOfCall() can
+// get the actual jithelper target.
+bool isCallToStopForGCJitHelper(SLOT instrPtr)
+{
+#if defined(_TARGET_ARM64_)
+ if (((*reinterpret_cast<DWORD*>(instrPtr)) & 0xFC000000) == 0x94000000) // Do we have a BL instruction?
+ {
+ // call through immediate
+ int imm26 = ((*((DWORD*)instrPtr)) & 0x03FFFFFF)<<2;
+ // SignExtend the immediate value.
+ imm26 = (imm26 << 4) >> 4;
+ DWORD* target = (DWORD*) (instrPtr + imm26);
+ // Call to jithelpers happens via jumpstub
+ if(*target == 0x58000050 /* ldr xip0, PC+8*/ && *(target+1) == 0xd61f0200 /* br xip0 */)
+ {
+ // get the actual jithelper target
+ target = *(((DWORD**)target) + 1);
+ if((TADDR)target == GetEEFuncEntryPoint(JIT_RareDisableHelper))
+ {
+ return true;
+ }
+ }
+ }
+#elif defined(_TARGET_ARM_)
+ if((instrPtr[1] & 0xf8) == 0xf0 && (instrPtr[3] & 0xc0) == 0xc0) // call using imm
+ {
+ int imm32 = GetThumb2BlRel24((UINT16 *)instrPtr);
+ WORD* target = (WORD*) (instrPtr + 4 + imm32);
+ // Is target a stub
+ if(*target == 0xf8df && *(target+1) == 0xf000) // ldr pc, [pc+4]
+ {
+ //get actual target
+ target = *((WORD**)target + 1);
+ if((TADDR)target == GetEEFuncEntryPoint(JIT_RareDisableHelper))
+ {
+ return true;
+ }
+ }
+ }
+#endif
+ return false;
+}
+
static size_t getRegVal(unsigned regNum, PCONTEXT regs)
{
return *getRegAddr(regNum, regs);