#include "gcinfodecoder.h"
#endif
+#ifdef HAVE_GCCOVER
+#include "gccover.h"
+#endif // HAVE_GCCOVER
+
#include "argdestination.h"
#define X86_INSTR_W_TEST_ESP 0x4485 // test [esp+N], eax
bool IsMarkerInstr(BYTE val)
{
- SUPPORTS_DAC;
+ SUPPORTS_DAC;
+
#ifdef _DEBUG
- return (val == X86_INSTR_INT3) || // Debugger might stomp with an int3
- (val == X86_INSTR_HLT && GCStress<cfg_any>::IsEnabled()); // GcCover might stomp with a Hlt
-#else
+ if (val == X86_INSTR_INT3)
+ {
+ return true;
+ }
+#ifdef HAVE_GCCOVER
+ else // GcCover might have stomped on the instruction
+ {
+ if (GCStress<cfg_any>::IsEnabled())
+ {
+ if (IsGcCoverageInterruptInstructionVal(val))
+ {
+ return true;
+ }
+ }
+ }
+#endif // HAVE_GCCOVER
+#endif // _DEBUG
+
return false;
-#endif
}
/* Check if the given instruction opcode is the one we expect.
return nullptr;
}
-
bool IsGcCoverageInterruptInstruction(PBYTE instrPtr)
{
+ UINT32 instrVal;
+
#if defined(_TARGET_ARM64_)
- UINT32 instrVal = *reinterpret_cast<UINT32*>(instrPtr);
- switch (instrVal)
- {
- case INTERRUPT_INSTR:
- case INTERRUPT_INSTR_CALL:
- case INTERRUPT_INSTR_PROTECT_RET:
- return true;
- default:
- return false;
- }
+ instrVal = *reinterpret_cast<UINT32*>(instrPtr);
#elif defined(_TARGET_ARM_)
-
size_t instrLen = GetARMInstructionLength(instrPtr);
if (instrLen == 2)
{
- UINT16 instrVal = *reinterpret_cast<UINT16*>(instrPtr);
- switch (instrVal)
- {
- case INTERRUPT_INSTR:
- case INTERRUPT_INSTR_CALL:
- case INTERRUPT_INSTR_PROTECT_RET:
- return true;
- default:
- return false;
- }
+ instrVal = *reinterpret_cast<UINT16*>(instrPtr);
}
else
{
- _ASSERTE(instrLen == 4);
- UINT32 instrVal = *reinterpret_cast<UINT32*>(instrPtr);
- switch (instrVal)
- {
- case INTERRUPT_INSTR_32:
- case INTERRUPT_INSTR_CALL_32:
- case INTERRUPT_INSTR_PROTECT_RET_32:
- return true;
- default:
- return false;
- }
+ instrVal = *reinterpret_cast<UINT32*>(instrPtr);
}
#else // x64 and x86
- UINT8 instrVal = *reinterpret_cast<UINT8*>(instrPtr);
- switch (instrVal)
- {
- case INTERRUPT_INSTR:
- case INTERRUPT_INSTR_CALL:
- case INTERRUPT_INSTR_PROTECT_FIRST_RET:
- case INTERRUPT_INSTR_PROTECT_SECOND_RET:
- case INTERRUPT_INSTR_PROTECT_BOTH_RET:
- return true;
- default:
- return false;
- }
+ instrVal = *instrPtr;
#endif
+
+ return IsGcCoverageInterruptInstructionVal(instrVal);
}
bool IsOriginalInstruction(PBYTE instrPtr, GCCoverageInfo* gcCover, DWORD offset)
{
instructionIsACallThroughRegister = TRUE;
}
-#endif
+#endif // _TARGET_XXXX_
// safe point must always be after a call instruction
// and cannot be both call by register & immediate
// The safe points are also marked at jump calls( a special variant of
*((WORD*)instrPtr - 1) = INTERRUPT_INSTR_CALL;
#elif defined(_TARGET_ARM64_)
*((DWORD*)instrPtr - 1) = INTERRUPT_INSTR_CALL;
-#endif
+#endif // _TARGET_XXXX_
}
else if(instructionIsACallThroughImmediate)
{
}
}
}
-#endif
+#endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
//Replaces the provided interruptible range with corresponding 2 or 4 byte gcStress illegal instruction
bool replaceInterruptibleRangesWithGcStressInstr (UINT32 startOffset, UINT32 stopOffset, LPVOID pGCCover)
PBYTE instrPtr = rangeStart;
while(instrPtr < rangeStop)
{
-
// The instruction about to be replaced cannot already be a gcstress instruction
_ASSERTE(!IsGcCoverageInterruptInstruction(instrPtr));
#if defined(_TARGET_ARM_)
if(!isCallToStopForGCJitHelper(instrPtr))
*((DWORD*)instrPtr) = INTERRUPT_INSTR;
instrPtr += 4;
-#endif
+#endif // TARGET_XXXX_
}
}
return FALSE;
}
-#endif
+#endif // defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
// Is this a call instruction to JIT_RareDisableHelper()
// We cannot insert GCStress instruction at this call
Thread *pThread = GetThread();
-
if (!IsGcCoverageInterruptInstruction(instrPtr))
{
// This assert can fail if another thread changed original instruction to
#pragma warning(pop)
#endif // _MSC_VER
-
#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
#define INTERRUPT_INSTR 0xF4 // X86 HLT instruction (any 1 byte illegal instruction will do)
#endif // _TARGET_*
+// The body of this method is in this header file to allow
+// mscordaccore.dll to link without getting an unsat symbol
+//
+inline bool IsGcCoverageInterruptInstructionVal(UINT32 instrVal)
+{
+#if defined(_TARGET_ARM64_)
+
+ switch (instrVal)
+ {
+ case INTERRUPT_INSTR:
+ case INTERRUPT_INSTR_CALL:
+ case INTERRUPT_INSTR_PROTECT_RET:
+ return true;
+ default:
+ return false;
+ }
+
+#elif defined(_TARGET_ARM_)
+
+ UINT16 instrVal16 = static_cast<UINT16>(instrVal);
+ size_t instrLen = GetARMInstructionLength(instrVal16);
+
+ if (instrLen == 2)
+ {
+ switch (instrVal16)
+ {
+ case INTERRUPT_INSTR:
+ case INTERRUPT_INSTR_CALL:
+ case INTERRUPT_INSTR_PROTECT_RET:
+ return true;
+ default:
+ return false;
+ }
+ }
+ else
+ {
+ _ASSERTE(instrLen == 4);
+
+ switch (instrVal)
+ {
+ case INTERRUPT_INSTR_32:
+ case INTERRUPT_INSTR_CALL_32:
+ case INTERRUPT_INSTR_PROTECT_RET_32:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+#else // x64 and x86
+
+ switch (instrVal)
+ {
+ case INTERRUPT_INSTR:
+ case INTERRUPT_INSTR_CALL:
+ case INTERRUPT_INSTR_PROTECT_FIRST_RET:
+ case INTERRUPT_INSTR_PROTECT_SECOND_RET:
+ case INTERRUPT_INSTR_PROTECT_BOTH_RET:
+ return true;
+ default:
+ return false;
+ }
+
+#endif // _TARGET_XXXX_
+}
+
+bool IsGcCoverageInterruptInstruction(PBYTE instrPtr);
+bool IsGcCoverageInterrupt(LPVOID ip);
+
#endif // HAVE_GCCOVER
#endif // !__GCCOVER_H__