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 | // Keep in sync with https://github.com/dotnet/corert/blob/master/src/Native/ObjWriter/cordebuginfo.h |
7 | // |
8 | |
9 | /**********************************************************************************/ |
10 | // DebugInfo types shared by JIT-EE interface and EE-Debugger interface |
11 | |
12 | class ICorDebugInfo |
13 | { |
14 | public: |
15 | /*----------------------------- Boundary-info ---------------------------*/ |
16 | |
17 | enum MappingTypes |
18 | { |
19 | NO_MAPPING = -1, |
20 | PROLOG = -2, |
21 | EPILOG = -3, |
22 | MAX_MAPPING_VALUE = -3 // Sentinal value. This should be set to the largest magnitude value in the enum |
23 | // so that the compression routines know the enum's range. |
24 | }; |
25 | |
26 | enum BoundaryTypes |
27 | { |
28 | NO_BOUNDARIES = 0x00, // No implicit boundaries |
29 | STACK_EMPTY_BOUNDARIES = 0x01, // Boundary whenever the IL evaluation stack is empty |
30 | NOP_BOUNDARIES = 0x02, // Before every CEE_NOP instruction |
31 | CALL_SITE_BOUNDARIES = 0x04, // Before every CEE_CALL, CEE_CALLVIRT, etc instruction |
32 | |
33 | // Set of boundaries that debugger should always reasonably ask the JIT for. |
34 | DEFAULT_BOUNDARIES = STACK_EMPTY_BOUNDARIES | NOP_BOUNDARIES | CALL_SITE_BOUNDARIES |
35 | }; |
36 | |
37 | // Note that SourceTypes can be OR'd together - it's possible that |
38 | // a sequence point will also be a stack_empty point, and/or a call site. |
39 | // The debugger will check to see if a boundary offset's source field & |
40 | // SEQUENCE_POINT is true to determine if the boundary is a sequence point. |
41 | |
42 | enum SourceTypes |
43 | { |
44 | SOURCE_TYPE_INVALID = 0x00, // To indicate that nothing else applies |
45 | SEQUENCE_POINT = 0x01, // The debugger asked for it. |
46 | STACK_EMPTY = 0x02, // The stack is empty here |
47 | CALL_SITE = 0x04, // This is a call site. |
48 | NATIVE_END_OFFSET_UNKNOWN = 0x08, // Indicates a epilog endpoint |
49 | CALL_INSTRUCTION = 0x10 // The actual instruction of a call. |
50 | |
51 | }; |
52 | |
53 | struct OffsetMapping |
54 | { |
55 | DWORD nativeOffset; |
56 | DWORD ilOffset; |
57 | SourceTypes source; // The debugger needs this so that |
58 | // we don't put Edit and Continue breakpoints where |
59 | // the stack isn't empty. We can put regular breakpoints |
60 | // there, though, so we need a way to discriminate |
61 | // between offsets. |
62 | }; |
63 | |
64 | /*------------------------------ Var-info -------------------------------*/ |
65 | |
66 | // Note: The debugger needs to target register numbers on platforms other than which the debugger itself |
67 | // is running. To this end it maintains its own values for REGNUM_SP and REGNUM_AMBIENT_SP across multiple |
68 | // platforms. So any change here that may effect these values should be reflected in the definitions |
69 | // contained in debug/inc/DbgIPCEvents.h. |
70 | enum RegNum |
71 | { |
72 | #ifdef _TARGET_X86_ |
73 | REGNUM_EAX, |
74 | REGNUM_ECX, |
75 | REGNUM_EDX, |
76 | REGNUM_EBX, |
77 | REGNUM_ESP, |
78 | REGNUM_EBP, |
79 | REGNUM_ESI, |
80 | REGNUM_EDI, |
81 | #elif _TARGET_ARM_ |
82 | REGNUM_R0, |
83 | REGNUM_R1, |
84 | REGNUM_R2, |
85 | REGNUM_R3, |
86 | REGNUM_R4, |
87 | REGNUM_R5, |
88 | REGNUM_R6, |
89 | REGNUM_R7, |
90 | REGNUM_R8, |
91 | REGNUM_R9, |
92 | REGNUM_R10, |
93 | REGNUM_R11, |
94 | REGNUM_R12, |
95 | REGNUM_SP, |
96 | REGNUM_LR, |
97 | REGNUM_PC, |
98 | #elif _TARGET_ARM64_ |
99 | REGNUM_X0, |
100 | REGNUM_X1, |
101 | REGNUM_X2, |
102 | REGNUM_X3, |
103 | REGNUM_X4, |
104 | REGNUM_X5, |
105 | REGNUM_X6, |
106 | REGNUM_X7, |
107 | REGNUM_X8, |
108 | REGNUM_X9, |
109 | REGNUM_X10, |
110 | REGNUM_X11, |
111 | REGNUM_X12, |
112 | REGNUM_X13, |
113 | REGNUM_X14, |
114 | REGNUM_X15, |
115 | REGNUM_X16, |
116 | REGNUM_X17, |
117 | REGNUM_X18, |
118 | REGNUM_X19, |
119 | REGNUM_X20, |
120 | REGNUM_X21, |
121 | REGNUM_X22, |
122 | REGNUM_X23, |
123 | REGNUM_X24, |
124 | REGNUM_X25, |
125 | REGNUM_X26, |
126 | REGNUM_X27, |
127 | REGNUM_X28, |
128 | REGNUM_FP, |
129 | REGNUM_LR, |
130 | REGNUM_SP, |
131 | REGNUM_PC, |
132 | #elif _TARGET_AMD64_ |
133 | REGNUM_RAX, |
134 | REGNUM_RCX, |
135 | REGNUM_RDX, |
136 | REGNUM_RBX, |
137 | REGNUM_RSP, |
138 | REGNUM_RBP, |
139 | REGNUM_RSI, |
140 | REGNUM_RDI, |
141 | REGNUM_R8, |
142 | REGNUM_R9, |
143 | REGNUM_R10, |
144 | REGNUM_R11, |
145 | REGNUM_R12, |
146 | REGNUM_R13, |
147 | REGNUM_R14, |
148 | REGNUM_R15, |
149 | #else |
150 | PORTABILITY_WARNING("Register numbers not defined on this platform" ) |
151 | #endif |
152 | REGNUM_COUNT, |
153 | REGNUM_AMBIENT_SP, // ambient SP support. Ambient SP is the original SP in the non-BP based frame. |
154 | // Ambient SP should not change even if there are push/pop operations in the method. |
155 | |
156 | #ifdef _TARGET_X86_ |
157 | REGNUM_FP = REGNUM_EBP, |
158 | REGNUM_SP = REGNUM_ESP, |
159 | #elif _TARGET_AMD64_ |
160 | REGNUM_SP = REGNUM_RSP, |
161 | #elif _TARGET_ARM_ |
162 | #ifdef REDHAWK |
163 | REGNUM_FP = REGNUM_R7, |
164 | #else |
165 | REGNUM_FP = REGNUM_R11, |
166 | #endif //REDHAWK |
167 | #elif _TARGET_ARM64_ |
168 | //Nothing to do here. FP is already alloted. |
169 | #else |
170 | // RegNum values should be properly defined for this platform |
171 | REGNUM_FP = 0, |
172 | REGNUM_SP = 1, |
173 | #endif |
174 | |
175 | }; |
176 | |
177 | // VarLoc describes the location of a native variable. Note that currently, VLT_REG_BYREF and VLT_STK_BYREF |
178 | // are only used for value types on X64. |
179 | |
180 | enum VarLocType |
181 | { |
182 | VLT_REG, // variable is in a register |
183 | VLT_REG_BYREF, // address of the variable is in a register |
184 | VLT_REG_FP, // variable is in an fp register |
185 | VLT_STK, // variable is on the stack (memory addressed relative to the frame-pointer) |
186 | VLT_STK_BYREF, // address of the variable is on the stack (memory addressed relative to the frame-pointer) |
187 | VLT_REG_REG, // variable lives in two registers |
188 | VLT_REG_STK, // variable lives partly in a register and partly on the stack |
189 | VLT_STK_REG, // reverse of VLT_REG_STK |
190 | VLT_STK2, // variable lives in two slots on the stack |
191 | VLT_FPSTK, // variable lives on the floating-point stack |
192 | VLT_FIXED_VA, // variable is a fixed argument in a varargs function (relative to VARARGS_HANDLE) |
193 | |
194 | VLT_COUNT, |
195 | VLT_INVALID, |
196 | }; |
197 | |
198 | // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc) |
199 | // eg. EAX |
200 | // VLT_REG_BYREF -- the specified register contains the address of the variable |
201 | // eg. [EAX] |
202 | |
203 | struct vlReg |
204 | { |
205 | RegNum vlrReg; |
206 | }; |
207 | |
208 | // VLT_STK -- Any 32 bit value which is on the stack |
209 | // eg. [ESP+0x20], or [EBP-0x28] |
210 | // VLT_STK_BYREF -- the specified stack location contains the address of the variable |
211 | // eg. mov EAX, [ESP+0x20]; [EAX] |
212 | |
213 | struct vlStk |
214 | { |
215 | RegNum vlsBaseReg; |
216 | signed vlsOffset; |
217 | }; |
218 | |
219 | // VLT_REG_REG -- TYP_LONG with both DWords enregistred |
220 | // eg. RBM_EAXEDX |
221 | |
222 | struct vlRegReg |
223 | { |
224 | RegNum vlrrReg1; |
225 | RegNum vlrrReg2; |
226 | }; |
227 | |
228 | // VLT_REG_STK -- Partly enregistered TYP_LONG |
229 | // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] } |
230 | |
231 | struct vlRegStk |
232 | { |
233 | RegNum vlrsReg; |
234 | struct |
235 | { |
236 | RegNum ; |
237 | signed ; |
238 | } ; |
239 | }; |
240 | |
241 | // VLT_STK_REG -- Partly enregistered TYP_LONG |
242 | // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX } |
243 | |
244 | struct vlStkReg |
245 | { |
246 | struct |
247 | { |
248 | RegNum vlsrsBaseReg; |
249 | signed vlsrsOffset; |
250 | } vlsrStk; |
251 | RegNum vlsrReg; |
252 | }; |
253 | |
254 | // VLT_STK2 -- Any 64 bit value which is on the stack, |
255 | // in 2 successsive DWords. |
256 | // eg 2 DWords at [ESP+0x10] |
257 | |
258 | struct vlStk2 |
259 | { |
260 | RegNum vls2BaseReg; |
261 | signed vls2Offset; |
262 | }; |
263 | |
264 | // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack) |
265 | // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk") |
266 | |
267 | struct vlFPstk |
268 | { |
269 | unsigned vlfReg; |
270 | }; |
271 | |
272 | // VLT_FIXED_VA -- fixed argument of a varargs function. |
273 | // The argument location depends on the size of the variable |
274 | // arguments (...). Inspecting the VARARGS_HANDLE indicates the |
275 | // location of the first arg. This argument can then be accessed |
276 | // relative to the position of the first arg |
277 | |
278 | struct vlFixedVarArg |
279 | { |
280 | unsigned vlfvOffset; |
281 | }; |
282 | |
283 | // VLT_MEMORY |
284 | |
285 | struct vlMemory |
286 | { |
287 | void *rpValue; // pointer to the in-process |
288 | // location of the value. |
289 | }; |
290 | |
291 | struct VarLoc |
292 | { |
293 | VarLocType vlType; |
294 | |
295 | union |
296 | { |
297 | ICorDebugInfo::vlReg vlReg; |
298 | ICorDebugInfo::vlStk vlStk; |
299 | ICorDebugInfo::vlRegReg vlRegReg; |
300 | ICorDebugInfo::vlRegStk vlRegStk; |
301 | ICorDebugInfo::vlStkReg vlStkReg; |
302 | ICorDebugInfo::vlStk2 vlStk2; |
303 | ICorDebugInfo::vlFPstk vlFPstk; |
304 | ICorDebugInfo::vlFixedVarArg vlFixedVarArg; |
305 | ICorDebugInfo::vlMemory vlMemory; |
306 | }; |
307 | }; |
308 | |
309 | // This is used to report implicit/hidden arguments |
310 | |
311 | enum |
312 | { |
313 | VARARGS_HND_ILNUM = -1, // Value for the CORINFO_VARARGS_HANDLE varNumber |
314 | RETBUF_ILNUM = -2, // Pointer to the return-buffer |
315 | TYPECTXT_ILNUM = -3, // ParamTypeArg for CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG |
316 | |
317 | UNKNOWN_ILNUM = -4, // Unknown variable |
318 | |
319 | MAX_ILNUM = -4 // Sentinal value. This should be set to the largest magnitude value in th enum |
320 | // so that the compression routines know the enum's range. |
321 | }; |
322 | |
323 | struct ILVarInfo |
324 | { |
325 | DWORD startOffset; |
326 | DWORD endOffset; |
327 | DWORD varNumber; |
328 | }; |
329 | |
330 | struct NativeVarInfo |
331 | { |
332 | DWORD startOffset; |
333 | DWORD endOffset; |
334 | DWORD varNumber; |
335 | VarLoc loc; |
336 | }; |
337 | }; |
338 | |