diff options
Diffstat (limited to 'src/vm/gccover.h')
-rw-r--r-- | src/vm/gccover.h | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/vm/gccover.h b/src/vm/gccover.h new file mode 100644 index 0000000000..b2dedefa31 --- /dev/null +++ b/src/vm/gccover.h @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +#ifndef __GCCOVER_H__ +#define __GCCOVER_H__ + +#ifdef HAVE_GCCOVER + +/****************************************************************************/ +/* GCCOverageInfo holds the state of which instructions have been visited by + a GC and which ones have not */ + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4200 ) // zero-sized array +#endif // _MSC_VER + +class GCCoverageInfo { +public: + IJitManager::MethodRegionInfo methodRegion; + BYTE* curInstr; // The last instruction that was able to execute + MethodDesc* lastMD; // Used to quickly figure out the culprite + + // Following 6 variables are for prolog / epilog walking coverage + ICodeManager* codeMan; // CodeMan for this method + GCInfoToken gcInfoToken; // gcInfo for this method + + Thread* callerThread; // Thread associated with context callerRegs + T_CONTEXT callerRegs; // register state when method was entered + unsigned gcCount; // GC count at the time we caputured the regs + bool doingEpilogChecks; // are we doing epilog unwind checks? (do we care about callerRegs?) + + enum { hasExecutedSize = 4 }; + unsigned hasExecuted[hasExecutedSize]; + unsigned totalCount; + + union + { + BYTE savedCode[0]; // really variable sized + // Note that DAC doesn't marshal the entire byte array automatically. + // Any client of this field needs to get the TADDR of this field and + // marshal over the bytes properly. + }; + + // Sloppy bitsets (will wrap, and not threadsafe) but best effort is OK + // since we just need half decent coverage. + BOOL IsBitSetForOffset(unsigned offset) { + unsigned dword = hasExecuted[(offset >> 5) % hasExecutedSize]; + return(dword & (1 << (offset & 0x1F))); + } + + void SetBitForOffset(unsigned offset) { + unsigned* dword = &hasExecuted[(offset >> 5) % hasExecutedSize]; + *dword |= (1 << (offset & 0x1F)) ; + } + + void SprinkleBreakpoints(BYTE * saveAddr, PCODE codeStart, size_t codeSize, size_t regionOffsetAdj, BOOL fZapped); + +}; + +#ifdef _MSC_VER +#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) +#define INTERRUPT_INSTR_CALL 0xFA // X86 CLI instruction +#define INTERRUPT_INSTR_PROTECT_RET 0xFB // X86 STI instruction + +#elif defined(_TARGET_ARM_) + +// 16-bit illegal instructions which will cause exception and cause +// control to go to GcStress codepath +#define INTERRUPT_INSTR 0xde00 +#define INTERRUPT_INSTR_CALL 0xde01 +#define INTERRUPT_INSTR_PROTECT_RET 0xde02 + +// 32-bit illegal instructions. It is necessary to replace a 16-bit instruction +// with a 16-bit illegal instruction, and a 32-bit instruction with a 32-bit +// illegal instruction, to make GC stress with the "IT" instruction work, since +// it counts the number of instructions that follow it, so we can't change that +// number by replacing a 32-bit instruction with a 16-bit illegal instruction +// followed by 16 bits of junk that might end up being a legal instruction. +// Use the "Permanently UNDEFINED" section in the "ARM Architecture Reference Manual", +// section A6.3.4 "Branches and miscellaneous control" table. +// Note that we write these as a single 32-bit write, not two 16-bit writes, so the values +// need to be arranged as the ARM decoder wants them, with the high-order halfword first +// (in little-endian order). +#define INTERRUPT_INSTR_32 0xa001f7f0 // 0xf7f0a001 +#define INTERRUPT_INSTR_CALL_32 0xa002f7f0 // 0xf7f0a002 +#define INTERRUPT_INSTR_PROTECT_RET_32 0xa003f7f0 // 0xf7f0a003 + +#elif defined(_TARGET_ARM64_) + +// The following encodings are undefined. They fall into section C4.5.8 - Data processing (2 source) of +// "Arm Architecture Reference Manual ARMv8" +// +#define INTERRUPT_INSTR 0xBADC0DE0 +#define INTERRUPT_INSTR_CALL 0xBADC0DE1 +#define INTERRUPT_INSTR_PROTECT_RET 0xBADC0DE2 + +#endif // _TARGET_* + +#endif // HAVE_GCCOVER + +#endif // !__GCCOVER_H__ |