Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2239 lines
68 KiB

  1. /**
  2. *** Copyright (C) 1996-1999 Intel Corporation. All rights reserved.
  3. ***
  4. *** The information and source code contained herein is the exclusive
  5. *** property of Intel Corporation and may not be disclosed, examined
  6. *** or reproduced in whole or in part without explicit written authorization
  7. *** from the company.
  8. ***
  9. ****************************************************************************
  10. ***
  11. *** WARNING: ntos\rtl\ia64\vunwind.c and sdktools\imagehlp\vwndia64.c are
  12. *** identical. For sake of maintenance and for debug purposes,
  13. ** please keep them as this. Thank you.
  14. ***
  15. ****************************************************************************
  16. **/
  17. #if !defined(BUILD_DBGHELP) && !defined(BUILD_IMAGEHLP)
  18. #include "ntrtlp.h"
  19. #else // !BUILD_DBGHELP && !BUILD_IMAGEHLP
  20. #define TARGET_IA64
  21. #define _CROSS_PLATFORM_
  22. #define _IA64REG_
  23. #include "walk.h"
  24. #include "private.h"
  25. #include <stdlib.h>
  26. #endif // !BUILD_DBGHELP && !BUILD_IMAGEHLP
  27. #ifdef _IMAGEHLP_SOURCE_
  28. #define NOT_IMAGEHLP(E)
  29. #define FUNCTION_ENTRY_IS_IMAGE_STYLE
  30. #define RtlVirtualUnwind VirtualUnwindIa64
  31. #define PRUNTIME_FUNCTION PIMAGE_RUNTIME_FUNCTION_ENTRY
  32. #define RUNTIME_FUNCTION IMAGE_RUNTIME_FUNCTION_ENTRY
  33. #define VUW_DEBUG_PRINT OutputDebugString
  34. #else // !_IMAGEHLP_SOURCE_
  35. #define NOT_IMAGEHLP(E) E
  36. #define VUW_DEBUG_PRINT DbgPrint
  37. #endif // !_IMAGEHLP_SOURCE_
  38. #ifdef MASK
  39. #undef MASK
  40. #endif // MASK
  41. #define MASK(bp,value) (value << bp)
  42. //
  43. // ABI values
  44. //
  45. #define SVR4_ABI 0
  46. #define HPUX_ABI 1
  47. #define NT_ABI 2
  48. #ifdef KERNEL_DEBUGGER
  49. #define FUNCTION_ENTRY_IS_IMAGE_STYLE
  50. #define RtlVirtualUnwind VirtualUnwind
  51. #endif
  52. #define STATE_RECORD_STACK_SIZE 32
  53. #define SPILLSIZE_OF_FLOAT128_IN_DWORDS 4
  54. #define SPILLSIZE_OF_ULONGLONG_IN_DWORDS 2
  55. #define REGISTER_SIZE sizeof(ULONGLONG)
  56. #define STATIC_REGISTER_SET_SIZE 32
  57. #define SLOTS_PER_BUNDLE 3
  58. #define R1_MASK 0xC0
  59. #define R1_PREFIX 0x0
  60. #define R1_REGION_TYPE_MASK 0x20
  61. #define R1_LENGTH_MASK 0x1F
  62. #define R2_MASK 0xE0
  63. #define R2_PREFIX 0x40
  64. #define R3_MASK 0xE0
  65. #define R3_PREFIX 0x60
  66. #define R3_REGION_TYPE_MASK 0x3
  67. #define P1_MASK 0xE0
  68. #define P1_PREFIX 0x80
  69. #define P2_MASK 0xF0
  70. #define P2_PREFIX 0xA0
  71. #define P3_MASK 0xF8
  72. #define P3_PREFIX 0xB0
  73. #define P4_MASK 0xFF
  74. #define P4_PREFIX 0xB8
  75. #define P5_MASK 0xFF
  76. #define P5_PREFIX 0xB9
  77. #define P6_MASK 0xE0
  78. #define P6_PREFIX 0xC0
  79. #define P7_MASK 0xF0
  80. #define P7_PREFIX 0xE0
  81. #define P8_MASK 0xFF
  82. #define P8_PREFIX 0xF0
  83. #define P9_MASK 0xFF
  84. #define P9_PREFIX 0xF1
  85. #define P10_MASK 0xFF
  86. #define P10_PREFIX 0xFF
  87. #define B1_MASK 0xC0
  88. #define B1_PREFIX 0x80
  89. #define B1_TYPE_MASK 0x20
  90. #define B1_LABEL_MASK 0x1F
  91. #define B2_MASK 0xE0
  92. #define B2_PREFIX 0xC0
  93. #define B2_ECOUNT_MASK 0x1F
  94. #define B3_MASK 0xF0
  95. #define B3_PREFIX 0xE0
  96. #define B4_MASK 0xF0
  97. #define B4_PREFIX 0xF0
  98. #define B4_TYPE_MASK 0x08
  99. //
  100. // P3 descriptor type
  101. //
  102. #define PSP_GR 0
  103. #define RP_GR 1
  104. #define PFS_GR 2
  105. #define PREDS_GR 3
  106. #define UNAT_GR 4
  107. #define LC_GR 5
  108. #define RP_BR 6
  109. #define RNAT_GR 7
  110. #define BSP_GR 8
  111. #define BSPSTORE_GR 9
  112. #define FPSR_GR 10
  113. #define PRIUNAT_GR 11
  114. //
  115. // P7 descriptor type
  116. //
  117. #define MEM_STACK_F 0
  118. #define MEM_STACK_V 1
  119. #define SPILL_BASE 2
  120. #define PSP_SPREL 3
  121. #define RP_WHEN 4
  122. #define RP_PSPREL 5
  123. #define PFS_WHEN 6
  124. #define PFS_PSPREL 7
  125. #define PREDS_WHEN 8
  126. #define PREDS_PSPREL 9
  127. #define LC_WHEN 10
  128. #define LC_PSPREL 11
  129. #define UNAT_WHEN 12
  130. #define UNAT_PSPREL 13
  131. #define FPSR_WHEN 14
  132. #define FPSR_PSPREL 15
  133. //
  134. // P8 descriptor type
  135. //
  136. #define PSP_PSPREL 0
  137. #define RP_SPREL 1
  138. #define PFS_SPREL 2
  139. #define PREDS_SPREL 3
  140. #define LC_SPREL 4
  141. #define UNAT_SPREL 5
  142. #define FPSR_SPREL 6
  143. #define BSP_WHEN 7
  144. #define BSP_PSPREL 8
  145. #define BSP_SPREL 9
  146. #define BSPSTORE_WHEN 10
  147. #define BSPSTORE_PSPREL 11
  148. #define BSPSTORE_SPREL 12
  149. #define RNAT_WHEN 13
  150. #define RNAT_PSPREL 14
  151. #define RNAT_SPREL 15
  152. #define PRIUNAT_WHEN 16
  153. #define PRIUNAT_PSPREL 17
  154. #define PRIUNAT_SPREL 18
  155. #define STACK_POINTER_GR 12
  156. #define FIRST_PRESERVED_GR 4
  157. #define LAST_PRESERVED_GR 7
  158. #define NUMBER_OF_PRESERVED_GR 4
  159. #define NUMBER_OF_SCRATCH_GR 24
  160. #define FIRST_LOW_PRESERVED_FR 2
  161. #define LAST_LOW_PRESERVED_FR 5
  162. #define NUMBER_OF_LOW_PRESERVED_FR 4
  163. #define FIRST_HIGH_PRESERVED_FR 16
  164. #define LAST_HIGH_PRESERVED_FR 31
  165. #define NUMBER_OF_HIGH_PRESERVED_FR 16
  166. #define NUMBER_OF_PRESERVED_FR (NUMBER_OF_LOW_PRESERVED_FR+NUMBER_OF_HIGH_PRESERVED_FR)
  167. #define FIRST_PRESERVED_BR 1
  168. #define LAST_PRESERVED_BR 5
  169. #define NUMBER_OF_PRESERVED_BR 5
  170. #define NUMBER_OF_PRESERVED_MISC 8
  171. #define NUMBER_OF_PRESERVED_REGISTERS (NUMBER_OF_PRESERVED_MISC+NUMBER_OF_PRESERVED_BR)
  172. #define REG_MISC_BASE 0
  173. #define REG_PREDS (REG_MISC_BASE+0)
  174. #define REG_SP (REG_MISC_BASE+1)
  175. #define REG_PFS (REG_MISC_BASE+2)
  176. #define REG_RP (REG_MISC_BASE+3)
  177. #define REG_UNAT (REG_MISC_BASE+4)
  178. #define REG_LC (REG_MISC_BASE+5)
  179. #define REG_NATS (REG_MISC_BASE+6)
  180. #define REG_FPSR (REG_MISC_BASE+7)
  181. #define REG_BR_BASE (REG_MISC_BASE+NUMBER_OF_PRESERVED_MISC)
  182. #define REG_BSP 0xff // REG_MISC_BASE+8
  183. #define REG_BSPSTORE 0xff // REG_MISC_BASE+9
  184. #define REG_RNAT 0xff // REG_MISC_BASE+10
  185. //
  186. // Where is a preserved register saved?
  187. //
  188. // 1. stack general register
  189. // 2. memory stack (pspoff)
  190. // 3. memory stack (spoff)
  191. // 4. branch register
  192. //
  193. #define GENERAL_REG 0
  194. #define PSP_RELATIVE 1
  195. #define SP_RELATIVE 2
  196. #define BRANCH_REG 3
  197. #define ADD_STATE_RECORD(States, RegionLength, DescBeginIndex) \
  198. States.Top++; \
  199. States.Top->IsTarget = FALSE; \
  200. States.Top->MiscMask = 0; \
  201. States.Top->FrMask = 0; \
  202. States.Top->GrMask = 0; \
  203. States.Top->Label = (LABEL)0; \
  204. States.Top->Ecount = 0; \
  205. States.Top->RegionLen = RegionLength; \
  206. States.Top->RegionBegin = UnwindContext.SlotCount; \
  207. States.Top->SpWhen = 0; \
  208. States.Top->SpAdjustment = 0; \
  209. States.Top->SpillBase = (States.Top-1)->SpillPtr; \
  210. States.Top->SpillPtr = (States.Top-1)->SpillPtr; \
  211. States.Top->Previous = States.Current; \
  212. States.Top->DescBegin = DescBeginIndex; \
  213. States.Current = States.Top
  214. #define VALID_LABEL_BIT_POSITION 15
  215. #define LABEL_REGION(Region, Label) \
  216. Region->Label = Label; \
  217. Region->MiscMask |= (1 << VALID_LABEL_BIT_POSITION)
  218. #define IS_REGION_LABELED(Region) \
  219. (Region->MiscMask & (1 << VALID_LABEL_BIT_POSITION))
  220. #define CHECK_LABEL(State, Label) \
  221. ( (IS_REGION_LABELED(State)) && (Label == State->Label) )
  222. #define EXTRACT_NAT_FROM_UNAT(NatBit) \
  223. NatBit = (UCHAR)((IntNats >> (((ULONG_PTR)Source & 0x1F8) >> 3)) & 0x1);
  224. #if DBG
  225. int UnwindDebugLevel = 0;
  226. # ifdef _IMAGEHLP_SOURCE_
  227. # define UW_DEBUG(x) if (UnwindDebugLevel) dbPrint##x
  228. # else
  229. # define UW_DEBUG(x) if (UnwindDebugLevel) DbgPrint##x
  230. # endif
  231. #else
  232. # define UW_DEBUG(x)
  233. #endif // DBG
  234. typedef struct _REGISTER_RECORD {
  235. ULONG Where : 2; // 2-bit field
  236. ULONG SaveOffset : 30; // 30 bits for offset, big enough?
  237. ULONG When; // slot offset relative to region
  238. } REGISTER_RECORD, *PREGISTER_RECORD;
  239. typedef ULONG LABEL;
  240. typedef struct _STATE_RECORD {
  241. struct _STATE_RECORD *Previous; // pointer to outer nested prologue
  242. BOOLEAN IsTarget; // TRUE if the control pc is in this prologue
  243. UCHAR GrMask; // Mask that specifies which GRs to be restored
  244. USHORT MiscMask; // Mask that specifies which BRs and misc. registers
  245. // are to be restored.
  246. // N.B. MSBit indicates Label is valid or not.
  247. ULONG FrMask; // Mask that specifies which FRs to be restored
  248. ULONG SpAdjustment; // size of stack frame allocated in the prologue
  249. ULONG SpWhen; // slot offset relative to region
  250. ULONG SpillPtr; // current spill location
  251. ULONG SpillBase; // spill base of the region
  252. ULONG RegionBegin; // first slot of region relative to function entry
  253. ULONG RegionLen; // number of slots in the region
  254. LABEL Label; // label that identifies a post-prologue state
  255. ULONG Ecount; // number of prologue regions to pop
  256. ULONG DescBegin; // first prologue descriptor for the region
  257. ULONG DescEnd; // last prologue descriptor for the region
  258. } STATE_RECORD, *PSTATE_RECORD;
  259. typedef struct _UNWIND_CONTEXT {
  260. REGISTER_RECORD MiscRegs[NUMBER_OF_PRESERVED_REGISTERS];
  261. REGISTER_RECORD Float[NUMBER_OF_PRESERVED_FR];
  262. REGISTER_RECORD Integer[NUMBER_OF_PRESERVED_GR];
  263. BOOLEAN ActiveRegionFound;
  264. UCHAR AlternateRp;
  265. USHORT Version;
  266. PUCHAR Descriptors; // beginning of descriptor data
  267. ULONG Size; // total size of all descriptors
  268. ULONG DescCount; // number of descriptor bytes processed
  269. ULONG TargetSlot;
  270. ULONG SlotCount;
  271. } UNWIND_CONTEXT, *PUNWIND_CONTEXT;
  272. typedef struct _STATE_RECORD_STACK {
  273. ULONG Size;
  274. PSTATE_RECORD Current;
  275. PSTATE_RECORD Top;
  276. PSTATE_RECORD Base;
  277. } STATE_RECORD_STACK, *PSTATE_RECORD_STACK;
  278. #define OFFSET(type, field) ((ULONG_PTR)(&((type *)0)->field))
  279. static USHORT MiscContextOffset[NUMBER_OF_PRESERVED_REGISTERS] = {
  280. OFFSET(CONTEXT, Preds),
  281. OFFSET(CONTEXT, IntSp),
  282. OFFSET(CONTEXT, RsPFS),
  283. OFFSET(CONTEXT, BrRp),
  284. OFFSET(CONTEXT, ApUNAT),
  285. OFFSET(CONTEXT, ApLC),
  286. 0,
  287. 0,
  288. OFFSET(CONTEXT, BrS0),
  289. OFFSET(CONTEXT, BrS1),
  290. OFFSET(CONTEXT, BrS2),
  291. OFFSET(CONTEXT, BrS3),
  292. OFFSET(CONTEXT, BrS4)
  293. };
  294. static USHORT MiscContextPointersOffset[NUMBER_OF_PRESERVED_REGISTERS] = {
  295. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, Preds),
  296. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, IntSp),
  297. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, RsPFS),
  298. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrRp),
  299. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, ApUNAT),
  300. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, ApLC),
  301. 0,
  302. 0,
  303. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS0),
  304. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS1),
  305. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS2),
  306. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS3),
  307. OFFSET(KNONVOLATILE_CONTEXT_POINTERS, BrS4)
  308. };
  309. static UCHAR P3RecordTypeToRegisterIndex[] =
  310. {REG_SP, REG_RP, REG_PFS, REG_PREDS, REG_UNAT, REG_LC, REG_RP,
  311. REG_RNAT, REG_BSP, REG_BSPSTORE, REG_FPSR};
  312. static UCHAR P7RecordTypeToRegisterIndex[] =
  313. {0, REG_SP, 0, REG_SP, REG_RP, REG_RP, REG_PFS, REG_PFS, REG_PREDS,
  314. REG_PREDS, REG_LC, REG_LC, REG_UNAT, REG_UNAT, REG_FPSR, REG_FPSR};
  315. static UCHAR P8RecordTypeToRegisterIndex[] =
  316. {REG_SP, REG_RP, REG_PFS, REG_PREDS, REG_LC, REG_UNAT, REG_FPSR,
  317. REG_BSP, REG_BSP, REG_BSP, REG_BSPSTORE, REG_BSPSTORE, REG_BSPSTORE,
  318. REG_RNAT, REG_RNAT, REG_RNAT, REG_NATS, REG_NATS, REG_NATS};
  319. UCHAR
  320. NewParsePrologueRegionPhase0 (
  321. IN PUNWIND_CONTEXT UwContext,
  322. IN PSTATE_RECORD StateRecord,
  323. IN OUT PUCHAR AbiImmContext
  324. );
  325. VOID
  326. NewParsePrologueRegionPhase1 (
  327. IN PUNWIND_CONTEXT UwContext,
  328. IN PSTATE_RECORD StateRecord
  329. );
  330. VOID
  331. SrInitialize (
  332. IN PSTATE_RECORD_STACK StateTable,
  333. IN PSTATE_RECORD StateRecord,
  334. IN ULONG Size
  335. )
  336. {
  337. StateTable->Size = Size;
  338. StateTable->Base = StateRecord;
  339. StateTable->Top = StateRecord;
  340. StateTable->Current = StateRecord;
  341. RtlZeroMemory(StateTable->Top, sizeof(STATE_RECORD));
  342. }
  343. ULONG
  344. ReadLEB128 (
  345. IN PUCHAR Descriptors,
  346. IN OUT PULONG CurrentDescIndex
  347. )
  348. {
  349. PUCHAR Buffer;
  350. ULONG Value;
  351. ULONG ShiftCount = 7;
  352. ULONG Count;
  353. Buffer = Descriptors + *CurrentDescIndex;
  354. Count = 1;
  355. Value = Buffer[0] & 0x7F;
  356. if (Buffer[0] & 0x80) {
  357. while (TRUE) {
  358. Value += ((Buffer[Count] & 0x7F) << ShiftCount);
  359. if (Buffer[Count++] & 0x80) {
  360. ShiftCount += 7;
  361. } else {
  362. break;
  363. }
  364. }
  365. }
  366. *CurrentDescIndex += Count;
  367. return Value;
  368. }
  369. ULONGLONG
  370. RestorePreservedRegisterFromGR (
  371. IN PCONTEXT Context,
  372. IN SHORT BsFrameSize,
  373. IN SHORT RNatSaveIndex,
  374. IN SHORT GrNumber,
  375. #ifdef _IMAGEHLP_SOURCE_
  376. IN HANDLE hProcess,
  377. IN PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  378. OUT BOOL *Succeed,
  379. #else
  380. OUT ULONG64 *SourceAddress,
  381. #endif // _IMAGEHLP_SOURCE_
  382. OUT PUCHAR Nat OPTIONAL
  383. )
  384. {
  385. ULONGLONG Result;
  386. SHORT Offset;
  387. SHORT Temp;
  388. #ifdef _IMAGEHLP_SOURCE_
  389. ULONG Size;
  390. #endif // _IMAGEHLP_SOURCE_
  391. #ifdef _IMAGEHLP_SOURCE_
  392. *Succeed = FALSE;
  393. #endif // _IMAGEHLP_SOURCE_
  394. if (GrNumber >= STATIC_REGISTER_SET_SIZE) {
  395. Offset = GrNumber - STATIC_REGISTER_SET_SIZE;
  396. if ( Offset < BsFrameSize ) {
  397. Temp = Offset + RNatSaveIndex - NAT_BITS_PER_RNAT_REG;
  398. while (Temp >= 0) {
  399. Offset++;
  400. Temp -= NAT_BITS_PER_RNAT_REG;
  401. }
  402. Offset = Offset * sizeof(ULONGLONG);
  403. #ifdef _IMAGEHLP_SOURCE_
  404. *Succeed = ReadMemory(hProcess, Context->RsBSP + Offset,
  405. &Result, sizeof(ULONGLONG), &Size);
  406. #else
  407. *SourceAddress = (ULONG64)(Context->RsBSP + Offset);
  408. Result = *(PULONGLONG)(Context->RsBSP + Offset);
  409. #endif // _IMAGEHLP_SOURCE_
  410. } else {
  411. UW_DEBUG(("ERROR: Invalid GR!\n"));
  412. }
  413. } else {
  414. if (GrNumber == 0 || GrNumber == 12) {
  415. //
  416. // Invalid GR number -> Invalid Unwind Descriptor
  417. //
  418. UW_DEBUG(("ERROR: Invalid GR!\n"));
  419. } else {
  420. UW_DEBUG(("WARNING: Target register is not a stacked GR!\n"));
  421. Offset = GrNumber - 1;
  422. NOT_IMAGEHLP(*SourceAddress = (ULONG64)(&Context->IntGp + Offset));
  423. Result = *(&Context->IntGp + Offset);
  424. #ifdef _IMAGEHLP_SOURCE_
  425. *Succeed = TRUE;
  426. #endif // _IMAGEHLP_SOURCE_
  427. }
  428. }
  429. if (ARGUMENT_PRESENT(Nat)) {
  430. //
  431. // TBD: Pick up the corresponding Nat bit
  432. //
  433. *Nat = (UCHAR) 0;
  434. }
  435. return (Result);
  436. }
  437. UCHAR
  438. ParseBodyRegionDescriptors (
  439. IN PUNWIND_CONTEXT UnwindContext,
  440. IN PSTATE_RECORD_STACK StateTable,
  441. IN ULONG RegionLen
  442. )
  443. {
  444. LABEL Label;
  445. UCHAR FirstByte;
  446. BOOLEAN EcountDefined;
  447. BOOLEAN CopyLabel;
  448. ULONG Ecount;
  449. ULONG SlotOffset;
  450. PSTATE_RECORD StateTablePtr;
  451. PUCHAR Descriptors;
  452. CopyLabel = EcountDefined = FALSE;
  453. Descriptors = UnwindContext->Descriptors;
  454. while (UnwindContext->DescCount < UnwindContext->Size) {
  455. FirstByte = Descriptors[UnwindContext->DescCount++];
  456. if ( (FirstByte & B1_MASK) == B1_PREFIX ) {
  457. Label = (LABEL)(FirstByte & B1_LABEL_MASK);
  458. if (FirstByte & B1_TYPE_MASK) {
  459. //
  460. // copy the entry state
  461. //
  462. CopyLabel = TRUE;
  463. } else {
  464. //
  465. // label the entry state
  466. //
  467. LABEL_REGION(StateTable->Top, Label);
  468. }
  469. UW_DEBUG(("Body region desc B1: copy=%d, label_num=%d\n",
  470. FirstByte & B1_TYPE_MASK ? TRUE : FALSE, Label));
  471. } else if ( (FirstByte & B2_MASK) == B2_PREFIX ) {
  472. Ecount = FirstByte & B2_ECOUNT_MASK;
  473. SlotOffset = ReadLEB128(Descriptors, &UnwindContext->DescCount);
  474. EcountDefined = TRUE;
  475. UW_DEBUG(("Epilog desc B2: ecount=%d, LEB128(slot)=%d\n",
  476. Ecount, SlotOffset));
  477. } else if ( (FirstByte & B3_MASK) == B3_PREFIX ) {
  478. SlotOffset = ReadLEB128(Descriptors, &UnwindContext->DescCount);
  479. Ecount = ReadLEB128(Descriptors, &UnwindContext->DescCount);
  480. EcountDefined = TRUE;
  481. UW_DEBUG(("Epilog desc B3: ecount=%d, LEB128 val=%d\n",
  482. Ecount, SlotOffset));
  483. } else if ( (FirstByte & B4_MASK) == B4_PREFIX ) {
  484. Label = ReadLEB128(Descriptors, &UnwindContext->DescCount);
  485. if (FirstByte & B4_TYPE_MASK) {
  486. //
  487. // copy the entry state
  488. //
  489. CopyLabel = TRUE;
  490. } else {
  491. //
  492. // label the current top of stack
  493. //
  494. LABEL_REGION(StateTable->Top, Label);
  495. }
  496. UW_DEBUG(("Body region desc B4: copy=%d, label_num=%d\n",
  497. FirstByte & B4_TYPE_MASK, Label));
  498. } else {
  499. //
  500. // Encounter another region header record
  501. //
  502. break;
  503. }
  504. }
  505. if (CopyLabel) {
  506. StateTablePtr = StateTable->Top;
  507. while (TRUE) {
  508. if (CHECK_LABEL(StateTablePtr, Label)) {
  509. StateTable->Current = StateTablePtr;
  510. break;
  511. } else if ((StateTablePtr == StateTable->Base)) {
  512. UW_DEBUG(("Undefined Label %d\n", Label));
  513. break;
  514. }
  515. StateTablePtr--;
  516. }
  517. }
  518. if (EcountDefined) {
  519. Ecount++; // Ecount specifies additional level of prologue
  520. // regions to undo (i.e. a value of 0 implies 1
  521. // prologue region)
  522. if (UnwindContext->ActiveRegionFound == FALSE) {
  523. while (Ecount-- > 0) {
  524. if (StateTable->Current->Previous) {
  525. StateTable->Current = StateTable->Current->Previous;
  526. }
  527. #if DBG
  528. else {
  529. UW_DEBUG(("WARNING: Ecount is greater than the # of active prologues!\n"));
  530. }
  531. #endif // DBG
  532. }
  533. } else {
  534. //
  535. // control PC is in this body/epilog region
  536. //
  537. if ((UnwindContext->SlotCount + RegionLen - SlotOffset)
  538. <= UnwindContext->TargetSlot)
  539. {
  540. PSTATE_RECORD SrPointer;
  541. StateTable->Current->Ecount = Ecount;
  542. SrPointer = StateTable->Current;
  543. while (Ecount > 0) {
  544. if (SrPointer->Previous) {
  545. SrPointer->Ecount = Ecount;
  546. SrPointer->SpWhen = 0;
  547. SrPointer->SpAdjustment = 0;
  548. SrPointer = SrPointer->Previous;
  549. }
  550. #if DBG
  551. else {
  552. UW_DEBUG(("WARNING: Ecount is greater than the # of active prologues!\n"));
  553. }
  554. #endif // DBG
  555. Ecount--;
  556. }
  557. }
  558. }
  559. }
  560. return FirstByte;
  561. }
  562. ULONGLONG
  563. ProcessInterruptRegion (
  564. #ifdef _IMAGEHLP_SOURCE_
  565. IN HANDLE hProcess,
  566. IN PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  567. #else
  568. IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
  569. #endif _IMAGEHLP_SOURCE_
  570. IN PUNWIND_CONTEXT UnwindContext,
  571. IN PCONTEXT Context,
  572. IN SHORT BsFrameSize,
  573. IN SHORT RNatSaveIndex,
  574. IN UCHAR AbiImmContext
  575. )
  576. {
  577. //
  578. // no prologue descriptor in interrupt region.
  579. //
  580. PCONTEXT PrevContext;
  581. ULONGLONG NextPc;
  582. ULONG Index;
  583. SHORT TempFrameSize;
  584. BOOLEAN Success;
  585. #ifdef _IMAGEHLP_SOURCE_
  586. ULONG Size;
  587. #else
  588. PVOID *Source;
  589. PVOID Address;
  590. #endif _IMAGEHLP_SOURCE_
  591. if (AbiImmContext != CONTEXT_FRAME) {
  592. PKTRAP_FRAME TrapFrame;
  593. PKEXCEPTION_FRAME ExFrame;
  594. #ifdef _IMAGEHLP_SOURCE_
  595. KTRAP_FRAME TF;
  596. KEXCEPTION_FRAME ExF;
  597. #endif // _IMAGEHLP_SOURCE_
  598. TrapFrame = (PKTRAP_FRAME) Context->IntSp;
  599. #ifdef _IMAGEHLP_SOURCE_
  600. if (!ReadMemory(hProcess, Context->IntSp, &TF, sizeof(KTRAP_FRAME), &Size))
  601. {
  602. return 0;
  603. }
  604. TrapFrame = &TF;
  605. #endif // _IMAGEHLP_SOURCE_
  606. Context->ApDCR = TrapFrame->ApDCR;
  607. Context->ApUNAT = TrapFrame->ApUNAT;
  608. Context->StFPSR = TrapFrame->StFPSR;
  609. Context->Preds = TrapFrame->Preds;
  610. Context->IntSp = TrapFrame->IntSp;
  611. Context->StIPSR = TrapFrame->StIPSR;
  612. Context->StIFS = TrapFrame->StIFS;
  613. Context->BrRp = TrapFrame->BrRp;
  614. Context->RsPFS = TrapFrame->RsPFS;
  615. #ifndef _IMAGEHLP_SOURCE_
  616. if (ARGUMENT_PRESENT(ContextPointers)) {
  617. ContextPointers->ApUNAT = &TrapFrame->ApUNAT;
  618. ContextPointers->IntSp = &TrapFrame->IntSp;
  619. ContextPointers->BrRp = &TrapFrame->BrRp;
  620. ContextPointers->RsPFS = &TrapFrame->RsPFS;
  621. ContextPointers->Preds = &TrapFrame->Preds;
  622. }
  623. #endif // _IMAGEHLP_SOURCE_
  624. switch (AbiImmContext) {
  625. case SYSCALL_FRAME:
  626. //
  627. // System Call Handler Frame
  628. //
  629. BsFrameSize = (SHORT)(TrapFrame->StIFS >> PFS_SIZE_SHIFT);
  630. BsFrameSize &= PFS_SIZE_MASK;
  631. break;
  632. case INTERRUPT_FRAME:
  633. case EXCEPTION_FRAME:
  634. //
  635. // External Interrupt Frame / Exception Frame
  636. //
  637. BsFrameSize = (SHORT)TrapFrame->StIFS & PFS_SIZE_MASK;
  638. break;
  639. default:
  640. break;
  641. }
  642. RNatSaveIndex = (SHORT)(TrapFrame->RsBSP >> 3) & NAT_BITS_PER_RNAT_REG;
  643. TempFrameSize = BsFrameSize - RNatSaveIndex;
  644. while (TempFrameSize > 0) {
  645. BsFrameSize++;
  646. TempFrameSize -= NAT_BITS_PER_RNAT_REG;
  647. }
  648. Context->RsBSP = TrapFrame->RsBSP - BsFrameSize * sizeof(ULONGLONG);
  649. Context->RsBSPSTORE = Context->RsBSP;
  650. Context->RsRNAT = TrapFrame->RsRNAT;
  651. NextPc = RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  652. ((TrapFrame->StIPSR >> PSR_RI) & 0x3));
  653. return (NextPc);
  654. }
  655. //
  656. // Kernel-to-User thunk, context of the previous frame can be
  657. // found on the user stack (i.e. context's address = sp+SCRATCH_AREA)
  658. //
  659. PrevContext = (PCONTEXT)(Context->IntSp + STACK_SCRATCH_AREA);
  660. #ifdef _IMAGEHLP_SOURCE_
  661. if (!ReadMemory(hProcess, (DWORD64)PrevContext, Context, sizeof(CONTEXT), &Size))
  662. {
  663. return 0;
  664. }
  665. NextPc = RtlIa64InsertIPSlotNumber(Context->StIIP,
  666. ((Context->StIPSR >> PSR_RI) & 0x3));
  667. #else
  668. RtlCopyMemory(&Context->BrRp, &PrevContext->BrRp,
  669. (NUMBER_OF_PRESERVED_BR+3) * sizeof(ULONGLONG));
  670. RtlCopyMemory(&Context->FltS0, &PrevContext->FltS0,
  671. NUMBER_OF_LOW_PRESERVED_FR * sizeof(FLOAT128));
  672. RtlCopyMemory(&Context->FltS4, &PrevContext->FltS4,
  673. NUMBER_OF_HIGH_PRESERVED_FR * sizeof(FLOAT128));
  674. RtlCopyMemory(&Context->IntS0, &PrevContext->IntS0,
  675. NUMBER_OF_PRESERVED_GR * sizeof(ULONGLONG));
  676. RtlCopyMemory(&Context->IntV0, &PrevContext->IntV0,
  677. NUMBER_OF_SCRATCH_GR * sizeof(ULONGLONG));
  678. Context->IntT0 = PrevContext->IntT0;
  679. Context->IntT1 = PrevContext->IntT1;
  680. Context->IntSp = PrevContext->IntSp;
  681. Context->IntNats = PrevContext->IntNats;
  682. Context->ApUNAT = PrevContext->ApUNAT;
  683. Context->ApLC = PrevContext->ApLC;
  684. Context->ApEC = PrevContext->ApEC;
  685. Context->Preds = PrevContext->Preds;
  686. Context->RsPFS = PrevContext->RsPFS;
  687. Context->RsBSP = PrevContext->RsBSP;
  688. Context->RsBSPSTORE = PrevContext->RsBSPSTORE;
  689. Context->RsRSC = PrevContext->RsRSC;
  690. Context->RsRNAT = PrevContext->RsRNAT;
  691. Context->StIFS = PrevContext->StIFS;
  692. Context->StIPSR = PrevContext->StIPSR;
  693. NextPc = RtlIa64InsertIPSlotNumber(PrevContext->StIIP,
  694. ((PrevContext->StIPSR >> PSR_RI) & 0x3));
  695. #endif // _IMAGEHLP_SOURCE_
  696. return(NextPc);
  697. }
  698. ULONGLONG
  699. RtlVirtualUnwind (
  700. #ifdef _IMAGEHLP_SOURCE_
  701. HANDLE hProcess,
  702. ULONGLONG ImageBase,
  703. ULONGLONG ControlPc,
  704. PRUNTIME_FUNCTION FunctionEntry,
  705. PCONTEXT ContextRecord,
  706. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory
  707. #define ContextPointers ((PKNONVOLATILE_CONTEXT_POINTERS)0)
  708. #else
  709. IN ULONGLONG ImageBase,
  710. IN ULONGLONG ControlPc,
  711. IN PRUNTIME_FUNCTION FunctionEntry,
  712. IN OUT PCONTEXT ContextRecord,
  713. OUT PBOOLEAN InFunction,
  714. OUT PFRAME_POINTERS EstablisherFrame,
  715. IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL
  716. #endif
  717. )
  718. /*++
  719. Routine Description:
  720. This function virtually unwinds the specfified function by executing its
  721. prologue code backwards.
  722. If the function is a leaf function, then the address where control left
  723. the previous frame is obtained from the context record. If the function
  724. is a nested function, but not an exception or interrupt frame, then the
  725. prologue code is executed backwards and the address where control left
  726. the previous frame is obtained from the updated context record.
  727. Otherwise, an exception or interrupt entry to the system is being unwound
  728. and an especially coded prologue restores the return address twice. Once
  729. from the fault instruction address and once from the saved return address
  730. register. The first restore is returned as the function value and the
  731. second restore is placed in the updated context record.
  732. If a context pointers record is specified, then the address where each
  733. nonvolatile registers is restored from is recorded in the appropriate
  734. element of the context pointers record.
  735. Arguments:
  736. ImageBase - Supplies the base address of the module to which the
  737. function belongs.
  738. ControlPc - Supplies the address where control left the specified
  739. function.
  740. FunctionEntry - Supplies the address of the function table entry for the
  741. specified function.
  742. ContextRecord - Supplies the address of a context record.
  743. InFunction - Supplies a pointer to a variable that receives whether the
  744. control PC is within the current function.
  745. EstablisherFrame - Supplies a pointer to a variable that receives the
  746. the establisher frame pointer value.
  747. ContextPointers - Supplies an optional pointer to a context pointers
  748. record.
  749. Return Value:
  750. The address where control left the previous frame is returned as the
  751. function value.
  752. --*/
  753. {
  754. #ifdef _IMAGEHLP_SOURCE_
  755. BOOL Succeed;
  756. #endif // _IMAGEHLP_SOURCE_
  757. PUCHAR Descriptors = NULL;
  758. UCHAR AbiImmContext = 0xFF;
  759. ULONG Mask;
  760. ULONGLONG NextPc;
  761. ULONG RegionLen;
  762. UCHAR FirstByte;
  763. UCHAR Nat;
  764. SHORT BsFrameSize; // in 8-byte units
  765. SHORT LocalFrameSize; // in 8-byte units
  766. SHORT TempFrameSize; // in 8-byte units
  767. SHORT RNatSaveIndex;
  768. ULONG i;
  769. PULONG Buffer;
  770. BOOLEAN IsPrologueRegion;
  771. BOOLEAN PspRestored;
  772. ULONGLONG PreviousIntSp;
  773. PVOID Destination;
  774. ULONG64 Source;
  775. ULONG64 *CtxPtr;
  776. ULONG64 *NatCtxPtr;
  777. ULONG64 IntNatsSource;
  778. ULONG64 IntNats;
  779. ULONG Size;
  780. ULONGLONG OldTopRnat;
  781. ULONGLONG NewTopRnat;
  782. UNWIND_INFO UnwindInfo;
  783. ULONG64 UnwindInfoPtr;
  784. UNWIND_CONTEXT UnwindContext;
  785. PSTATE_RECORD SrPointer;
  786. STATE_RECORD_STACK StateTable;
  787. STATE_RECORD StateRecords[STATE_RECORD_STACK_SIZE];
  788. BsFrameSize = (SHORT)ContextRecord->StIFS & PFS_SIZE_MASK;
  789. RNatSaveIndex = (SHORT)(ContextRecord->RsBSP >> 3) & NAT_BITS_PER_RNAT_REG;
  790. TempFrameSize = RNatSaveIndex + BsFrameSize - NAT_BITS_PER_RNAT_REG;
  791. while (TempFrameSize >= 0) {
  792. BsFrameSize++;
  793. TempFrameSize -= NAT_BITS_PER_RNAT_REG;
  794. }
  795. UnwindInfoPtr = ImageBase + FunctionEntry->UnwindInfoAddress;
  796. #ifdef _IMAGEHLP_SOURCE_
  797. if (!ReadMemory( hProcess, (ULONG64)UnwindInfoPtr,
  798. &UnwindInfo, sizeof(UNWIND_INFO), &Size))
  799. {
  800. return 0;
  801. }
  802. UnwindContext.Version = UnwindInfo.Version;
  803. Size = UnwindInfo.DataLength * sizeof(ULONGLONG);
  804. if (Size) {
  805. Descriptors = (PUCHAR) MemAlloc (Size);
  806. if (!ReadMemory(hProcess,(ULONG64)(UnwindInfoPtr+sizeof(UNWIND_INFO)), Descriptors, Size, &Size)) {
  807. return 0;
  808. }
  809. }
  810. #else
  811. UnwindContext.Version = ((PUNWIND_INFO)UnwindInfoPtr)->Version;
  812. Size = ((PUNWIND_INFO)UnwindInfoPtr)->DataLength * sizeof(ULONGLONG);
  813. Descriptors = (PUCHAR)UnwindInfoPtr + sizeof(UNWIND_INFO);
  814. #endif // _IMAGEHLP_SOURCE_
  815. UnwindContext.Size = Size;
  816. UnwindContext.ActiveRegionFound = FALSE;
  817. UnwindContext.AlternateRp = 0;
  818. UnwindContext.DescCount = 0;
  819. UnwindContext.SlotCount = 0;
  820. UnwindContext.TargetSlot = (ULONG)(((ControlPc - FunctionEntry->BeginAddress - ImageBase) >> 4) * SLOTS_PER_BUNDLE + ((ControlPc >> 2) & 0x3));
  821. UnwindContext.Descriptors = Descriptors;
  822. SrInitialize(&StateTable, StateRecords, STATE_RECORD_STACK_SIZE);
  823. if (Size) {
  824. FirstByte = Descriptors[UnwindContext.DescCount++];
  825. }
  826. while ( (UnwindContext.DescCount < UnwindContext.Size) &&
  827. (!UnwindContext.ActiveRegionFound) )
  828. {
  829. //
  830. // Assume a prologue region but not an interrupt region.
  831. //
  832. IsPrologueRegion = TRUE;
  833. //
  834. // Based on the type of region header, dispatch
  835. // to the corresponding routine that processes
  836. // the succeeding descriptors until the next
  837. // region header record.
  838. //
  839. if ((FirstByte & R1_MASK) == R1_PREFIX) {
  840. //
  841. // region header record in short format
  842. //
  843. RegionLen = FirstByte & R1_LENGTH_MASK;
  844. if (FirstByte & R1_REGION_TYPE_MASK) {
  845. IsPrologueRegion = FALSE;
  846. } else {
  847. ADD_STATE_RECORD(StateTable, RegionLen, UnwindContext.DescCount);
  848. }
  849. UW_DEBUG(("Region R1 format: body=%x, length=%d\n",
  850. IsPrologueRegion ? 0 : 1, RegionLen));
  851. } else if ((FirstByte & R2_MASK) == R2_PREFIX) {
  852. //
  853. // general prologue region header
  854. // N.B. Skip the 2nd byte of the header and proceed to read
  855. // the region length; the header descriptors will be
  856. // processed again in phase 1.
  857. //
  858. ULONG R2DescIndex;
  859. R2DescIndex = UnwindContext.DescCount - 1;
  860. UnwindContext.DescCount++;
  861. RegionLen = ReadLEB128(Descriptors, &UnwindContext.DescCount);
  862. ADD_STATE_RECORD(StateTable, RegionLen, R2DescIndex);
  863. UW_DEBUG(("Region R2: body=0, length=%d\n", RegionLen));
  864. } else if ((FirstByte & R3_MASK) == R3_PREFIX) {
  865. //
  866. // region header record in long format
  867. //
  868. RegionLen = ReadLEB128(Descriptors, &UnwindContext.DescCount);
  869. switch (FirstByte & R3_REGION_TYPE_MASK) {
  870. case 0: // prologue region header
  871. ADD_STATE_RECORD(StateTable, RegionLen, UnwindContext.DescCount);
  872. break;
  873. case 1: // body region header
  874. IsPrologueRegion = FALSE;
  875. break;
  876. }
  877. UW_DEBUG(("Region R3: body=%x, length=%d\n",
  878. IsPrologueRegion ? 0 : 1, RegionLen));
  879. } else {
  880. //
  881. // Not a region header record -> Invalid unwind descriptor.
  882. //
  883. UW_DEBUG(("Invalid unwind descriptor!\n"));
  884. }
  885. if (UnwindContext.TargetSlot < (UnwindContext.SlotCount + RegionLen)) {
  886. UnwindContext.ActiveRegionFound = TRUE;
  887. StateTable.Current->IsTarget = IsPrologueRegion;
  888. }
  889. if (IsPrologueRegion) {
  890. FirstByte = NewParsePrologueRegionPhase0(&UnwindContext,
  891. StateTable.Current,
  892. &AbiImmContext);
  893. } else {
  894. FirstByte = ParseBodyRegionDescriptors(&UnwindContext,
  895. &StateTable,
  896. RegionLen);
  897. }
  898. UnwindContext.SlotCount += RegionLen;
  899. }
  900. //
  901. // Restore the value of psp and save the current NatCr.
  902. // N.B. If the value is restored from stack/bstore, turn off the
  903. // corresponding sp bit in the saved mask associated with the
  904. // prologue region in which psp is saved.
  905. //
  906. if (ARGUMENT_PRESENT(ContextPointers)) {
  907. IntNatsSource = (ULONG64)ContextPointers->ApUNAT;
  908. }
  909. IntNats = ContextRecord->ApUNAT;
  910. PreviousIntSp = ContextRecord->IntSp;
  911. PspRestored = FALSE;
  912. SrPointer = StateTable.Current;
  913. while (SrPointer != StateTable.Base) {
  914. NewParsePrologueRegionPhase1(&UnwindContext, SrPointer);
  915. if (SrPointer->MiscMask & (1 << REG_SP)) {
  916. if (UnwindContext.MiscRegs[REG_SP].Where == GENERAL_REG) {
  917. PreviousIntSp = RestorePreservedRegisterFromGR (
  918. ContextRecord,
  919. BsFrameSize,
  920. RNatSaveIndex,
  921. (SHORT)UnwindContext.MiscRegs[REG_SP].SaveOffset,
  922. #ifdef _IMAGEHLP_SOURCE_
  923. hProcess,
  924. ReadMemory,
  925. &Succeed,
  926. #else
  927. &Source,
  928. #endif // _IMAGEHLP_SOURCE_
  929. &Nat
  930. );
  931. #ifdef _IMAGEHLP_SOURCE_
  932. if (!Succeed) {
  933. return 0;
  934. }
  935. #endif // _IMAGEHLP_SOURCE_
  936. } else {
  937. Source = ContextRecord->IntSp + UnwindContext.MiscRegs[REG_SP].SaveOffset*4;
  938. #ifdef _IMAGEHLP_SOURCE_
  939. if (!ReadMemory(hProcess, (ULONG64)(Source), &PreviousIntSp, sizeof(ULONGLONG), &Size)) {
  940. return 0;
  941. }
  942. #else
  943. PreviousIntSp = *(PULONGLONG)Source;
  944. #endif // _IMAGEHLP_SOURCE_
  945. EXTRACT_NAT_FROM_UNAT(Nat);
  946. }
  947. ContextRecord->IntNats &= ~(0x1 << STACK_POINTER_GR);
  948. ContextRecord->IntNats |= (Nat << STACK_POINTER_GR);
  949. SrPointer->MiscMask &= ~(1 << REG_SP);
  950. if (ARGUMENT_PRESENT(ContextPointers)) {
  951. CtxPtr = (ULONG64 *)((ULONG_PTR)ContextPointers +
  952. MiscContextPointersOffset[REG_SP]);
  953. *CtxPtr = Source;
  954. }
  955. PspRestored = TRUE;
  956. }
  957. if (PspRestored == FALSE) {
  958. PreviousIntSp += SrPointer->SpAdjustment * 4;
  959. }
  960. SrPointer = SrPointer->Previous;
  961. }
  962. if (AbiImmContext != 0xFF) {
  963. ContextRecord->IntSp = PreviousIntSp; // trap/context frame address
  964. NextPc = ProcessInterruptRegion(
  965. #ifdef _IMAGEHLP_SOURCE_
  966. hProcess,
  967. ReadMemory,
  968. #else
  969. ContextPointers,
  970. #endif _IMAGEHLP_SOURCE_
  971. &UnwindContext,
  972. ContextRecord,
  973. BsFrameSize,
  974. RNatSaveIndex,
  975. AbiImmContext);
  976. goto FastExit;
  977. }
  978. //
  979. // Restore the contents of any preserved registers saved in this frame.
  980. //
  981. SrPointer = StateTable.Current;
  982. while (SrPointer != StateTable.Base) {
  983. Mask = SrPointer->MiscMask;
  984. UW_DEBUG(("MiscMask = 0x%x\n", Mask));
  985. for (i = 0; i < NUMBER_OF_PRESERVED_REGISTERS; i++) {
  986. Destination = (PVOID)((ULONG_PTR)ContextRecord + MiscContextOffset[i]);
  987. if (Mask & 0x1) {
  988. if (ARGUMENT_PRESENT(ContextPointers)) {
  989. CtxPtr = (ULONG64 *)((ULONG_PTR)ContextPointers +
  990. MiscContextPointersOffset[i]);
  991. Source = *CtxPtr;
  992. }
  993. if (UnwindContext.MiscRegs[i].Where == GENERAL_REG) {
  994. *(PULONGLONG)Destination =
  995. RestorePreservedRegisterFromGR (
  996. ContextRecord,
  997. BsFrameSize,
  998. RNatSaveIndex,
  999. (SHORT)UnwindContext.MiscRegs[i].SaveOffset,
  1000. #ifdef _IMAGEHLP_SOURCE_
  1001. hProcess,
  1002. ReadMemory,
  1003. &Succeed,
  1004. #else
  1005. &Source,
  1006. #endif // _IMAGEHLP_SOURCE_
  1007. NULL
  1008. );
  1009. #ifdef _IMAGEHLP_SOURCE_
  1010. if (!Succeed) {
  1011. return 0;
  1012. }
  1013. #endif // _IMAGEHLP_SOURCE_
  1014. } else if (UnwindContext.MiscRegs[i].Where == BRANCH_REG) {
  1015. //
  1016. // restore return pointer from branch register
  1017. //
  1018. USHORT Offset;
  1019. Offset = (USHORT)UnwindContext.MiscRegs[i].SaveOffset-FIRST_PRESERVED_BR;
  1020. Source = (ULONG64)(&ContextRecord->BrS0 + Offset);
  1021. #ifdef _IMAGEHLP_SOURCE_
  1022. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) {
  1023. return 0;
  1024. }
  1025. #else
  1026. *(PULONGLONG)Destination = *(PULONGLONG)(Source);
  1027. #endif // _IMAGEHLP_SOURCE_
  1028. } else if (UnwindContext.MiscRegs[i].Where == PSP_RELATIVE) {
  1029. if ((SrPointer->Ecount == 0) || (UnwindContext.MiscRegs[i].SaveOffset <= (STACK_SCRATCH_AREA/sizeof(ULONG)))) {
  1030. Source = PreviousIntSp + STACK_SCRATCH_AREA
  1031. - UnwindContext.MiscRegs[i].SaveOffset*4;
  1032. if (i == REG_NATS) {
  1033. Destination = (PVOID)&IntNats;
  1034. IntNatsSource = Source;
  1035. }
  1036. #ifdef _IMAGEHLP_SOURCE_
  1037. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) {
  1038. return 0;
  1039. }
  1040. #else
  1041. *(PULONGLONG)Destination = *(PULONGLONG)(Source);
  1042. #endif // _IMAGEHLP_SOURCE_
  1043. }
  1044. } else if (UnwindContext.MiscRegs[i].Where == SP_RELATIVE) {
  1045. //
  1046. // Make the necessary adjustment depending on whether
  1047. // the preserved register is saved before or after the
  1048. // stack pointer has been adjusted in this prologue.
  1049. //
  1050. if (UnwindContext.MiscRegs[i].When >= SrPointer->SpWhen && (SrPointer->RegionLen != 0))
  1051. Source = ContextRecord->IntSp
  1052. + UnwindContext.MiscRegs[i].SaveOffset*4;
  1053. else
  1054. Source = ContextRecord->IntSp+SrPointer->SpAdjustment*4
  1055. + UnwindContext.MiscRegs[i].SaveOffset*4;
  1056. if (i == REG_NATS) {
  1057. Destination = (PVOID)&IntNats;
  1058. IntNatsSource = Source;
  1059. }
  1060. #ifdef _IMAGEHLP_SOURCE_
  1061. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) {
  1062. return 0;
  1063. }
  1064. #else
  1065. *(PULONGLONG)Destination = *(PULONGLONG)(Source);
  1066. #endif // _IMAGEHLP_SOURCE_
  1067. }
  1068. if (ARGUMENT_PRESENT(ContextPointers) && (i != REG_NATS)) {
  1069. *CtxPtr = Source;
  1070. }
  1071. } else if (Mask == 0) {
  1072. //
  1073. // No more registers to restore
  1074. //
  1075. break;
  1076. }
  1077. Mask = Mask >> 1;
  1078. }
  1079. //
  1080. // Restore preserved FRs (f2 - f5, f16 - f31)
  1081. //
  1082. Mask = SrPointer->FrMask;
  1083. Destination = (PVOID)&ContextRecord->FltS0;
  1084. CtxPtr = (ULONG64 *)&ContextPointers->FltS0;
  1085. UW_DEBUG(("FrMask = 0x%x\n", Mask));
  1086. for (i = 0; i < NUMBER_OF_PRESERVED_FR; i++) {
  1087. if (Mask & 0x1) {
  1088. if ((SrPointer->Ecount == 0) || (UnwindContext.Float[i].SaveOffset <= (STACK_SCRATCH_AREA/sizeof(ULONG)))) {
  1089. Source = PreviousIntSp + STACK_SCRATCH_AREA
  1090. - UnwindContext.Float[i].SaveOffset*4;
  1091. #ifdef _IMAGEHLP_SOURCE_
  1092. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(FLOAT128), &Size)) {
  1093. return 0;
  1094. }
  1095. #else
  1096. *(FLOAT128 *)Destination = *(FLOAT128 *)Source;
  1097. #endif // _IMAGEHLP_SOURCE_
  1098. if (ARGUMENT_PRESENT(ContextPointers)) {
  1099. *CtxPtr = Source;
  1100. }
  1101. }
  1102. } else if (Mask == 0) {
  1103. break;
  1104. }
  1105. Mask = Mask >> 1;
  1106. if (i == (NUMBER_OF_LOW_PRESERVED_FR - 1)) {
  1107. Destination = (PVOID)&ContextRecord->FltS4;
  1108. CtxPtr = (ULONG64 *)(&ContextPointers->FltS4);
  1109. } else {
  1110. Destination = (PVOID)((FLOAT128 *)Destination+1);
  1111. CtxPtr++;
  1112. }
  1113. }
  1114. //
  1115. // Restore preserved GRs (r4 - r7)
  1116. //
  1117. Mask = SrPointer->GrMask;
  1118. Destination = (PVOID)&ContextRecord->IntS0;
  1119. CtxPtr = (ULONG64 *)&ContextPointers->IntS0;
  1120. NatCtxPtr = (ULONG64 *)&ContextPointers->IntS0Nat;
  1121. UW_DEBUG(("GrMask = 0x%x\n", Mask));
  1122. for (i = 0; i < NUMBER_OF_PRESERVED_GR; i++)
  1123. {
  1124. if (Mask & 0x1) {
  1125. if ((SrPointer->Ecount == 0) || (UnwindContext.Integer[i].SaveOffset <= (STACK_SCRATCH_AREA/sizeof(ULONG)))) {
  1126. Source = PreviousIntSp + STACK_SCRATCH_AREA
  1127. - UnwindContext.Integer[i].SaveOffset*4;
  1128. #ifdef _IMAGEHLP_SOURCE_
  1129. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) {
  1130. return 0;
  1131. }
  1132. #else
  1133. *(PULONGLONG)Destination = *(PULONGLONG)Source;
  1134. #endif // _IMAGEHLP_SOURCE_
  1135. EXTRACT_NAT_FROM_UNAT(Nat);
  1136. Nat = (UCHAR)((IntNats >> (((ULONG_PTR)Source & 0x1F8) >> 3)) & 0x1);
  1137. ContextRecord->IntNats &= ~(0x1 << (i+FIRST_PRESERVED_GR));
  1138. ContextRecord->IntNats |= (Nat << (i+FIRST_PRESERVED_GR));
  1139. #ifndef _IMAGEHLP_SOURCE_
  1140. if (ARGUMENT_PRESENT(ContextPointers)) {
  1141. *CtxPtr = Source;
  1142. *NatCtxPtr = IntNatsSource;
  1143. }
  1144. #endif
  1145. }
  1146. } else if (Mask == 0) {
  1147. break;
  1148. }
  1149. Mask = Mask >> 1;
  1150. Destination = (PVOID)((PULONGLONG)Destination+1);
  1151. CtxPtr++;
  1152. NatCtxPtr++;
  1153. }
  1154. ContextRecord->IntSp += SrPointer->SpAdjustment * 4;
  1155. SrPointer = SrPointer->Previous;
  1156. }
  1157. ContextRecord->IntSp = PreviousIntSp;
  1158. //
  1159. // Restore the value of the epilogue count from the PFS
  1160. //
  1161. ContextRecord->ApEC = (ContextRecord->RsPFS >> PFS_EC_SHIFT) &
  1162. ~(((ULONGLONG)1 << PFS_EC_SIZE) - 1);
  1163. if (ARGUMENT_PRESENT(ContextPointers)) {
  1164. ContextPointers->ApEC = ContextPointers->RsPFS;
  1165. }
  1166. FastExit:
  1167. NOT_IMAGEHLP(*InFunction = TRUE);
  1168. NOT_IMAGEHLP(EstablisherFrame->MemoryStackFp = ContextRecord->IntSp);
  1169. NOT_IMAGEHLP(EstablisherFrame->BackingStoreFp = ContextRecord->RsBSP);
  1170. #ifdef _IMAGEHLP_SOURCE_
  1171. if (Descriptors)
  1172. MemFree(Descriptors);
  1173. #endif // _IMAGEHLP_SOURCE_
  1174. if (AbiImmContext == 0xFF) {
  1175. NextPc = *(&ContextRecord->BrRp + UnwindContext.AlternateRp);
  1176. #ifndef _IMAGEHLP_SOURCE_
  1177. NextPc = RtlIa64InsertIPSlotNumber((NextPc-0x10), 2);
  1178. #endif // _IMAGEHLP_SOURCE_
  1179. //
  1180. // determine the local frame size of previous frame and compute
  1181. // the new bsp.
  1182. //
  1183. OldTopRnat = (ContextRecord->RsBSP+(BsFrameSize-1)*8) | RNAT_ALIGNMENT;
  1184. ContextRecord->StIFS = MASK(IFS_V, (ULONGLONG)1) | ContextRecord->RsPFS;
  1185. BsFrameSize = (SHORT)ContextRecord->StIFS & PFS_SIZE_MASK;
  1186. LocalFrameSize = (SHORT)(ContextRecord->StIFS >> PFS_SIZE_SHIFT) & PFS_SIZE_MASK;
  1187. TempFrameSize = LocalFrameSize - RNatSaveIndex;
  1188. while (TempFrameSize > 0) {
  1189. LocalFrameSize++;
  1190. BsFrameSize++;
  1191. TempFrameSize -= NAT_BITS_PER_RNAT_REG;
  1192. }
  1193. ContextRecord->RsBSP -= LocalFrameSize * 8;
  1194. ContextRecord->RsBSPSTORE = ContextRecord->RsBSP;
  1195. //
  1196. // determine if the RNAT field needs to be updated.
  1197. //
  1198. NewTopRnat = (ContextRecord->RsBSP+(BsFrameSize-1)*8) | RNAT_ALIGNMENT;
  1199. if (NewTopRnat < OldTopRnat) {
  1200. #ifdef _IMAGEHLP_SOURCE_
  1201. Destination = &ContextRecord->RsRNAT;
  1202. Source = NewTopRnat;
  1203. if (!ReadMemory(hProcess, (ULONG64)Source, Destination, 8, &Size)) {
  1204. return 0;
  1205. }
  1206. #else
  1207. ContextRecord->RsRNAT = *(PULONGLONG)(NewTopRnat);
  1208. #endif // _IMAGEHLP_SOURCE_
  1209. }
  1210. }
  1211. #ifdef _IMAGEHLP_SOURCE_
  1212. UW_DEBUG(("NextPc = 0x%lx, PSP = 0x%lx, BSP = 0x%lx\n",
  1213. (ULONGLONG)NextPc,
  1214. (ULONGLONG)ContextRecord->IntSp,
  1215. (ULONGLONG)ContextRecord->RsBSP));
  1216. #else
  1217. UW_DEBUG(("NextPc = 0x%lx, PSP = 0x%lx, BSP = 0x%lx\n",
  1218. (ULONGLONG)NextPc,
  1219. EstablisherFrame->MemoryStackFp,
  1220. EstablisherFrame->BackingStoreFp));
  1221. #endif // _IMAGEHLP_SOURCE_
  1222. return (NextPc);
  1223. }
  1224. UCHAR
  1225. NewParsePrologueRegionPhase0 (
  1226. IN PUNWIND_CONTEXT UwContext,
  1227. IN PSTATE_RECORD State,
  1228. IN OUT PUCHAR AbiImmContext
  1229. )
  1230. {
  1231. PUCHAR Desc = UwContext->Descriptors;
  1232. ULONG Offset;
  1233. ULONG FrameSize;
  1234. ULONG Index;
  1235. UCHAR RecType;
  1236. UCHAR FirstByte;
  1237. UCHAR SecondByte;
  1238. ULONG GrSave;
  1239. ULONG TempMask;
  1240. ULONG i;
  1241. while (UwContext->DescCount < UwContext->Size) {
  1242. FirstByte = Desc[UwContext->DescCount++];
  1243. if ( (FirstByte & P1_MASK) == P1_PREFIX) {
  1244. continue;
  1245. } else if ( (FirstByte & P2_MASK) == P2_PREFIX ) {
  1246. UwContext->DescCount++;
  1247. } else if ( (FirstByte & P3_MASK) == P3_PREFIX ) {
  1248. UwContext->DescCount++;
  1249. } else if ( (FirstByte & P4_MASK) == P4_PREFIX ) {
  1250. UwContext->DescCount += ((State->RegionLen+3) >> 2);
  1251. } else if ( (FirstByte & P5_MASK) == P5_PREFIX ) {
  1252. UwContext->DescCount += 3;
  1253. } else if ( (FirstByte & P6_MASK) == P6_PREFIX ) {
  1254. continue;
  1255. } else if ( (FirstByte & P7_MASK) == P7_PREFIX ) {
  1256. RecType = FirstByte & ~P7_MASK;
  1257. switch (RecType) {
  1258. case MEM_STACK_F:
  1259. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1260. FrameSize = ReadLEB128(Desc, &UwContext->DescCount);
  1261. if (UwContext->TargetSlot > (UwContext->SlotCount+Offset) || State->RegionLen == 0)
  1262. {
  1263. State->SpAdjustment += FrameSize*4;
  1264. State->SpWhen = Offset;
  1265. }
  1266. break;
  1267. case SPILL_BASE:
  1268. State->SpillBase = ReadLEB128(Desc, &UwContext->DescCount);
  1269. State->SpillPtr = State->SpillBase;
  1270. break;
  1271. case MEM_STACK_V:
  1272. case RP_WHEN:
  1273. case PFS_WHEN:
  1274. case PREDS_WHEN:
  1275. case LC_WHEN:
  1276. case UNAT_WHEN:
  1277. case FPSR_WHEN:
  1278. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1279. if ((State->IsTarget) &&
  1280. (UwContext->TargetSlot > (UwContext->SlotCount+Offset)))
  1281. {
  1282. Index = P7RecordTypeToRegisterIndex[RecType];
  1283. if (!(State->MiscMask & (1 << Index))) {
  1284. State->MiscMask |= MASK(Index,1);
  1285. UwContext->MiscRegs[Index].When = Offset;
  1286. } else {
  1287. UW_DEBUG(("Duplicate descriptors,"));
  1288. UW_DEBUG(("unwinder may produce incorrect result!\n"));
  1289. }
  1290. }
  1291. UW_DEBUG(("Prolog P7: type=%d slot= %d\n", RecType, Offset));
  1292. break;
  1293. case PSP_SPREL:
  1294. case RP_PSPREL:
  1295. case PFS_PSPREL:
  1296. case PREDS_PSPREL:
  1297. case LC_PSPREL:
  1298. case UNAT_PSPREL:
  1299. case FPSR_PSPREL:
  1300. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1301. break;
  1302. default:
  1303. UW_DEBUG(("Invalid record type for descriptor P7!\n"));
  1304. }
  1305. } else if ( (FirstByte & P8_MASK) == P8_PREFIX ) {
  1306. RecType = Desc[UwContext->DescCount++];
  1307. switch (RecType) {
  1308. case PSP_PSPREL:
  1309. case RP_SPREL:
  1310. case PFS_SPREL:
  1311. case PREDS_SPREL:
  1312. case LC_SPREL:
  1313. case UNAT_SPREL:
  1314. case FPSR_SPREL:
  1315. case BSP_PSPREL:
  1316. case BSP_SPREL:
  1317. case BSPSTORE_PSPREL:
  1318. case BSPSTORE_SPREL:
  1319. case RNAT_PSPREL:
  1320. case RNAT_SPREL:
  1321. case PRIUNAT_PSPREL:
  1322. case PRIUNAT_SPREL:
  1323. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1324. UW_DEBUG(("Prolog P8: type=%d slot= %d\n", RecType, Offset));
  1325. break;
  1326. case BSP_WHEN:
  1327. case BSPSTORE_WHEN:
  1328. case RNAT_WHEN:
  1329. case PRIUNAT_WHEN:
  1330. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1331. if ((State->IsTarget) &&
  1332. (UwContext->TargetSlot > (UwContext->SlotCount+Offset)))
  1333. {
  1334. Index = P7RecordTypeToRegisterIndex[RecType];
  1335. if (!(State->MiscMask & (1 << Index))) {
  1336. State->MiscMask |= MASK(Index,1);
  1337. UwContext->MiscRegs[Index].When = Offset;
  1338. } else {
  1339. UW_DEBUG(("Duplicate descriptors,"));
  1340. UW_DEBUG(("unwinder may produce incorrect result!\n"));
  1341. }
  1342. }
  1343. UW_DEBUG(("Prolog P8: type=%d slot= %d\n", RecType, Offset));
  1344. break;
  1345. default:
  1346. UW_DEBUG(("Invalid record type for descriptor P8!\n"));
  1347. }
  1348. } else if ( (FirstByte & P9_MASK) == P9_PREFIX ) {
  1349. UwContext->DescCount += 2;
  1350. VUW_DEBUG_PRINT("Format P9 not supported yet!\n");
  1351. } else if ( (FirstByte & P10_MASK) == P10_PREFIX ) {
  1352. UCHAR Abi = Desc[UwContext->DescCount++];
  1353. UCHAR Context = Desc[UwContext->DescCount++];
  1354. *AbiImmContext = Context;
  1355. if (Abi != NT_ABI) {
  1356. VUW_DEBUG_PRINT("Unknown ABI unwind descriptor\n");
  1357. }
  1358. } else {
  1359. //
  1360. // Encounter another region header record
  1361. //
  1362. break;
  1363. }
  1364. }
  1365. State->DescEnd = UwContext->DescCount - 2;
  1366. return FirstByte;
  1367. }
  1368. VOID
  1369. NewParsePrologueRegionPhase1 (
  1370. IN PUNWIND_CONTEXT UwContext,
  1371. IN PSTATE_RECORD State
  1372. )
  1373. {
  1374. ULONG FrameSize;
  1375. ULONG Offset;
  1376. ULONG GrSave;
  1377. ULONG BrBase;
  1378. ULONG Index;
  1379. ULONG Count;
  1380. UCHAR RecType;
  1381. UCHAR FirstByte, SecondByte; // 1st & 2nd bytes of a region header record
  1382. ULONG DescIndex;
  1383. ULONG ImaskBegin;
  1384. UCHAR NextBr, NextGr, NextFr;
  1385. USHORT MiscMask;
  1386. ULONG TempMask;
  1387. ULONG FrMask = 0;
  1388. UCHAR BrMask = 0;
  1389. UCHAR GrMask = 0;
  1390. PUCHAR Desc = UwContext->Descriptors;
  1391. BOOLEAN SpillMaskOmitted = TRUE;
  1392. DescIndex = State->DescBegin;
  1393. FirstByte = Desc[DescIndex];
  1394. if ((FirstByte & R2_MASK) == R2_PREFIX) {
  1395. //
  1396. // general prologue region header; need to process it first
  1397. //
  1398. ULONG GrSave, Count;
  1399. UCHAR MiscMask;
  1400. UCHAR SecondByte;
  1401. USHORT i;
  1402. DescIndex++;
  1403. SecondByte = Desc[DescIndex++];
  1404. MiscMask = ((FirstByte & 0x7) << 1) | ((SecondByte & 0x80) >> 7);
  1405. GrSave = SecondByte & 0x7F;
  1406. ReadLEB128(Desc, &DescIndex); // advance the descriptor index
  1407. if (GrSave < STATIC_REGISTER_SET_SIZE) {
  1408. UW_DEBUG(("Invalid unwind descriptor!\n"));
  1409. }
  1410. UW_DEBUG(("Region R2: rmask=%x,grsave=%d,length=%d\n",
  1411. MiscMask, GrSave, State->RegionLen));
  1412. Count = 0;
  1413. for (Index = REG_PREDS; Index <= REG_RP; Index++) {
  1414. if (MiscMask & 0x1) {
  1415. if (!(State->IsTarget) ||
  1416. (State->MiscMask & MASK(Index,1)))
  1417. {
  1418. UwContext->MiscRegs[Index].Where = GENERAL_REG;
  1419. UwContext->MiscRegs[Index].SaveOffset = GrSave+Count;
  1420. UwContext->MiscRegs[Index].When = 0;
  1421. State->MiscMask |= MASK(Index,1);
  1422. }
  1423. Count++;
  1424. }
  1425. MiscMask = MiscMask >> 1;
  1426. }
  1427. }
  1428. while (DescIndex <= State->DescEnd) {
  1429. FirstByte = Desc[DescIndex++];
  1430. if ( (FirstByte & P1_MASK) == P1_PREFIX) {
  1431. BrMask = FirstByte & ~P1_MASK;
  1432. State->MiscMask |= (BrMask << REG_BR_BASE);
  1433. UW_DEBUG(("Prolog P1: brmask=%x\n", BrMask));
  1434. for (Count = REG_BR_BASE;
  1435. Count < REG_BR_BASE+NUMBER_OF_PRESERVED_BR;
  1436. Count++)
  1437. {
  1438. if (BrMask & 0x1) {
  1439. UwContext->MiscRegs[Count].Where = PSP_RELATIVE;
  1440. UwContext->MiscRegs[Count].When = State->RegionLen;
  1441. }
  1442. BrMask = BrMask >> 1;
  1443. }
  1444. } else if ( (FirstByte & P2_MASK) == P2_PREFIX ) {
  1445. SecondByte = Desc[DescIndex++];
  1446. GrSave = SecondByte & 0x7F;
  1447. BrMask = ((FirstByte & ~P2_MASK) << 1) | ((SecondByte & 0x80) >> 7);
  1448. UW_DEBUG(("Prolog P2: brmask=%x reg base=%d\n", BrMask, GrSave));
  1449. State->MiscMask |= (BrMask << REG_BR_BASE);
  1450. for (Count = REG_BR_BASE;
  1451. Count < REG_BR_BASE+NUMBER_OF_PRESERVED_BR;
  1452. Count++)
  1453. {
  1454. if (BrMask & 0x1) {
  1455. UwContext->MiscRegs[Count].Where = GENERAL_REG;
  1456. UwContext->MiscRegs[Count].SaveOffset = GrSave++;
  1457. }
  1458. BrMask = BrMask >> 1;
  1459. }
  1460. } else if ( (FirstByte & P3_MASK) == P3_PREFIX ) {
  1461. SecondByte = Desc[DescIndex++];
  1462. RecType = ((SecondByte & 0x80) >> 7) | ((FirstByte & 0x7) << 1);
  1463. Index = P3RecordTypeToRegisterIndex[RecType];
  1464. if (RecType == RP_BR)
  1465. {
  1466. UwContext->AlternateRp = SecondByte & 0x7F;
  1467. }
  1468. else if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1469. {
  1470. UwContext->MiscRegs[Index].Where = GENERAL_REG;
  1471. UwContext->MiscRegs[Index].SaveOffset = SecondByte & 0x7F;
  1472. UwContext->MiscRegs[Index].When = 0;
  1473. State->MiscMask |= MASK(Index,1);
  1474. UW_DEBUG(("Prolog P3: type=%d reg=%d\n",
  1475. RecType, UwContext->MiscRegs[Index].SaveOffset));
  1476. }
  1477. } else if ( (FirstByte & P4_MASK) == P4_PREFIX ) {
  1478. SpillMaskOmitted = FALSE;
  1479. ImaskBegin = DescIndex;
  1480. DescIndex += ((State->RegionLen+3) >> 2);
  1481. } else if ( (FirstByte & P5_MASK) == P5_PREFIX ) {
  1482. GrMask = (Desc[DescIndex] & 0xF0) >> 4;
  1483. FrMask = ((ULONG)(Desc[DescIndex] & 0xF) << 16) |
  1484. ((ULONG)Desc[DescIndex+1] << 8) |
  1485. ((ULONG)Desc[DescIndex+2]);
  1486. DescIndex += 3; // increment the descriptor index
  1487. State->GrMask |= GrMask;
  1488. State->FrMask |= FrMask;
  1489. UW_DEBUG(("Prolog P5: grmask = %x, frmask = %x\n",
  1490. State->GrMask, State->FrMask));
  1491. } else if ( (FirstByte & P6_MASK) == P6_PREFIX ) {
  1492. if (FirstByte & 0x10) {
  1493. GrMask = FirstByte & 0xF;
  1494. State->GrMask |= GrMask;
  1495. } else {
  1496. FrMask = FirstByte & 0xF;
  1497. State->FrMask |= FrMask;
  1498. }
  1499. UW_DEBUG(("Prolog P6: is_gr = %d, mask = %x\n",
  1500. (FirstByte & 0x10) ? 1 : 0,
  1501. (FirstByte & 0x10) ? State->GrMask : State->FrMask));
  1502. } else if ( (FirstByte & P7_MASK) == P7_PREFIX ) {
  1503. RecType = FirstByte & ~P7_MASK;
  1504. switch (RecType) {
  1505. case PSP_SPREL:
  1506. //
  1507. // sp-relative location
  1508. //
  1509. Index = P7RecordTypeToRegisterIndex[RecType];
  1510. Offset = ReadLEB128(Desc, &DescIndex);
  1511. if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1512. {
  1513. UwContext->MiscRegs[Index].Where = SP_RELATIVE;
  1514. UwContext->MiscRegs[Index].SaveOffset = Offset;
  1515. if (!(State->MiscMask & MASK(Index,1))) {
  1516. UwContext->MiscRegs[Index].When = State->RegionLen;
  1517. State->MiscMask |= MASK(Index,1);
  1518. }
  1519. }
  1520. UW_DEBUG(("Prolog P7: type=%d spoff = %d\n", RecType, Offset));
  1521. break;
  1522. case RP_PSPREL:
  1523. case PFS_PSPREL:
  1524. case PREDS_PSPREL:
  1525. case LC_PSPREL:
  1526. case UNAT_PSPREL:
  1527. case FPSR_PSPREL:
  1528. //
  1529. // psp-relative location
  1530. //
  1531. Index = P7RecordTypeToRegisterIndex[RecType];
  1532. Offset = ReadLEB128(Desc, &DescIndex);
  1533. if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1534. {
  1535. UwContext->MiscRegs[Index].Where = PSP_RELATIVE;
  1536. UwContext->MiscRegs[Index].SaveOffset = Offset;
  1537. UwContext->MiscRegs[Index].When = 0;
  1538. State->MiscMask |= MASK(Index,1);
  1539. }
  1540. UW_DEBUG(("Prolog P7: type=%d pspoff= %d\n", RecType, Offset));
  1541. break;
  1542. case MEM_STACK_V:
  1543. case RP_WHEN:
  1544. case PFS_WHEN:
  1545. case PREDS_WHEN:
  1546. case LC_WHEN:
  1547. case UNAT_WHEN:
  1548. case FPSR_WHEN:
  1549. //
  1550. // Nevermind processing these descriptors because they
  1551. // have been taken care of in phase 0
  1552. //
  1553. Offset = ReadLEB128(Desc, &DescIndex);
  1554. break;
  1555. case MEM_STACK_F:
  1556. Offset = ReadLEB128(Desc, &DescIndex);
  1557. FrameSize = ReadLEB128(Desc, &DescIndex);
  1558. UW_DEBUG(("Prolog P7: type=%d Slot=%d FrameSize=%d\n",
  1559. RecType, Offset, FrameSize));
  1560. break;
  1561. case SPILL_BASE:
  1562. State->SpillBase = ReadLEB128(Desc, &DescIndex);
  1563. State->SpillPtr = State->SpillBase;
  1564. UW_DEBUG(("Prolog P7: type=%d, spillbase=%d\n",
  1565. RecType, State->SpillBase));
  1566. break;
  1567. default:
  1568. UW_DEBUG(("invalid unwind descriptors\n"));
  1569. }
  1570. } else if ( (FirstByte & P8_MASK) == P8_PREFIX ) {
  1571. RecType = Desc[DescIndex++];
  1572. switch (RecType) {
  1573. case PSP_PSPREL:
  1574. VUW_DEBUG_PRINT("Unsupported Unwind Descriptor!\n");
  1575. break;
  1576. case RP_SPREL:
  1577. case PFS_SPREL:
  1578. case PREDS_SPREL:
  1579. case LC_SPREL:
  1580. case UNAT_SPREL:
  1581. case FPSR_SPREL:
  1582. case BSP_SPREL:
  1583. case BSPSTORE_SPREL:
  1584. case RNAT_SPREL:
  1585. case PRIUNAT_SPREL:
  1586. //
  1587. // sp-relative location
  1588. //
  1589. Index = P8RecordTypeToRegisterIndex[RecType];
  1590. Offset = ReadLEB128(Desc, &DescIndex);
  1591. if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1592. {
  1593. UwContext->MiscRegs[Index].Where = SP_RELATIVE;
  1594. UwContext->MiscRegs[Index].SaveOffset = Offset;
  1595. if (!(State->MiscMask & MASK(Index,1))) {
  1596. UwContext->MiscRegs[Index].When=State->RegionLen;
  1597. State->MiscMask |= MASK(Index,1);
  1598. }
  1599. }
  1600. UW_DEBUG(("Prolog P8: type=%d spoff= %d\n", RecType, Offset));
  1601. break;
  1602. case BSP_PSPREL:
  1603. case BSPSTORE_PSPREL:
  1604. case RNAT_PSPREL:
  1605. case PRIUNAT_PSPREL:
  1606. //
  1607. // psp-relative location
  1608. //
  1609. Index = P8RecordTypeToRegisterIndex[RecType];
  1610. Offset = ReadLEB128(Desc, &DescIndex);
  1611. if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1612. {
  1613. UwContext->MiscRegs[Index].Where = PSP_RELATIVE;
  1614. UwContext->MiscRegs[Index].SaveOffset = Offset;
  1615. UwContext->MiscRegs[Index].When = 0;
  1616. State->MiscMask |= MASK(Index,1);
  1617. }
  1618. UW_DEBUG(("Prolog P8: type=%d pspoff= %d\n", RecType, Offset));
  1619. break;
  1620. case BSP_WHEN:
  1621. case BSPSTORE_WHEN:
  1622. case RNAT_WHEN:
  1623. case PRIUNAT_WHEN:
  1624. //
  1625. // Nevermind processing these descriptors because they
  1626. // have been taken care of in phase 0
  1627. //
  1628. Offset = ReadLEB128(Desc, &DescIndex);
  1629. break;
  1630. default:
  1631. UW_DEBUG(("Invalid record type for descriptor P8!\n"));
  1632. }
  1633. } else if ( (FirstByte & P9_MASK) == P9_PREFIX ) {
  1634. DescIndex += 2;
  1635. VUW_DEBUG_PRINT("Format P9 not supported yet!\n");
  1636. } else if ( (FirstByte & P10_MASK) == P10_PREFIX ) {
  1637. UCHAR Abi = Desc[DescIndex++];
  1638. UCHAR Context = Desc[DescIndex++];
  1639. } else {
  1640. UW_DEBUG(("Invalid descriptor!\n"));
  1641. }
  1642. }
  1643. GrMask = State->GrMask;
  1644. FrMask = State->FrMask;
  1645. BrMask = State->MiscMask >> REG_BR_BASE;
  1646. if (!(GrMask | FrMask | BrMask)) {
  1647. return;
  1648. } else if (SpillMaskOmitted && !(State->IsTarget)) {
  1649. //
  1650. // When spillmask is omitted, floating point registers, general
  1651. // registers, and then branch regisers are spilled in order.
  1652. // They are not modified in the prologue region; therefore, there
  1653. // is no need to restore their contents when the control ip is
  1654. // in this prologue region.
  1655. //
  1656. // 1. floating point registers
  1657. State->SpillPtr &= ~(SPILLSIZE_OF_FLOAT128_IN_DWORDS - 1);
  1658. NextFr = NUMBER_OF_PRESERVED_FR - 1;
  1659. while (FrMask & 0xFFFFF) {
  1660. if (FrMask & 0x80000) {
  1661. State->SpillPtr += SPILLSIZE_OF_FLOAT128_IN_DWORDS;
  1662. UwContext->Float[NextFr].SaveOffset = State->SpillPtr;
  1663. }
  1664. FrMask = FrMask << 1;
  1665. NextFr--;
  1666. }
  1667. // 2. branch registers
  1668. NextBr = REG_BR_BASE + NUMBER_OF_PRESERVED_BR - 1;
  1669. while (BrMask & 0x1F) {
  1670. if (BrMask & 0x10) {
  1671. if (UwContext->MiscRegs[NextBr].Where == PSP_RELATIVE) {
  1672. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1673. UwContext->MiscRegs[NextBr].SaveOffset = State->SpillPtr;
  1674. }
  1675. }
  1676. BrMask = BrMask << 1;
  1677. NextBr--;
  1678. }
  1679. // 3. general registers
  1680. NextGr = NUMBER_OF_PRESERVED_GR - 1;
  1681. while (GrMask & 0xF) {
  1682. if (GrMask & 0x8) {
  1683. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1684. UwContext->Integer[NextGr].SaveOffset = State->SpillPtr;
  1685. }
  1686. GrMask = GrMask << 1;
  1687. NextGr--;
  1688. }
  1689. } else if (SpillMaskOmitted && State->IsTarget) {
  1690. State->GrMask = 0;
  1691. State->FrMask = 0;
  1692. State->MiscMask &= MASK(REG_BR_BASE, 1) - 1;
  1693. } else if (SpillMaskOmitted == FALSE) {
  1694. ULONG Length;
  1695. if (State->IsTarget) {
  1696. //
  1697. // control ip is in the prologue region; clear the masks
  1698. // and then process the imask to determine which preserved
  1699. // Gr/Fr/Br have been saved and set the corresponding bits.
  1700. //
  1701. State->GrMask = 0;
  1702. State->FrMask = 0;
  1703. State->MiscMask &= MASK(REG_BR_BASE, 1) - 1;
  1704. Length = UwContext->TargetSlot - State->RegionBegin;
  1705. } else {
  1706. Length = State->RegionLen;
  1707. }
  1708. NextGr = NUMBER_OF_PRESERVED_GR - 1;
  1709. NextBr = NUMBER_OF_PRESERVED_BR - 1;
  1710. NextFr = NUMBER_OF_PRESERVED_FR - 1;
  1711. for (Count = 0; Count < Length; Count++) {
  1712. if ((Count % 4) == 0) {
  1713. FirstByte = Desc[ImaskBegin++];
  1714. } else {
  1715. FirstByte = FirstByte << 2;
  1716. }
  1717. switch (FirstByte & 0xC0) {
  1718. case 0x40: // 0x01 - save next fr
  1719. while ( !(FrMask & 0x80000) && (NextFr > 0) ) {
  1720. NextFr--;
  1721. FrMask = FrMask << 1;
  1722. }
  1723. UW_DEBUG(("spilled register FS%lx\n", (ULONG)NextFr));
  1724. State->FrMask |= MASK(NextFr,1);
  1725. UwContext->Float[NextFr].When = Count;
  1726. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1727. State->SpillPtr &= ~(SPILLSIZE_OF_FLOAT128_IN_DWORDS - 1);
  1728. State->SpillPtr += SPILLSIZE_OF_FLOAT128_IN_DWORDS;
  1729. UwContext->Float[NextFr].SaveOffset = State->SpillPtr;
  1730. NextFr--;
  1731. FrMask = FrMask << 1;
  1732. break;
  1733. case 0x80: // 0x10 - save next gr
  1734. while ( !(GrMask & 0x8) && (NextGr > 0) ) {
  1735. NextGr--;
  1736. GrMask = GrMask << 1;
  1737. }
  1738. UW_DEBUG(("spilled register S%lx\n", (ULONG)NextGr));
  1739. State->GrMask |= MASK(NextGr,1);
  1740. UwContext->Integer[NextGr].When = Count;
  1741. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1742. UwContext->Integer[NextGr].SaveOffset = State->SpillPtr;
  1743. NextGr--;
  1744. GrMask = GrMask << 1;
  1745. break;
  1746. case 0xC0: // 0x11 - save next br
  1747. while ( !(BrMask & 0x10) && (NextBr > 0) ) {
  1748. NextBr--;
  1749. BrMask = BrMask << 1;
  1750. }
  1751. UW_DEBUG(("spilled register BS%lx\n", (ULONG)NextBr));
  1752. Index = REG_BR_BASE + NextBr;
  1753. State->MiscMask |= MASK(Index,1);
  1754. UwContext->MiscRegs[Index].When = Count;
  1755. if (UwContext->MiscRegs[Index].Where == PSP_RELATIVE) {
  1756. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1757. UwContext->MiscRegs[Index].SaveOffset = State->SpillPtr;
  1758. }
  1759. NextBr--;
  1760. BrMask = BrMask << 1;
  1761. break;
  1762. default: // 0x00 - save no register
  1763. break;
  1764. }
  1765. }
  1766. }
  1767. }