1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5
6
7#ifndef __GCCOVER_H__
8#define __GCCOVER_H__
9
10#ifdef HAVE_GCCOVER
11
12/****************************************************************************/
13/* GCCOverageInfo holds the state of which instructions have been visited by
14 a GC and which ones have not */
15
16#ifdef _MSC_VER
17#pragma warning(push)
18#pragma warning(disable : 4200 ) // zero-sized array
19#endif // _MSC_VER
20
21class GCCoverageInfo {
22public:
23 IJitManager::MethodRegionInfo methodRegion;
24 BYTE* curInstr; // The last instruction that was able to execute
25 MethodDesc* lastMD; // Used to quickly figure out the culprite
26
27 // Following 6 variables are for prolog / epilog walking coverage
28 ICodeManager* codeMan; // CodeMan for this method
29 GCInfoToken gcInfoToken; // gcInfo for this method
30
31 Thread* callerThread; // Thread associated with context callerRegs
32 T_CONTEXT callerRegs; // register state when method was entered
33 unsigned gcCount; // GC count at the time we caputured the regs
34 bool doingEpilogChecks; // are we doing epilog unwind checks? (do we care about callerRegs?)
35
36 enum { hasExecutedSize = 4 };
37 unsigned hasExecuted[hasExecutedSize];
38 unsigned totalCount;
39
40 union
41 {
42 BYTE savedCode[0]; // really variable sized
43 // Note that DAC doesn't marshal the entire byte array automatically.
44 // Any client of this field needs to get the TADDR of this field and
45 // marshal over the bytes properly.
46 };
47
48 // Sloppy bitsets (will wrap, and not threadsafe) but best effort is OK
49 // since we just need half decent coverage.
50 BOOL IsBitSetForOffset(unsigned offset) {
51 unsigned dword = hasExecuted[(offset >> 5) % hasExecutedSize];
52 return(dword & (1 << (offset & 0x1F)));
53 }
54
55 void SetBitForOffset(unsigned offset) {
56 unsigned* dword = &hasExecuted[(offset >> 5) % hasExecutedSize];
57 *dword |= (1 << (offset & 0x1F)) ;
58 }
59
60 void SprinkleBreakpoints(BYTE * saveAddr, PCODE codeStart, size_t codeSize, size_t regionOffsetAdj, BOOL fZapped);
61
62};
63
64#ifdef _MSC_VER
65#pragma warning(pop)
66#endif // _MSC_VER
67
68
69#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
70
71#define INTERRUPT_INSTR 0xF4 // X86 HLT instruction (any 1 byte illegal instruction will do)
72#define INTERRUPT_INSTR_CALL 0xFA // X86 CLI instruction
73#define INTERRUPT_INSTR_PROTECT_RET 0xFB // X86 STI instruction
74
75#elif defined(_TARGET_ARM_)
76
77// 16-bit illegal instructions which will cause exception and cause
78// control to go to GcStress codepath
79#define INTERRUPT_INSTR 0xde00
80#define INTERRUPT_INSTR_CALL 0xde03 // 0xde01 generates SIGTRAP (breakpoint) instead of SIGILL on Unix
81#define INTERRUPT_INSTR_PROTECT_RET 0xde02
82
83// 32-bit illegal instructions. It is necessary to replace a 16-bit instruction
84// with a 16-bit illegal instruction, and a 32-bit instruction with a 32-bit
85// illegal instruction, to make GC stress with the "IT" instruction work, since
86// it counts the number of instructions that follow it, so we can't change that
87// number by replacing a 32-bit instruction with a 16-bit illegal instruction
88// followed by 16 bits of junk that might end up being a legal instruction.
89// Use the "Permanently UNDEFINED" section in the "ARM Architecture Reference Manual",
90// section A6.3.4 "Branches and miscellaneous control" table.
91// Note that we write these as a single 32-bit write, not two 16-bit writes, so the values
92// need to be arranged as the ARM decoder wants them, with the high-order halfword first
93// (in little-endian order).
94#define INTERRUPT_INSTR_32 0xa001f7f0 // 0xf7f0a001
95#define INTERRUPT_INSTR_CALL_32 0xa002f7f0 // 0xf7f0a002
96#define INTERRUPT_INSTR_PROTECT_RET_32 0xa003f7f0 // 0xf7f0a003
97
98#elif defined(_TARGET_ARM64_)
99
100// The following encodings are undefined. They fall into section C4.5.8 - Data processing (2 source) of
101// "Arm Architecture Reference Manual ARMv8"
102//
103#define INTERRUPT_INSTR 0xBADC0DE0
104#define INTERRUPT_INSTR_CALL 0xBADC0DE1
105#define INTERRUPT_INSTR_PROTECT_RET 0xBADC0DE2
106
107#endif // _TARGET_*
108
109#endif // HAVE_GCCOVER
110
111#endif // !__GCCOVER_H__
112