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 UnwindInfo XX
9XX XX
10XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12*/
13
14#include "jitpch.h"
15#ifdef _MSC_VER
16#pragma hdrstop
17#endif
18
19#if defined(_TARGET_ARM_) && defined(_TARGET_UNIX_)
20int Compiler::mapRegNumToDwarfReg(regNumber reg)
21{
22 int dwarfReg = DWARF_REG_ILLEGAL;
23
24 switch (reg)
25 {
26 case REG_R0:
27 dwarfReg = 0;
28 break;
29 case REG_R1:
30 dwarfReg = 1;
31 break;
32 case REG_R2:
33 dwarfReg = 2;
34 break;
35 case REG_R3:
36 dwarfReg = 3;
37 break;
38 case REG_R4:
39 dwarfReg = 4;
40 break;
41 case REG_R5:
42 dwarfReg = 5;
43 break;
44 case REG_R6:
45 dwarfReg = 6;
46 break;
47 case REG_R7:
48 dwarfReg = 7;
49 break;
50 case REG_R8:
51 dwarfReg = 8;
52 break;
53 case REG_R9:
54 dwarfReg = 9;
55 break;
56 case REG_R10:
57 dwarfReg = 10;
58 break;
59 case REG_R11:
60 dwarfReg = 11;
61 break;
62 case REG_R12:
63 dwarfReg = 12;
64 break;
65 case REG_R13:
66 dwarfReg = 13;
67 break;
68 case REG_R14:
69 dwarfReg = 14;
70 break;
71 case REG_R15:
72 dwarfReg = 15;
73 break;
74 case REG_F0:
75 dwarfReg = 64;
76 break;
77 case REG_F1:
78 dwarfReg = 65;
79 break;
80 case REG_F2:
81 dwarfReg = 66;
82 break;
83 case REG_F3:
84 dwarfReg = 67;
85 break;
86 case REG_F4:
87 dwarfReg = 68;
88 break;
89 case REG_F5:
90 dwarfReg = 69;
91 break;
92 case REG_F6:
93 dwarfReg = 70;
94 break;
95 case REG_F7:
96 dwarfReg = 71;
97 break;
98 case REG_F8:
99 dwarfReg = 72;
100 break;
101 case REG_F9:
102 dwarfReg = 73;
103 break;
104 case REG_F10:
105 dwarfReg = 74;
106 break;
107 case REG_F11:
108 dwarfReg = 75;
109 break;
110 case REG_F12:
111 dwarfReg = 76;
112 break;
113 case REG_F13:
114 dwarfReg = 77;
115 break;
116 case REG_F14:
117 dwarfReg = 78;
118 break;
119 case REG_F15:
120 dwarfReg = 79;
121 break;
122 case REG_F16:
123 dwarfReg = 80;
124 break;
125 case REG_F17:
126 dwarfReg = 81;
127 break;
128 case REG_F18:
129 dwarfReg = 82;
130 break;
131 case REG_F19:
132 dwarfReg = 83;
133 break;
134 case REG_F20:
135 dwarfReg = 84;
136 break;
137 case REG_F21:
138 dwarfReg = 85;
139 break;
140 case REG_F22:
141 dwarfReg = 86;
142 break;
143 case REG_F23:
144 dwarfReg = 87;
145 break;
146 case REG_F24:
147 dwarfReg = 88;
148 break;
149 case REG_F25:
150 dwarfReg = 89;
151 break;
152 case REG_F26:
153 dwarfReg = 90;
154 break;
155 case REG_F27:
156 dwarfReg = 91;
157 break;
158 case REG_F28:
159 dwarfReg = 92;
160 break;
161 case REG_F29:
162 dwarfReg = 93;
163 break;
164 case REG_F30:
165 dwarfReg = 94;
166 break;
167 case REG_F31:
168 dwarfReg = 95;
169 break;
170 default:
171 noway_assert(!"unexpected REG_NUM");
172 }
173
174 return dwarfReg;
175}
176#endif // _TARGET_ARM_ && _TARGET_UNIX_
177
178#ifdef _TARGET_ARMARCH_
179
180/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
181XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
182XX XX
183XX Unwind APIs XX
184XX XX
185XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
186XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
187*/
188
189void Compiler::unwindBegProlog()
190{
191 assert(compGeneratingProlog);
192
193#if defined(_TARGET_UNIX_)
194 if (generateCFIUnwindCodes())
195 {
196 unwindBegPrologCFI();
197 return;
198 }
199#endif // _TARGET_UNIX_
200
201 FuncInfoDsc* func = funCurrentFunc();
202
203 // There is only one prolog for a function/funclet, and it comes first. So now is
204 // a good time to initialize all the unwind data structures.
205
206 emitLocation* startLoc;
207 emitLocation* endLoc;
208 unwindGetFuncLocations(func, true, &startLoc, &endLoc);
209
210 func->uwi.InitUnwindInfo(this, startLoc, endLoc);
211 func->uwi.CaptureLocation();
212
213 func->uwiCold = NULL; // No cold data yet
214}
215
216void Compiler::unwindEndProlog()
217{
218 assert(compGeneratingProlog);
219}
220
221void Compiler::unwindBegEpilog()
222{
223 assert(compGeneratingEpilog);
224
225#if defined(_TARGET_UNIX_)
226 if (generateCFIUnwindCodes())
227 {
228 return;
229 }
230#endif // _TARGET_UNIX_
231
232 funCurrentFunc()->uwi.AddEpilog();
233}
234
235void Compiler::unwindEndEpilog()
236{
237 assert(compGeneratingEpilog);
238}
239
240#if defined(_TARGET_ARM_)
241
242void Compiler::unwindPushPopMaskInt(regMaskTP maskInt, bool useOpsize16)
243{
244 // floating point registers cannot be specified in 'maskInt'
245 assert((maskInt & RBM_ALLFLOAT) == 0);
246
247 UnwindInfo* pu = &funCurrentFunc()->uwi;
248
249 if (useOpsize16)
250 {
251 // The 16-bit opcode only encode R0-R7 and LR
252 assert((maskInt & ~(RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3 | RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_LR)) == 0);
253
254 bool shortFormat = false;
255 BYTE val = 0;
256
257 if ((maskInt & (RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3)) == 0)
258 {
259 regMaskTP matchMask = maskInt & (RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7);
260 regMaskTP valMask = RBM_R4;
261 while (val < 4)
262 {
263 if (matchMask == valMask)
264 {
265 shortFormat = true;
266 break;
267 }
268
269 valMask <<= 1;
270 valMask |= RBM_R4;
271
272 val++;
273 }
274 }
275
276 if (shortFormat)
277 {
278 // D0-D7 : pop {r4-rX,lr} (X=4-7) (opsize 16)
279 pu->AddCode(0xD0 | ((maskInt >> 12) & 0x4) | val);
280 }
281 else
282 {
283 // EC-ED : pop {r0-r7,lr} (opsize 16)
284 pu->AddCode(0xEC | ((maskInt >> 14) & 0x1), (BYTE)maskInt);
285 }
286 }
287 else
288 {
289 assert((maskInt &
290 ~(RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3 | RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8 | RBM_R9 | RBM_R10 |
291 RBM_R11 | RBM_R12 | RBM_LR)) == 0);
292
293 bool shortFormat = false;
294 BYTE val = 0;
295
296 if (((maskInt & (RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3)) == 0) &&
297 ((maskInt & (RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8)) == (RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8)))
298 {
299 regMaskTP matchMask = maskInt & (RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8 | RBM_R9 | RBM_R10 | RBM_R11);
300 regMaskTP valMask = RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8;
301 while (val < 4)
302 {
303 if (matchMask == valMask)
304 {
305 shortFormat = true;
306 break;
307 }
308
309 valMask <<= 1;
310 valMask |= RBM_R4;
311
312 val++;
313 }
314 }
315
316 if (shortFormat)
317 {
318 // D8-DF : pop {r4-rX,lr} (X=8-11) (opsize 32)
319 pu->AddCode(0xD8 | ((maskInt >> 12) & 0x4) | val);
320 }
321 else
322 {
323 // 80-BF : pop {r0-r12,lr} (opsize 32)
324 pu->AddCode(0x80 | ((maskInt >> 8) & 0x1F) | ((maskInt >> 9) & 0x20), (BYTE)maskInt);
325 }
326 }
327}
328
329void Compiler::unwindPushPopMaskFloat(regMaskTP maskFloat)
330{
331 // Only floating pointer registers can be specified in 'maskFloat'
332 assert((maskFloat & ~RBM_ALLFLOAT) == 0);
333
334 // If the maskFloat is zero there is no unwind code to emit
335 //
336 if (maskFloat == RBM_NONE)
337 {
338 return;
339 }
340
341 UnwindInfo* pu = &funCurrentFunc()->uwi;
342
343 BYTE val = 0;
344 regMaskTP valMask = (RBM_F16 | RBM_F17);
345
346 while (maskFloat != valMask)
347 {
348 valMask <<= 2;
349 valMask |= (RBM_F16 | RBM_F17);
350
351 val++;
352
353 if (val == 8)
354 {
355 noway_assert(!"Illegal maskFloat");
356 }
357 }
358
359 // E0-E7 : vpop {d8-dX} (X=8-15) (opsize 32)
360 assert(0 <= val && val <= 7);
361 pu->AddCode(0xE0 | val);
362}
363
364void Compiler::unwindPushMaskInt(regMaskTP maskInt)
365{
366 // Only r0-r12 and lr are supported
367 assert((maskInt &
368 ~(RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3 | RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8 | RBM_R9 | RBM_R10 |
369 RBM_R11 | RBM_R12 | RBM_LR)) == 0);
370
371#if defined(_TARGET_UNIX_)
372 if (generateCFIUnwindCodes())
373 {
374 // If we are pushing LR, we should give unwind codes in terms of caller's PC
375 if (maskInt & RBM_LR)
376 {
377 maskInt = (maskInt & ~RBM_LR) | RBM_PC;
378 }
379 unwindPushPopMaskCFI(maskInt, false);
380 return;
381 }
382#endif // _TARGET_UNIX_
383
384 bool useOpsize16 = ((maskInt & (RBM_LOW_REGS | RBM_LR)) == maskInt); // Can PUSH use the 16-bit encoding?
385 unwindPushPopMaskInt(maskInt, useOpsize16);
386}
387
388void Compiler::unwindPushMaskFloat(regMaskTP maskFloat)
389{
390 // Only floating point registers should be in maskFloat
391 assert((maskFloat & RBM_ALLFLOAT) == maskFloat);
392
393#if defined(_TARGET_UNIX_)
394 if (generateCFIUnwindCodes())
395 {
396 unwindPushPopMaskCFI(maskFloat, true);
397 return;
398 }
399#endif // _TARGET_UNIX_
400
401 unwindPushPopMaskFloat(maskFloat);
402}
403
404void Compiler::unwindPopMaskInt(regMaskTP maskInt)
405{
406#if defined(_TARGET_UNIX_)
407 if (generateCFIUnwindCodes())
408 {
409 return;
410 }
411#endif // _TARGET_UNIX_
412
413 // Only r0-r12 and lr and pc are supported (pc is mapped to lr when encoding)
414 assert((maskInt &
415 ~(RBM_R0 | RBM_R1 | RBM_R2 | RBM_R3 | RBM_R4 | RBM_R5 | RBM_R6 | RBM_R7 | RBM_R8 | RBM_R9 | RBM_R10 |
416 RBM_R11 | RBM_R12 | RBM_LR | RBM_PC)) == 0);
417
418 bool useOpsize16 = ((maskInt & (RBM_LOW_REGS | RBM_PC)) == maskInt); // Can POP use the 16-bit encoding?
419
420 // If we are popping PC, then we'll return from the function. In this case, we assume
421 // the first thing the prolog did was push LR, so give the unwind codes in terms of
422 // the LR that was pushed. Note that the epilog unwind codes are meant to reverse
423 // the effect of the prolog. For "pop {pc}", the prolog had "push {lr}", so we need
424 // an epilog code to model the reverse of that.
425 if (maskInt & RBM_PC)
426 {
427 maskInt = (maskInt & ~RBM_PC) | RBM_LR;
428 }
429 unwindPushPopMaskInt(maskInt, useOpsize16);
430}
431
432void Compiler::unwindPopMaskFloat(regMaskTP maskFloat)
433{
434#if defined(_TARGET_UNIX_)
435 if (generateCFIUnwindCodes())
436 {
437 return;
438 }
439#endif // _TARGET_UNIX_
440
441 // Only floating point registers should be in maskFloat
442 assert((maskFloat & RBM_ALLFLOAT) == maskFloat);
443 unwindPushPopMaskFloat(maskFloat);
444}
445
446void Compiler::unwindAllocStack(unsigned size)
447{
448#if defined(_TARGET_UNIX_)
449 if (generateCFIUnwindCodes())
450 {
451 if (compGeneratingProlog)
452 {
453 unwindAllocStackCFI(size);
454 }
455 return;
456 }
457#endif // _TARGET_UNIX_
458
459 UnwindInfo* pu = &funCurrentFunc()->uwi;
460
461 assert(size % 4 == 0);
462 size /= 4;
463
464 if (size <= 0x7F)
465 {
466 // 00-7F : add sp, sp, #X*4 (opsize 16)
467 pu->AddCode((BYTE)size);
468 }
469 else if (size <= 0x3FF)
470 {
471 // E8-EB : addw sp, sp, #X*4 (opsize 32)
472 pu->AddCode(0xE8 | (BYTE)(size >> 8), (BYTE)size);
473 }
474 else if (size <= 0xFFFF)
475 {
476 // F7 : add sp, sp, #X*4 (opsize 16)
477 // F9 : add sp, sp, #X*4 (opsize 32)
478 //
479 // For large stack size, the most significant bits
480 // are stored first (and next to the opCode (F9)) per the unwind spec.
481 unsigned instrSizeInBytes = pu->GetInstructionSize();
482 BYTE b1 = (instrSizeInBytes == 2) ? 0xF7 : 0xF9;
483 pu->AddCode(b1,
484 (BYTE)(size >> 8), // msb
485 (BYTE)size); // lsb
486 }
487 else
488 {
489 // F8 : add sp, sp, #X*4 (opsize 16)
490 // FA : add sp, sp, #X*4 (opsize 32)
491 //
492 // For large stack size, the most significant bits
493 // are stored first (and next to the opCode (FA)) per the unwind spec.
494 unsigned instrSizeInBytes = pu->GetInstructionSize();
495 BYTE b1 = (instrSizeInBytes == 2) ? 0xF8 : 0xFA;
496 pu->AddCode(b1, (BYTE)(size >> 16), (BYTE)(size >> 8), (BYTE)size);
497 }
498}
499
500void Compiler::unwindSetFrameReg(regNumber reg, unsigned offset)
501{
502#if defined(_TARGET_UNIX_)
503 if (generateCFIUnwindCodes())
504 {
505 if (compGeneratingProlog)
506 {
507 unwindSetFrameRegCFI(reg, offset);
508 }
509 return;
510 }
511#endif // _TARGET_UNIX_
512
513 UnwindInfo* pu = &funCurrentFunc()->uwi;
514
515 // Arm unwind info does not allow offset
516 assert(offset == 0);
517 assert(0 <= reg && reg <= 15);
518
519 // C0-CF : mov sp, rX (opsize 16)
520 pu->AddCode((BYTE)(0xC0 + reg));
521}
522
523void Compiler::unwindSaveReg(regNumber reg, unsigned offset)
524{
525 unreached();
526}
527
528void Compiler::unwindBranch16()
529{
530#if defined(_TARGET_UNIX_)
531 if (generateCFIUnwindCodes())
532 {
533 return;
534 }
535#endif // _TARGET_UNIX_
536
537 UnwindInfo* pu = &funCurrentFunc()->uwi;
538
539 // TODO-CQ: need to handle changing the exit code from 0xFF to 0xFD. Currently, this will waste an extra 0xFF at the
540 // end, automatically added.
541 pu->AddCode(0xFD);
542}
543
544void Compiler::unwindNop(unsigned codeSizeInBytes) // codeSizeInBytes is 2 or 4 bytes for Thumb2 instruction
545{
546#if defined(_TARGET_UNIX_)
547 if (generateCFIUnwindCodes())
548 {
549 return;
550 }
551#endif // _TARGET_UNIX_
552
553 UnwindInfo* pu = &funCurrentFunc()->uwi;
554
555#ifdef DEBUG
556 if (verbose)
557 {
558 printf("unwindNop: adding NOP for %d byte instruction\n", codeSizeInBytes);
559 }
560#endif
561
562 INDEBUG(pu->uwiAddingNOP = true);
563
564 if (codeSizeInBytes == 2)
565 {
566 // FB : nop (opsize 16)
567 pu->AddCode(0xFB);
568 }
569 else
570 {
571 noway_assert(codeSizeInBytes == 4);
572
573 // FC : nop (opsize 32)
574 pu->AddCode(0xFC);
575 }
576
577 INDEBUG(pu->uwiAddingNOP = false);
578}
579
580#endif // defined(_TARGET_ARM_)
581
582// The instructions between the last captured "current state" and the current instruction
583// are in the prolog but have no effect for unwinding. Emit the appropriate NOP unwind codes
584// for them.
585void Compiler::unwindPadding()
586{
587#if defined(_TARGET_UNIX_)
588 if (generateCFIUnwindCodes())
589 {
590 return;
591 }
592#endif // _TARGET_UNIX_
593
594 UnwindInfo* pu = &funCurrentFunc()->uwi;
595 genEmitter->emitUnwindNopPadding(pu->GetCurrentEmitterLocation(), this);
596}
597
598// Ask the VM to reserve space for the unwind information for the function and
599// all its funclets.
600void Compiler::unwindReserve()
601{
602 assert(!compGeneratingProlog);
603 assert(!compGeneratingEpilog);
604
605 assert(compFuncInfoCount > 0);
606 for (unsigned funcIdx = 0; funcIdx < compFuncInfoCount; funcIdx++)
607 {
608 unwindReserveFunc(funGetFunc(funcIdx));
609 }
610}
611
612void Compiler::unwindReserveFunc(FuncInfoDsc* func)
613{
614 BOOL isFunclet = (func->funKind == FUNC_ROOT) ? FALSE : TRUE;
615 bool funcHasColdSection = false;
616
617#if defined(_TARGET_UNIX_)
618 if (generateCFIUnwindCodes())
619 {
620 DWORD unwindCodeBytes = 0;
621 if (fgFirstColdBlock != nullptr)
622 {
623 eeReserveUnwindInfo(isFunclet, true /*isColdCode*/, unwindCodeBytes);
624 }
625 unwindCodeBytes = (DWORD)(func->cfiCodes->size() * sizeof(CFI_CODE));
626 eeReserveUnwindInfo(isFunclet, false /*isColdCode*/, unwindCodeBytes);
627
628 return;
629 }
630#endif // _TARGET_UNIX_
631
632 // If there is cold code, split the unwind data between the hot section and the
633 // cold section. This needs to be done before we split into fragments, as each
634 // of the hot and cold sections can have multiple fragments.
635
636 if (fgFirstColdBlock != NULL)
637 {
638 assert(!isFunclet); // TODO-CQ: support hot/cold splitting with EH
639
640 emitLocation* startLoc;
641 emitLocation* endLoc;
642 unwindGetFuncLocations(func, false, &startLoc, &endLoc);
643
644 func->uwiCold = new (this, CMK_UnwindInfo) UnwindInfo();
645 func->uwiCold->InitUnwindInfo(this, startLoc, endLoc);
646 func->uwiCold->HotColdSplitCodes(&func->uwi);
647
648 funcHasColdSection = true;
649 }
650
651 // First we need to split the function or funclet into fragments that are no larger
652 // than 512K, so the fragment size will fit in the unwind data "Function Length" field.
653 // The ARM Exception Data specification "Function Fragments" section describes this.
654 func->uwi.Split();
655
656 func->uwi.Reserve(isFunclet, true);
657
658 // After the hot section, split and reserve the cold section
659
660 if (funcHasColdSection)
661 {
662 assert(func->uwiCold != NULL);
663
664 func->uwiCold->Split();
665 func->uwiCold->Reserve(isFunclet, false);
666 }
667}
668
669// unwindEmit: Report all the unwind information to the VM.
670// Arguments:
671// pHotCode: Pointer to the beginning of the memory with the function and funclet hot code
672// pColdCode: Pointer to the beginning of the memory with the function and funclet cold code.
673
674void Compiler::unwindEmit(void* pHotCode, void* pColdCode)
675{
676 assert(compFuncInfoCount > 0);
677 for (unsigned funcIdx = 0; funcIdx < compFuncInfoCount; funcIdx++)
678 {
679 unwindEmitFunc(funGetFunc(funcIdx), pHotCode, pColdCode);
680 }
681}
682
683void Compiler::unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode)
684{
685 // Verify that the JIT enum is in sync with the JIT-EE interface enum
686 static_assert_no_msg(FUNC_ROOT == (FuncKind)CORJIT_FUNC_ROOT);
687 static_assert_no_msg(FUNC_HANDLER == (FuncKind)CORJIT_FUNC_HANDLER);
688 static_assert_no_msg(FUNC_FILTER == (FuncKind)CORJIT_FUNC_FILTER);
689
690#if defined(_TARGET_UNIX_)
691 if (generateCFIUnwindCodes())
692 {
693 unwindEmitFuncCFI(func, pHotCode, pColdCode);
694 return;
695 }
696#endif // _TARGET_UNIX_
697
698 func->uwi.Allocate((CorJitFuncKind)func->funKind, pHotCode, pColdCode, true);
699
700 if (func->uwiCold != NULL)
701 {
702 func->uwiCold->Allocate((CorJitFuncKind)func->funKind, pHotCode, pColdCode, false);
703 }
704}
705
706#if defined(_TARGET_ARM_)
707
708/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
709XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
710XX XX
711XX Unwind Info Debug helpers XX
712XX XX
713XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
714XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
715*/
716
717#ifdef DEBUG
718
719// Return the opcode size of an instruction, in bytes, given the first byte of
720// its corresponding unwind code.
721
722unsigned GetOpcodeSizeFromUnwindHeader(BYTE b1)
723{
724 static BYTE s_UnwindOpsize[256] = {
725 // array of opsizes, in bytes (as specified in the ARM unwind specification)
726 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 00-0F
727 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 10-1F
728 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 20-2F
729 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 30-3F
730 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 40-4F
731 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 50-5F
732 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 60-6F
733 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 70-7F
734 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 80-8F
735 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 90-9F
736 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // A0-AF
737 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // B0-BF
738 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0-CF
739 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, // D0-DF
740 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 4, // E0-EF
741 0, 0, 0, 0, 0, 4, 4, 2, 2, 4, 4, 2, 4, 2, 4, 0 // F0-FF
742 };
743
744 BYTE opsize = s_UnwindOpsize[b1];
745 assert(opsize == 2 ||
746 opsize == 4); // We shouldn't get a code with no opsize (the 0xFF end code is handled specially)
747 return opsize;
748}
749
750// Return the size of the unwind code (from 1 to 4 bytes), given the first byte of the unwind bytes
751
752unsigned GetUnwindSizeFromUnwindHeader(BYTE b1)
753{
754 static BYTE s_UnwindSize[256] = {
755 // array of unwind sizes, in bytes (as specified in the ARM unwind specification)
756 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 00-0F
757 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10-1F
758 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20-2F
759 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30-3F
760 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40-4F
761 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 50-5F
762 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60-6F
763 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 70-7F
764 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 80-8F
765 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 90-9F
766 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // A0-AF
767 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // B0-BF
768 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C0-CF
769 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D0-DF
770 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, // E0-EF
771 1, 1, 1, 1, 1, 2, 2, 3, 4, 3, 4, 1, 1, 1, 1, 1 // F0-FF
772 };
773
774 unsigned size = s_UnwindSize[b1];
775 assert(1 <= size && size <= 4);
776 return size;
777}
778
779#endif // DEBUG
780
781/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
782XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
783XX XX
784XX Unwind Info Support Classes XX
785XX XX
786XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
787XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
788*/
789
790///////////////////////////////////////////////////////////////////////////////
791//
792// UnwindCodesBase
793//
794///////////////////////////////////////////////////////////////////////////////
795
796#ifdef DEBUG
797
798// Walk the prolog codes and calculate the size of the prolog or epilog, in bytes.
799// The 0xFD and 0xFE "end + NOP" codes need to be handled differently between
800// the prolog and epilog. They count as pure "end" codes in a prolog, but they
801// count as 16 and 32 bit NOPs (respectively), as well as an "end", in an epilog.
802unsigned UnwindCodesBase::GetCodeSizeFromUnwindCodes(bool isProlog)
803{
804 BYTE* pCodesStart = GetCodes();
805 BYTE* pCodes = pCodesStart;
806 unsigned size = 0;
807 for (;;)
808 {
809 BYTE b1 = *pCodes;
810 if (b1 >= 0xFD)
811 {
812 // 0xFD, 0xFE, 0xFF are "end" codes
813
814 if (!isProlog && (b1 == 0xFD || b1 == 0xFE))
815 {
816 // Count the special "end + NOP" code size in the epilog
817 size += GetOpcodeSizeFromUnwindHeader(b1);
818 }
819
820 break; // We hit an "end" code; we're done
821 }
822 size += GetOpcodeSizeFromUnwindHeader(b1);
823 pCodes += GetUnwindSizeFromUnwindHeader(b1);
824 assert(pCodes - pCodesStart < 256); // 255 is the absolute maximum number of code bytes allowed
825 }
826 return size;
827}
828
829#endif // DEBUG
830
831#endif // defined(_TARGET_ARM_)
832
833///////////////////////////////////////////////////////////////////////////////
834//
835// UnwindPrologCodes
836//
837///////////////////////////////////////////////////////////////////////////////
838
839// We're going to use the prolog codes memory to store the final unwind data.
840// Ensure we have enough memory to store everything. If 'epilogBytes' > 0, then
841// move the prolog codes so there are 'epilogBytes' bytes after the prolog codes.
842// Set the header pointer for future use, adding the header bytes (this pointer
843// is updated when a header byte is added), and remember the index that points
844// to the beginning of the header.
845
846void UnwindPrologCodes::SetFinalSize(int headerBytes, int epilogBytes)
847{
848#ifdef DEBUG
849 // We're done adding codes. Check that we didn't accidentally create a bigger prolog.
850 unsigned codeSize = GetCodeSizeFromUnwindCodes(true);
851 assert(codeSize <= MAX_PROLOG_SIZE_BYTES);
852#endif // DEBUG
853
854 int prologBytes = Size();
855
856 EnsureSize(headerBytes + prologBytes + epilogBytes + 3); // 3 = padding bytes for alignment
857
858 upcUnwindBlockSlot = upcCodeSlot - headerBytes - epilogBytes; // Index of the first byte of the unwind header
859
860 assert(upcMemSize == upcUnwindBlockSlot + headerBytes + prologBytes + epilogBytes + 3);
861
862 upcHeaderSlot = upcUnwindBlockSlot - 1; // upcHeaderSlot is always incremented before storing
863 assert(upcHeaderSlot >= -1);
864
865 if (epilogBytes > 0)
866 {
867 // The prolog codes that are already at the end of the array need to get moved to the middle,
868 // with space for the non-matching epilog codes to follow.
869
870 memmove_s(&upcMem[upcUnwindBlockSlot + headerBytes], upcMemSize - (upcUnwindBlockSlot + headerBytes),
871 &upcMem[upcCodeSlot], prologBytes);
872
873 // Note that the three UWC_END padding bytes still exist at the end of the array.
874 CLANG_FORMAT_COMMENT_ANCHOR;
875
876#ifdef DEBUG
877 // Zero out the epilog codes memory, to ensure we've copied the right bytes. Don't zero the padding bytes.
878 memset(&upcMem[upcUnwindBlockSlot + headerBytes + prologBytes], 0, epilogBytes);
879#endif // DEBUG
880
881 upcEpilogSlot =
882 upcUnwindBlockSlot + headerBytes + prologBytes; // upcEpilogSlot points to the next epilog location to fill
883
884 // Update upcCodeSlot to point at the new beginning of the prolog codes
885 upcCodeSlot = upcUnwindBlockSlot + headerBytes;
886 }
887}
888
889// Add a header word. Header words are added starting at the beginning, in order: first to last.
890// This is in contrast to the prolog unwind codes, which are added in reverse order.
891void UnwindPrologCodes::AddHeaderWord(DWORD d)
892{
893 assert(-1 <= upcHeaderSlot);
894 assert(upcHeaderSlot + 4 < upcCodeSlot); // Don't collide with the unwind codes that are already there!
895
896 // Store it byte-by-byte in little-endian format. We've already ensured there is enough space
897 // in SetFinalSize().
898 upcMem[++upcHeaderSlot] = (BYTE)d;
899 upcMem[++upcHeaderSlot] = (BYTE)(d >> 8);
900 upcMem[++upcHeaderSlot] = (BYTE)(d >> 16);
901 upcMem[++upcHeaderSlot] = (BYTE)(d >> 24);
902}
903
904// AppendEpilog: copy the epilog bytes to the next epilog bytes slot
905void UnwindPrologCodes::AppendEpilog(UnwindEpilogInfo* pEpi)
906{
907 assert(upcEpilogSlot != -1);
908
909 int epiSize = pEpi->Size();
910 memcpy_s(&upcMem[upcEpilogSlot], upcMemSize - upcEpilogSlot - 3, pEpi->GetCodes(),
911 epiSize); // -3 to avoid writing to the alignment padding
912 assert(pEpi->GetStartIndex() ==
913 upcEpilogSlot - upcCodeSlot); // Make sure we copied it where we expected to copy it.
914
915 upcEpilogSlot += epiSize;
916 assert(upcEpilogSlot <= upcMemSize - 3);
917}
918
919// GetFinalInfo: return a pointer to the final unwind info to hand to the VM, and the size of this info in bytes
920void UnwindPrologCodes::GetFinalInfo(/* OUT */ BYTE** ppUnwindBlock, /* OUT */ ULONG* pUnwindBlockSize)
921{
922 assert(upcHeaderSlot + 1 == upcCodeSlot); // We better have filled in the header before asking for the final data!
923
924 *ppUnwindBlock = &upcMem[upcUnwindBlockSlot];
925
926 // We put 4 'end' codes at the end for padding, so we can ensure we have an
927 // unwind block that is a multiple of 4 bytes in size. Subtract off three 'end'
928 // codes (leave one), and then align the size up to a multiple of 4.
929 *pUnwindBlockSize = AlignUp((UINT)(upcMemSize - upcUnwindBlockSlot - 3), sizeof(DWORD));
930}
931
932// Do the argument unwind codes match our unwind codes?
933// If they don't match, return -1. If they do, return the offset into
934// our codes at which they match. Note that this means that the
935// argument codes can match a subset of our codes. The subset needs to be at
936// the end, for the "end" code to match.
937//
938// This is similar to UnwindEpilogInfo::Match().
939//
940#if defined(_TARGET_ARM_)
941// Note that if we wanted to handle 0xFD and 0xFE codes, by converting
942// an existing 0xFF code to one of those, we might do that here.
943#endif // defined(_TARGET_ARM_)
944
945int UnwindPrologCodes::Match(UnwindEpilogInfo* pEpi)
946{
947 if (Size() < pEpi->Size())
948 {
949 return -1;
950 }
951
952 int matchIndex = Size() - pEpi->Size();
953
954 if (0 == memcmp(GetCodes() + matchIndex, pEpi->GetCodes(), pEpi->Size()))
955 {
956 return matchIndex;
957 }
958
959 return -1;
960}
961
962// Copy the prolog codes from another prolog. The only time this is legal is
963// if we are at the initial state and no prolog codes have been added.
964// This is used to create the 'phantom' prolog for non-first fragments.
965
966void UnwindPrologCodes::CopyFrom(UnwindPrologCodes* pCopyFrom)
967{
968 assert(uwiComp == pCopyFrom->uwiComp);
969 assert(upcMem == upcMemLocal);
970 assert(upcMemSize == UPC_LOCAL_COUNT);
971 assert(upcHeaderSlot == -1);
972 assert(upcEpilogSlot == -1);
973
974 // Copy the codes
975 EnsureSize(pCopyFrom->upcMemSize);
976 assert(upcMemSize == pCopyFrom->upcMemSize);
977 memcpy_s(upcMem, upcMemSize, pCopyFrom->upcMem, pCopyFrom->upcMemSize);
978
979 // Copy the other data
980 upcCodeSlot = pCopyFrom->upcCodeSlot;
981 upcHeaderSlot = pCopyFrom->upcHeaderSlot;
982 upcEpilogSlot = pCopyFrom->upcEpilogSlot;
983 upcUnwindBlockSlot = pCopyFrom->upcUnwindBlockSlot;
984}
985
986void UnwindPrologCodes::EnsureSize(int requiredSize)
987{
988 if (requiredSize > upcMemSize)
989 {
990 // Reallocate, and copy everything to a new array.
991
992 // Choose the next power of two size. This may or may not be the best choice.
993 noway_assert((requiredSize & 0xC0000000) == 0); // too big!
994 int newSize;
995 for (newSize = upcMemSize << 1; newSize < requiredSize; newSize <<= 1)
996 {
997 // do nothing
998 }
999
1000 BYTE* newUnwindCodes = new (uwiComp, CMK_UnwindInfo) BYTE[newSize];
1001 memcpy_s(newUnwindCodes + newSize - upcMemSize, upcMemSize, upcMem,
1002 upcMemSize); // copy the existing data to the end
1003#ifdef DEBUG
1004 // Clear the old unwind codes; nobody should be looking at them
1005 memset(upcMem, 0xFF, upcMemSize);
1006#endif // DEBUG
1007 upcMem = newUnwindCodes; // we don't free anything that used to be there since we have a no-release allocator
1008 upcCodeSlot += newSize - upcMemSize;
1009 upcMemSize = newSize;
1010 }
1011}
1012
1013#ifdef DEBUG
1014void UnwindPrologCodes::Dump(int indent)
1015{
1016 printf("%*sUnwindPrologCodes @0x%08p, size:%d:\n", indent, "", dspPtr(this), sizeof(*this));
1017 printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
1018 printf("%*s &upcMemLocal[0]: 0x%08p\n", indent, "", dspPtr(&upcMemLocal[0]));
1019 printf("%*s upcMem: 0x%08p\n", indent, "", dspPtr(upcMem));
1020 printf("%*s upcMemSize: %d\n", indent, "", upcMemSize);
1021 printf("%*s upcCodeSlot: %d\n", indent, "", upcCodeSlot);
1022 printf("%*s upcHeaderSlot: %d\n", indent, "", upcHeaderSlot);
1023 printf("%*s upcEpilogSlot: %d\n", indent, "", upcEpilogSlot);
1024 printf("%*s upcUnwindBlockSlot: %d\n", indent, "", upcUnwindBlockSlot);
1025
1026 if (upcMemSize > 0)
1027 {
1028 printf("%*s codes:", indent, "");
1029 for (int i = 0; i < upcMemSize; i++)
1030 {
1031 printf(" %02x", upcMem[i]);
1032 if (i == upcCodeSlot)
1033 printf(" <-C");
1034 else if (i == upcHeaderSlot)
1035 printf(" <-H");
1036 else if (i == upcEpilogSlot)
1037 printf(" <-E");
1038 else if (i == upcUnwindBlockSlot)
1039 printf(" <-U");
1040 }
1041 printf("\n");
1042 }
1043}
1044#endif // DEBUG
1045
1046///////////////////////////////////////////////////////////////////////////////
1047//
1048// UnwindEpilogCodes
1049//
1050///////////////////////////////////////////////////////////////////////////////
1051
1052void UnwindEpilogCodes::EnsureSize(int requiredSize)
1053{
1054 if (requiredSize > uecMemSize)
1055 {
1056 // Reallocate, and copy everything to a new array.
1057
1058 // Choose the next power of two size. This may or may not be the best choice.
1059 noway_assert((requiredSize & 0xC0000000) == 0); // too big!
1060 int newSize;
1061 for (newSize = uecMemSize << 1; newSize < requiredSize; newSize <<= 1)
1062 {
1063 // do nothing
1064 }
1065
1066 BYTE* newUnwindCodes = new (uwiComp, CMK_UnwindInfo) BYTE[newSize];
1067 memcpy_s(newUnwindCodes, newSize, uecMem, uecMemSize);
1068#ifdef DEBUG
1069 // Clear the old unwind codes; nobody should be looking at them
1070 memset(uecMem, 0xFF, uecMemSize);
1071#endif // DEBUG
1072 uecMem = newUnwindCodes; // we don't free anything that used to be there since we have a no-release allocator
1073 // uecCodeSlot stays the same
1074 uecMemSize = newSize;
1075 }
1076}
1077
1078#ifdef DEBUG
1079void UnwindEpilogCodes::Dump(int indent)
1080{
1081 printf("%*sUnwindEpilogCodes @0x%08p, size:%d:\n", indent, "", dspPtr(this), sizeof(*this));
1082 printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
1083 printf("%*s &uecMemLocal[0]: 0x%08p\n", indent, "", dspPtr(&uecMemLocal[0]));
1084 printf("%*s uecMem: 0x%08p\n", indent, "", dspPtr(uecMem));
1085 printf("%*s uecMemSize: %d\n", indent, "", uecMemSize);
1086 printf("%*s uecCodeSlot: %d\n", indent, "", uecCodeSlot);
1087 printf("%*s uecFinalized: %s\n", indent, "", dspBool(uecFinalized));
1088
1089 if (uecMemSize > 0)
1090 {
1091 printf("%*s codes:", indent, "");
1092 for (int i = 0; i < uecMemSize; i++)
1093 {
1094 printf(" %02x", uecMem[i]);
1095 if (i == uecCodeSlot)
1096 printf(" <-C"); // Indicate the current pointer
1097 }
1098 printf("\n");
1099 }
1100}
1101#endif // DEBUG
1102
1103///////////////////////////////////////////////////////////////////////////////
1104//
1105// UnwindEpilogInfo
1106//
1107///////////////////////////////////////////////////////////////////////////////
1108
1109// Do the current unwind codes match those of the argument epilog?
1110// If they don't match, return -1. If they do, return the offset into
1111// our codes at which the argument codes match. Note that this means that
1112// the argument codes can match a subset of our codes. The subset needs to be at
1113// the end, for the "end" code to match.
1114//
1115// Note that if we wanted to handle 0xFD and 0xFE codes, by converting
1116// an existing 0xFF code to one of those, we might do that here.
1117
1118int UnwindEpilogInfo::Match(UnwindEpilogInfo* pEpi)
1119{
1120 if (Matches())
1121 {
1122 // We are already matched to someone else, and won't provide codes to the final layout
1123 return -1;
1124 }
1125
1126 if (Size() < pEpi->Size())
1127 {
1128 return -1;
1129 }
1130
1131 int matchIndex = Size() - pEpi->Size();
1132
1133 if (0 == memcmp(GetCodes() + matchIndex, pEpi->GetCodes(), pEpi->Size()))
1134 {
1135 return matchIndex;
1136 }
1137
1138 return -1;
1139}
1140
1141void UnwindEpilogInfo::CaptureEmitLocation()
1142{
1143 noway_assert(epiEmitLocation == NULL); // This function is only called once per epilog
1144 epiEmitLocation = new (uwiComp, CMK_UnwindInfo) emitLocation();
1145 epiEmitLocation->CaptureLocation(uwiComp->genEmitter);
1146}
1147
1148void UnwindEpilogInfo::FinalizeOffset()
1149{
1150 epiStartOffset = epiEmitLocation->CodeOffset(uwiComp->genEmitter);
1151}
1152
1153#ifdef DEBUG
1154void UnwindEpilogInfo::Dump(int indent)
1155{
1156 printf("%*sUnwindEpilogInfo @0x%08p, size:%d:\n", indent, "", dspPtr(this), sizeof(*this));
1157 printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
1158 printf("%*s epiNext: 0x%08p\n", indent, "", dspPtr(epiNext));
1159 printf("%*s epiEmitLocation: 0x%08p\n", indent, "", dspPtr(epiEmitLocation));
1160 printf("%*s epiStartOffset: 0x%x\n", indent, "", epiStartOffset);
1161 printf("%*s epiMatches: %s\n", indent, "", dspBool(epiMatches));
1162 printf("%*s epiStartIndex: %d\n", indent, "", epiStartIndex);
1163
1164 epiCodes.Dump(indent + 2);
1165}
1166#endif // DEBUG
1167
1168///////////////////////////////////////////////////////////////////////////////
1169//
1170// UnwindFragmentInfo
1171//
1172///////////////////////////////////////////////////////////////////////////////
1173
1174UnwindFragmentInfo::UnwindFragmentInfo(Compiler* comp, emitLocation* emitLoc, bool hasPhantomProlog)
1175 : UnwindBase(comp)
1176 , ufiNext(NULL)
1177 , ufiEmitLoc(emitLoc)
1178 , ufiHasPhantomProlog(hasPhantomProlog)
1179 , ufiPrologCodes(comp)
1180 , ufiEpilogFirst(comp)
1181 , ufiEpilogList(NULL)
1182 , ufiEpilogLast(NULL)
1183 , ufiCurCodes(&ufiPrologCodes)
1184 , ufiSize(0)
1185 , ufiStartOffset(UFI_ILLEGAL_OFFSET)
1186{
1187#ifdef DEBUG
1188 ufiNum = 1;
1189 ufiInProlog = true;
1190 ufiInitialized = UFI_INITIALIZED_PATTERN;
1191#endif // DEBUG
1192}
1193
1194void UnwindFragmentInfo::FinalizeOffset()
1195{
1196 if (ufiEmitLoc == NULL)
1197 {
1198 // NULL emit location means the beginning of the code. This is to handle the first fragment prolog.
1199 ufiStartOffset = 0;
1200 }
1201 else
1202 {
1203 ufiStartOffset = ufiEmitLoc->CodeOffset(uwiComp->genEmitter);
1204 }
1205
1206 for (UnwindEpilogInfo* pEpi = ufiEpilogList; pEpi != NULL; pEpi = pEpi->epiNext)
1207 {
1208 pEpi->FinalizeOffset();
1209 }
1210}
1211
1212void UnwindFragmentInfo::AddEpilog()
1213{
1214 assert(ufiInitialized == UFI_INITIALIZED_PATTERN);
1215
1216#ifdef DEBUG
1217 if (ufiInProlog)
1218 {
1219 assert(ufiEpilogList == NULL);
1220 ufiInProlog = false;
1221 }
1222 else
1223 {
1224 assert(ufiEpilogList != NULL);
1225 }
1226#endif // DEBUG
1227
1228 // Either allocate a new epilog object, or, for the first one, use the
1229 // preallocated one that is a member of the UnwindFragmentInfo class.
1230
1231 UnwindEpilogInfo* newepi;
1232
1233 if (ufiEpilogList == NULL)
1234 {
1235 // Use the epilog that's in the class already. Be sure to initialize it!
1236 newepi = ufiEpilogList = &ufiEpilogFirst;
1237 }
1238 else
1239 {
1240 newepi = new (uwiComp, CMK_UnwindInfo) UnwindEpilogInfo(uwiComp);
1241 }
1242
1243 // Put the new epilog at the end of the epilog list
1244
1245 if (ufiEpilogLast != NULL)
1246 {
1247 ufiEpilogLast->epiNext = newepi;
1248 }
1249
1250 ufiEpilogLast = newepi;
1251
1252 // What is the starting code offset of the epilog? Store an emitter location
1253 // so we can ask the emitter later, after codegen.
1254
1255 newepi->CaptureEmitLocation();
1256
1257 // Put subsequent unwind codes in this new epilog
1258
1259 ufiCurCodes = &newepi->epiCodes;
1260}
1261
1262// Copy the prolog codes from the 'pCopyFrom' fragment. These prolog codes will
1263// become 'phantom' prolog codes in this fragment. Note that this fragment should
1264// not have any prolog codes currently; it is at the initial state.
1265
1266void UnwindFragmentInfo::CopyPrologCodes(UnwindFragmentInfo* pCopyFrom)
1267{
1268 ufiPrologCodes.CopyFrom(&pCopyFrom->ufiPrologCodes);
1269#ifdef _TARGET_ARM64_
1270 ufiPrologCodes.AddCode(UWC_END_C);
1271#endif
1272}
1273
1274// Split the epilog codes that currently exist in 'pSplitFrom'. The ones that represent
1275// epilogs that start at or after the location represented by 'emitLoc' are removed
1276// from 'pSplitFrom' and moved to this fragment. Note that this fragment should not have
1277// any epilog codes currently; it is at the initial state.
1278
1279void UnwindFragmentInfo::SplitEpilogCodes(emitLocation* emitLoc, UnwindFragmentInfo* pSplitFrom)
1280{
1281 UnwindEpilogInfo* pEpiPrev;
1282 UnwindEpilogInfo* pEpi;
1283
1284 UNATIVE_OFFSET splitOffset = emitLoc->CodeOffset(uwiComp->genEmitter);
1285
1286 for (pEpiPrev = NULL, pEpi = pSplitFrom->ufiEpilogList; pEpi != NULL; pEpiPrev = pEpi, pEpi = pEpi->epiNext)
1287 {
1288 pEpi->FinalizeOffset(); // Get the offset of the epilog from the emitter so we can compare it
1289 if (pEpi->GetStartOffset() >= splitOffset)
1290 {
1291 // This epilog and all following epilogs, which must be in order of increasing offsets,
1292 // get moved to this fragment.
1293
1294 // Splice in the epilogs to this fragment. Set the head of the epilog
1295 // list to this epilog.
1296 ufiEpilogList = pEpi; // In this case, don't use 'ufiEpilogFirst'
1297 ufiEpilogLast = pSplitFrom->ufiEpilogLast;
1298
1299 // Splice out the tail of the list from the 'pSplitFrom' epilog list
1300 pSplitFrom->ufiEpilogLast = pEpiPrev;
1301 if (pSplitFrom->ufiEpilogLast == NULL)
1302 {
1303 pSplitFrom->ufiEpilogList = NULL;
1304 }
1305 else
1306 {
1307 pSplitFrom->ufiEpilogLast->epiNext = NULL;
1308 }
1309
1310 // No more codes should be added once we start splitting
1311 pSplitFrom->ufiCurCodes = NULL;
1312 ufiCurCodes = NULL;
1313
1314 break;
1315 }
1316 }
1317}
1318
1319// Is this epilog at the end of an unwind fragment? Ask the emitter.
1320// Note that we need to know this before all code offsets are finalized,
1321// so we can determine whether we can omit an epilog scope word for a
1322// single matching epilog.
1323
1324bool UnwindFragmentInfo::IsAtFragmentEnd(UnwindEpilogInfo* pEpi)
1325{
1326 return uwiComp->genEmitter->emitIsFuncEnd(pEpi->epiEmitLocation, (ufiNext == NULL) ? NULL : ufiNext->ufiEmitLoc);
1327}
1328
1329// Merge the unwind codes as much as possible.
1330// This function is called before all offsets are final.
1331// Also, compute the size of the final unwind block. Store this
1332// and some other data for later, when we actually emit the
1333// unwind block.
1334
1335void UnwindFragmentInfo::MergeCodes()
1336{
1337 assert(ufiInitialized == UFI_INITIALIZED_PATTERN);
1338
1339 unsigned epilogCount = 0;
1340 unsigned epilogCodeBytes = 0; // The total number of unwind code bytes used by epilogs that don't match the
1341 // prolog codes
1342 unsigned epilogIndex = ufiPrologCodes.Size(); // The "Epilog Start Index" for the next non-matching epilog codes
1343 UnwindEpilogInfo* pEpi;
1344
1345 for (pEpi = ufiEpilogList; pEpi != NULL; pEpi = pEpi->epiNext)
1346 {
1347 ++epilogCount;
1348
1349 pEpi->FinalizeCodes();
1350
1351 // Does this epilog match the prolog?
1352 // NOTE: for the purpose of matching, we don't handle the 0xFD and 0xFE end codes that allow slightly unequal
1353 // prolog and epilog codes.
1354
1355 int matchIndex;
1356
1357 matchIndex = ufiPrologCodes.Match(pEpi);
1358 if (matchIndex != -1)
1359 {
1360 pEpi->SetMatches();
1361 pEpi->SetStartIndex(matchIndex); // Prolog codes start at zero, so matchIndex is exactly the start index
1362 }
1363 else
1364 {
1365 // The epilog codes don't match the prolog codes. Do they match any of the epilogs
1366 // we've seen so far?
1367
1368 bool matched = false;
1369 for (UnwindEpilogInfo* pEpi2 = ufiEpilogList; pEpi2 != pEpi; pEpi2 = pEpi2->epiNext)
1370 {
1371 matchIndex = pEpi2->Match(pEpi);
1372 if (matchIndex != -1)
1373 {
1374 // Use the same epilog index as the one we matched, as it has already been set.
1375 pEpi->SetMatches();
1376 pEpi->SetStartIndex(pEpi2->GetStartIndex() + matchIndex); // We might match somewhere inside pEpi2's
1377 // codes, in which case matchIndex > 0
1378 matched = true;
1379 break;
1380 }
1381 }
1382
1383 if (!matched)
1384 {
1385 pEpi->SetStartIndex(epilogIndex); // We'll copy these codes to the next available location
1386 epilogCodeBytes += pEpi->Size();
1387 epilogIndex += pEpi->Size();
1388 }
1389 }
1390 }
1391
1392 DWORD codeBytes = ufiPrologCodes.Size() + epilogCodeBytes;
1393 codeBytes = AlignUp(codeBytes, sizeof(DWORD));
1394
1395 DWORD codeWords =
1396 codeBytes / sizeof(DWORD); // This is how many words we need to store all the unwind codes in the unwind block
1397
1398 // Do we need the 2nd header word for "Extended Code Words" or "Extended Epilog Count"?
1399
1400 bool needExtendedCodeWordsEpilogCount =
1401 (codeWords > UW_MAX_CODE_WORDS_COUNT) || (epilogCount > UW_MAX_EPILOG_COUNT);
1402
1403 // How many epilog scope words do we need?
1404
1405 bool setEBit = false; // do we need to set the E bit?
1406 unsigned epilogScopes = epilogCount; // Note that this could be zero if we have no epilogs!
1407
1408 if (epilogCount == 1)
1409 {
1410 assert(ufiEpilogList != NULL);
1411 assert(ufiEpilogList->epiNext == NULL);
1412
1413 if (ufiEpilogList->Matches() && (ufiEpilogList->GetStartIndex() == 0) && // The match is with the prolog
1414 !needExtendedCodeWordsEpilogCount && IsAtFragmentEnd(ufiEpilogList))
1415 {
1416 epilogScopes = 0; // Don't need any epilog scope words
1417 setEBit = true;
1418 }
1419 }
1420
1421 DWORD headerBytes = (1 // Always need first header DWORD
1422 + (needExtendedCodeWordsEpilogCount ? 1 : 0) // Do we need the 2nd DWORD for Extended Code
1423 // Words or Extended Epilog Count?
1424 + epilogScopes // One DWORD per epilog scope, for EBit = 0
1425 ) *
1426 sizeof(DWORD); // convert it to bytes
1427
1428 DWORD finalSize = headerBytes + codeBytes; // Size of actual unwind codes, aligned up to 4-byte words,
1429 // including end padding if necessary
1430
1431 // Construct the final unwind information.
1432
1433 // We re-use the memory for the prolog unwind codes to construct the full unwind data. If all the epilogs
1434 // match the prolog, this is easy: we just prepend the header. If there are epilog codes that don't match
1435 // the prolog, we still use the prolog codes memory, but it's a little more complicated, since the
1436 // unwind info is ordered as: (a) header, (b) prolog codes, (c) non-matching epilog codes. And, the prolog
1437 // codes array is filled in from end-to-beginning. So, we compute the size of memory we need, ensure we
1438 // have that much memory, and then copy the prolog codes to the right place, appending the non-matching
1439 // epilog codes and prepending the header.
1440
1441 ufiPrologCodes.SetFinalSize(headerBytes, epilogCodeBytes);
1442
1443 if (epilogCodeBytes != 0)
1444 {
1445 // We need to copy the epilog code bytes to their final memory location
1446
1447 for (pEpi = ufiEpilogList; pEpi != NULL; pEpi = pEpi->epiNext)
1448 {
1449 if (!pEpi->Matches())
1450 {
1451 ufiPrologCodes.AppendEpilog(pEpi);
1452 }
1453 }
1454 }
1455
1456 // Save some data for later
1457
1458 ufiSize = finalSize;
1459 ufiSetEBit = setEBit;
1460 ufiNeedExtendedCodeWordsEpilogCount = needExtendedCodeWordsEpilogCount;
1461 ufiCodeWords = codeWords;
1462 ufiEpilogScopes = epilogScopes;
1463}
1464
1465// Finalize: Prepare the unwind information for the VM. Compute and prepend the unwind header.
1466
1467void UnwindFragmentInfo::Finalize(UNATIVE_OFFSET functionLength)
1468{
1469 assert(ufiInitialized == UFI_INITIALIZED_PATTERN);
1470
1471#ifdef DEBUG
1472 if (0 && uwiComp->verbose)
1473 {
1474 printf("*************** Before fragment #%d finalize\n", ufiNum);
1475 Dump();
1476 }
1477#endif
1478
1479// Compute the header
1480
1481#if defined(_TARGET_ARM_)
1482 noway_assert((functionLength & 1) == 0);
1483 DWORD headerFunctionLength = functionLength / 2;
1484#elif defined(_TARGET_ARM64_)
1485 noway_assert((functionLength & 3) == 0);
1486 DWORD headerFunctionLength = functionLength / 4;
1487#endif // _TARGET_ARM64_
1488
1489 DWORD headerVers = 0; // Version of the unwind info is zero. No other version number is currently defined.
1490 DWORD headerXBit = 0; // We never generate "exception data", but the VM might add some.
1491 DWORD headerEBit;
1492#if defined(_TARGET_ARM_)
1493 DWORD headerFBit = ufiHasPhantomProlog ? 1 : 0; // Is this data a fragment in the sense of the unwind data
1494 // specification? That is, do the prolog codes represent a real
1495 // prolog or not?
1496#endif // defined(_TARGET_ARM_)
1497 DWORD headerEpilogCount; // This depends on how we set headerEBit.
1498 DWORD headerCodeWords;
1499 DWORD headerExtendedEpilogCount = 0; // This depends on how we set headerEBit.
1500 DWORD headerExtendedCodeWords = 0;
1501
1502 if (ufiSetEBit)
1503 {
1504 headerEBit = 1;
1505 headerEpilogCount = ufiEpilogList->GetStartIndex(); // probably zero -- the start of the prolog codes!
1506 headerCodeWords = ufiCodeWords;
1507 }
1508 else
1509 {
1510 headerEBit = 0;
1511
1512 if (ufiNeedExtendedCodeWordsEpilogCount)
1513 {
1514 headerEpilogCount = 0;
1515 headerCodeWords = 0;
1516 headerExtendedEpilogCount = ufiEpilogScopes;
1517 headerExtendedCodeWords = ufiCodeWords;
1518 }
1519 else
1520 {
1521 headerEpilogCount = ufiEpilogScopes;
1522 headerCodeWords = ufiCodeWords;
1523 }
1524 }
1525
1526 // Start writing the header
1527
1528 noway_assert(headerFunctionLength <=
1529 0x3FFFFU); // We create fragments to prevent this from firing, so if it hits, we have an internal error
1530
1531 if ((headerEpilogCount > UW_MAX_EPILOG_COUNT) || (headerCodeWords > UW_MAX_CODE_WORDS_COUNT))
1532 {
1533 IMPL_LIMITATION("unwind data too large");
1534 }
1535
1536#if defined(_TARGET_ARM_)
1537 DWORD header = headerFunctionLength | (headerVers << 18) | (headerXBit << 20) | (headerEBit << 21) |
1538 (headerFBit << 22) | (headerEpilogCount << 23) | (headerCodeWords << 28);
1539#elif defined(_TARGET_ARM64_)
1540 DWORD header = headerFunctionLength | (headerVers << 18) | (headerXBit << 20) | (headerEBit << 21) |
1541 (headerEpilogCount << 22) | (headerCodeWords << 27);
1542#endif // defined(_TARGET_ARM64_)
1543
1544 ufiPrologCodes.AddHeaderWord(header);
1545
1546 // Construct the second header word, if needed
1547
1548 if (ufiNeedExtendedCodeWordsEpilogCount)
1549 {
1550 noway_assert(headerEBit == 0);
1551 noway_assert(headerEpilogCount == 0);
1552 noway_assert(headerCodeWords == 0);
1553 noway_assert((headerExtendedEpilogCount > UW_MAX_EPILOG_COUNT) ||
1554 (headerExtendedCodeWords > UW_MAX_CODE_WORDS_COUNT));
1555
1556 if ((headerExtendedEpilogCount > UW_MAX_EXTENDED_EPILOG_COUNT) ||
1557 (headerExtendedCodeWords > UW_MAX_EXTENDED_CODE_WORDS_COUNT))
1558 {
1559 IMPL_LIMITATION("unwind data too large");
1560 }
1561
1562 DWORD header2 = headerExtendedEpilogCount | (headerExtendedCodeWords << 16);
1563
1564 ufiPrologCodes.AddHeaderWord(header2);
1565 }
1566
1567 // Construct the epilog scope words, if needed
1568
1569 if (!ufiSetEBit)
1570 {
1571 for (UnwindEpilogInfo* pEpi = ufiEpilogList; pEpi != NULL; pEpi = pEpi->epiNext)
1572 {
1573#if defined(_TARGET_ARM_)
1574 DWORD headerCondition = 0xE; // The epilog is unconditional. We don't have epilogs under the IT instruction.
1575#endif // defined(_TARGET_ARM_)
1576
1577 // The epilog must strictly follow the prolog. The prolog is in the first fragment of
1578 // the hot section. If this epilog is at the start of a fragment, it can't be the
1579 // first fragment in the hot section. We actually don't know if we're processing
1580 // the hot or cold section (or a funclet), so we can't distinguish these cases. Thus,
1581 // we just assert that the epilog starts within the fragment.
1582 assert(pEpi->GetStartOffset() >= GetStartOffset());
1583
1584 // We report the offset of an epilog as the offset from the beginning of the function/funclet fragment,
1585 // NOT the offset from the beginning of the main function.
1586 DWORD headerEpilogStartOffset = pEpi->GetStartOffset() - GetStartOffset();
1587
1588#if defined(_TARGET_ARM_)
1589 noway_assert((headerEpilogStartOffset & 1) == 0);
1590 headerEpilogStartOffset /= 2; // The unwind data stores the actual offset divided by 2 (since the low bit of
1591 // the actual offset is always zero)
1592#elif defined(_TARGET_ARM64_)
1593 noway_assert((headerEpilogStartOffset & 3) == 0);
1594 headerEpilogStartOffset /= 4; // The unwind data stores the actual offset divided by 4 (since the low 2 bits
1595 // of the actual offset is always zero)
1596#endif // defined(_TARGET_ARM64_)
1597
1598 DWORD headerEpilogStartIndex = pEpi->GetStartIndex();
1599
1600 if ((headerEpilogStartOffset > UW_MAX_EPILOG_START_OFFSET) ||
1601 (headerEpilogStartIndex > UW_MAX_EPILOG_START_INDEX))
1602 {
1603 IMPL_LIMITATION("unwind data too large");
1604 }
1605
1606#if defined(_TARGET_ARM_)
1607 DWORD epilogScopeWord = headerEpilogStartOffset | (headerCondition << 20) | (headerEpilogStartIndex << 24);
1608#elif defined(_TARGET_ARM64_)
1609 DWORD epilogScopeWord = headerEpilogStartOffset | (headerEpilogStartIndex << 22);
1610#endif // defined(_TARGET_ARM64_)
1611
1612 ufiPrologCodes.AddHeaderWord(epilogScopeWord);
1613 }
1614 }
1615
1616 // The unwind code words are already here, following the header, so we're done!
1617}
1618
1619void UnwindFragmentInfo::Reserve(BOOL isFunclet, bool isHotCode)
1620{
1621 assert(isHotCode || !isFunclet); // TODO-CQ: support hot/cold splitting in functions with EH
1622
1623 MergeCodes();
1624
1625 BOOL isColdCode = isHotCode ? FALSE : TRUE;
1626
1627 ULONG unwindSize = Size();
1628
1629#ifdef DEBUG
1630 if (uwiComp->verbose)
1631 {
1632 if (ufiNum != 1)
1633 printf("reserveUnwindInfo: fragment #%d:\n", ufiNum);
1634 }
1635#endif
1636
1637 uwiComp->eeReserveUnwindInfo(isFunclet, isColdCode, unwindSize);
1638}
1639
1640// Allocate the unwind info for a fragment with the VM.
1641// Arguments:
1642// funKind: funclet kind
1643// pHotCode: hot section code buffer
1644// pColdCode: cold section code buffer
1645// funcEndOffset: offset of the end of this function/funclet. Used if this fragment is the last one for a
1646// function/funclet.
1647// isHotCode: are we allocating the unwind info for the hot code section?
1648
1649void UnwindFragmentInfo::Allocate(
1650 CorJitFuncKind funKind, void* pHotCode, void* pColdCode, UNATIVE_OFFSET funcEndOffset, bool isHotCode)
1651{
1652 UNATIVE_OFFSET startOffset;
1653 UNATIVE_OFFSET endOffset;
1654 UNATIVE_OFFSET codeSize;
1655
1656 // We don't support hot/cold splitting with EH, so if there is cold code, this
1657 // better not be a funclet!
1658 // TODO-CQ: support funclets in cold code
1659
1660 noway_assert(isHotCode || funKind == CORJIT_FUNC_ROOT);
1661
1662 // Compute the final size, and start and end offsets of the fragment
1663
1664 startOffset = GetStartOffset();
1665
1666 if (ufiNext == NULL)
1667 {
1668 // This is the last fragment, so the fragment extends to the end of the function/fragment.
1669 assert(funcEndOffset != 0);
1670 endOffset = funcEndOffset;
1671 }
1672 else
1673 {
1674 // The fragment length is all the code between the beginning of this fragment
1675 // and the beginning of the next fragment. Note that all fragments have had their
1676 // offsets computed before any fragment is allocated.
1677 endOffset = ufiNext->GetStartOffset();
1678 }
1679
1680 assert(endOffset > startOffset);
1681 codeSize = endOffset - startOffset;
1682
1683 // Finalize the fragment unwind block to hand to the VM
1684
1685 Finalize(codeSize);
1686
1687 // Get the final unwind information and hand it to the VM
1688
1689 ULONG unwindBlockSize;
1690 BYTE* pUnwindBlock;
1691
1692 GetFinalInfo(&pUnwindBlock, &unwindBlockSize);
1693
1694#ifdef DEBUG
1695 if (uwiComp->opts.dspUnwind)
1696 {
1697 DumpUnwindInfo(uwiComp, isHotCode, startOffset, endOffset, pUnwindBlock, unwindBlockSize);
1698 }
1699#endif // DEBUG
1700
1701 // Adjust for cold or hot code:
1702 // 1. The VM doesn't want the cold code pointer unless this is cold code.
1703 // 2. The startOffset and endOffset need to be from the base of the hot section for hot code
1704 // and from the base of the cold section for cold code
1705
1706 if (isHotCode)
1707 {
1708 assert(endOffset <= uwiComp->info.compTotalHotCodeSize);
1709 pColdCode = NULL;
1710 }
1711 else
1712 {
1713 assert(startOffset >= uwiComp->info.compTotalHotCodeSize);
1714 startOffset -= uwiComp->info.compTotalHotCodeSize;
1715 endOffset -= uwiComp->info.compTotalHotCodeSize;
1716 }
1717
1718#ifdef DEBUG
1719 if (uwiComp->verbose)
1720 {
1721 if (ufiNum != 1)
1722 printf("unwindEmit: fragment #%d:\n", ufiNum);
1723 }
1724#endif // DEBUG
1725
1726 uwiComp->eeAllocUnwindInfo((BYTE*)pHotCode, (BYTE*)pColdCode, startOffset, endOffset, unwindBlockSize, pUnwindBlock,
1727 funKind);
1728}
1729
1730#ifdef DEBUG
1731void UnwindFragmentInfo::Dump(int indent)
1732{
1733 unsigned count;
1734 UnwindEpilogInfo* pEpi;
1735
1736 count = 0;
1737 for (pEpi = ufiEpilogList; pEpi != NULL; pEpi = pEpi->epiNext)
1738 {
1739 ++count;
1740 }
1741
1742 printf("%*sUnwindFragmentInfo #%d, @0x%08p, size:%d:\n", indent, "", ufiNum, dspPtr(this), sizeof(*this));
1743 printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
1744 printf("%*s ufiNext: 0x%08p\n", indent, "", dspPtr(ufiNext));
1745 printf("%*s ufiEmitLoc: 0x%08p\n", indent, "", dspPtr(ufiEmitLoc));
1746 printf("%*s ufiHasPhantomProlog: %s\n", indent, "", dspBool(ufiHasPhantomProlog));
1747 printf("%*s %d epilog%s\n", indent, "", count, (count != 1) ? "s" : "");
1748 printf("%*s ufiEpilogList: 0x%08p\n", indent, "", dspPtr(ufiEpilogList));
1749 printf("%*s ufiEpilogLast: 0x%08p\n", indent, "", dspPtr(ufiEpilogLast));
1750 printf("%*s ufiCurCodes: 0x%08p\n", indent, "", dspPtr(ufiCurCodes));
1751 printf("%*s ufiSize: %u\n", indent, "", ufiSize);
1752 printf("%*s ufiSetEBit: %s\n", indent, "", dspBool(ufiSetEBit));
1753 printf("%*s ufiNeedExtendedCodeWordsEpilogCount: %s\n", indent, "", dspBool(ufiNeedExtendedCodeWordsEpilogCount));
1754 printf("%*s ufiCodeWords: %u\n", indent, "", ufiCodeWords);
1755 printf("%*s ufiEpilogScopes: %u\n", indent, "", ufiEpilogScopes);
1756 printf("%*s ufiStartOffset: 0x%x\n", indent, "", ufiStartOffset);
1757 printf("%*s ufiInProlog: %s\n", indent, "", dspBool(ufiInProlog));
1758 printf("%*s ufiInitialized: 0x%08x\n", indent, "", ufiInitialized);
1759
1760 ufiPrologCodes.Dump(indent + 2);
1761
1762 for (pEpi = ufiEpilogList; pEpi != NULL; pEpi = pEpi->epiNext)
1763 {
1764 pEpi->Dump(indent + 2);
1765 }
1766}
1767#endif // DEBUG
1768
1769///////////////////////////////////////////////////////////////////////////////
1770//
1771// UnwindInfo
1772//
1773///////////////////////////////////////////////////////////////////////////////
1774
1775void UnwindInfo::InitUnwindInfo(Compiler* comp, emitLocation* startLoc, emitLocation* endLoc)
1776{
1777 uwiComp = comp;
1778
1779 // The first fragment is a member of UnwindInfo, so it doesn't need to be allocated.
1780 // However, its constructor needs to be explicitly called, since the constructor for
1781 // UnwindInfo is not called.
1782
1783 uwiFragmentFirst.UnwindFragmentInfo::UnwindFragmentInfo(comp, startLoc, false);
1784
1785 uwiFragmentLast = &uwiFragmentFirst;
1786
1787 uwiEndLoc = endLoc;
1788
1789 // Allocate an emitter location object. It is initialized to something
1790 // invalid: it has a null 'ig' that needs to get set before it can be used.
1791 // Note that when we create an UnwindInfo for the cold section, this never
1792 // gets initialized with anything useful, since we never add unwind codes
1793 // to the cold section; we simply distribute the existing (previously added) codes.
1794 uwiCurLoc = new (uwiComp, CMK_UnwindInfo) emitLocation();
1795
1796#ifdef DEBUG
1797 uwiInitialized = UWI_INITIALIZED_PATTERN;
1798 uwiAddingNOP = false;
1799#endif // DEBUG
1800}
1801
1802// Split the unwind codes in 'puwi' into those that are in the hot section (leave them in 'puwi')
1803// and those that are in the cold section (move them to 'this'). There is exactly one fragment
1804// in each UnwindInfo; the fragments haven't been split for size, yet.
1805
1806void UnwindInfo::HotColdSplitCodes(UnwindInfo* puwi)
1807{
1808 // Ensure that there is exactly a single fragment in both the hot and the cold sections
1809 assert(&uwiFragmentFirst == uwiFragmentLast);
1810 assert(&puwi->uwiFragmentFirst == puwi->uwiFragmentLast);
1811 assert(uwiFragmentLast->ufiNext == NULL);
1812 assert(puwi->uwiFragmentLast->ufiNext == NULL);
1813
1814 // The real prolog is in the hot section, so this, cold, section has a phantom prolog
1815 uwiFragmentLast->ufiHasPhantomProlog = true;
1816 uwiFragmentLast->CopyPrologCodes(puwi->uwiFragmentLast);
1817
1818 // Now split the epilog codes
1819 uwiFragmentLast->SplitEpilogCodes(uwiFragmentLast->ufiEmitLoc, puwi->uwiFragmentLast);
1820}
1821
1822// Split the function or funclet into fragments that are no larger than 512K,
1823// so the fragment size will fit in the unwind data "Function Length" field.
1824// The ARM Exception Data specification "Function Fragments" section describes this.
1825// We split the function so that it is no larger than 512K bytes, or the value of
1826// the COMPlus_JitSplitFunctionSize value, if defined (and smaller). We must determine
1827// how to split the function/funclet before we issue the instructions, so we can
1828// reserve the unwind space with the VM. The instructions issued may shrink (but not
1829// expand!) during issuing (although this is extremely rare in any case, and may not
1830// actually occur on ARM), so we don't finalize actual sizes or offsets.
1831//
1832// ARM64 has very similar limitations, except functions can be up to 1MB. TODO-ARM64-Bug?: make sure this works!
1833//
1834// We don't split any prolog or epilog. Ideally, we might not split an instruction,
1835// although that doesn't matter because the unwind at any point would still be
1836// well-defined.
1837
1838void UnwindInfo::Split()
1839{
1840 UNATIVE_OFFSET maxFragmentSize; // The maximum size of a code fragment in bytes
1841
1842 maxFragmentSize = UW_MAX_FRAGMENT_SIZE_BYTES;
1843
1844#ifdef DEBUG
1845 // Consider COMPlus_JitSplitFunctionSize
1846 unsigned splitFunctionSize = (unsigned)JitConfig.JitSplitFunctionSize();
1847
1848 if (splitFunctionSize != 0)
1849 if (splitFunctionSize < maxFragmentSize)
1850 maxFragmentSize = splitFunctionSize;
1851#endif // DEBUG
1852
1853 // Now, there should be exactly one fragment.
1854
1855 assert(uwiFragmentLast != NULL);
1856 assert(uwiFragmentLast == &uwiFragmentFirst);
1857 assert(uwiFragmentLast->ufiNext == NULL);
1858
1859 // Find the code size of this function/funclet.
1860
1861 UNATIVE_OFFSET startOffset;
1862 UNATIVE_OFFSET endOffset;
1863 UNATIVE_OFFSET codeSize;
1864
1865 if (uwiFragmentLast->ufiEmitLoc == NULL)
1866 {
1867 // NULL emit location means the beginning of the code. This is to handle the first fragment prolog.
1868 startOffset = 0;
1869 }
1870 else
1871 {
1872 startOffset = uwiFragmentLast->ufiEmitLoc->CodeOffset(uwiComp->genEmitter);
1873 }
1874
1875 if (uwiEndLoc == NULL)
1876 {
1877 // Note that compTotalHotCodeSize and compTotalColdCodeSize are computed before issuing instructions
1878 // from the emitter instruction group offsets, and will be accurate unless the issued code shrinks.
1879 // compNativeCodeSize is precise, but is only set after instructions are issued, which is too late
1880 // for us, since we need to decide how many fragments we need before the code memory is allocated
1881 // (which is before instruction issuing).
1882 UNATIVE_OFFSET estimatedTotalCodeSize =
1883 uwiComp->info.compTotalHotCodeSize + uwiComp->info.compTotalColdCodeSize;
1884 assert(estimatedTotalCodeSize != 0);
1885 endOffset = estimatedTotalCodeSize;
1886 }
1887 else
1888 {
1889 endOffset = uwiEndLoc->CodeOffset(uwiComp->genEmitter);
1890 }
1891
1892 assert(endOffset > startOffset); // there better be at least 1 byte of code
1893 codeSize = endOffset - startOffset;
1894
1895 // Now that we know the code size for this section (main function hot or cold, or funclet),
1896 // figure out how many fragments we're going to need.
1897
1898 UNATIVE_OFFSET numberOfFragments = (codeSize + maxFragmentSize - 1) / maxFragmentSize; // round up
1899 assert(numberOfFragments > 0);
1900
1901 if (numberOfFragments == 1)
1902 {
1903 // No need to split; we're done
1904 return;
1905 }
1906
1907 // Now, we're going to commit to splitting the function into "numberOfFragments" fragments,
1908 // for the purpose of unwind information. We need to do the actual splits so we can figure out
1909 // the size of each piece of unwind data for the call to reserveUnwindInfo(). We won't know
1910 // the actual offsets of the splits since we haven't issued the instructions yet, so store
1911 // an emitter location instead of an offset, and "finalize" the offset in the unwindEmit() phase,
1912 // like we do for the function length and epilog offsets.
1913 CLANG_FORMAT_COMMENT_ANCHOR;
1914
1915#ifdef DEBUG
1916 if (uwiComp->verbose)
1917 {
1918 printf("Split unwind info into %d fragments (function/funclet size: %d, maximum fragment size: %d)\n",
1919 numberOfFragments, codeSize, maxFragmentSize);
1920 }
1921#endif // DEBUG
1922
1923 // Call the emitter to do the split, and call us back for every split point it chooses.
1924 uwiComp->genEmitter->emitSplit(uwiFragmentLast->ufiEmitLoc, uwiEndLoc, maxFragmentSize, (void*)this,
1925 EmitSplitCallback);
1926
1927#ifdef DEBUG
1928 // Did the emitter split the function/funclet into as many fragments as we asked for?
1929 // It might be fewer if the COMPlus_JitSplitFunctionSize was used, but it better not
1930 // be fewer if we're splitting into 512K blocks!
1931
1932 unsigned fragCount = 0;
1933 for (UnwindFragmentInfo* pFrag = &uwiFragmentFirst; pFrag != NULL; pFrag = pFrag->ufiNext)
1934 {
1935 ++fragCount;
1936 }
1937 if (fragCount < numberOfFragments)
1938 {
1939 if (uwiComp->verbose)
1940 {
1941 printf("WARNING: asked the emitter for %d fragments, but only got %d\n", numberOfFragments, fragCount);
1942 }
1943
1944 // If this fires, then we split into fewer fragments than we asked for, and we are using
1945 // the default, unwind-data-defined 512K maximum fragment size. We won't be able to fit
1946 // this fragment into the unwind data! If you set COMPlus_JitSplitFunctionSize to something
1947 // small, we might not be able to split into as many fragments as asked for, because we
1948 // can't split prologs or epilogs.
1949 assert(maxFragmentSize != UW_MAX_FRAGMENT_SIZE_BYTES);
1950 }
1951#endif // DEBUG
1952}
1953
1954/*static*/ void UnwindInfo::EmitSplitCallback(void* context, emitLocation* emitLoc)
1955{
1956 UnwindInfo* puwi = (UnwindInfo*)context;
1957 puwi->AddFragment(emitLoc);
1958}
1959
1960// Reserve space for the unwind info for all fragments
1961
1962void UnwindInfo::Reserve(BOOL isFunclet, bool isHotCode)
1963{
1964 assert(uwiInitialized == UWI_INITIALIZED_PATTERN);
1965 assert(isHotCode || !isFunclet);
1966
1967 for (UnwindFragmentInfo* pFrag = &uwiFragmentFirst; pFrag != NULL; pFrag = pFrag->ufiNext)
1968 {
1969 pFrag->Reserve(isFunclet, isHotCode);
1970 }
1971}
1972
1973// Allocate and populate VM unwind info for all fragments
1974
1975void UnwindInfo::Allocate(CorJitFuncKind funKind, void* pHotCode, void* pColdCode, bool isHotCode)
1976{
1977 assert(uwiInitialized == UWI_INITIALIZED_PATTERN);
1978
1979 UnwindFragmentInfo* pFrag;
1980
1981 // First, finalize all the offsets (the location of the beginning of fragments, and epilogs),
1982 // so a fragment can use the finalized offset of the subsequent fragment to determine its code size.
1983
1984 UNATIVE_OFFSET endOffset;
1985
1986 if (uwiEndLoc == NULL)
1987 {
1988 assert(uwiComp->info.compNativeCodeSize != 0);
1989 endOffset = uwiComp->info.compNativeCodeSize;
1990 }
1991 else
1992 {
1993 endOffset = uwiEndLoc->CodeOffset(uwiComp->genEmitter);
1994 }
1995
1996 for (pFrag = &uwiFragmentFirst; pFrag != NULL; pFrag = pFrag->ufiNext)
1997 {
1998 pFrag->FinalizeOffset();
1999 }
2000
2001 for (pFrag = &uwiFragmentFirst; pFrag != NULL; pFrag = pFrag->ufiNext)
2002 {
2003 pFrag->Allocate(funKind, pHotCode, pColdCode, endOffset, isHotCode);
2004 }
2005}
2006
2007void UnwindInfo::AddEpilog()
2008{
2009 assert(uwiInitialized == UWI_INITIALIZED_PATTERN);
2010 assert(uwiFragmentLast != NULL);
2011 uwiFragmentLast->AddEpilog();
2012 CaptureLocation();
2013}
2014
2015#if defined(_TARGET_ARM_)
2016
2017unsigned UnwindInfo::GetInstructionSize()
2018{
2019 assert(uwiInitialized == UWI_INITIALIZED_PATTERN);
2020 return uwiComp->genEmitter->emitGetInstructionSize(uwiCurLoc);
2021}
2022
2023#endif // defined(_TARGET_ARM_)
2024
2025void UnwindInfo::CaptureLocation()
2026{
2027 assert(uwiInitialized == UWI_INITIALIZED_PATTERN);
2028 assert(uwiCurLoc != NULL);
2029 uwiCurLoc->CaptureLocation(uwiComp->genEmitter);
2030}
2031
2032void UnwindInfo::AddFragment(emitLocation* emitLoc)
2033{
2034 assert(uwiInitialized == UWI_INITIALIZED_PATTERN);
2035 assert(uwiFragmentLast != NULL);
2036
2037 UnwindFragmentInfo* newFrag = new (uwiComp, CMK_UnwindInfo) UnwindFragmentInfo(uwiComp, emitLoc, true);
2038
2039#ifdef DEBUG
2040 newFrag->ufiNum = uwiFragmentLast->ufiNum + 1;
2041#endif // DEBUG
2042
2043 newFrag->CopyPrologCodes(&uwiFragmentFirst);
2044 newFrag->SplitEpilogCodes(emitLoc, uwiFragmentLast);
2045
2046 // Link the new fragment in at the end of the fragment list
2047 uwiFragmentLast->ufiNext = newFrag;
2048 uwiFragmentLast = newFrag;
2049}
2050
2051#ifdef DEBUG
2052
2053#if defined(_TARGET_ARM_)
2054
2055// Given the first byte of the unwind code, check that its opsize matches
2056// the last instruction added in the emitter.
2057void UnwindInfo::CheckOpsize(BYTE b1)
2058{
2059 // Adding NOP padding goes through the same path, but doesn't update the location to indicate
2060 // the correct location of the instruction for which we are adding a NOP, so just skip the
2061 // assert. Should be ok, because the emitter is telling us the size of the instruction for
2062 // which we are adding the NOP.
2063 if (uwiAddingNOP)
2064 return;
2065
2066 unsigned opsizeInBytes = GetOpcodeSizeFromUnwindHeader(b1);
2067 unsigned instrSizeInBytes = GetInstructionSize();
2068 assert(opsizeInBytes == instrSizeInBytes);
2069}
2070
2071#endif // defined(_TARGET_ARM_)
2072
2073void UnwindInfo::Dump(bool isHotCode, int indent)
2074{
2075 unsigned count;
2076 UnwindFragmentInfo* pFrag;
2077
2078 count = 0;
2079 for (pFrag = &uwiFragmentFirst; pFrag != NULL; pFrag = pFrag->ufiNext)
2080 {
2081 ++count;
2082 }
2083
2084 printf("%*sUnwindInfo %s@0x%08p, size:%d:\n", indent, "", isHotCode ? "" : "COLD ", dspPtr(this), sizeof(*this));
2085 printf("%*s uwiComp: 0x%08p\n", indent, "", dspPtr(uwiComp));
2086 printf("%*s %d fragment%s\n", indent, "", count, (count != 1) ? "s" : "");
2087 printf("%*s uwiFragmentLast: 0x%08p\n", indent, "", dspPtr(uwiFragmentLast));
2088 printf("%*s uwiEndLoc: 0x%08p\n", indent, "", dspPtr(uwiEndLoc));
2089 printf("%*s uwiInitialized: 0x%08x\n", indent, "", uwiInitialized);
2090
2091 for (pFrag = &uwiFragmentFirst; pFrag != NULL; pFrag = pFrag->ufiNext)
2092 {
2093 pFrag->Dump(indent + 2);
2094 }
2095}
2096
2097#endif // DEBUG
2098
2099#if defined(_TARGET_ARM_)
2100
2101/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2102XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2103XX XX
2104XX Debug dumpers XX
2105XX XX
2106XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2107XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2108*/
2109
2110#ifdef DEBUG
2111
2112// start is 0-based index from LSB, length is number of bits
2113DWORD ExtractBits(DWORD dw, DWORD start, DWORD length)
2114{
2115 return (dw >> start) & ((1 << length) - 1);
2116}
2117
2118// Dump an integer register set. 'x' is an array of bits where bit 0 = r0, bit 1 = r1, etc.
2119// The highest register considered is r12.
2120// If 'lr' is non-zero, the "lr" register is emitted last.
2121// Returns the number of characters printed.
2122DWORD DumpIntRegSet(DWORD x, DWORD lr)
2123{
2124 assert(x != 0 || lr != 0); // we must have one
2125 assert((x & 0xE000) == 0); // don't handle r13 (sp), r14 (lr), r15 (pc) in 'x'
2126 DWORD printed = 0;
2127
2128 printf("{");
2129 ++printed;
2130 bool first = true;
2131 DWORD bitMask = 1;
2132 for (DWORD bitNum = 0; bitNum < 12; bitNum++)
2133 {
2134 if (x & bitMask)
2135 {
2136 if (!first)
2137 {
2138 printf(",");
2139 ++printed;
2140 }
2141 printf("r%u", bitNum);
2142 printed += (bitNum < 10) ? 2 : 3;
2143 first = false;
2144 }
2145 bitMask <<= 1;
2146 }
2147 if (lr)
2148 {
2149 if (!first)
2150 {
2151 printf(",");
2152 ++printed;
2153 }
2154 printf("lr");
2155 printed += 2;
2156 }
2157 printf("}");
2158 ++printed;
2159
2160 return printed;
2161}
2162
2163// Dump a register set range from register 'start' to register 'end'.
2164// rtype should be "r" or "d" to indicate register type.
2165// If 'lr' is non-zero, the "lr" register is emitted last. (Note that
2166// 'lr' should be zero for rtype == "d".)
2167// Returns the number of characters printed.
2168DWORD DumpRegSetRange(const char* const rtype, DWORD start, DWORD end, DWORD lr)
2169{
2170 assert(start <= end);
2171 DWORD printed = 0;
2172 DWORD rtypeLen = (DWORD)strlen(rtype);
2173
2174 printf("{");
2175 ++printed;
2176 bool first = true;
2177 for (DWORD reg = start; reg <= end; reg++)
2178 {
2179 if (!first)
2180 {
2181 printf(",");
2182 ++printed;
2183 }
2184 printf("%s%u", rtype, reg);
2185 printed += rtypeLen + ((reg < 10) ? 1 : 2);
2186 first = false;
2187 }
2188 if (lr)
2189 {
2190 assert(!first); // If 'lr' is set, it can't be first, since we require a non-empty range
2191 printf(",lr");
2192 printed += 3;
2193 }
2194 printf("}");
2195 ++printed;
2196
2197 return printed;
2198}
2199
2200// Dump the opsize.
2201// Returns the number of characters printed.
2202DWORD DumpOpsize(DWORD padding, DWORD opsize)
2203{
2204 if (padding > 100) // underflow?
2205 padding = 4;
2206 DWORD printed = padding;
2207 for (; padding > 0; padding--)
2208 printf(" ");
2209 printf("; opsize %d\n", opsize);
2210 return printed + 11; // assumes opsize is always 2 digits
2211}
2212
2213// Dump the unwind data.
2214// Arguments:
2215// isHotCode: true if this unwind data is for the hot section
2216// startOffset: byte offset of the code start that this unwind data represents
2217// endOffset: byte offset of the code end that this unwind data represents
2218// pHeader: pointer to the unwind data blob
2219// unwindBlockSize: size in bytes of the unwind data blob
2220
2221void DumpUnwindInfo(Compiler* comp,
2222 bool isHotCode,
2223 UNATIVE_OFFSET startOffset,
2224 UNATIVE_OFFSET endOffset,
2225 const BYTE* const pHeader,
2226 ULONG unwindBlockSize)
2227{
2228 printf("Unwind Info%s:\n", isHotCode ? "" : " COLD");
2229
2230 // pHeader is not guaranteed to be aligned. We put four 0xFF end codes at the end
2231 // to provide padding, and round down to get a multiple of 4 bytes in size.
2232 DWORD UNALIGNED* pdw = (DWORD UNALIGNED*)pHeader;
2233 DWORD dw;
2234
2235 dw = *pdw++;
2236
2237 DWORD codeWords = ExtractBits(dw, 28, 4);
2238 DWORD epilogCount = ExtractBits(dw, 23, 5);
2239 DWORD FBit = ExtractBits(dw, 22, 1);
2240 DWORD EBit = ExtractBits(dw, 21, 1);
2241 DWORD XBit = ExtractBits(dw, 20, 1);
2242 DWORD Vers = ExtractBits(dw, 18, 2);
2243 DWORD functionLength = ExtractBits(dw, 0, 18);
2244
2245 printf(" >> Start offset : 0x%06x (not in unwind data)\n", comp->dspOffset(startOffset));
2246 printf(" >> End offset : 0x%06x (not in unwind data)\n", comp->dspOffset(endOffset));
2247 printf(" Code Words : %u\n", codeWords);
2248 printf(" Epilog Count : %u\n", epilogCount);
2249 printf(" F bit : %u\n", FBit);
2250 printf(" E bit : %u\n", EBit);
2251 printf(" X bit : %u\n", XBit);
2252 printf(" Vers : %u\n", Vers);
2253 printf(" Function Length : %u (0x%05x) Actual length = %u (0x%06x)\n", functionLength, functionLength,
2254 functionLength * 2, functionLength * 2);
2255
2256 assert(functionLength * 2 == endOffset - startOffset);
2257
2258 if (codeWords == 0 && epilogCount == 0)
2259 {
2260 // We have an extension word specifying a larger number of Code Words or Epilog Counts
2261 // than can be specified in the header word.
2262
2263 dw = *pdw++;
2264
2265 codeWords = ExtractBits(dw, 16, 8);
2266 epilogCount = ExtractBits(dw, 0, 16);
2267 assert((dw & 0xF0000000) == 0); // reserved field should be zero
2268
2269 printf(" ---- Extension word ----\n");
2270 printf(" Extended Code Words : %u\n", codeWords);
2271 printf(" Extended Epilog Count : %u\n", epilogCount);
2272 }
2273
2274 bool epilogStartAt[256] = {}; // One byte per possible epilog start index; initialized to false
2275
2276 if (EBit == 0)
2277 {
2278 // We have an array of epilog scopes
2279
2280 printf(" ---- Epilog scopes ----\n");
2281 if (epilogCount == 0)
2282 {
2283 printf(" No epilogs\n");
2284 }
2285 else
2286 {
2287 for (DWORD scope = 0; scope < epilogCount; scope++)
2288 {
2289 dw = *pdw++;
2290
2291 DWORD epilogStartOffset = ExtractBits(dw, 0, 18);
2292 DWORD res = ExtractBits(dw, 18, 2);
2293 DWORD condition = ExtractBits(dw, 20, 4);
2294 DWORD epilogStartIndex = ExtractBits(dw, 24, 8);
2295
2296 // Note that epilogStartOffset for a funclet is the offset from the beginning
2297 // of the current funclet, not the offset from the beginning of the main function.
2298 // To help find it when looking through JitDump output, also show the offset from
2299 // the beginning of the main function.
2300 DWORD epilogStartOffsetFromMainFunctionBegin = epilogStartOffset * 2 + startOffset;
2301
2302 assert(res == 0);
2303
2304 printf(" ---- Scope %d\n", scope);
2305 printf(" Epilog Start Offset : %u (0x%05x) Actual offset = %u (0x%06x) Offset from main "
2306 "function begin = %u (0x%06x)\n",
2307 comp->dspOffset(epilogStartOffset), comp->dspOffset(epilogStartOffset),
2308 comp->dspOffset(epilogStartOffset * 2), comp->dspOffset(epilogStartOffset * 2),
2309 comp->dspOffset(epilogStartOffsetFromMainFunctionBegin),
2310 comp->dspOffset(epilogStartOffsetFromMainFunctionBegin));
2311 printf(" Condition : %u (0x%x)%s\n", condition, condition,
2312 (condition == 0xE) ? " (always)" : "");
2313 printf(" Epilog Start Index : %u (0x%02x)\n", epilogStartIndex, epilogStartIndex);
2314
2315 epilogStartAt[epilogStartIndex] = true; // an epilog starts at this offset in the unwind codes
2316 }
2317 }
2318 }
2319 else
2320 {
2321 printf(" --- One epilog, unwind codes at %u\n", epilogCount);
2322 assert(epilogCount < _countof(epilogStartAt));
2323 epilogStartAt[epilogCount] = true; // the one and only epilog starts its unwind codes at this offset
2324 }
2325
2326 if (FBit)
2327 {
2328 printf(" ---- Note: 'F' bit is set. Prolog codes are for a 'phantom' prolog.\n");
2329 }
2330
2331 // Dump the unwind codes
2332
2333 printf(" ---- Unwind codes ----\n");
2334
2335 DWORD countOfUnwindCodes = codeWords * 4;
2336 PBYTE pUnwindCode = (PBYTE)pdw;
2337 BYTE b1, b2, b3, b4;
2338 DWORD x, y;
2339 DWORD opsize;
2340 DWORD opCol = 52;
2341 DWORD printed;
2342 for (DWORD i = 0; i < countOfUnwindCodes; i++)
2343 {
2344 // Does this byte start an epilog sequence? If so, note that fact.
2345 if (epilogStartAt[i])
2346 {
2347 printf(" ---- Epilog start at index %u ----\n", i);
2348 }
2349
2350 b1 = *pUnwindCode++;
2351
2352 if ((b1 & 0x80) == 0)
2353 {
2354 // 00-7F : add sp, sp, #X*4 (opsize 16)
2355 x = b1 & 0x7F;
2356 printf(" %02X add sp, sp, #%-8d", b1, x * 4);
2357 DumpOpsize(opCol - 37, 16);
2358 }
2359 else if ((b1 & 0xC0) == 0x80)
2360 {
2361 // 80-BF : pop {r0-r12,lr} (X = bitmask) (opsize 32)
2362 assert(i + 1 < countOfUnwindCodes);
2363 b2 = *pUnwindCode++;
2364 i++;
2365
2366 DWORD LBit = ExtractBits(b1, 5, 1);
2367 x = ((DWORD)(b1 & 0x1F) << 8) | (DWORD)b2;
2368
2369 printf(" %02X %02X pop ", b1, b2);
2370 printed = 20;
2371 printed += DumpIntRegSet(x, LBit);
2372 DumpOpsize(opCol - printed, 32);
2373 }
2374 else if ((b1 & 0xF0) == 0xC0)
2375 {
2376 // C0-CF : mov sp, rX (X=0-15) (opsize 16)
2377 x = b1 & 0xF;
2378 printf(" %02X mov sp, r%u", b1, x);
2379 printed = 25 + ((x > 10) ? 2 : 1);
2380 DumpOpsize(opCol - printed, 16);
2381 }
2382 else if ((b1 & 0xF8) == 0xD0)
2383 {
2384 // D0-D7 : pop {r4-rX,lr} (X=4-7) (opsize 16)
2385 x = b1 & 0x3;
2386 DWORD LBit = b1 & 0x4;
2387 printf(" %02X pop ", b1);
2388 printed = 20;
2389 printed += DumpRegSetRange("r", 4, x + 4, LBit);
2390 DumpOpsize(opCol - printed, 16);
2391 }
2392 else if ((b1 & 0xF8) == 0xD8)
2393 {
2394 // D8-DF : pop {r4-rX,lr} (X=8-11) (opsize 32)
2395 x = b1 & 0x3;
2396 DWORD LBit = b1 & 0x4;
2397 printf(" %02X pop ", b1);
2398 printed = 20;
2399 printed += DumpRegSetRange("r", 4, x + 8, LBit);
2400 DumpOpsize(opCol - printed, 32);
2401 }
2402 else if ((b1 & 0xF8) == 0xE0)
2403 {
2404 // E0-E7 : vpop {d8-dX} (X=8-15) (opsize 32)
2405 x = b1 & 0x7;
2406 printf(" %02X vpop ", b1);
2407 printed = 21;
2408 printed += DumpRegSetRange("d", 8, x + 8, 0);
2409 DumpOpsize(opCol - printed, 32);
2410 }
2411 else if ((b1 & 0xFC) == 0xE8)
2412 {
2413 // E8-EB : addw sp, sp, #X*4 (opsize 32)
2414 assert(i + 1 < countOfUnwindCodes);
2415 b2 = *pUnwindCode++;
2416 i++;
2417
2418 x = ((DWORD)(b1 & 0x3) << 8) | (DWORD)b2;
2419
2420 printf(" %02X %02X addw sp, sp, #%-8u", b1, b2, x * 4);
2421 DumpOpsize(opCol - 38, 32);
2422 }
2423 else if ((b1 & 0xFE) == 0xEC)
2424 {
2425 // EC-ED : pop {r0-r7,lr} (X = bitmask) (opsize 16)
2426 assert(i + 1 < countOfUnwindCodes);
2427 b2 = *pUnwindCode++;
2428 i++;
2429
2430 DWORD LBit = ExtractBits(b1, 0, 1);
2431 x = (DWORD)b2;
2432
2433 printf(" %02X %02X pop ", b1, b2);
2434 printed = 20;
2435 printed += DumpIntRegSet(x, LBit);
2436 DumpOpsize(opCol - printed, 16);
2437 }
2438 else if (b1 == 0xEE)
2439 {
2440 assert(i + 1 < countOfUnwindCodes);
2441 b2 = *pUnwindCode++;
2442 i++;
2443
2444 if ((b2 & 0xF0) == 0)
2445 {
2446 // EE/0x (opsize 16)
2447 x = b2 & 0xF;
2448 printf(" %02X %02X Microsoft-specific (x = %02X)", b1, b2, x);
2449 DumpOpsize(4, 16);
2450 }
2451 else
2452 {
2453 // EE/xy (opsize 16)
2454 x = ExtractBits(b2, 4, 4);
2455 y = ExtractBits(b2, 0, 4);
2456 printf(" %02X %02X Available (x = %02X, y = %02X)", b1, b2, x, y);
2457 DumpOpsize(4, 16);
2458 }
2459 }
2460 else if (b1 == 0xEF)
2461 {
2462 assert(i + 1 < countOfUnwindCodes);
2463 b2 = *pUnwindCode++;
2464 i++;
2465
2466 if ((b2 & 0xF0) == 0)
2467 {
2468 // EF/0x : ldr lr, [sp], #X*4 (opsize 32)
2469 x = b2 & 0xF;
2470 printf(" %02X %02X ldr lr, [sp], #%-8u", b1, b2, x * 4);
2471 DumpOpsize(opCol - 39, 32);
2472 }
2473 else
2474 {
2475 // EF/xy (opsize 32)
2476 x = ExtractBits(b2, 4, 4);
2477 y = ExtractBits(b2, 0, 4);
2478 printf(" %02X %02X Available (x = %02X, y = %02X)", b1, b2, x, y);
2479 DumpOpsize(4, 32);
2480 }
2481 }
2482 else if ((b1 & 0xF7) == 0xF0)
2483 {
2484 // F0-F4
2485 x = b1 & 0x7;
2486 printf(" %02X Available (x = %02X)\n", b1, x);
2487 }
2488 else if (b1 == 0xF5)
2489 {
2490 // F5 : vpop {dS-dE} (opsize 32)
2491
2492 assert(i + 1 < countOfUnwindCodes);
2493 b2 = *pUnwindCode++;
2494 i++;
2495
2496 DWORD s = ExtractBits(b2, 4, 4);
2497 DWORD e = ExtractBits(b2, 0, 4);
2498
2499 printf(" %02X %02X vpop ", b1, b2);
2500 printed = 21;
2501 printed += DumpRegSetRange("d", s, e, 0);
2502 DumpOpsize(opCol - printed, 32);
2503 }
2504 else if (b1 == 0xF6)
2505 {
2506 // F6 : vpop {d(S+16)-d(E+16)} (opsize 32)
2507
2508 assert(i + 1 < countOfUnwindCodes);
2509 b2 = *pUnwindCode++;
2510 i++;
2511
2512 DWORD s = ExtractBits(b2, 4, 4);
2513 DWORD e = ExtractBits(b2, 0, 4);
2514
2515 printf(" %02X %02X vpop ", b1, b2);
2516 printed = 21;
2517 printed += DumpRegSetRange("d", s + 16, e + 16, 0);
2518 DumpOpsize(opCol - printed, 32);
2519 }
2520 else if (b1 == 0xF7 || b1 == 0xF9)
2521 {
2522 // F7, F9 : add sp, sp, #X*4
2523 // 0xF7 has opsize 16, 0xF9 has opsize 32
2524
2525 assert(i + 2 < countOfUnwindCodes);
2526 b2 = *pUnwindCode++;
2527 b3 = *pUnwindCode++;
2528 i += 2;
2529
2530 x = ((DWORD)b2 << 8) | (DWORD)b3;
2531
2532 opsize = (b1 == 0xF7) ? 16 : 32;
2533
2534 printf(" %02X %02X %02X add sp, sp, #%-8u", b1, b2, b3, x * 4, opsize);
2535 DumpOpsize(opCol - 37, opsize);
2536 }
2537 else if (b1 == 0xF8 || b1 == 0xFA)
2538 {
2539 // F8, FA : add sp, sp, #X*4
2540 // 0xF8 has opsize 16, 0xFA has opsize 32
2541
2542 assert(i + 3 < countOfUnwindCodes);
2543 b2 = *pUnwindCode++;
2544 b3 = *pUnwindCode++;
2545 b4 = *pUnwindCode++;
2546 i += 3;
2547
2548 x = ((DWORD)b2 << 16) | ((DWORD)b3 << 8) | (DWORD)b4;
2549
2550 opsize = (b1 == 0xF8) ? 16 : 32;
2551
2552 printf(" %02X %02X %02X %02X add sp, sp, #%-8u", b1, b2, b3, b4, x * 4, opsize);
2553 DumpOpsize(opCol - 37, opsize);
2554 }
2555 else if (b1 == 0xFB || b1 == 0xFC)
2556 {
2557 // FB, FC : nop
2558 // 0xFB has opsize 16, 0xFC has opsize 32
2559
2560 opsize = (b1 == 0xFB) ? 16 : 32;
2561
2562 printf(" %02X nop", b1, opsize);
2563 DumpOpsize(opCol - 19, opsize);
2564 }
2565 else if (b1 == 0xFD || b1 == 0xFE)
2566 {
2567 // FD, FE : end + nop
2568 // 0xFD has opsize 16, 0xFE has opsize 32
2569
2570 opsize = (b1 == 0xFD) ? 16 : 32;
2571
2572 printf(" %02X end + nop", b1, opsize);
2573 DumpOpsize(opCol - 25, opsize);
2574 }
2575 else if (b1 == 0xFF)
2576 {
2577 // FF : end
2578
2579 printf(" %02X end\n", b1);
2580 }
2581 else
2582 {
2583 assert(!"Internal error decoding unwind codes");
2584 }
2585 }
2586
2587 pdw += codeWords;
2588 assert((PBYTE)pdw == pUnwindCode);
2589 assert((PBYTE)pdw == pHeader + unwindBlockSize);
2590
2591 assert(XBit == 0); // We don't handle the case where exception data is present, such as the Exception Handler RVA
2592
2593 printf("\n");
2594}
2595
2596#endif // DEBUG
2597
2598#endif // defined(_TARGET_ARM_)
2599
2600#endif // _TARGET_ARMARCH_
2601