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/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7XX XX
8XX GCDecode XX
9XX XX
10XX Logic to decode the JIT method header and GC pointer tables XX
11XX XX
12XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
13XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
14*/
15
16
17#ifdef _TARGET_X86_
18
19/* This file is shared between the VM and JIT/IL and SOS/Strike directories */
20
21#include "gcinfotypes.h"
22
23/*****************************************************************************/
24/*
25 * This entire file depends upon GC2_ENCODING being set to 1
26 *
27 *****************************************************************************/
28
29size_t FASTCALL decodeUnsigned(PTR_CBYTE src, unsigned* val)
30{
31 LIMITED_METHOD_CONTRACT;
32
33 size_t size = 1;
34 BYTE byte = *src++;
35 unsigned value = byte & 0x7f;
36 while (byte & 0x80) {
37 size++;
38 byte = *src++;
39 value <<= 7;
40 value += byte & 0x7f;
41 }
42 *val = value;
43 return size;
44}
45
46size_t FASTCALL decodeUDelta(PTR_CBYTE src, unsigned* value, unsigned lastValue)
47{
48 CONTRACTL {
49 NOTHROW;
50 GC_NOTRIGGER;
51 } CONTRACTL_END;
52
53 unsigned delta;
54 size_t size = decodeUnsigned(src, &delta);
55 *value = lastValue + delta;
56 return size;
57}
58
59size_t FASTCALL decodeSigned(PTR_CBYTE src, int* val)
60{
61 CONTRACTL {
62 NOTHROW;
63 GC_NOTRIGGER;
64 } CONTRACTL_END;
65
66 size_t size = 1;
67 BYTE byte = *src++;
68 BYTE first = byte;
69 int value = byte & 0x3f;
70 while (byte & 0x80)
71 {
72 size++;
73 byte = *src++;
74 value <<= 7;
75 value += byte & 0x7f;
76 }
77 if (first & 0x40)
78 value = -value;
79 *val = value;
80 return size;
81}
82
83/*****************************************************************************/
84
85#if defined(_MSC_VER)
86#pragma optimize("tgy", on)
87#endif
88
89PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header)
90{
91 LIMITED_METHOD_DAC_CONTRACT;
92
93 BYTE nextByte = *table++;
94 BYTE encoding = nextByte & 0x7f;
95 GetInfoHdr(encoding, header);
96 while (nextByte & MORE_BYTES_TO_FOLLOW)
97 {
98 nextByte = *table++;
99 encoding = nextByte & ADJ_ENCODING_MAX;
100 // encoding here always corresponds to codes in InfoHdrAdjust set
101
102 if (encoding < NEXT_FOUR_START)
103 {
104 if (encoding < SET_ARGCOUNT)
105 {
106 header->frameSize = encoding - SET_FRAMESIZE;
107 }
108 else if (encoding < SET_PROLOGSIZE)
109 {
110 header->argCount = encoding - SET_ARGCOUNT;
111 }
112 else if (encoding < SET_EPILOGSIZE)
113 {
114 header->prologSize = encoding - SET_PROLOGSIZE;
115 }
116 else if (encoding < SET_EPILOGCNT)
117 {
118 header->epilogSize = encoding - SET_EPILOGSIZE;
119 }
120 else if (encoding < SET_UNTRACKED)
121 {
122 header->epilogCount = (encoding - SET_EPILOGCNT) / 2;
123 header->epilogAtEnd = ((encoding - SET_EPILOGCNT) & 1) == 1;
124 assert(!header->epilogAtEnd || (header->epilogCount == 1));
125 }
126 else if (encoding < FIRST_FLIP)
127 {
128 header->untrackedCnt = encoding - SET_UNTRACKED;
129 _ASSERTE(header->untrackedCnt != HAS_UNTRACKED);
130 }
131 else switch (encoding)
132 {
133 default:
134 assert(!"Unexpected encoding");
135 break;
136 case FLIP_EDI_SAVED:
137 header->ediSaved ^= 1;
138 break;
139 case FLIP_ESI_SAVED:
140 header->esiSaved ^= 1;
141 break;
142 case FLIP_EBX_SAVED:
143 header->ebxSaved ^= 1;
144 break;
145 case FLIP_EBP_SAVED:
146 header->ebpSaved ^= 1;
147 break;
148 case FLIP_EBP_FRAME:
149 header->ebpFrame ^= 1;
150 break;
151 case FLIP_INTERRUPTIBLE:
152 header->interruptible ^= 1;
153 break;
154 case FLIP_DOUBLE_ALIGN:
155 header->doubleAlign ^= 1;
156 break;
157 case FLIP_SECURITY:
158 header->security ^= 1;
159 break;
160 case FLIP_HANDLERS:
161 header->handlers ^= 1;
162 break;
163 case FLIP_LOCALLOC:
164 header->localloc ^= 1;
165 break;
166 case FLIP_EDITnCONTINUE:
167 header->editNcontinue ^= 1;
168 break;
169 case FLIP_VAR_PTR_TABLE_SZ:
170 header->varPtrTableSize ^= HAS_VARPTR;
171 break;
172 case FFFF_UNTRACKED_CNT:
173 header->untrackedCnt = HAS_UNTRACKED;
174 break;
175 case FLIP_VARARGS:
176 header->varargs ^= 1;
177 break;
178 case FLIP_PROF_CALLBACKS:
179 header->profCallbacks ^= 1;
180 break;
181 case FLIP_HAS_GENERICS_CONTEXT:
182 header->genericsContext ^= 1;
183 break;
184 case FLIP_GENERICS_CONTEXT_IS_METHODDESC:
185 header->genericsContextIsMethodDesc ^= 1;
186 break;
187 case FLIP_HAS_GS_COOKIE:
188 header->gsCookieOffset ^= HAS_GS_COOKIE_OFFSET;
189 break;
190 case FLIP_SYNC:
191 header->syncStartOffset ^= HAS_SYNC_OFFSET;
192 break;
193 case FLIP_REV_PINVOKE_FRAME:
194 _ASSERTE(GCInfoEncodesRevPInvokeFrame(version));
195 header->revPInvokeOffset ^= HAS_REV_PINVOKE_FRAME_OFFSET;
196 break;
197
198 case NEXT_OPCODE:
199 _ASSERTE((nextByte & MORE_BYTES_TO_FOLLOW) && "Must have another code");
200 nextByte = *table++;
201 encoding = nextByte & ADJ_ENCODING_MAX;
202 // encoding here always corresponds to codes in InfoHdrAdjust2 set
203
204 if (encoding < SET_RET_KIND_MAX)
205 {
206 _ASSERTE(GCInfoEncodesReturnKind(version));
207 header->returnKind = (ReturnKind)encoding;
208 }
209 else
210 {
211 assert(!"Unexpected encoding");
212 }
213 break;
214 }
215 }
216 else
217 {
218 unsigned char lowBits;
219 switch (encoding >> 4)
220 {
221 default:
222 assert(!"Unexpected encoding");
223 break;
224 case 5:
225 assert(NEXT_FOUR_FRAMESIZE == 0x50);
226 lowBits = encoding & 0xf;
227 header->frameSize <<= 4;
228 header->frameSize += lowBits;
229 break;
230 case 6:
231 assert(NEXT_FOUR_ARGCOUNT == 0x60);
232 lowBits = encoding & 0xf;
233 header->argCount <<= 4;
234 header->argCount += lowBits;
235 break;
236 case 7:
237 if ((encoding & 0x8) == 0)
238 {
239 assert(NEXT_THREE_PROLOGSIZE == 0x70);
240 lowBits = encoding & 0x7;
241 header->prologSize <<= 3;
242 header->prologSize += lowBits;
243 }
244 else
245 {
246 assert(NEXT_THREE_EPILOGSIZE == 0x78);
247 lowBits = encoding & 0x7;
248 header->epilogSize <<= 3;
249 header->epilogSize += lowBits;
250 }
251 break;
252 }
253 }
254 }
255 return table;
256}
257
258void FASTCALL decodeCallPattern(int pattern,
259 unsigned * argCnt,
260 unsigned * regMask,
261 unsigned * argMask,
262 unsigned * codeDelta)
263{
264 CONTRACTL {
265 NOTHROW;
266 GC_NOTRIGGER;
267 SUPPORTS_DAC;
268 } CONTRACTL_END;
269
270 assert((pattern>=0) && (pattern<80));
271 CallPattern pat;
272 pat.val = callPatternTable[pattern];
273 *argCnt = pat.fld.argCnt;
274 *regMask = pat.fld.regMask; // EBP,EBX,ESI,EDI
275 *argMask = pat.fld.argMask;
276 *codeDelta = pat.fld.codeDelta;
277}
278
279#define YES HAS_VARPTR
280
281const InfoHdrSmall infoHdrShortcut[128] = {
282// Prolog size
283// |
284// | Epilog size
285// | |
286// | | Epilog count
287// | | |
288// | | | Epilog at end
289// | | | |
290// | | | | EDI saved
291// | | | | |
292// | | | | | ESI saved
293// | | | | | |
294// | | | | | | EBX saved
295// | | | | | | |
296// | | | | | | | EBP saved
297// | | | | | | | |
298// | | | | | | | | EBP-frame
299// | | | | | | | | |
300// | | | | | | | | | Interruptible method
301// | | | | | | | | | |
302// | | | | | | | | | | doubleAlign
303// | | | | | | | | | | |
304// | | | | | | | | | | | security flag
305// | | | | | | | | | | | |
306// | | | | | | | | | | | | handlers
307// | | | | | | | | | | | | |
308// | | | | | | | | | | | | | localloc
309// | | | | | | | | | | | | | |
310// | | | | | | | | | | | | | | edit and continue
311// | | | | | | | | | | | | | | |
312// | | | | | | | | | | | | | | | varargs
313// | | | | | | | | | | | | | | | |
314// | | | | | | | | | | | | | | | | ProfCallbacks
315// | | | | | | | | | | | | | | | | |
316// | | | | | | | | | | | | | | | | | genericsContext
317// | | | | | | | | | | | | | | | | | |
318// | | | | | | | | | | | | | | | | | | genericsContextIsMethodDesc
319// | | | | | | | | | | | | | | | | | | |
320// | | | | | | | | | | | | | | | | | | | returnKind
321// | | | | | | | | | | | | | | | | | | | |
322// | | | | | | | | | | | | | | | | | | | | Arg count
323// | | | | | | | | | | | | | | | | | | | | | Counted occurences
324// | | | | | | | | | | | | | | | | | | | | | Frame size |
325// | | | | | | | | | | | | | | | | | | | | | | |
326// | | | | | | | | | | | | | | | | | | | | | | untrackedCnt | Header encoding
327// | | | | | | | | | | | | | | | | | | | | | | | | |
328// | | | | | | | | | | | | | | | | | | | | | | | varPtrTable | |
329// | | | | | | | | | | | | | | | | | | | | | | | | | |
330// | | | | | | | | | | | | | | | | | | | | | | | | gsCookieOffs | |
331// | | | | | | | | | | | | | | | | | | | | | | | | | | |
332// | | | | | | | | | | | | | | | | | | | | | | | | | syncOffs | |
333// | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
334// | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
335// | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
336// v v v v v v v v v v v v v v v v v v v v v v v v v v v v v
337 { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1139 00
338 { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 128738 01
339 { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3696 02
340 { 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 402 03
341 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 4259 04
342 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 3379 05
343 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 2058 06
344 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 728 07
345 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 984 08
346 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }, // 606 09
347 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0 }, // 1110 0a
348 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0 }, // 414 0b
349 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1553 0c
350 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 584 0d
351 { 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 2182 0e
352 { 1, 2, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3445 0f
353 { 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1369 10
354 { 1, 2, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 515 11
355 { 1, 2, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 21127 12
356 { 1, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3517 13
357 { 1, 2, 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 750 14
358 { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1876 15
359 { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1665 16
360 { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 729 17
361 { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 484 18
362 { 1, 4, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 331 19
363 { 2, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 1a
364 { 2, 3, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 964 1b
365 { 2, 3, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3713 1c
366 { 2, 3, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 466 1d
367 { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1325 1e
368 { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 712 1f
369 { 2, 3, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 588 20
370 { 2, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 20542 21
371 { 2, 3, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3802 22
372 { 2, 3, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 798 23
373 { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1900 24
374 { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 385 25
375 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1617 26
376 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1743 27
377 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 909 28
378 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 602 29
379 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 352 2a
380 { 2, 6, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 657 2b
381 { 2, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1283 2c
382 { 2, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1286 2d
383 { 3, 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1495 2e
384 { 3, 4, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1989 2f
385 { 3, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1154 30
386 { 3, 4, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 9300 31
387 { 3, 4, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 392 32
388 { 3, 4, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1720 33
389 { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1246 34
390 { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 800 35
391 { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1179 36
392 { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1368 37
393 { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 349 38
394 { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 505 39
395 { 3, 6, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 629 3a
396 { 3, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, YES }, // 365 3b
397 { 4, 5, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 487 3c
398 { 4, 5, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1752 3d
399 { 4, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1959 3e
400 { 4, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2436 3f
401 { 4, 5, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 861 40
402 { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1459 41
403 { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 950 42
404 { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1491 43
405 { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 879 44
406 { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 408 45
407 { 5, 4, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 4870 46
408 { 5, 6, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 359 47
409 { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 915 48
410 { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 412 49
411 { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1288 4a
412 { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1591 4b
413 { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 361 4c
414 { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0 }, // 623 4d
415 { 5, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // 1239 4e
416 { 6, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 457 4f
417 { 6, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 606 50
418 { 6, 4, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1073 51
419 { 6, 4, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 508 52
420 { 6, 6, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 330 53
421 { 6, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1709 54
422 { 6, 7, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1164 55
423 { 7, 4, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 556 56
424 { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 529 57
425 { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 1423 58
426 { 7, 8, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 2455 59
427 { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 956 5a
428 { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1399 5b
429 { 7, 8, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 587 5c
430 { 7, 10, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 743 5d
431 { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0 }, // 1004 5e
432 { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, YES }, // 487 5f
433 { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0 }, // 337 60
434 { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, YES }, // 361 61
435 { 8, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 560 62
436 { 8, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1377 63
437 { 9, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 877 64
438 { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 3041 65
439 { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 349 66
440 { 10, 5, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 2061 67
441 { 10, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 577 68
442 { 11, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 1195 69
443 { 12, 5, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 491 6a
444 { 13, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, YES }, // 627 6b
445 { 13, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0 }, // 1099 6c
446 { 13, 10, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 488 6d
447 { 14, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 574 6e
448 { 16, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 1281 6f
449 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1881 70
450 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 339 71
451 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, // 2594 72
452 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 339 73
453 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 2107 74
454 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 2372 75
455 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, YES }, // 1078 76
456 { 16, 7, 2, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 384 77
457 { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 4, 1, YES }, // 1541 78
458 { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 4, 1, YES }, // 975 79
459 { 19, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 546 7a
460 { 24, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 675 7b
461 { 45, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 902 7c
462 { 51, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, YES }, // 432 7d
463 { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 7e
464 { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0 }, // 703 7f
465};
466
467bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const
468{
469#ifdef _ASSERTE
470 // target cannot have place-holder values.
471 _ASSERTE(target.untrackedCnt != HAS_UNTRACKED &&
472 target.varPtrTableSize != HAS_VARPTR &&
473 target.gsCookieOffset != HAS_GS_COOKIE_OFFSET &&
474 target.syncStartOffset != HAS_SYNC_OFFSET &&
475 target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET);
476#endif
477
478 // compare two InfoHdr's up to but not including the untrackCnt field
479 if (memcmp(this, &target, offsetof(InfoHdr, untrackedCnt)) != 0)
480 return false;
481
482 if (untrackedCnt != target.untrackedCnt) {
483 if (target.untrackedCnt <= SET_UNTRACKED_MAX)
484 return false;
485 else if (untrackedCnt != HAS_UNTRACKED)
486 return false;
487 }
488
489 if (varPtrTableSize != target.varPtrTableSize) {
490 if ((varPtrTableSize != 0) != (target.varPtrTableSize != 0))
491 return false;
492 }
493
494 if (target.gsCookieOffset != INVALID_GS_COOKIE_OFFSET)
495 return false;
496
497 if (target.syncStartOffset != INVALID_SYNC_OFFSET)
498 return false;
499
500 if (target.revPInvokeOffset!= INVALID_REV_PINVOKE_OFFSET)
501 return false;
502
503 return true;
504}
505
506
507const unsigned callCommonDelta[4] = { 6,8,10,12 };
508
509/*
510 * In the callPatternTable each 32-bit unsigned value represents four bytes:
511 *
512 * byte0,byte1,byte2,byte3 => codeDelta,argMask,regMask,argCnt
513 * for example 0x0c000301 => codeDelta of 12, argMask of 0,
514 * regMask of 0x3, argCnt of 1
515 *
516 * Furthermore within the table the following maximum values are in place:
517 *
518 * codeDelta <= CP_MAX_CODE_DELTA // (0x23)
519 * argCnt <= CP_MAX_ARG_CNT // (0x02)
520 * argMask <= CP_MAX_ARG_MASK // (0x00)
521 *
522 * Note that ARG_CNT is the count of pushed args for a nested call site.
523 * And since the first two arguments are always passed in registers
524 * an ARG_CNT of 1 would mean that the nested call site had three arguments
525 *
526 * Note that ARG_MASK is the mask of pushed args that contain GC pointers
527 * since the first two arguments are always passed in registers it is
528 * a fairly rare occurance to push a GC pointer as an argument, since it
529 * only occurs for nested calls, when the third or later argument for the
530 * outer call contains a GC ref.
531 *
532 * Additionally the encoding of the regMask uses the following bits:
533 * EDI = 0x1, ESI = 0x2, EBX = 0x4, EBP = 0x8
534 *
535 */
536const unsigned callPatternTable[80] = { // # of occurences
537 0x0a000200, // 30109
538 0x0c000200, // 22970
539 0x0c000201, // 19005
540 0x0a000300, // 12193
541 0x0c000300, // 10614
542 0x0e000200, // 10253
543 0x10000200, // 9746
544 0x0b000200, // 9698
545 0x0d000200, // 9625
546 0x08000200, // 8909
547 0x0c000301, // 8522
548 0x11000200, // 7382
549 0x0e000300, // 7357
550 0x12000200, // 7139
551 0x10000300, // 7062
552 0x11000300, // 6970
553 0x0a000201, // 6842
554 0x0a000100, // 6803
555 0x0f000200, // 6795
556 0x13000200, // 6559
557 0x08000300, // 6079
558 0x15000200, // 5874
559 0x0d000201, // 5492
560 0x0c000100, // 5193
561 0x0d000300, // 5165
562 0x23000200, // 5143
563 0x1b000200, // 5035
564 0x14000200, // 4872
565 0x0f000300, // 4850
566 0x0a000700, // 4781
567 0x09000200, // 4560
568 0x12000300, // 4496
569 0x16000200, // 4180
570 0x07000200, // 4021
571 0x09000300, // 4012
572 0x0c000700, // 3988
573 0x0c000600, // 3946
574 0x0e000100, // 3823
575 0x1a000200, // 3764
576 0x18000200, // 3744
577 0x17000200, // 3736
578 0x1f000200, // 3671
579 0x13000300, // 3559
580 0x0a000600, // 3214
581 0x0e000600, // 3109
582 0x08000201, // 2984
583 0x0b000300, // 2928
584 0x0a000301, // 2859
585 0x07000100, // 2826
586 0x13000100, // 2782
587 0x09000301, // 2644
588 0x19000200, // 2638
589 0x11000700, // 2618
590 0x21000200, // 2518
591 0x0d000202, // 2484
592 0x10000100, // 2480
593 0x0f000600, // 2413
594 0x14000300, // 2363
595 0x0c000500, // 2362
596 0x08000301, // 2285
597 0x20000200, // 2245
598 0x10000700, // 2240
599 0x0f000100, // 2236
600 0x1e000200, // 2214
601 0x0c000400, // 2193
602 0x16000300, // 2171
603 0x12000600, // 2132
604 0x22000200, // 2011
605 0x1d000200, // 2011
606 0x0c000f00, // 1996
607 0x0e000700, // 1971
608 0x0a000400, // 1970
609 0x09000201, // 1932
610 0x10000600, // 1903
611 0x15000300, // 1847
612 0x0a000101, // 1814
613 0x0a000b00, // 1771
614 0x0c000601, // 1737
615 0x09000700, // 1737
616 0x07000300, // 1684
617};
618
619#endif // _TARGET_X86_
620