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 |
6 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
7 | XX XX |
8 | XX GCDecode XX |
9 | XX XX |
10 | XX Logic to decode the JIT method header and GC pointer tables XX |
11 | XX XX |
12 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
13 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
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 | |
29 | size_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 | |
46 | size_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 | |
59 | size_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 | |
89 | PTR_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 | |
258 | void 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 | |
281 | const 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 | |
467 | bool 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 | |
507 | const 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 | */ |
536 | const 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 | |