Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

vunwind.c

Go to the documentation of this file.
00001 00018 #if !defined(BUILD_DBGHELP) && !defined(BUILD_IMAGEHLP) 00019 00020 #include "ntrtlp.h" 00021 00022 #else // !BUILD_DBGHELP && !BUILD_IMAGEHLP 00023 00024 #define TARGET_IA64 00025 #define _CROSS_PLATFORM_ 00026 #define _IA64REG_ 00027 #include "walk.h" 00028 #include "private.h" 00029 #include <stdlib.h> 00030 00031 #endif // !BUILD_DBGHELP && !BUILD_IMAGEHLP 00032 00033 #ifdef _IMAGEHLP_SOURCE_ 00034 00035 #define NOT_IMAGEHLP(E) 00036 #define FUNCTION_ENTRY_IS_IMAGE_STYLE 00037 #define RtlVirtualUnwind VirtualUnwindIa64 00038 #define PRUNTIME_FUNCTION PIMAGE_RUNTIME_FUNCTION_ENTRY 00039 #define RUNTIME_FUNCTION IMAGE_RUNTIME_FUNCTION_ENTRY 00040 #define VUW_DEBUG_PRINT OutputDebugString 00041 00042 #else // !_IMAGEHLP_SOURCE_ 00043 00044 #define NOT_IMAGEHLP(E) E 00045 #define VUW_DEBUG_PRINT DbgPrint 00046 00047 #endif // !_IMAGEHLP_SOURCE_ 00048 00049 #ifdef MASK 00050 #undef MASK 00051 #endif // MASK 00052 #define MASK(bp,value) (value << bp) 00053 00054 // 00055 // ABI values 00056 // 00057 00058 #define SVR4_ABI 0 00059 #define HPUX_ABI 1 00060 #define NT_ABI 2 00061 00062 00063 #ifdef KERNEL_DEBUGGER 00064 #define FUNCTION_ENTRY_IS_IMAGE_STYLE 00065 #define RtlVirtualUnwind VirtualUnwind 00066 #endif 00067 00068 #define STATE_RECORD_STACK_SIZE 32 00069 00070 #define SPILLSIZE_OF_FLOAT128_IN_DWORDS 4 00071 #define SPILLSIZE_OF_ULONGLONG_IN_DWORDS 2 00072 00073 #define REGISTER_SIZE sizeof(ULONGLONG) 00074 #define STATIC_REGISTER_SET_SIZE 32 00075 #define SLOTS_PER_BUNDLE 3 00076 00077 #define R1_MASK 0xC0 00078 #define R1_PREFIX 0x0 00079 #define R1_REGION_TYPE_MASK 0x20 00080 #define R1_LENGTH_MASK 0x1F 00081 00082 #define R2_MASK 0xE0 00083 #define R2_PREFIX 0x40 00084 00085 #define R3_MASK 0xE0 00086 #define R3_PREFIX 0x60 00087 #define R3_REGION_TYPE_MASK 0x3 00088 00089 #define P1_MASK 0xE0 00090 #define P1_PREFIX 0x80 00091 #define P2_MASK 0xF0 00092 #define P2_PREFIX 0xA0 00093 #define P3_MASK 0xF8 00094 #define P3_PREFIX 0xB0 00095 #define P4_MASK 0xFF 00096 #define P4_PREFIX 0xB8 00097 #define P5_MASK 0xFF 00098 #define P5_PREFIX 0xB9 00099 #define P6_MASK 0xE0 00100 #define P6_PREFIX 0xC0 00101 #define P7_MASK 0xF0 00102 #define P7_PREFIX 0xE0 00103 #define P8_MASK 0xFF 00104 #define P8_PREFIX 0xF0 00105 #define P9_MASK 0xFF 00106 #define P9_PREFIX 0xF1 00107 #define P10_MASK 0xFF 00108 #define P10_PREFIX 0xFF 00109 00110 #define B1_MASK 0xC0 00111 #define B1_PREFIX 0x80 00112 #define B1_TYPE_MASK 0x20 00113 #define B1_LABEL_MASK 0x1F 00114 #define B2_MASK 0xE0 00115 #define B2_PREFIX 0xC0 00116 #define B2_ECOUNT_MASK 0x1F 00117 #define B3_MASK 0xF0 00118 #define B3_PREFIX 0xE0 00119 #define B4_MASK 0xF0 00120 #define B4_PREFIX 0xF0 00121 #define B4_TYPE_MASK 0x08 00122 00123 // 00124 // P3 descriptor type 00125 // 00126 00127 #define PSP_GR 0 00128 #define RP_GR 1 00129 #define PFS_GR 2 00130 #define PREDS_GR 3 00131 #define UNAT_GR 4 00132 #define LC_GR 5 00133 #define RP_BR 6 00134 #define RNAT_GR 7 00135 #define BSP_GR 8 00136 #define BSPSTORE_GR 9 00137 #define FPSR_GR 10 00138 #define PRIUNAT_GR 11 00139 00140 // 00141 // P7 descriptor type 00142 // 00143 00144 #define MEM_STACK_F 0 00145 #define MEM_STACK_V 1 00146 #define SPILL_BASE 2 00147 #define PSP_SPREL 3 00148 #define RP_WHEN 4 00149 #define RP_PSPREL 5 00150 #define PFS_WHEN 6 00151 #define PFS_PSPREL 7 00152 #define PREDS_WHEN 8 00153 #define PREDS_PSPREL 9 00154 #define LC_WHEN 10 00155 #define LC_PSPREL 11 00156 #define UNAT_WHEN 12 00157 #define UNAT_PSPREL 13 00158 #define FPSR_WHEN 14 00159 #define FPSR_PSPREL 15 00160 00161 // 00162 // P8 descriptor type 00163 // 00164 00165 #define PSP_PSPREL 0 00166 #define RP_SPREL 1 00167 #define PFS_SPREL 2 00168 #define PREDS_SPREL 3 00169 #define LC_SPREL 4 00170 #define UNAT_SPREL 5 00171 #define FPSR_SPREL 6 00172 #define BSP_WHEN 7 00173 #define BSP_PSPREL 8 00174 #define BSP_SPREL 9 00175 #define BSPSTORE_WHEN 10 00176 #define BSPSTORE_PSPREL 11 00177 #define BSPSTORE_SPREL 12 00178 #define RNAT_WHEN 13 00179 #define RNAT_PSPREL 14 00180 #define RNAT_SPREL 15 00181 #define PRIUNAT_WHEN 16 00182 #define PRIUNAT_PSPREL 17 00183 #define PRIUNAT_SPREL 18 00184 00185 00186 #define STACK_POINTER_GR 12 00187 00188 #define FIRST_PRESERVED_GR 4 00189 #define LAST_PRESERVED_GR 7 00190 #define NUMBER_OF_PRESERVED_GR 4 00191 00192 #define FIRST_LOW_PRESERVED_FR 2 00193 #define LAST_LOW_PRESERVED_FR 5 00194 #define NUMBER_OF_LOW_PRESERVED_FR 4 00195 00196 #define FIRST_HIGH_PRESERVED_FR 16 00197 #define LAST_HIGH_PRESERVED_FR 31 00198 #define NUMBER_OF_HIGH_PRESERVED_FR 16 00199 #define NUMBER_OF_PRESERVED_FR NUMBER_OF_LOW_PRESERVED_FR+NUMBER_OF_HIGH_PRESERVED_FR 00200 00201 #define FIRST_PRESERVED_BR 1 00202 #define LAST_PRESERVED_BR 5 00203 #define NUMBER_OF_PRESERVED_BR 5 00204 00205 #define NUMBER_OF_PRESERVED_MISC 7 00206 00207 #define NUMBER_OF_PRESERVED_REGISTERS 12 00208 00209 00210 #define REG_MISC_BASE 0 00211 #define REG_PREDS REG_MISC_BASE+0 00212 #define REG_SP REG_MISC_BASE+1 00213 #define REG_PFS REG_MISC_BASE+2 00214 #define REG_RP REG_MISC_BASE+3 00215 #define REG_UNAT REG_MISC_BASE+4 00216 #define REG_LC REG_MISC_BASE+5 00217 #define REG_NATS REG_MISC_BASE+6 00218 00219 #define REG_BR_BASE REG_MISC_BASE+NUMBER_OF_PRESERVED_MISC 00220 00221 #define REG_FPSR 0xff // REG_MISC_BASE+7 00222 #define REG_BSP 0xff // REG_MISC_BASE+8 00223 #define REG_BSPSTORE 0xff // REG_MISC_BASE+9 00224 #define REG_RNAT 0xff // REG_MISC_BASE+10 00225 00226 // 00227 // Where is a preserved register saved? 00228 // 00229 // 1. stack general register 00230 // 2. memory stack (pspoff) 00231 // 3. memory stack (spoff) 00232 // 4. branch register 00233 // 00234 00235 #define GENERAL_REG 0 00236 #define PSP_RELATIVE 1 00237 #define SP_RELATIVE 2 00238 #define BRANCH_REG 3 00239 00240 00241 #define ADD_STATE_RECORD(States, RegionLength, DescBeginIndex) \ 00242 States.Top++; \ 00243 States.Top->IsTarget = FALSE; \ 00244 States.Top->MiscMask = 0; \ 00245 States.Top->FrMask = 0; \ 00246 States.Top->GrMask = 0; \ 00247 States.Top->Label = (LABEL)0; \ 00248 States.Top->Ecount = 0; \ 00249 States.Top->RegionLen = RegionLength; \ 00250 States.Top->RegionBegin = UnwindContext.SlotCount; \ 00251 States.Top->SpWhen = 0; \ 00252 States.Top->SpAdjustment = 0; \ 00253 States.Top->SpillBase = (States.Top-1)->SpillPtr; \ 00254 States.Top->SpillPtr = (States.Top-1)->SpillPtr; \ 00255 States.Top->Previous = States.Current; \ 00256 States.Top->DescBegin = DescBeginIndex; \ 00257 States.Current = States.Top 00258 00259 00260 #define VALID_LABEL_BIT_POSITION 15 00261 00262 #define LABEL_REGION(Region, Label) \ 00263 Region->Label = Label; \ 00264 Region->MiscMask |= (1 << VALID_LABEL_BIT_POSITION) 00265 00266 #define IS_REGION_LABELED(Region) \ 00267 (Region->MiscMask & (1 << VALID_LABEL_BIT_POSITION)) 00268 00269 #define CHECK_LABEL(State, Label) \ 00270 ( (IS_REGION_LABELED(State)) && (Label == State->Label) ) 00271 00272 00273 #define EXTRACT_NAT_FROM_UNAT(NatBit) \ 00274 NatBit = (UCHAR)((IntNats >> (((ULONG_PTR)Source & 0x1F8) >> 3)) & 0x1); 00275 00276 00277 #if DBG 00278 int UnwindDebugLevel = 0; 00279 # ifdef _IMAGEHLP_SOURCE_ 00280 # define UW_DEBUG(x) if (UnwindDebugLevel) dbPrint##x 00281 # else 00282 # define UW_DEBUG(x) if (UnwindDebugLevel) DbgPrint##x 00283 # endif 00284 #else 00285 # define UW_DEBUG(x) 00286 #endif // DBG 00287 00288 00289 00290 typedef struct _REGISTER_RECORD { 00291 ULONG Where : 2; // 2-bit field 00292 ULONG SaveOffset : 30; // 30 bits for offset, big enough? 00293 ULONG When; // slot offset relative to region 00294 } REGISTER_RECORD, *PREGISTER_RECORD; 00295 00296 typedef ULONG LABEL; 00297 00298 typedef struct _STATE_RECORD { 00299 struct _STATE_RECORD *Previous; // pointer to outer nested prologue 00300 BOOLEAN IsTarget; // TRUE if the control pc is in this prologue 00301 UCHAR GrMask; // Mask that specifies which GRs to be restored 00302 USHORT MiscMask; // Mask that specifies which BRs and misc. registers 00303 // are to be restored. 00304 // N.B. MSBit indicates Label is valid or not. 00305 ULONG FrMask; // Mask that specifies which FRs to be restored 00306 ULONG SpAdjustment; // size of stack frame allocated in the prologue 00307 ULONG SpWhen; // slot offset relative to region 00308 ULONG SpillPtr; // current spill location 00309 ULONG SpillBase; // spill base of the region 00310 ULONG RegionBegin; // first slot of region relative to function entry 00311 ULONG RegionLen; // number of slots in the region 00312 LABEL Label; // label that identifies a post-prologue state 00313 ULONG Ecount; // number of prologue regions to pop 00314 ULONG DescBegin; // first prologue descriptor for the region 00315 ULONG DescEnd; // last prologue descriptor for the region 00316 } STATE_RECORD, *PSTATE_RECORD; 00317 00318 typedef struct _UNWIND_CONTEXT { 00319 REGISTER_RECORD MiscRegs[NUMBER_OF_PRESERVED_REGISTERS]; 00320 REGISTER_RECORD Float[NUMBER_OF_PRESERVED_FR]; 00321 REGISTER_RECORD Integer[NUMBER_OF_PRESERVED_GR]; 00322 BOOLEAN ActiveRegionFound; 00323 USHORT Version; 00324 PUCHAR Descriptors; // beginning of descriptor data 00325 ULONG Size; // total size of all descriptors 00326 ULONG DescCount; // number of descriptor bytes processed 00327 ULONG TargetSlot; 00328 ULONG SlotCount; 00329 } UNWIND_CONTEXT, *PUNWIND_CONTEXT; 00330 00331 typedef struct _STATE_RECORD_STACK { 00332 ULONG Size; 00333 PSTATE_RECORD Current; 00334 PSTATE_RECORD Top; 00335 PSTATE_RECORD Base; 00336 } STATE_RECORD_STACK, *PSTATE_RECORD_STACK; 00337 00338 #define OFFSET(type, field) ((ULONG_PTR)(&((type *)0)->field)) 00339 00340 static USHORT MiscContextOffset[NUMBER_OF_PRESERVED_REGISTERS] = { 00341 OFFSET(CONTEXT, Preds), 00342 OFFSET(CONTEXT, IntSp), 00343 OFFSET(CONTEXT, RsPFS), 00344 OFFSET(CONTEXT, BrRp), 00345 OFFSET(CONTEXT, ApUNAT), 00346 OFFSET(CONTEXT, ApLC), 00347 0, 00348 OFFSET(CONTEXT, BrS0), 00349 OFFSET(CONTEXT, BrS1), 00350 OFFSET(CONTEXT, BrS2), 00351 OFFSET(CONTEXT, BrS3), 00352 OFFSET(CONTEXT, BrS4) 00353 }; 00354 00355 static USHORT MiscContextPointersOffset[NUMBER_OF_PRESERVED_REGISTERS] = { 00356 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, Preds), 00357 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, IntSp), 00358 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, RsPFS), 00359 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrRp), 00360 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, ApUNAT), 00361 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, ApLC), 00362 0, 00363 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS0), 00364 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS1), 00365 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS2), 00366 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS3), 00367 OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS4) 00368 }; 00369 00370 static UCHAR P3RecordTypeToRegisterIndex[] = 00371 {REG_SP, REG_RP, REG_PFS, REG_PREDS, REG_UNAT, REG_LC, REG_RP}; 00372 00373 static UCHAR P7RecordTypeToRegisterIndex[] = 00374 {0, REG_SP, 0, REG_SP, REG_RP, REG_RP, REG_PFS, REG_PFS, REG_PREDS, 00375 REG_PREDS, REG_LC, REG_LC, REG_UNAT, REG_UNAT, REG_FPSR, REG_FPSR}; 00376 00377 static UCHAR P8RecordTypeToRegisterIndex[] = 00378 {REG_SP, REG_RP, REG_PFS, REG_PREDS, REG_LC, REG_UNAT, REG_FPSR, 00379 REG_BSP, REG_BSP, REG_BSP, REG_BSPSTORE, REG_BSPSTORE, REG_BSPSTORE, 00380 REG_RNAT, REG_RNAT, REG_RNAT, REG_NATS, REG_NATS, REG_NATS}; 00381 00382 UCHAR 00383 NewParsePrologueRegionPhase0 ( 00384 IN PUNWIND_CONTEXT UwContext, 00385 IN PSTATE_RECORD StateRecord, 00386 IN OUT PUCHAR AbiImmContext 00387 ); 00388 00389 VOID 00390 NewParsePrologueRegionPhase1 ( 00391 IN PUNWIND_CONTEXT UwContext, 00392 IN PSTATE_RECORD StateRecord 00393 ); 00394 00395 00396 VOID 00397 SrInitialize ( 00398 IN PSTATE_RECORD_STACK StateTable, 00399 IN PSTATE_RECORD StateRecord, 00400 IN ULONG Size 00401 ) 00402 { 00403 StateTable->Size = Size; 00404 StateTable->Base = StateRecord; 00405 StateTable->Top = StateRecord; 00406 StateTable->Current = StateRecord; 00407 RtlZeroMemory(StateTable->Top, sizeof(STATE_RECORD)); 00408 } 00409 00410 00411 ULONG 00412 ReadLEB128 ( 00413 IN PUCHAR Descriptors, 00414 IN OUT PULONG CurrentDescIndex 00415 ) 00416 { 00417 PUCHAR Buffer; 00418 ULONG Value; 00419 ULONG ShiftCount = 7; 00420 ULONG Count; 00421 00422 Buffer = Descriptors + *CurrentDescIndex; 00423 Count = 1; 00424 00425 Value = Buffer[0] & 0x7F; 00426 if (Buffer[0] & 0x80) { 00427 while (TRUE) { 00428 Value += ((Buffer[Count] & 0x7F) << ShiftCount); 00429 if (Buffer[Count++] & 0x80) { 00430 ShiftCount += 7; 00431 } else { 00432 break; 00433 } 00434 } 00435 } 00436 00437 *CurrentDescIndex += Count; 00438 00439 return Value; 00440 } 00441 00442 00443 ULONGLONG 00444 RestorePreservedRegisterFromGR ( 00445 IN PCONTEXT Context, 00446 IN SHORT BsFrameSize, 00447 IN SHORT RNatSaveIndex, 00448 IN SHORT GrNumber, 00449 #ifdef _IMAGEHLP_SOURCE_ 00450 IN HANDLE hProcess, 00451 IN PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory, 00452 OUT BOOL *Succeed, 00453 #else 00454 OUT ULONG64 *SourceAddress, 00455 #endif // _IMAGEHLP_SOURCE_ 00456 OUT PUCHAR Nat OPTIONAL 00457 ) 00458 { 00459 ULONGLONG Result; 00460 SHORT Offset; 00461 SHORT Temp; 00462 #ifdef _IMAGEHLP_SOURCE_ 00463 ULONG Size; 00464 #endif // _IMAGEHLP_SOURCE_ 00465 00466 #ifdef _IMAGEHLP_SOURCE_ 00467 *Succeed = FALSE; 00468 #endif // _IMAGEHLP_SOURCE_ 00469 00470 if (GrNumber >= STATIC_REGISTER_SET_SIZE) { 00471 00472 Offset = GrNumber - STATIC_REGISTER_SET_SIZE; 00473 if ( Offset < BsFrameSize ) { 00474 00475 Temp = Offset + RNatSaveIndex - NAT_BITS_PER_RNAT_REG; 00476 while (Temp >= 0) { 00477 Offset++; 00478 Temp -= NAT_BITS_PER_RNAT_REG; 00479 } 00480 Offset = Offset * sizeof(ULONGLONG); 00481 00482 #ifdef _IMAGEHLP_SOURCE_ 00483 *Succeed = ReadMemory(hProcess, Context->RsBSP + Offset, 00484 &Result, sizeof(ULONGLONG), &Size); 00485 #else 00486 *SourceAddress = (ULONG64)(Context->RsBSP + Offset); 00487 Result = *(PULONGLONG)(Context->RsBSP + Offset); 00488 #endif // _IMAGEHLP_SOURCE_ 00489 00490 } else { 00491 00492 UW_DEBUG(("ERROR: Invalid GR!\n")); 00493 } 00494 00495 } else { 00496 00497 if (GrNumber == 0 || GrNumber == 12) { 00498 00499 // 00500 // Invalid GR number -> Invalid Unwind Descriptor 00501 // 00502 00503 UW_DEBUG(("ERROR: Invalid GR!\n")); 00504 00505 } else { 00506 00507 UW_DEBUG(("WARNING: Target register is not a stacked GR!\n")); 00508 Offset = GrNumber - 1; 00509 NOT_IMAGEHLP(*SourceAddress = (ULONG64)(&Context->IntGp + Offset)); 00510 Result = *(&Context->IntGp + Offset); 00511 00512 #ifdef _IMAGEHLP_SOURCE_ 00513 *Succeed = TRUE; 00514 #endif // _IMAGEHLP_SOURCE_ 00515 00516 } 00517 } 00518 00519 if (ARGUMENT_PRESENT(Nat)) { 00520 00521 // 00522 // TBD: Pick up the corresponding Nat bit 00523 // 00524 00525 *Nat = (UCHAR) 0; 00526 00527 } 00528 00529 return (Result); 00530 } 00531 00532 00533 UCHAR 00534 ParseBodyRegionDescriptors ( 00535 IN PUNWIND_CONTEXT UnwindContext, 00536 IN PSTATE_RECORD_STACK StateTable, 00537 IN ULONG RegionLen 00538 ) 00539 { 00540 LABEL Label; 00541 UCHAR FirstByte; 00542 BOOLEAN EcountDefined; 00543 BOOLEAN CopyLabel; 00544 ULONG Ecount; 00545 ULONG SlotOffset; 00546 PSTATE_RECORD StateTablePtr; 00547 PUCHAR Descriptors; 00548 00549 CopyLabel = EcountDefined = FALSE; 00550 Descriptors = UnwindContext->Descriptors; 00551 00552 while (UnwindContext->DescCount < UnwindContext->Size) { 00553 00554 FirstByte = Descriptors[UnwindContext->DescCount++]; 00555 00556 if ( (FirstByte & B1_MASK) == B1_PREFIX ) { 00557 00558 Label = (LABEL)(FirstByte & B1_LABEL_MASK); 00559 if (FirstByte & B1_TYPE_MASK) { 00560 00561 // 00562 // copy the entry state 00563 // 00564 00565 CopyLabel = TRUE; 00566 00567 } else { 00568 00569 // 00570 // label the entry state 00571 // 00572 00573 LABEL_REGION(StateTable->Top, Label); 00574 } 00575 00576 UW_DEBUG(("Body region desc B1: copy=%d, label_num=%d\n", 00577 FirstByte & B1_TYPE_MASK ? TRUE : FALSE, Label)); 00578 00579 } else if ( (FirstByte & B2_MASK) == B2_PREFIX ) { 00580 00581 Ecount = FirstByte & B2_ECOUNT_MASK; 00582 SlotOffset = ReadLEB128(Descriptors, &UnwindContext->DescCount); 00583 EcountDefined = TRUE; 00584 00585 UW_DEBUG(("Epilog desc B2: ecount=%d, LEB128(slot)=%d\n", 00586 Ecount, SlotOffset)); 00587 00588 } else if ( (FirstByte & B3_MASK) == B3_PREFIX ) { 00589 00590 SlotOffset = ReadLEB128(Descriptors, &UnwindContext->DescCount); 00591 Ecount = ReadLEB128(Descriptors, &UnwindContext->DescCount); 00592 EcountDefined = TRUE; 00593 00594 UW_DEBUG(("Epilog desc B3: ecount=%d, LEB128 val=%d\n", 00595 Ecount, SlotOffset)); 00596 00597 } else if ( (FirstByte & B4_MASK) == B4_PREFIX ) { 00598 00599 Label = ReadLEB128(Descriptors, &UnwindContext->DescCount); 00600 00601 if (FirstByte & B4_TYPE_MASK) { 00602 00603 // 00604 // copy the entry state 00605 // 00606 00607 CopyLabel = TRUE; 00608 00609 } else { 00610 00611 // 00612 // label the current top of stack 00613 // 00614 00615 LABEL_REGION(StateTable->Top, Label); 00616 } 00617 00618 UW_DEBUG(("Body region desc B4: copy=%d, label_num=%d\n", 00619 FirstByte & B4_TYPE_MASK, Label)); 00620 00621 } else { 00622 00623 // 00624 // Encounter another region header record 00625 // 00626 00627 break; 00628 } 00629 } 00630 00631 if (CopyLabel) { 00632 StateTablePtr = StateTable->Top; 00633 while (TRUE) { 00634 if (CHECK_LABEL(StateTablePtr, Label)) { 00635 StateTable->Current = StateTablePtr; 00636 break; 00637 } else if ((StateTablePtr == StateTable->Base)) { 00638 UW_DEBUG(("Undefined Label %d\n", Label)); 00639 break; 00640 } 00641 StateTablePtr--; 00642 } 00643 } 00644 00645 if (EcountDefined) { 00646 00647 Ecount++; // Ecount specifies additional level of prologue 00648 // regions to undo (i.e. a value of 0 implies 1 00649 // prologue region) 00650 00651 if (UnwindContext->ActiveRegionFound == FALSE) { 00652 while (Ecount-- > 0) { 00653 if (StateTable->Current->Previous) { 00654 StateTable->Current = StateTable->Current->Previous; 00655 } 00656 00657 #if DBG 00658 else { 00659 UW_DEBUG(("WARNING: Ecount is greater than the # of active prologues!\n")); 00660 } 00661 #endif // DBG 00662 00663 } 00664 } else { 00665 00666 // 00667 // control PC is in this body/epilog region 00668 // 00669 00670 if ((UnwindContext->SlotCount + RegionLen - SlotOffset) 00671 <= UnwindContext->TargetSlot) 00672 { 00673 PSTATE_RECORD SrPointer; 00674 00675 StateTable->Current->Ecount = Ecount; 00676 SrPointer = StateTable->Current; 00677 while (Ecount > 0) { 00678 00679 if (SrPointer->Previous) { 00680 SrPointer->Ecount = Ecount; 00681 SrPointer->SpWhen = 0; 00682 SrPointer->SpAdjustment = 0; 00683 SrPointer = SrPointer->Previous; 00684 } 00685 00686 #if DBG 00687 else { 00688 UW_DEBUG(("WARNING: Ecount is greater than the # of active prologues!\n")); 00689 } 00690 #endif // DBG 00691 Ecount--; 00692 00693 } 00694 } 00695 } 00696 } 00697 00698 return FirstByte; 00699 } 00700 00701 00702 ULONGLONG 00703 ProcessInterruptRegion ( 00704 #ifdef _IMAGEHLP_SOURCE_ 00705 IN HANDLE hProcess, 00706 IN PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory, 00707 #else 00708 IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, 00709 #endif _IMAGEHLP_SOURCE_ 00710 IN PUNWIND_CONTEXT UnwindContext, 00711 IN PCONTEXT Context, 00712 IN SHORT BsFrameSize, 00713 IN SHORT RNatSaveIndex, 00714 IN UCHAR AbiImmContext 00715 ) 00716 { 00717 // 00718 // no prologue descriptor in interrupt region. 00719 // 00720 00721 PCONTEXT PrevContext; 00722 ULONGLONG NextPc; 00723 ULONG Index; 00724 SHORT TempFrameSize; 00725 BOOLEAN Success; 00726 #ifdef _IMAGEHLP_SOURCE_ 00727 ULONG Size; 00728 #else 00729 PVOID *Source; 00730 PVOID Address; 00731 #endif _IMAGEHLP_SOURCE_ 00732 00733 00734 if (AbiImmContext != CONTEXT_FRAME) { 00735 00736 PKTRAP_FRAME TrapFrame; 00737 PKEXCEPTION_FRAME ExFrame; 00738 #ifdef _IMAGEHLP_SOURCE_ 00739 KTRAP_FRAME TF; 00740 KEXCEPTION_FRAME ExF; 00741 #endif // _IMAGEHLP_SOURCE_ 00742 00743 TrapFrame = (PKTRAP_FRAME) Context->IntSp; 00744 #ifdef _IMAGEHLP_SOURCE_ 00745 if (!ReadMemory(hProcess, Context->IntSp, &TF, sizeof(KTRAP_FRAME), &Size)) 00746 { 00747 return 0; 00748 } 00749 TrapFrame = &TF; 00750 #endif // _IMAGEHLP_SOURCE_ 00751 00752 Context->ApDCR = TrapFrame->ApDCR; 00753 Context->ApUNAT = TrapFrame->ApUNAT; 00754 Context->StFPSR = TrapFrame->StFPSR; 00755 Context->Preds = TrapFrame->Preds; 00756 Context->IntSp = TrapFrame->IntSp; 00757 Context->StIPSR = TrapFrame->StIPSR; 00758 Context->StIFS = TrapFrame->StIFS; 00759 Context->BrRp = TrapFrame->BrRp; 00760 Context->RsPFS = TrapFrame->RsPFS; 00761 00762 #ifndef _IMAGEHLP_SOURCE_ 00763 if (ARGUMENT_PRESENT(ContextPointers)) { 00764 ContextPointers->ApUNAT = &TrapFrame->ApUNAT; 00765 ContextPointers->IntSp = &TrapFrame->IntSp; 00766 ContextPointers->BrRp = &TrapFrame->BrRp; 00767 ContextPointers->RsPFS = &TrapFrame->RsPFS; 00768 ContextPointers->Preds = &TrapFrame->Preds; 00769 } 00770 #endif // _IMAGEHLP_SOURCE_ 00771 00772 switch (AbiImmContext) { 00773 00774 case SYSCALL_FRAME: 00775 00776 // 00777 // System Call Handler Frame 00778 // 00779 00780 BsFrameSize = (SHORT)(TrapFrame->StIFS >> PFS_SIZE_SHIFT); 00781 BsFrameSize &= PFS_SIZE_MASK; 00782 break; 00783 00784 case INTERRUPT_FRAME: 00785 case EXCEPTION_FRAME: 00786 00787 // 00788 // External Interrupt Frame / Exception Frame 00789 // 00790 00791 BsFrameSize = (SHORT)TrapFrame->StIFS & PFS_SIZE_MASK; 00792 break; 00793 00794 default: 00795 00796 break; 00797 } 00798 00799 RNatSaveIndex = (SHORT)(TrapFrame->RsBSP >> 3) & NAT_BITS_PER_RNAT_REG; 00800 TempFrameSize = BsFrameSize - RNatSaveIndex; 00801 while (TempFrameSize > 0) { 00802 BsFrameSize++; 00803 TempFrameSize -= NAT_BITS_PER_RNAT_REG; 00804 } 00805 00806 Context->RsBSP = TrapFrame->RsBSP - BsFrameSize * sizeof(ULONGLONG); 00807 Context->RsBSPSTORE = Context->RsBSP; 00808 Context->RsRNAT = TrapFrame->RsRNAT; 00809 00810 NextPc = RtlIa64InsertIPSlotNumber(TrapFrame->StIIP, 00811 ((TrapFrame->StIPSR >> PSR_RI) & 0x3)); 00812 00813 return (NextPc); 00814 } 00815 00816 // 00817 // Kernel-to-User thunk, context of the previous frame can be 00818 // found on the user stack (i.e. context's address = sp+SCRATCH_AREA) 00819 // 00820 00821 PrevContext = (PCONTEXT)(Context->IntSp + STACK_SCRATCH_AREA); 00822 #ifdef _IMAGEHLP_SOURCE_ 00823 if (!ReadMemory(hProcess, (DWORD64)PrevContext, Context, sizeof(CONTEXT), &Size)) 00824 { 00825 return 0; 00826 } 00827 NextPc = RtlIa64InsertIPSlotNumber(Context->StIIP, 00828 ((Context->StIPSR >> PSR_RI) & 0x3)); 00829 #else 00830 00831 RtlCopyMemory(&Context->BrRp, &PrevContext->BrRp, 00832 (NUMBER_OF_PRESERVED_BR+1) * sizeof(ULONGLONG)); 00833 RtlCopyMemory(&Context->FltS0, &PrevContext->FltS0, 00834 NUMBER_OF_LOW_PRESERVED_FR * sizeof(FLOAT128)); 00835 RtlCopyMemory(&Context->FltS4, &PrevContext->FltS4, 00836 NUMBER_OF_HIGH_PRESERVED_FR * sizeof(FLOAT128)); 00837 RtlCopyMemory(&Context->IntS0, &PrevContext->IntS0, 00838 NUMBER_OF_PRESERVED_GR * sizeof(ULONGLONG)); 00839 00840 Context->IntSp = PrevContext->IntSp; 00841 Context->IntNats = PrevContext->IntNats; 00842 Context->ApUNAT = PrevContext->ApUNAT; 00843 Context->ApLC = PrevContext->ApLC; 00844 Context->ApEC = PrevContext->ApEC; 00845 Context->Preds = PrevContext->Preds; 00846 Context->RsPFS = PrevContext->RsPFS; 00847 Context->RsBSP = PrevContext->RsBSP; 00848 Context->RsBSPSTORE = PrevContext->RsBSPSTORE; 00849 Context->RsRSC = PrevContext->RsRSC; 00850 Context->RsRNAT = PrevContext->RsRNAT; 00851 Context->StIFS = PrevContext->StIFS; 00852 Context->StIPSR = PrevContext->StIPSR; 00853 NextPc = RtlIa64InsertIPSlotNumber(PrevContext->StIIP, 00854 ((PrevContext->StIPSR >> PSR_RI) & 0x3)); 00855 00856 #endif // _IMAGEHLP_SOURCE_ 00857 00858 return(NextPc); 00859 } 00860 00861 00862 ULONGLONG 00863 RtlVirtualUnwind ( 00864 #ifdef _IMAGEHLP_SOURCE_ 00865 HANDLE hProcess, 00866 ULONGLONG ImageBase, 00867 ULONGLONG ControlPc, 00868 PRUNTIME_FUNCTION FunctionEntry, 00869 PCONTEXT ContextRecord, 00870 PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory 00871 #define ContextPointers ((PKNONVOLATILE_CONTEXT_POINTERS)0) 00872 #else 00873 IN ULONGLONG ImageBase, 00874 IN ULONGLONG ControlPc, 00875 IN PRUNTIME_FUNCTION FunctionEntry, 00876 IN OUT PCONTEXT ContextRecord, 00877 OUT PBOOLEAN InFunction, 00878 OUT PFRAME_POINTERS EstablisherFrame, 00879 IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL 00880 #endif 00881 ) 00882 00883 /*++ 00884 00885 Routine Description: 00886 00887 This function virtually unwinds the specfified function by executing its 00888 prologue code backwards. 00889 00890 If the function is a leaf function, then the address where control left 00891 the previous frame is obtained from the context record. If the function 00892 is a nested function, but not an exception or interrupt frame, then the 00893 prologue code is executed backwards and the address where control left 00894 the previous frame is obtained from the updated context record. 00895 00896 Otherwise, an exception or interrupt entry to the system is being unwound 00897 and an especially coded prologue restores the return address twice. Once 00898 from the fault instruction address and once from the saved return address 00899 register. The first restore is returned as the function value and the 00900 second restore is placed in the updated context record. 00901 00902 If a context pointers record is specified, then the address where each 00903 nonvolatile registers is restored from is recorded in the appropriate 00904 element of the context pointers record. 00905 00906 Arguments: 00907 00908 ImageBase - Supplies the base address of the module to which the 00909 function belongs. 00910 00911 ControlPc - Supplies the address where control left the specified 00912 function. 00913 00914 FunctionEntry - Supplies the address of the function table entry for the 00915 specified function. 00916 00917 ContextRecord - Supplies the address of a context record. 00918 00919 InFunction - Supplies a pointer to a variable that receives whether the 00920 control PC is within the current function. 00921 00922 EstablisherFrame - Supplies a pointer to a variable that receives the 00923 the establisher frame pointer value. 00924 00925 ContextPointers - Supplies an optional pointer to a context pointers 00926 record. 00927 00928 Return Value: 00929 00930 The address where control left the previous frame is returned as the 00931 function value. 00932 00933 --*/ 00934 00935 { 00936 #ifdef _IMAGEHLP_SOURCE_ 00937 BOOL Succeed; 00938 #endif // _IMAGEHLP_SOURCE_ 00939 PUCHAR Descriptors = NULL; 00940 UCHAR AbiImmContext = 0xFF; 00941 ULONG Mask; 00942 ULONGLONG NextPc; 00943 ULONG RegionLen; 00944 UCHAR FirstByte; 00945 UCHAR Nat; 00946 SHORT BsFrameSize; // in 8-byte units 00947 SHORT LocalFrameSize; // in 8-byte units 00948 SHORT TempFrameSize; // in 8-byte units 00949 SHORT RNatSaveIndex; 00950 ULONG i; 00951 PULONG Buffer; 00952 BOOLEAN IsPrologueRegion; 00953 BOOLEAN PspRestored; 00954 ULONGLONG PreviousIntSp; 00955 PVOID Destination; 00956 ULONG64 Source; 00957 ULONG64 *CtxPtr; 00958 ULONG64 *NatCtxPtr; 00959 ULONG64 IntNatsSource; 00960 ULONG64 IntNats; 00961 ULONG Size; 00962 ULONGLONG OldTopRnat; 00963 ULONGLONG NewTopRnat; 00964 UNWIND_INFO UnwindInfo; 00965 ULONG64 UnwindInfoPtr; 00966 UNWIND_CONTEXT UnwindContext; 00967 PSTATE_RECORD SrPointer; 00968 STATE_RECORD_STACK StateTable; 00969 STATE_RECORD StateRecords[STATE_RECORD_STACK_SIZE]; 00970 00971 00972 BsFrameSize = (SHORT)ContextRecord->StIFS & PFS_SIZE_MASK; 00973 RNatSaveIndex = (SHORT)(ContextRecord->RsBSP >> 3) & NAT_BITS_PER_RNAT_REG; 00974 TempFrameSize = RNatSaveIndex + BsFrameSize - NAT_BITS_PER_RNAT_REG; 00975 while (TempFrameSize >= 0) { 00976 BsFrameSize++; 00977 TempFrameSize -= NAT_BITS_PER_RNAT_REG; 00978 } 00979 00980 UnwindInfoPtr = ImageBase + FunctionEntry->UnwindInfoAddress; 00981 #ifdef _IMAGEHLP_SOURCE_ 00982 if (!ReadMemory( hProcess, (ULONG64)UnwindInfoPtr, 00983 &UnwindInfo, sizeof(UNWIND_INFO), &Size)) 00984 { 00985 return 0; 00986 } 00987 00988 UnwindContext.Version = UnwindInfo.Version; 00989 Size = UnwindInfo.DataLength * sizeof(ULONGLONG); 00990 if (Size) { 00991 Descriptors = (PUCHAR) MemAlloc (Size); 00992 if (!ReadMemory(hProcess,(ULONG64)(UnwindInfoPtr+sizeof(UNWIND_INFO)), Descriptors, Size, &Size)) { 00993 return 0; 00994 } 00995 } 00996 #else 00997 UnwindContext.Version = ((PUNWIND_INFO)UnwindInfoPtr)->Version; 00998 Size = ((PUNWIND_INFO)UnwindInfoPtr)->DataLength * sizeof(ULONGLONG); 00999 Descriptors = (PUCHAR)UnwindInfoPtr + sizeof(UNWIND_INFO); 01000 #endif // _IMAGEHLP_SOURCE_ 01001 01002 UnwindContext.Size = Size; 01003 UnwindContext.ActiveRegionFound = FALSE; 01004 UnwindContext.DescCount = 0; 01005 UnwindContext.SlotCount = 0; 01006 UnwindContext.TargetSlot = (ULONG)(((ControlPc - FunctionEntry->BeginAddress - ImageBase) >> 4) * SLOTS_PER_BUNDLE + ((ControlPc >> 2) & 0x3)); 01007 UnwindContext.Descriptors = Descriptors; 01008 01009 SrInitialize(&StateTable, StateRecords, STATE_RECORD_STACK_SIZE); 01010 01011 if (Size) { 01012 FirstByte = Descriptors[UnwindContext.DescCount++]; 01013 } 01014 01015 01016 while ( (UnwindContext.DescCount < UnwindContext.Size) && 01017 (!UnwindContext.ActiveRegionFound) ) 01018 { 01019 01020 // 01021 // Assume a prologue region but not an interrupt region. 01022 // 01023 01024 IsPrologueRegion = TRUE; 01025 01026 // 01027 // Based on the type of region header, dispatch 01028 // to the corresponding routine that processes 01029 // the succeeding descriptors until the next 01030 // region header record. 01031 // 01032 01033 if ((FirstByte & R1_MASK) == R1_PREFIX) { 01034 01035 // 01036 // region header record in short format 01037 // 01038 01039 RegionLen = FirstByte & R1_LENGTH_MASK; 01040 01041 if (FirstByte & R1_REGION_TYPE_MASK) { 01042 IsPrologueRegion = FALSE; 01043 } else { 01044 ADD_STATE_RECORD(StateTable, RegionLen, UnwindContext.DescCount); 01045 } 01046 01047 UW_DEBUG(("Region R1 format: body=%x, length=%d\n", 01048 IsPrologueRegion ? 0 : 1, RegionLen)); 01049 01050 } else if ((FirstByte & R2_MASK) == R2_PREFIX) { 01051 01052 // 01053 // general prologue region header 01054 // N.B. Skip the 2nd byte of the header and proceed to read 01055 // the region length; the header descriptors will be 01056 // processed again in phase 1. 01057 // 01058 01059 ULONG R2DescIndex; 01060 01061 R2DescIndex = UnwindContext.DescCount - 1; 01062 UnwindContext.DescCount++; 01063 RegionLen = ReadLEB128(Descriptors, &UnwindContext.DescCount); 01064 ADD_STATE_RECORD(StateTable, RegionLen, R2DescIndex); 01065 UW_DEBUG(("Region R2: body=0, length=%d\n", RegionLen)); 01066 01067 } else if ((FirstByte & R3_MASK) == R3_PREFIX) { 01068 01069 // 01070 // region header record in long format 01071 // 01072 01073 RegionLen = ReadLEB128(Descriptors, &UnwindContext.DescCount); 01074 01075 switch (FirstByte & R3_REGION_TYPE_MASK) { 01076 01077 case 0: // prologue region header 01078 01079 ADD_STATE_RECORD(StateTable, RegionLen, UnwindContext.DescCount); 01080 break; 01081 01082 case 1: // body region header 01083 01084 IsPrologueRegion = FALSE; 01085 break; 01086 01087 } 01088 01089 UW_DEBUG(("Region R3: body=%x, length=%d\n", 01090 IsPrologueRegion ? 0 : 1, RegionLen)); 01091 01092 } else { 01093 01094 // 01095 // Not a region header record -> Invalid unwind descriptor. 01096 // 01097 01098 UW_DEBUG(("Invalid unwind descriptor!\n")); 01099 01100 } 01101 01102 if (UnwindContext.TargetSlot < (UnwindContext.SlotCount + RegionLen)) { 01103 UnwindContext.ActiveRegionFound = TRUE; 01104 StateTable.Current->IsTarget = IsPrologueRegion; 01105 } 01106 01107 if (IsPrologueRegion) { 01108 FirstByte = NewParsePrologueRegionPhase0(&UnwindContext, 01109 StateTable.Current, 01110 &AbiImmContext); 01111 } else { 01112 FirstByte = ParseBodyRegionDescriptors(&UnwindContext, 01113 &StateTable, 01114 RegionLen); 01115 } 01116 01117 UnwindContext.SlotCount += RegionLen; 01118 } 01119 01120 // 01121 // Restore the value of psp and save the current NatCr. 01122 // N.B. If the value is restored from stack/bstore, turn off the 01123 // corresponding sp bit in the saved mask associated with the 01124 // prologue region in which psp is saved. 01125 // 01126 01127 if (ARGUMENT_PRESENT(ContextPointers)) { 01128 IntNatsSource = (ULONG64)ContextPointers->ApUNAT; 01129 } 01130 IntNats = ContextRecord->ApUNAT; 01131 PreviousIntSp = ContextRecord->IntSp; 01132 PspRestored = FALSE; 01133 01134 SrPointer = StateTable.Current; 01135 while (SrPointer != StateTable.Base) { 01136 NewParsePrologueRegionPhase1(&UnwindContext, SrPointer); 01137 01138 if (SrPointer->MiscMask & (1 << REG_SP)) { 01139 if (UnwindContext.MiscRegs[REG_SP].Where == GENERAL_REG) { 01140 PreviousIntSp = RestorePreservedRegisterFromGR ( 01141 ContextRecord, 01142 BsFrameSize, 01143 RNatSaveIndex, 01144 (SHORT)UnwindContext.MiscRegs[REG_SP].SaveOffset, 01145 #ifdef _IMAGEHLP_SOURCE_ 01146 hProcess, 01147 ReadMemory, 01148 &Succeed, 01149 #else 01150 &Source, 01151 #endif // _IMAGEHLP_SOURCE_ 01152 &Nat 01153 ); 01154 #ifdef _IMAGEHLP_SOURCE_ 01155 if (!Succeed) { 01156 return 0; 01157 } 01158 #endif // _IMAGEHLP_SOURCE_ 01159 01160 } else { 01161 01162 Source = ContextRecord->IntSp + UnwindContext.MiscRegs[REG_SP].SaveOffset*4; 01163 #ifdef _IMAGEHLP_SOURCE_ 01164 if (!ReadMemory(hProcess, (ULONG64)(Source), &PreviousIntSp, sizeof(ULONGLONG), &Size)) { 01165 return 0; 01166 } 01167 #else 01168 PreviousIntSp = *(PULONGLONG)Source; 01169 #endif // _IMAGEHLP_SOURCE_ 01170 EXTRACT_NAT_FROM_UNAT(Nat); 01171 01172 } 01173 ContextRecord->IntNats &= ~(0x1 << STACK_POINTER_GR); 01174 ContextRecord->IntNats |= (Nat << STACK_POINTER_GR); 01175 SrPointer->MiscMask &= ~(1 << REG_SP); 01176 if (ARGUMENT_PRESENT(ContextPointers)) { 01177 CtxPtr = (ULONG64 *)((ULONG_PTR)ContextPointers + 01178 MiscContextPointersOffset[REG_SP]); 01179 *CtxPtr = Source; 01180 } 01181 PspRestored = TRUE; 01182 } 01183 if (PspRestored == FALSE) { 01184 PreviousIntSp += SrPointer->SpAdjustment * 4; 01185 } 01186 SrPointer = SrPointer->Previous; 01187 } 01188 01189 if (AbiImmContext != 0xFF) { 01190 01191 ContextRecord->IntSp = PreviousIntSp; // trap/context frame address 01192 NextPc = ProcessInterruptRegion( 01193 #ifdef _IMAGEHLP_SOURCE_ 01194 hProcess, 01195 ReadMemory, 01196 #else 01197 ContextPointers, 01198 #endif _IMAGEHLP_SOURCE_ 01199 &UnwindContext, 01200 ContextRecord, 01201 BsFrameSize, 01202 RNatSaveIndex, 01203 AbiImmContext); 01204 01205 goto FastExit; 01206 } 01207 01208 // 01209 // Restore the contents of any preserved registers saved in this frame. 01210 // 01211 01212 SrPointer = StateTable.Current; 01213 while (SrPointer != StateTable.Base) { 01214 01215 Mask = SrPointer->MiscMask; 01216 UW_DEBUG(("MiscMask = 0x%x\n", Mask)); 01217 01218 for (i = 0; i < NUMBER_OF_PRESERVED_REGISTERS; i++) { 01219 Destination = (PVOID)((ULONG_PTR)ContextRecord + MiscContextOffset[i]); 01220 if (Mask & 0x1) { 01221 01222 if (ARGUMENT_PRESENT(ContextPointers)) { 01223 CtxPtr = (ULONG64 *)((ULONG_PTR)ContextPointers + 01224 MiscContextPointersOffset[i]); 01225 Source = *CtxPtr; 01226 } 01227 01228 if (UnwindContext.MiscRegs[i].Where == GENERAL_REG) { 01229 01230 *(PULONGLONG)Destination = 01231 RestorePreservedRegisterFromGR ( 01232 ContextRecord, 01233 BsFrameSize, 01234 RNatSaveIndex, 01235 (SHORT)UnwindContext.MiscRegs[i].SaveOffset, 01236 #ifdef _IMAGEHLP_SOURCE_ 01237 hProcess, 01238 ReadMemory, 01239 &Succeed, 01240 #else 01241 &Source, 01242 #endif // _IMAGEHLP_SOURCE_ 01243 NULL 01244 ); 01245 #ifdef _IMAGEHLP_SOURCE_ 01246 if (!Succeed) { 01247 return 0; 01248 } 01249 #endif // _IMAGEHLP_SOURCE_ 01250 01251 } else if (UnwindContext.MiscRegs[i].Where == BRANCH_REG) { 01252 01253 // 01254 // restore return pointer from branch register 01255 // 01256 01257 USHORT Offset; 01258 01259 Offset = (USHORT)UnwindContext.MiscRegs[i].SaveOffset-FIRST_PRESERVED_BR; 01260 Source = (ULONG64)(&ContextRecord->BrS0 + Offset); 01261 #ifdef _IMAGEHLP_SOURCE_ 01262 if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) { 01263 return 0; 01264 } 01265 #else 01266 *(PULONGLONG)Destination = *(PULONGLONG)(Source); 01267 #endif // _IMAGEHLP_SOURCE_ 01268 01269 } else if (UnwindContext.MiscRegs[i].Where == PSP_RELATIVE) { 01270 01271 if ((SrPointer->Ecount == 0) || (UnwindContext.MiscRegs[i].SaveOffset <= (STACK_SCRATCH_AREA/sizeof(ULONG)))) { 01272 Source = PreviousIntSp + STACK_SCRATCH_AREA 01273 - UnwindContext.MiscRegs[i].SaveOffset*4; 01274 01275 if (i == REG_NATS) { 01276 Destination = (PVOID)&IntNats; 01277 IntNatsSource = Source; 01278 } 01279 01280 #ifdef _IMAGEHLP_SOURCE_ 01281 if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) { 01282 return 0; 01283 } 01284 #else 01285 *(PULONGLONG)Destination = *(PULONGLONG)(Source); 01286 #endif // _IMAGEHLP_SOURCE_ 01287 } 01288 01289 } else if (UnwindContext.MiscRegs[i].Where == SP_RELATIVE) { 01290 01291 // 01292 // Make the necessary adjustment depending on whether 01293 // the preserved register is saved before or after the 01294 // stack pointer has been adjusted in this prologue. 01295 // 01296 01297 if (UnwindContext.MiscRegs[i].When >= SrPointer->SpWhen) 01298 Source = ContextRecord->IntSp 01299 + UnwindContext.MiscRegs[i].SaveOffset*4; 01300 else 01301 Source = ContextRecord->IntSp+SrPointer->SpAdjustment*4 01302 + UnwindContext.MiscRegs[i].SaveOffset*4; 01303 01304 if (i == REG_NATS) { 01305 Destination = (PVOID)&IntNats; 01306 IntNatsSource = Source; 01307 } 01308 01309 #ifdef _IMAGEHLP_SOURCE_ 01310 if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) { 01311 return 0; 01312 } 01313 #else 01314 *(PULONGLONG)Destination = *(PULONGLONG)(Source); 01315 #endif // _IMAGEHLP_SOURCE_ 01316 } 01317 01318 if (ARGUMENT_PRESENT(ContextPointers) && (i != REG_NATS)) { 01319 *CtxPtr = Source; 01320 } 01321 01322 } else if (Mask == 0) { 01323 01324 // 01325 // No more registers to restore 01326 // 01327 01328 break; 01329 } 01330 01331 Mask = Mask >> 1; 01332 } 01333 01334 // 01335 // Restore preserved FRs (f2 - f5, f16 - f31) 01336 // 01337 01338 Mask = SrPointer->FrMask; 01339 Destination = (PVOID)&ContextRecord->FltS0; 01340 CtxPtr = (ULONG64 *)&ContextPointers->FltS0; 01341 01342 UW_DEBUG(("FrMask = 0x%x\n", Mask)); 01343 for (i = 0; i < NUMBER_OF_PRESERVED_FR; i++) { 01344 if (Mask & 0x1) { 01345 01346 if ((SrPointer->Ecount == 0) || (UnwindContext.Float[i].SaveOffset <= (STACK_SCRATCH_AREA/sizeof(ULONG)))) { 01347 Source = PreviousIntSp + STACK_SCRATCH_AREA 01348 - UnwindContext.Float[i].SaveOffset*4; 01349 #ifdef _IMAGEHLP_SOURCE_ 01350 if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(FLOAT128), &Size)) { 01351 return 0; 01352 } 01353 #else 01354 *(FLOAT128 *)Destination = *(FLOAT128 *)Source; 01355 #endif // _IMAGEHLP_SOURCE_ 01356 01357 if (ARGUMENT_PRESENT(ContextPointers)) { 01358 *CtxPtr = Source; 01359 } 01360 } 01361 01362 } else if (Mask == 0) { 01363 break; 01364 } 01365 01366 Mask = Mask >> 1; 01367 01368 if (i == (NUMBER_OF_LOW_PRESERVED_FR - 1)) { 01369 Destination = (PVOID)&ContextRecord->FltS4; 01370 CtxPtr = (ULONG64 *)(&ContextPointers->FltS4); 01371 } else { 01372 Destination = (PVOID)((FLOAT128 *)Destination+1); 01373 CtxPtr++; 01374 } 01375 } 01376 01377 // 01378 // Restore preserved GRs (r4 - r7) 01379 // 01380 01381 Mask = SrPointer->GrMask; 01382 Destination = (PVOID)&ContextRecord->IntS0; 01383 CtxPtr = (ULONG64 *)&ContextPointers->IntS0; 01384 NatCtxPtr = (ULONG64 *)&ContextPointers->IntS0Nat; 01385 01386 UW_DEBUG(("GrMask = 0x%x\n", Mask)); 01387 for (i = 0; i < NUMBER_OF_PRESERVED_GR; i++) 01388 { 01389 if (Mask & 0x1) { 01390 01391 if ((SrPointer->Ecount == 0) || (UnwindContext.Integer[i].SaveOffset <= (STACK_SCRATCH_AREA/sizeof(ULONG)))) { 01392 Source = PreviousIntSp + STACK_SCRATCH_AREA 01393 - UnwindContext.Integer[i].SaveOffset*4; 01394 01395 #ifdef _IMAGEHLP_SOURCE_ 01396 if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) { 01397 return 0; 01398 } 01399 #else 01400 *(PULONGLONG)Destination = *(PULONGLONG)Source; 01401 #endif // _IMAGEHLP_SOURCE_ 01402 EXTRACT_NAT_FROM_UNAT(Nat); 01403 Nat = (UCHAR)((IntNats >> (((ULONG_PTR)Source & 0x1F8) >> 3)) & 0x1); 01404 ContextRecord->IntNats &= ~(0x1 << (i+FIRST_PRESERVED_GR)); 01405 ContextRecord->IntNats |= (Nat << (i+FIRST_PRESERVED_GR)); 01406 01407 #ifndef _IMAGEHLP_SOURCE_ 01408 if (ARGUMENT_PRESENT(ContextPointers)) { 01409 *CtxPtr = Source; 01410 *NatCtxPtr = IntNatsSource; 01411 } 01412 #endif 01413 } 01414 01415 } else if (Mask == 0) { 01416 break; 01417 } 01418 01419 Mask = Mask >> 1; 01420 Destination = (PVOID)((PULONGLONG)Destination+1); 01421 CtxPtr++; 01422 NatCtxPtr++; 01423 } 01424 01425 ContextRecord->IntSp += SrPointer->SpAdjustment * 4; 01426 SrPointer = SrPointer->Previous; 01427 } 01428 01429 ContextRecord->IntSp = PreviousIntSp; 01430 01431 // 01432 // Restore the value of the epilogue count from the PFS 01433 // 01434 01435 ContextRecord->ApEC = (ContextRecord->RsPFS >> PFS_EC_SHIFT) & 01436 ~(((ULONGLONG)1 << PFS_EC_SIZE) - 1); 01437 if (ARGUMENT_PRESENT(ContextPointers)) { 01438 ContextPointers->ApEC = ContextPointers->RsPFS; 01439 } 01440 01441 01442 FastExit: 01443 01444 NOT_IMAGEHLP(*InFunction = TRUE); 01445 NOT_IMAGEHLP(EstablisherFrame->MemoryStackFp = ContextRecord->IntSp); 01446 NOT_IMAGEHLP(EstablisherFrame->BackingStoreFp = ContextRecord->RsBSP); 01447 01448 #ifdef _IMAGEHLP_SOURCE_ 01449 if (Descriptors) 01450 MemFree(Descriptors); 01451 #endif // _IMAGEHLP_SOURCE_ 01452 01453 if (AbiImmContext == 0xFF) { 01454 01455 #ifdef _IMAGEHLP_SOURCE_ 01456 NextPc = ContextRecord->BrRp; 01457 #else 01458 NextPc = RtlIa64InsertIPSlotNumber((ContextRecord->BrRp-16), 2); 01459 #endif // _IMAGEHLP_SOURCE_ 01460 01461 // 01462 // determine the local frame size of previous frame and compute 01463 // the new bsp. 01464 // 01465 01466 OldTopRnat = (ContextRecord->RsBSP+(BsFrameSize-1)*8) | RNAT_ALIGNMENT; 01467 01468 ContextRecord->StIFS = MASK(IFS_V, (ULONGLONG)1) | ContextRecord->RsPFS; 01469 BsFrameSize = (SHORT)ContextRecord->StIFS & PFS_SIZE_MASK; 01470 LocalFrameSize = (SHORT)(ContextRecord->StIFS >> PFS_SIZE_SHIFT) & PFS_SIZE_MASK; 01471 TempFrameSize = LocalFrameSize - RNatSaveIndex; 01472 while (TempFrameSize > 0) { 01473 LocalFrameSize++; 01474 BsFrameSize++; 01475 TempFrameSize -= NAT_BITS_PER_RNAT_REG; 01476 } 01477 ContextRecord->RsBSP -= LocalFrameSize * 8; 01478 ContextRecord->RsBSPSTORE = ContextRecord->RsBSP; 01479 01480 // 01481 // determine if the RNAT field needs to be updated. 01482 // 01483 01484 NewTopRnat = (ContextRecord->RsBSP+(BsFrameSize-1)*8) | RNAT_ALIGNMENT; 01485 01486 if (NewTopRnat < OldTopRnat) { 01487 01488 #ifdef _IMAGEHLP_SOURCE_ 01489 Destination = &ContextRecord->RsRNAT; 01490 Source = NewTopRnat; 01491 if (!ReadMemory(hProcess, (ULONG64)Source, Destination, 8, &Size)) { 01492 return 0; 01493 } 01494 #else 01495 ContextRecord->RsRNAT = *(PULONGLONG)(NewTopRnat); 01496 #endif // _IMAGEHLP_SOURCE_ 01497 01498 } 01499 } 01500 01501 #ifdef _IMAGEHLP_SOURCE_ 01502 UW_DEBUG(("NextPc = 0x%lx, PSP = 0x%lx, BSP = 0x%lx\n", 01503 (ULONGLONG)NextPc, 01504 (ULONGLONG)ContextRecord->IntSp, 01505 (ULONGLONG)ContextRecord->RsBSP)); 01506 #else 01507 UW_DEBUG(("NextPc = 0x%lx, PSP = 0x%lx, BSP = 0x%lx\n", 01508 (ULONGLONG)NextPc, 01509 EstablisherFrame->MemoryStackFp, 01510 EstablisherFrame->BackingStoreFp)); 01511 #endif // _IMAGEHLP_SOURCE_ 01512 return (NextPc); 01513 } 01514 01515 01516 UCHAR 01517 NewParsePrologueRegionPhase0 ( 01518 IN PUNWIND_CONTEXT UwContext, 01519 IN PSTATE_RECORD State, 01520 IN OUT PUCHAR AbiImmContext 01521 ) 01522 { 01523 PUCHAR Desc = UwContext->Descriptors; 01524 ULONG Offset; 01525 ULONG FrameSize; 01526 ULONG Index; 01527 UCHAR RecType; 01528 UCHAR FirstByte; 01529 UCHAR SecondByte; 01530 ULONG GrSave; 01531 ULONG TempMask; 01532 ULONG i; 01533 01534 while (UwContext->DescCount < UwContext->Size) { 01535 01536 FirstByte = Desc[UwContext->DescCount++]; 01537 01538 if ( (FirstByte & P1_MASK) == P1_PREFIX) { 01539 01540 continue; 01541 01542 } else if ( (FirstByte & P2_MASK) == P2_PREFIX ) { 01543 01544 UwContext->DescCount++; 01545 01546 } else if ( (FirstByte & P3_MASK) == P3_PREFIX ) { 01547 01548 UwContext->DescCount++; 01549 01550 } else if ( (FirstByte & P4_MASK) == P4_PREFIX ) { 01551 01552 UwContext->DescCount += ((State->RegionLen+3) >> 2); 01553 01554 } else if ( (FirstByte & P5_MASK) == P5_PREFIX ) { 01555 01556 UwContext->DescCount += 3; 01557 01558 } else if ( (FirstByte & P6_MASK) == P6_PREFIX ) { 01559 01560 continue; 01561 01562 } else if ( (FirstByte & P7_MASK) == P7_PREFIX ) { 01563 01564 RecType = FirstByte & ~P7_MASK; 01565 01566 switch (RecType) { 01567 01568 case MEM_STACK_F: 01569 01570 Offset = ReadLEB128(Desc, &UwContext->DescCount); 01571 FrameSize = ReadLEB128(Desc, &UwContext->DescCount); 01572 01573 if (UwContext->TargetSlot > (UwContext->SlotCount+Offset)) 01574 { 01575 State->SpAdjustment += FrameSize*4; 01576 State->SpWhen = Offset; 01577 } 01578 break; 01579 01580 case SPILL_BASE: 01581 01582 State->SpillBase = ReadLEB128(Desc, &UwContext->DescCount); 01583 State->SpillPtr = State->SpillBase; 01584 break; 01585 01586 case MEM_STACK_V: 01587 case RP_WHEN: 01588 case PFS_WHEN: 01589 case PREDS_WHEN: 01590 case LC_WHEN: 01591 case UNAT_WHEN: 01592 case FPSR_WHEN: 01593 01594 Offset = ReadLEB128(Desc, &UwContext->DescCount); 01595 if ((State->IsTarget) && 01596 (UwContext->TargetSlot > (UwContext->SlotCount+Offset))) 01597 { 01598 Index = P7RecordTypeToRegisterIndex[RecType]; 01599 if (!(State->MiscMask & (1 << Index))) { 01600 State->MiscMask |= MASK(Index,1); 01601 UwContext->MiscRegs[Index].When = Offset; 01602 } else { 01603 UW_DEBUG(("Duplicate descriptors,")); 01604 UW_DEBUG(("unwinder may produce incorrect result!\n")); 01605 } 01606 } 01607 UW_DEBUG(("Prolog P7: type=%d slot= %d\n", RecType, Offset)); 01608 break; 01609 01610 case PSP_SPREL: 01611 case RP_PSPREL: 01612 case PFS_PSPREL: 01613 case PREDS_PSPREL: 01614 case LC_PSPREL: 01615 case UNAT_PSPREL: 01616 case FPSR_PSPREL: 01617 01618 Offset = ReadLEB128(Desc, &UwContext->DescCount); 01619 break; 01620 01621 default: 01622 01623 UW_DEBUG(("Invalid record type for descriptor P7!\n")); 01624 01625 } 01626 01627 } else if ( (FirstByte & P8_MASK) == P8_PREFIX ) { 01628 01629 RecType = Desc[UwContext->DescCount++]; 01630 01631 switch (RecType) { 01632 01633 case PSP_PSPREL: 01634 case RP_SPREL: 01635 case PFS_SPREL: 01636 case PREDS_SPREL: 01637 case LC_SPREL: 01638 case UNAT_SPREL: 01639 case FPSR_SPREL: 01640 case BSP_PSPREL: 01641 case BSP_SPREL: 01642 case BSPSTORE_PSPREL: 01643 case BSPSTORE_SPREL: 01644 case RNAT_PSPREL: 01645 case RNAT_SPREL: 01646 case PRIUNAT_PSPREL: 01647 case PRIUNAT_SPREL: 01648 01649 Offset = ReadLEB128(Desc, &UwContext->DescCount); 01650 UW_DEBUG(("Prolog P8: type=%d slot= %d\n", RecType, Offset)); 01651 break; 01652 01653 case BSP_WHEN: 01654 case BSPSTORE_WHEN: 01655 case RNAT_WHEN: 01656 case PRIUNAT_WHEN: 01657 01658 Offset = ReadLEB128(Desc, &UwContext->DescCount); 01659 if ((State->IsTarget) && 01660 (UwContext->TargetSlot > (UwContext->SlotCount+Offset))) 01661 { 01662 Index = P7RecordTypeToRegisterIndex[RecType]; 01663 if (!(State->MiscMask & (1 << Index))) { 01664 State->MiscMask |= MASK(Index,1); 01665 UwContext->MiscRegs[Index].When = Offset; 01666 } else { 01667 UW_DEBUG(("Duplicate descriptors,")); 01668 UW_DEBUG(("unwinder may produce incorrect result!\n")); 01669 } 01670 } 01671 UW_DEBUG(("Prolog P8: type=%d slot= %d\n", RecType, Offset)); 01672 break; 01673 01674 default: 01675 01676 UW_DEBUG(("Invalid record type for descriptor P8!\n")); 01677 01678 } 01679 01680 } else if ( (FirstByte & P9_MASK) == P9_PREFIX ) { 01681 01682 UwContext->DescCount += 2; 01683 VUW_DEBUG_PRINT("Format P9 not supported yet!\n"); 01684 01685 } else if ( (FirstByte & P10_MASK) == P10_PREFIX ) { 01686 01687 UCHAR Abi = Desc[UwContext->DescCount++]; 01688 UCHAR Context = Desc[UwContext->DescCount++]; 01689 01690 *AbiImmContext = Context; 01691 01692 if (Abi != NT_ABI) { 01693 VUW_DEBUG_PRINT("Unknown ABI unwind descriptor\n"); 01694 } 01695 01696 } else { 01697 01698 // 01699 // Encounter another region header record 01700 // 01701 01702 break; 01703 } 01704 } 01705 01706 State->DescEnd = UwContext->DescCount - 2; 01707 01708 return FirstByte; 01709 } 01710 01711 VOID 01712 NewParsePrologueRegionPhase1 ( 01713 IN PUNWIND_CONTEXT UwContext, 01714 IN PSTATE_RECORD State 01715 ) 01716 { 01717 ULONG FrameSize; 01718 ULONG Offset; 01719 ULONG GrSave; 01720 ULONG BrBase; 01721 ULONG Index; 01722 ULONG Count; 01723 UCHAR RecType; 01724 UCHAR FirstByte, SecondByte; // 1st & 2nd bytes of a region header record 01725 ULONG DescIndex; 01726 ULONG ImaskBegin; 01727 UCHAR NextBr, NextGr, NextFr; 01728 USHORT MiscMask; 01729 ULONG TempMask; 01730 ULONG FrMask = 0; 01731 UCHAR BrMask = 0; 01732 UCHAR GrMask = 0; 01733 PUCHAR Desc = UwContext->Descriptors; 01734 BOOLEAN SpillMaskOmitted = TRUE; 01735 01736 DescIndex = State->DescBegin; 01737 01738 FirstByte = Desc[DescIndex]; 01739 01740 if ((FirstByte & R2_MASK) == R2_PREFIX) { 01741 01742 // 01743 // general prologue region header; need to process it first 01744 // 01745 01746 ULONG GrSave, Count; 01747 UCHAR MiscMask; 01748 UCHAR SecondByte; 01749 USHORT i; 01750 01751 DescIndex++; 01752 SecondByte = Desc[DescIndex++]; 01753 MiscMask = ((FirstByte & 0x7) << 1) | ((SecondByte & 0x80) >> 7); 01754 GrSave = SecondByte & 0x7F; 01755 ReadLEB128(Desc, &DescIndex); // advance the descriptor index 01756 01757 if (GrSave < STATIC_REGISTER_SET_SIZE) { 01758 UW_DEBUG(("Invalid unwind descriptor!\n")); 01759 } 01760 01761 UW_DEBUG(("Region R2: rmask=%x,grsave=%d,length=%d\n", 01762 MiscMask, GrSave, State->RegionLen)); 01763 01764 Count = 0; 01765 for (Index = REG_PREDS; Index <= REG_RP; Index++) { 01766 if (MiscMask & 0x1) { 01767 if (!(State->IsTarget) || 01768 (State->MiscMask & MASK(Index,1))) 01769 { 01770 UwContext->MiscRegs[Index].Where = GENERAL_REG; 01771 UwContext->MiscRegs[Index].SaveOffset = GrSave+Count; 01772 UwContext->MiscRegs[Index].When = 0; 01773 State->MiscMask |= MASK(Index,1); 01774 } 01775 Count++; 01776 } 01777 MiscMask = MiscMask >> 1; 01778 } 01779 } 01780 01781 while (DescIndex <= State->DescEnd) { 01782 01783 FirstByte = Desc[DescIndex++]; 01784 01785 if ( (FirstByte & P1_MASK) == P1_PREFIX) { 01786 01787 BrMask = FirstByte & ~P1_MASK; 01788 State->MiscMask |= (BrMask << REG_BR_BASE); 01789 01790 UW_DEBUG(("Prolog P1: brmask=%x\n", BrMask)); 01791 01792 for (Count = REG_BR_BASE; 01793 Count < REG_BR_BASE+NUMBER_OF_PRESERVED_BR; 01794 Count++) 01795 { 01796 if (BrMask & 0x1) { 01797 UwContext->MiscRegs[Count].Where = PSP_RELATIVE; 01798 UwContext->MiscRegs[Count].When = State->RegionLen; 01799 } 01800 BrMask = BrMask >> 1; 01801 } 01802 01803 } else if ( (FirstByte & P2_MASK) == P2_PREFIX ) { 01804 01805 SecondByte = Desc[DescIndex++]; 01806 GrSave = SecondByte & 0x7F; 01807 BrMask = ((FirstByte & ~P2_MASK) << 1) | ((SecondByte & 0x80) >> 7); 01808 UW_DEBUG(("Prolog P2: brmask=%x reg base=%d\n", BrMask, GrSave)); 01809 01810 State->MiscMask |= (BrMask << REG_BR_BASE); 01811 01812 for (Count = REG_BR_BASE; 01813 Count < REG_BR_BASE+NUMBER_OF_PRESERVED_BR; 01814 Count++) 01815 { 01816 if (BrMask & 0x1) { 01817 UwContext->MiscRegs[Count].Where = GENERAL_REG; 01818 UwContext->MiscRegs[Count].SaveOffset = GrSave++; 01819 } 01820 BrMask = BrMask >> 1; 01821 } 01822 01823 } else if ( (FirstByte & P3_MASK) == P3_PREFIX ) { 01824 01825 SecondByte = Desc[DescIndex++]; 01826 RecType = ((SecondByte & 0x80) >> 7) | ((FirstByte & 0x7) << 1); 01827 Index = P3RecordTypeToRegisterIndex[RecType]; 01828 01829 if (!(State->IsTarget) || 01830 (State->MiscMask & MASK(Index,1))) 01831 { 01832 if (RecType == RP_BR) { 01833 UwContext->MiscRegs[Index].Where = BRANCH_REG; 01834 } else { 01835 UwContext->MiscRegs[Index].Where = GENERAL_REG; 01836 } 01837 UwContext->MiscRegs[Index].SaveOffset = SecondByte & 0x7F; 01838 UwContext->MiscRegs[Index].When = 0; 01839 State->MiscMask |= MASK(Index,1); 01840 01841 UW_DEBUG(("Prolog P3: type=%d reg=%d\n", 01842 RecType, UwContext->MiscRegs[Index].SaveOffset)); 01843 } 01844 01845 } else if ( (FirstByte & P4_MASK) == P4_PREFIX ) { 01846 01847 SpillMaskOmitted = FALSE; 01848 ImaskBegin = DescIndex; 01849 DescIndex += ((State->RegionLen+3) >> 2); 01850 01851 } else if ( (FirstByte & P5_MASK) == P5_PREFIX ) { 01852 01853 GrMask = (Desc[DescIndex] & 0xF0) >> 4; 01854 FrMask = ((ULONG)(Desc[DescIndex] & 0xF) << 16) | 01855 ((ULONG)Desc[DescIndex+1] << 8) | 01856 ((ULONG)Desc[DescIndex+2]); 01857 01858 DescIndex += 3; // increment the descriptor index 01859 01860 State->GrMask |= GrMask; 01861 State->FrMask |= FrMask; 01862 01863 UW_DEBUG(("Prolog P5: grmask = %x, frmask = %x\n", 01864 State->GrMask, State->FrMask)); 01865 01866 } else if ( (FirstByte & P6_MASK) == P6_PREFIX ) { 01867 01868 if (FirstByte & 0x10) { 01869 01870 GrMask = FirstByte & 0xF; 01871 State->GrMask |= GrMask; 01872 01873 } else { 01874 01875 FrMask = FirstByte & 0xF; 01876 State->FrMask |= FrMask; 01877 01878 } 01879 01880 UW_DEBUG(("Prolog P6: is_gr = %d, mask = %x\n", 01881 (FirstByte & 0x10) ? 1 : 0, 01882 (FirstByte & 0x10) ? State->GrMask : State->FrMask)); 01883 01884 } else if ( (FirstByte & P7_MASK) == P7_PREFIX ) { 01885 01886 RecType = FirstByte & ~P7_MASK; 01887 01888 switch (RecType) { 01889 01890 case PSP_SPREL: 01891 01892 // 01893 // sp-relative location 01894 // 01895 01896 Index = P7RecordTypeToRegisterIndex[RecType]; 01897 Offset = ReadLEB128(Desc, &DescIndex); 01898 if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1))) 01899 { 01900 UwContext->MiscRegs[Index].Where = SP_RELATIVE; 01901 UwContext->MiscRegs[Index].SaveOffset = Offset; 01902 if (!(State->MiscMask & MASK(Index,1))) { 01903 UwContext->MiscRegs[Index].When = State->RegionLen; 01904 State->MiscMask |= MASK(Index,1); 01905 } 01906 } 01907 UW_DEBUG(("Prolog P7: type=%d spoff = %d\n", RecType, Offset)); 01908 break; 01909 01910 01911 case RP_PSPREL: 01912 case PFS_PSPREL: 01913 case PREDS_PSPREL: 01914 case LC_PSPREL: 01915 case UNAT_PSPREL: 01916 case FPSR_PSPREL: 01917 01918 // 01919 // psp-relative location 01920 // 01921 01922 Index = P7RecordTypeToRegisterIndex[RecType]; 01923 Offset = ReadLEB128(Desc, &DescIndex); 01924 if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1))) 01925 { 01926 UwContext->MiscRegs[Index].Where = PSP_RELATIVE; 01927 UwContext->MiscRegs[Index].SaveOffset = Offset; 01928 UwContext->MiscRegs[Index].When = 0; 01929 State->MiscMask |= MASK(Index,1); 01930 } 01931 UW_DEBUG(("Prolog P7: type=%d pspoff= %d\n", RecType, Offset)); 01932 break; 01933 01934 case MEM_STACK_V: 01935 case RP_WHEN: 01936 case PFS_WHEN: 01937 case PREDS_WHEN: 01938 case LC_WHEN: 01939 case UNAT_WHEN: 01940 case FPSR_WHEN: 01941 01942 // 01943 // Nevermind processing these descriptors because they 01944 // have been taken care of in phase 0 01945 // 01946 01947 Offset = ReadLEB128(Desc, &DescIndex); 01948 break; 01949 01950 case MEM_STACK_F: 01951 01952 Offset = ReadLEB128(Desc, &DescIndex); 01953 FrameSize = ReadLEB128(Desc, &DescIndex); 01954 01955 UW_DEBUG(("Prolog P7: type=%d Slot=%d FrameSize=%d\n", 01956 RecType, Offset, FrameSize)); 01957 break; 01958 01959 case SPILL_BASE: 01960 01961 State->SpillBase = ReadLEB128(Desc, &DescIndex); 01962 State->SpillPtr = State->SpillBase; 01963 UW_DEBUG(("Prolog P7: type=%d, spillbase=%d\n", 01964 RecType, State->SpillBase)); 01965 break; 01966 01967 default: 01968 01969 UW_DEBUG(("invalid unwind descriptors\n")); 01970 01971 } 01972 01973 } else if ( (FirstByte & P8_MASK) == P8_PREFIX ) { 01974 01975 RecType = Desc[DescIndex++]; 01976 01977 switch (RecType) { 01978 01979 case PSP_PSPREL: 01980 VUW_DEBUG_PRINT("Unsupported Unwind Descriptor!\n"); 01981 break; 01982 01983 case RP_SPREL: 01984 case PFS_SPREL: 01985 case PREDS_SPREL: 01986 case LC_SPREL: 01987 case UNAT_SPREL: 01988 case FPSR_SPREL: 01989 case BSP_SPREL: 01990 case BSPSTORE_SPREL: 01991 case RNAT_SPREL: 01992 case PRIUNAT_SPREL: 01993 01994 // 01995 // sp-relative location 01996 // 01997 01998 Index = P8RecordTypeToRegisterIndex[RecType]; 01999 Offset = ReadLEB128(Desc, &DescIndex); 02000 if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1))) 02001 { 02002 UwContext->MiscRegs[Index].Where = SP_RELATIVE; 02003 UwContext->MiscRegs[Index].SaveOffset = Offset; 02004 if (!(State->MiscMask & MASK(Index,1))) { 02005 UwContext->MiscRegs[Index].When=State->RegionLen; 02006 State->MiscMask |= MASK(Index,1); 02007 } 02008 } 02009 UW_DEBUG(("Prolog P8: type=%d spoff= %d\n", RecType, Offset)); 02010 break; 02011 02012 case BSP_PSPREL: 02013 case BSPSTORE_PSPREL: 02014 case RNAT_PSPREL: 02015 case PRIUNAT_PSPREL: 02016 02017 // 02018 // psp-relative location 02019 // 02020 02021 Index = P8RecordTypeToRegisterIndex[RecType]; 02022 Offset = ReadLEB128(Desc, &DescIndex); 02023 if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1))) 02024 { 02025 UwContext->MiscRegs[Index].Where = PSP_RELATIVE; 02026 UwContext->MiscRegs[Index].SaveOffset = Offset; 02027 UwContext->MiscRegs[Index].When = 0; 02028 State->MiscMask |= MASK(Index,1); 02029 } 02030 UW_DEBUG(("Prolog P8: type=%d pspoff= %d\n", RecType, Offset)); 02031 break; 02032 02033 case BSP_WHEN: 02034 case BSPSTORE_WHEN: 02035 case RNAT_WHEN: 02036 case PRIUNAT_WHEN: 02037 02038 // 02039 // Nevermind processing these descriptors because they 02040 // have been taken care of in phase 0 02041 // 02042 02043 Offset = ReadLEB128(Desc, &DescIndex); 02044 break; 02045 02046 default: 02047 02048 UW_DEBUG(("Invalid record type for descriptor P8!\n")); 02049 02050 } 02051 02052 } else if ( (FirstByte & P9_MASK) == P9_PREFIX ) { 02053 02054 DescIndex += 2; 02055 VUW_DEBUG_PRINT("Format P9 not supported yet!\n"); 02056 02057 } else if ( (FirstByte & P10_MASK) == P10_PREFIX ) { 02058 02059 UCHAR Abi = Desc[DescIndex++]; 02060 UCHAR Context = Desc[DescIndex++]; 02061 02062 } else { 02063 02064 UW_DEBUG(("Invalid descriptor!\n")); 02065 02066 } 02067 } 02068 02069 GrMask = State->GrMask; 02070 FrMask = State->FrMask; 02071 BrMask = State->MiscMask >> REG_BR_BASE; 02072 02073 if (!(GrMask | FrMask | BrMask)) { 02074 02075 return; 02076 02077 } else if (SpillMaskOmitted && !(State->IsTarget)) { 02078 02079 // 02080 // When spillmask is omitted, floating point registers, general 02081 // registers, and then branch regisers are spilled in order. 02082 // They are not modified in the prologue region; therefore, there 02083 // is no need to restore their contents when the control ip is 02084 // in this prologue region. 02085 // 02086 02087 // 1. floating point registers 02088 02089 State->SpillPtr &= ~(SPILLSIZE_OF_FLOAT128_IN_DWORDS - 1); 02090 NextFr = NUMBER_OF_PRESERVED_FR - 1; 02091 while (FrMask & 0xFFFFF) { 02092 if (FrMask & 0x80000) { 02093 State->SpillPtr += SPILLSIZE_OF_FLOAT128_IN_DWORDS; 02094 UwContext->Float[NextFr].SaveOffset = State->SpillPtr; 02095 } 02096 FrMask = FrMask << 1; 02097 NextFr--; 02098 } 02099 02100 // 2. branch registers 02101 02102 NextBr = REG_BR_BASE + NUMBER_OF_PRESERVED_BR - 1; 02103 while (BrMask & 0x1F) { 02104 if (BrMask & 0x10) { 02105 if (UwContext->MiscRegs[Index].Where == PSP_RELATIVE) { 02106 State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS; 02107 UwContext->MiscRegs[NextBr].SaveOffset = State->SpillPtr; 02108 } 02109 } 02110 BrMask = BrMask << 1; 02111 NextBr--; 02112 } 02113 02114 // 3. general registers 02115 02116 NextGr = NUMBER_OF_PRESERVED_GR - 1; 02117 while (GrMask & 0xF) { 02118 if (GrMask & 0x8) { 02119 State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS; 02120 UwContext->Integer[NextGr].SaveOffset = State->SpillPtr; 02121 } 02122 GrMask = GrMask << 1; 02123 NextGr--; 02124 } 02125 02126 } else if (SpillMaskOmitted && State->IsTarget) { 02127 02128 State->GrMask = 0; 02129 State->FrMask = 0; 02130 State->MiscMask &= MASK(REG_BR_BASE, 1) - 1; 02131 02132 } else if (SpillMaskOmitted == FALSE) { 02133 02134 ULONG Length; 02135 02136 if (State->IsTarget) { 02137 02138 // 02139 // control ip is in the prologue region; clear the masks 02140 // and then process the imask to determine which preserved 02141 // Gr/Fr/Br have been saved and set the corresponding bits. 02142 // 02143 02144 State->GrMask = 0; 02145 State->FrMask = 0; 02146 State->MiscMask &= MASK(REG_BR_BASE, 1) - 1; 02147 Length = UwContext->TargetSlot - State->RegionBegin; 02148 } else { 02149 Length = State->RegionLen; 02150 } 02151 02152 NextGr = NUMBER_OF_PRESERVED_GR - 1; 02153 NextBr = NUMBER_OF_PRESERVED_BR - 1; 02154 NextFr = NUMBER_OF_PRESERVED_FR - 1; 02155 for (Count = 0; Count < Length; Count++) { 02156 02157 if ((Count % 4) == 0) { 02158 FirstByte = Desc[ImaskBegin++]; 02159 } else { 02160 FirstByte = FirstByte << 2; 02161 } 02162 02163 switch (FirstByte & 0xC0) { 02164 02165 case 0x40: // 0x01 - save next fr 02166 02167 while ( !(FrMask & 0x80000) && (NextFr > 0) ) { 02168 NextFr--; 02169 FrMask = FrMask << 1; 02170 } 02171 02172 UW_DEBUG(("spilled register FS%lx\n", (ULONG)NextFr)); 02173 02174 State->FrMask |= MASK(NextFr,1); 02175 UwContext->Float[NextFr].When = Count; 02176 State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS; 02177 State->SpillPtr &= ~(SPILLSIZE_OF_FLOAT128_IN_DWORDS - 1); 02178 State->SpillPtr += SPILLSIZE_OF_FLOAT128_IN_DWORDS; 02179 UwContext->Float[NextFr].SaveOffset = State->SpillPtr; 02180 02181 NextFr--; 02182 FrMask = FrMask << 1; 02183 break; 02184 02185 case 0x80: // 0x10 - save next gr 02186 02187 while ( !(GrMask & 0x8) && (NextGr > 0) ) { 02188 NextGr--; 02189 GrMask = GrMask << 1; 02190 } 02191 02192 UW_DEBUG(("spilled register S%lx\n", (ULONG)NextGr)); 02193 02194 State->GrMask |= MASK(NextGr,1); 02195 UwContext->Integer[NextGr].When = Count; 02196 State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS; 02197 UwContext->Integer[NextGr].SaveOffset = State->SpillPtr; 02198 02199 NextGr--; 02200 GrMask = GrMask << 1; 02201 break; 02202 02203 case 0xC0: // 0x11 - save next br 02204 02205 while ( !(BrMask & 0x10) && (NextBr > 0) ) { 02206 NextBr--; 02207 BrMask = BrMask << 1; 02208 } 02209 02210 UW_DEBUG(("spilled register BS%lx\n", (ULONG)NextBr)); 02211 02212 Index = REG_BR_BASE + NextBr; 02213 State->MiscMask |= MASK(Index,1); 02214 UwContext->MiscRegs[Index].When = Count; 02215 if (UwContext->MiscRegs[Index].Where == PSP_RELATIVE) { 02216 State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS; 02217 UwContext->MiscRegs[Index].SaveOffset = State->SpillPtr; 02218 } 02219 02220 NextBr--; 02221 BrMask = BrMask << 1; 02222 break; 02223 02224 default: // 0x00 - save no register 02225 break; 02226 02227 } 02228 } 02229 } 02230 }

Generated on Sat May 15 19:42:24 2004 for test by doxygen 1.3.7