Leaked source code of windows server 2003
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.

2261 lines
70 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 GrNumber,
  373. #ifdef _IMAGEHLP_SOURCE_
  374. IN HANDLE hProcess,
  375. IN PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  376. OUT BOOL *Succeed,
  377. #else
  378. OUT ULONG64 *SourceAddress,
  379. #endif // _IMAGEHLP_SOURCE_
  380. OUT PUCHAR Nat OPTIONAL
  381. )
  382. {
  383. ULONGLONG Result;
  384. SHORT Offset;
  385. IA64_PFS TempIFS;
  386. ULONG64 TempBsp;
  387. #ifdef _IMAGEHLP_SOURCE_
  388. ULONG Size;
  389. #endif // _IMAGEHLP_SOURCE_
  390. #ifdef _IMAGEHLP_SOURCE_
  391. *Succeed = FALSE;
  392. #endif // _IMAGEHLP_SOURCE_
  393. if (GrNumber >= STATIC_REGISTER_SET_SIZE) {
  394. Offset = GrNumber - STATIC_REGISTER_SET_SIZE;
  395. TempIFS.ull = Context->StIFS;
  396. if ( Offset < TempIFS.sb.pfs_sof ) {
  397. TempBsp = RtlpRseGrowByNumber (Context->RsBSP, Offset);
  398. #ifdef _IMAGEHLP_SOURCE_
  399. *Succeed = ReadMemory(hProcess, TempBsp,
  400. &Result, sizeof(ULONGLONG), &Size);
  401. #else
  402. *SourceAddress = TempBsp;
  403. Result = *(PULONGLONG)TempBsp;
  404. #endif // _IMAGEHLP_SOURCE_
  405. } else {
  406. UW_DEBUG(("ERROR: Invalid GR!\n"));
  407. }
  408. } else {
  409. if (GrNumber == 0 || GrNumber == 12) {
  410. //
  411. // Invalid GR number -> Invalid Unwind Descriptor
  412. //
  413. UW_DEBUG(("ERROR: Invalid GR!\n"));
  414. } else {
  415. UW_DEBUG(("WARNING: Target register is not a stacked GR!\n"));
  416. Offset = GrNumber - 1;
  417. NOT_IMAGEHLP(*SourceAddress = (ULONG64)(&Context->IntGp + Offset));
  418. Result = *(&Context->IntGp + Offset);
  419. #ifdef _IMAGEHLP_SOURCE_
  420. *Succeed = TRUE;
  421. #endif // _IMAGEHLP_SOURCE_
  422. }
  423. }
  424. if (ARGUMENT_PRESENT(Nat)) {
  425. //
  426. // TBD: Pick up the corresponding Nat bit
  427. //
  428. *Nat = (UCHAR) 0;
  429. }
  430. return (Result);
  431. }
  432. UCHAR
  433. ParseBodyRegionDescriptors (
  434. IN PUNWIND_CONTEXT UnwindContext,
  435. IN PSTATE_RECORD_STACK StateTable,
  436. IN ULONG RegionLen
  437. )
  438. {
  439. LABEL Label;
  440. UCHAR FirstByte;
  441. BOOLEAN EcountDefined;
  442. BOOLEAN CopyLabel;
  443. ULONG Ecount;
  444. ULONG SlotOffset;
  445. PSTATE_RECORD StateTablePtr;
  446. PUCHAR Descriptors;
  447. CopyLabel = EcountDefined = FALSE;
  448. Descriptors = UnwindContext->Descriptors;
  449. while (UnwindContext->DescCount < UnwindContext->Size) {
  450. FirstByte = Descriptors[UnwindContext->DescCount++];
  451. if ( (FirstByte & B1_MASK) == B1_PREFIX ) {
  452. Label = (LABEL)(FirstByte & B1_LABEL_MASK);
  453. if (FirstByte & B1_TYPE_MASK) {
  454. //
  455. // copy the entry state
  456. //
  457. CopyLabel = TRUE;
  458. } else {
  459. //
  460. // label the entry state
  461. //
  462. LABEL_REGION(StateTable->Top, Label);
  463. }
  464. UW_DEBUG(("Body region desc B1: copy=%d, label_num=%d\n",
  465. FirstByte & B1_TYPE_MASK ? TRUE : FALSE, Label));
  466. } else if ( (FirstByte & B2_MASK) == B2_PREFIX ) {
  467. Ecount = FirstByte & B2_ECOUNT_MASK;
  468. SlotOffset = ReadLEB128(Descriptors, &UnwindContext->DescCount);
  469. EcountDefined = TRUE;
  470. UW_DEBUG(("Epilog desc B2: ecount=%d, LEB128(slot)=%d\n",
  471. Ecount, SlotOffset));
  472. } else if ( (FirstByte & B3_MASK) == B3_PREFIX ) {
  473. SlotOffset = ReadLEB128(Descriptors, &UnwindContext->DescCount);
  474. Ecount = ReadLEB128(Descriptors, &UnwindContext->DescCount);
  475. EcountDefined = TRUE;
  476. UW_DEBUG(("Epilog desc B3: ecount=%d, LEB128 val=%d\n",
  477. Ecount, SlotOffset));
  478. } else if ( (FirstByte & B4_MASK) == B4_PREFIX ) {
  479. Label = ReadLEB128(Descriptors, &UnwindContext->DescCount);
  480. if (FirstByte & B4_TYPE_MASK) {
  481. //
  482. // copy the entry state
  483. //
  484. CopyLabel = TRUE;
  485. } else {
  486. //
  487. // label the current top of stack
  488. //
  489. LABEL_REGION(StateTable->Top, Label);
  490. }
  491. UW_DEBUG(("Body region desc B4: copy=%d, label_num=%d\n",
  492. FirstByte & B4_TYPE_MASK, Label));
  493. } else {
  494. //
  495. // Encounter another region header record
  496. //
  497. break;
  498. }
  499. }
  500. if (CopyLabel) {
  501. StateTablePtr = StateTable->Top;
  502. while (TRUE) {
  503. if (CHECK_LABEL(StateTablePtr, Label)) {
  504. StateTable->Current = StateTablePtr;
  505. break;
  506. } else if ((StateTablePtr == StateTable->Base)) {
  507. UW_DEBUG(("Undefined Label %d\n", Label));
  508. break;
  509. }
  510. StateTablePtr--;
  511. }
  512. }
  513. if (EcountDefined) {
  514. Ecount++; // Ecount specifies additional level of prologue
  515. // regions to undo (i.e. a value of 0 implies 1
  516. // prologue region)
  517. if (UnwindContext->ActiveRegionFound == FALSE) {
  518. while (Ecount-- > 0) {
  519. if (StateTable->Current->Previous) {
  520. StateTable->Current = StateTable->Current->Previous;
  521. }
  522. #if DBG
  523. else {
  524. UW_DEBUG(("WARNING: Ecount is greater than the # of active prologues!\n"));
  525. }
  526. #endif // DBG
  527. }
  528. } else {
  529. //
  530. // control PC is in this body/epilog region
  531. //
  532. if ((UnwindContext->SlotCount + RegionLen - SlotOffset)
  533. <= UnwindContext->TargetSlot)
  534. {
  535. PSTATE_RECORD SrPointer;
  536. StateTable->Current->Ecount = Ecount;
  537. SrPointer = StateTable->Current;
  538. while (Ecount > 0) {
  539. if (SrPointer->Previous) {
  540. SrPointer->Ecount = Ecount;
  541. SrPointer->SpWhen = 0;
  542. SrPointer->SpAdjustment = 0;
  543. SrPointer = SrPointer->Previous;
  544. }
  545. #if DBG
  546. else {
  547. UW_DEBUG(("WARNING: Ecount is greater than the # of active prologues!\n"));
  548. }
  549. #endif // DBG
  550. Ecount--;
  551. }
  552. }
  553. }
  554. }
  555. return FirstByte;
  556. }
  557. ULONGLONG
  558. ProcessInterruptRegion (
  559. #ifdef _IMAGEHLP_SOURCE_
  560. IN HANDLE hProcess,
  561. IN PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  562. #else
  563. IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
  564. OUT PFRAME_POINTERS EstablisherFrame,
  565. #endif _IMAGEHLP_SOURCE_
  566. IN PUNWIND_CONTEXT UnwindContext,
  567. IN PCONTEXT Context,
  568. IN UCHAR AbiImmContext
  569. )
  570. {
  571. //
  572. // no prologue descriptor in interrupt region.
  573. //
  574. PCONTEXT PrevContext;
  575. ULONGLONG NextPc;
  576. ULONG Index;
  577. BOOLEAN Success;
  578. #ifdef _IMAGEHLP_SOURCE_
  579. ULONG Size;
  580. #else
  581. PVOID *Source;
  582. PVOID Address;
  583. #endif _IMAGEHLP_SOURCE_
  584. if (AbiImmContext != CONTEXT_FRAME) {
  585. PKTRAP_FRAME TrapFrame;
  586. PKEXCEPTION_FRAME ExFrame;
  587. #ifdef _IMAGEHLP_SOURCE_
  588. KTRAP_FRAME TF;
  589. KEXCEPTION_FRAME ExF;
  590. #endif // _IMAGEHLP_SOURCE_
  591. TrapFrame = (PKTRAP_FRAME) Context->IntSp;
  592. #ifdef _IMAGEHLP_SOURCE_
  593. if (!ReadMemory(hProcess, Context->IntSp, &TF, sizeof(KTRAP_FRAME), &Size))
  594. {
  595. return 0;
  596. }
  597. TrapFrame = &TF;
  598. #endif // _IMAGEHLP_SOURCE_
  599. Context->ApUNAT = TrapFrame->ApUNAT;
  600. Context->StFPSR = TrapFrame->StFPSR;
  601. Context->Preds = TrapFrame->Preds;
  602. Context->IntSp = TrapFrame->IntSp;
  603. Context->StIPSR = TrapFrame->StIPSR;
  604. Context->StIFS = TrapFrame->StIFS;
  605. Context->BrRp = TrapFrame->BrRp;
  606. Context->RsPFS = TrapFrame->RsPFS;
  607. if (TRAP_FRAME_TYPE(TrapFrame) != SYSCALL_FRAME) {
  608. //
  609. // The temporary registers need to be preserved,
  610. // becuase a leaf function may save a perserved
  611. // register tempoary register.
  612. //
  613. Context->ApCCV = TrapFrame->ApCCV;
  614. Context->SegCSD = TrapFrame->SegCSD;
  615. Context->IntT0 = TrapFrame->IntT0;
  616. Context->IntT1 = TrapFrame->IntT1;
  617. Context->IntT2 = TrapFrame->IntT2;
  618. Context->IntT3 = TrapFrame->IntT3;
  619. Context->IntT4 = TrapFrame->IntT4;
  620. //
  621. // t5 - t22
  622. //
  623. memcpy(&Context->IntT5, &TrapFrame->IntT5, 18*sizeof(ULONGLONG));
  624. //
  625. // Set branch registers from trap frame & exception frame
  626. //
  627. Context->BrT0 = TrapFrame->BrT0;
  628. Context->BrT1 = TrapFrame->BrT1;
  629. }
  630. #ifndef _IMAGEHLP_SOURCE_
  631. if (ARGUMENT_PRESENT(ContextPointers)) {
  632. ContextPointers->ApUNAT = &TrapFrame->ApUNAT;
  633. ContextPointers->IntSp = &TrapFrame->IntSp;
  634. ContextPointers->BrRp = &TrapFrame->BrRp;
  635. ContextPointers->RsPFS = &TrapFrame->RsPFS;
  636. ContextPointers->Preds = &TrapFrame->Preds;
  637. }
  638. //
  639. // Inorder for top level exception handers such as KiSystemServiceHandler,
  640. // the establisher frame must look like it is part of the kernel stack
  641. // not the user stack.
  642. //
  643. EstablisherFrame->MemoryStackFp = (ULONGLONG) TrapFrame + sizeof(KTRAP_FRAME);
  644. EstablisherFrame->BackingStoreFp = Context->RsBSP;
  645. #endif // _IMAGEHLP_SOURCE_
  646. switch (AbiImmContext) {
  647. case SYSCALL_FRAME:
  648. //
  649. // System Call Handler Frame
  650. //
  651. Context->RsBSP = RtlpRseShrinkBySOL(TrapFrame->RsBSP, TrapFrame->StIFS);
  652. break;
  653. case INTERRUPT_FRAME:
  654. case EXCEPTION_FRAME:
  655. //
  656. // External Interrupt Frame / Exception Frame
  657. //
  658. Context->RsBSP = RtlpRseShrinkBySOF(TrapFrame->RsBSP, TrapFrame->StIFS);
  659. break;
  660. default:
  661. //
  662. // should not happen
  663. //
  664. UW_DEBUG(("Invalid AbiImmContext type!\n"));
  665. break;
  666. }
  667. Context->RsBSPSTORE = Context->RsBSP;
  668. Context->RsRNAT = TrapFrame->RsRNAT;
  669. NextPc = RtlIa64InsertIPSlotNumber(TrapFrame->StIIP,
  670. ((TrapFrame->StIPSR >> PSR_RI) & 0x3));
  671. return (NextPc);
  672. }
  673. //
  674. // Kernel-to-User thunk, context of the previous frame can be
  675. // found on the user stack (i.e. context's address = sp+SCRATCH_AREA)
  676. //
  677. PrevContext = (PCONTEXT)(Context->IntSp + STACK_SCRATCH_AREA);
  678. #ifdef _IMAGEHLP_SOURCE_
  679. if (!ReadMemory(hProcess, (DWORD64)PrevContext, Context, sizeof(CONTEXT), &Size))
  680. {
  681. return 0;
  682. }
  683. NextPc = RtlIa64InsertIPSlotNumber(Context->StIIP,
  684. ((Context->StIPSR >> PSR_RI) & 0x3));
  685. #else
  686. RtlCopyMemory(&Context->BrRp, &PrevContext->BrRp,
  687. (NUMBER_OF_PRESERVED_BR+3) * sizeof(ULONGLONG));
  688. RtlCopyMemory(&Context->FltS0, &PrevContext->FltS0,
  689. NUMBER_OF_LOW_PRESERVED_FR * sizeof(FLOAT128));
  690. RtlCopyMemory(&Context->FltS4, &PrevContext->FltS4,
  691. NUMBER_OF_HIGH_PRESERVED_FR * sizeof(FLOAT128));
  692. RtlCopyMemory(&Context->IntS0, &PrevContext->IntS0,
  693. NUMBER_OF_PRESERVED_GR * sizeof(ULONGLONG));
  694. RtlCopyMemory(&Context->IntV0, &PrevContext->IntV0,
  695. NUMBER_OF_SCRATCH_GR * sizeof(ULONGLONG));
  696. Context->IntT0 = PrevContext->IntT0;
  697. Context->IntT1 = PrevContext->IntT1;
  698. Context->IntSp = PrevContext->IntSp;
  699. Context->IntNats = PrevContext->IntNats;
  700. Context->ApUNAT = PrevContext->ApUNAT;
  701. Context->ApLC = PrevContext->ApLC;
  702. Context->ApEC = PrevContext->ApEC;
  703. Context->Preds = PrevContext->Preds;
  704. Context->RsPFS = PrevContext->RsPFS;
  705. Context->RsBSP = PrevContext->RsBSP;
  706. Context->RsBSPSTORE = PrevContext->RsBSPSTORE;
  707. Context->RsRSC = PrevContext->RsRSC;
  708. Context->RsRNAT = PrevContext->RsRNAT;
  709. Context->StIFS = PrevContext->StIFS;
  710. Context->StIPSR = PrevContext->StIPSR;
  711. NextPc = RtlIa64InsertIPSlotNumber(PrevContext->StIIP,
  712. ((PrevContext->StIPSR >> PSR_RI) & 0x3));
  713. EstablisherFrame->MemoryStackFp = Context->IntSp;
  714. EstablisherFrame->BackingStoreFp = Context->RsBSP;
  715. #endif // _IMAGEHLP_SOURCE_
  716. return(NextPc);
  717. }
  718. ULONGLONG
  719. RtlVirtualUnwind (
  720. #ifdef _IMAGEHLP_SOURCE_
  721. HANDLE hProcess,
  722. ULONGLONG ImageBase,
  723. ULONGLONG ControlPc,
  724. PRUNTIME_FUNCTION FunctionEntry,
  725. PCONTEXT ContextRecord,
  726. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory
  727. #define ContextPointers ((PKNONVOLATILE_CONTEXT_POINTERS)0)
  728. #else
  729. IN ULONGLONG ImageBase,
  730. IN ULONGLONG ControlPc,
  731. IN PRUNTIME_FUNCTION FunctionEntry,
  732. IN OUT PCONTEXT ContextRecord,
  733. OUT PBOOLEAN InFunction,
  734. OUT PFRAME_POINTERS EstablisherFrame,
  735. IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL
  736. #endif
  737. )
  738. /*++
  739. Routine Description:
  740. This function virtually unwinds the specfified function by executing its
  741. prologue code backwards.
  742. If the function is a leaf function, then the address where control left
  743. the previous frame is obtained from the context record. If the function
  744. is a nested function, but not an exception or interrupt frame, then the
  745. prologue code is executed backwards and the address where control left
  746. the previous frame is obtained from the updated context record.
  747. Otherwise, an exception or interrupt entry to the system is being unwound
  748. and an especially coded prologue restores the return address twice. Once
  749. from the fault instruction address and once from the saved return address
  750. register. The first restore is returned as the function value and the
  751. second restore is placed in the updated context record.
  752. If a context pointers record is specified, then the address where each
  753. nonvolatile registers is restored from is recorded in the appropriate
  754. element of the context pointers record.
  755. Arguments:
  756. ImageBase - Supplies the base address of the module to which the
  757. function belongs.
  758. ControlPc - Supplies the address where control left the specified
  759. function.
  760. FunctionEntry - Supplies the address of the function table entry for the
  761. specified function.
  762. ContextRecord - Supplies the address of a context record.
  763. InFunction - Supplies a pointer to a variable that receives whether the
  764. control PC is within the current function.
  765. EstablisherFrame - Supplies a pointer to a variable that receives the
  766. the establisher frame pointer value.
  767. ContextPointers - Supplies an optional pointer to a context pointers
  768. record.
  769. Return Value:
  770. The address where control left the previous frame is returned as the
  771. function value.
  772. --*/
  773. {
  774. #ifdef _IMAGEHLP_SOURCE_
  775. BOOL Succeed;
  776. #endif // _IMAGEHLP_SOURCE_
  777. PUCHAR Descriptors = NULL;
  778. UCHAR AbiImmContext = 0xFF;
  779. ULONG Mask;
  780. ULONGLONG NextPc;
  781. ULONG RegionLen;
  782. UCHAR FirstByte;
  783. UCHAR Nat;
  784. SHORT LocalFrameSize; // in 8-byte units
  785. ULONG i;
  786. PULONG Buffer;
  787. BOOLEAN IsPrologueRegion;
  788. BOOLEAN PspRestored;
  789. ULONGLONG PreviousIntSp;
  790. PVOID Destination;
  791. ULONG64 Source;
  792. ULONG64 *CtxPtr;
  793. ULONG64 *NatCtxPtr;
  794. ULONG64 IntNatsSource;
  795. ULONG64 IntNats;
  796. ULONG Size;
  797. PULONGLONG OldTopRnat;
  798. PULONGLONG NewTopRnat;
  799. UNWIND_INFO UnwindInfo;
  800. ULONG64 UnwindInfoPtr;
  801. UNWIND_CONTEXT UnwindContext;
  802. PSTATE_RECORD SrPointer;
  803. STATE_RECORD_STACK StateTable;
  804. STATE_RECORD StateRecords[STATE_RECORD_STACK_SIZE];
  805. UnwindInfoPtr = ImageBase + FunctionEntry->UnwindInfoAddress;
  806. #ifdef _IMAGEHLP_SOURCE_
  807. if (!ReadMemory( hProcess, (ULONG64)UnwindInfoPtr,
  808. &UnwindInfo, sizeof(UNWIND_INFO), &Size))
  809. {
  810. return 0;
  811. }
  812. UnwindContext.Version = UnwindInfo.Version;
  813. Size = UnwindInfo.DataLength * sizeof(ULONGLONG);
  814. if (Size) {
  815. Descriptors = (PUCHAR) MemAlloc (Size);
  816. if (!ReadMemory(hProcess,(ULONG64)(UnwindInfoPtr+sizeof(UNWIND_INFO)), Descriptors, Size, &Size)) {
  817. return 0;
  818. }
  819. }
  820. #else
  821. UnwindContext.Version = ((PUNWIND_INFO)UnwindInfoPtr)->Version;
  822. Size = ((PUNWIND_INFO)UnwindInfoPtr)->DataLength * sizeof(ULONGLONG);
  823. Descriptors = (PUCHAR)UnwindInfoPtr + sizeof(UNWIND_INFO);
  824. #endif // _IMAGEHLP_SOURCE_
  825. UnwindContext.Size = Size;
  826. UnwindContext.ActiveRegionFound = FALSE;
  827. UnwindContext.AlternateRp = 0;
  828. UnwindContext.DescCount = 0;
  829. UnwindContext.SlotCount = 0;
  830. UnwindContext.TargetSlot = (ULONG)(((ControlPc - FunctionEntry->BeginAddress - ImageBase) >> 4) * SLOTS_PER_BUNDLE + ((ControlPc >> 2) & 0x3));
  831. UnwindContext.Descriptors = Descriptors;
  832. SrInitialize(&StateTable, StateRecords, STATE_RECORD_STACK_SIZE);
  833. if (Size) {
  834. FirstByte = Descriptors[UnwindContext.DescCount++];
  835. }
  836. while ( (UnwindContext.DescCount < UnwindContext.Size) &&
  837. (!UnwindContext.ActiveRegionFound) )
  838. {
  839. //
  840. // Assume a prologue region but not an interrupt region.
  841. //
  842. IsPrologueRegion = TRUE;
  843. //
  844. // Based on the type of region header, dispatch
  845. // to the corresponding routine that processes
  846. // the succeeding descriptors until the next
  847. // region header record.
  848. //
  849. if ((FirstByte & R1_MASK) == R1_PREFIX) {
  850. //
  851. // region header record in short format
  852. //
  853. RegionLen = FirstByte & R1_LENGTH_MASK;
  854. if (FirstByte & R1_REGION_TYPE_MASK) {
  855. IsPrologueRegion = FALSE;
  856. } else {
  857. ADD_STATE_RECORD(StateTable, RegionLen, UnwindContext.DescCount);
  858. }
  859. UW_DEBUG(("Region R1 format: body=%x, length=%d\n",
  860. IsPrologueRegion ? 0 : 1, RegionLen));
  861. } else if ((FirstByte & R2_MASK) == R2_PREFIX) {
  862. //
  863. // general prologue region header
  864. // N.B. Skip the 2nd byte of the header and proceed to read
  865. // the region length; the header descriptors will be
  866. // processed again in phase 1.
  867. //
  868. ULONG R2DescIndex;
  869. R2DescIndex = UnwindContext.DescCount - 1;
  870. UnwindContext.DescCount++;
  871. RegionLen = ReadLEB128(Descriptors, &UnwindContext.DescCount);
  872. ADD_STATE_RECORD(StateTable, RegionLen, R2DescIndex);
  873. UW_DEBUG(("Region R2: body=0, length=%d\n", RegionLen));
  874. } else if ((FirstByte & R3_MASK) == R3_PREFIX) {
  875. //
  876. // region header record in long format
  877. //
  878. RegionLen = ReadLEB128(Descriptors, &UnwindContext.DescCount);
  879. switch (FirstByte & R3_REGION_TYPE_MASK) {
  880. case 0: // prologue region header
  881. ADD_STATE_RECORD(StateTable, RegionLen, UnwindContext.DescCount);
  882. break;
  883. case 1: // body region header
  884. IsPrologueRegion = FALSE;
  885. break;
  886. }
  887. UW_DEBUG(("Region R3: body=%x, length=%d\n",
  888. IsPrologueRegion ? 0 : 1, RegionLen));
  889. } else {
  890. //
  891. // Not a region header record -> Invalid unwind descriptor.
  892. //
  893. UW_DEBUG(("Invalid unwind descriptor!\n"));
  894. }
  895. if (UnwindContext.TargetSlot < (UnwindContext.SlotCount + RegionLen)) {
  896. UnwindContext.ActiveRegionFound = TRUE;
  897. StateTable.Current->IsTarget = IsPrologueRegion;
  898. }
  899. if (IsPrologueRegion) {
  900. FirstByte = NewParsePrologueRegionPhase0(&UnwindContext,
  901. StateTable.Current,
  902. &AbiImmContext);
  903. } else {
  904. FirstByte = ParseBodyRegionDescriptors(&UnwindContext,
  905. &StateTable,
  906. RegionLen);
  907. }
  908. UnwindContext.SlotCount += RegionLen;
  909. }
  910. //
  911. // Restore the value of psp and save the current NatCr.
  912. // N.B. If the value is restored from stack/bstore, turn off the
  913. // corresponding sp bit in the saved mask associated with the
  914. // prologue region in which psp is saved.
  915. //
  916. if (ARGUMENT_PRESENT(ContextPointers)) {
  917. IntNatsSource = (ULONG64)ContextPointers->ApUNAT;
  918. }
  919. IntNats = ContextRecord->ApUNAT;
  920. PreviousIntSp = ContextRecord->IntSp;
  921. PspRestored = FALSE;
  922. SrPointer = StateTable.Current;
  923. while (SrPointer != StateTable.Base) {
  924. NewParsePrologueRegionPhase1(&UnwindContext, SrPointer);
  925. if (SrPointer->MiscMask & (1 << REG_SP)) {
  926. if (UnwindContext.MiscRegs[REG_SP].Where == GENERAL_REG) {
  927. PreviousIntSp = RestorePreservedRegisterFromGR (
  928. ContextRecord,
  929. (SHORT)UnwindContext.MiscRegs[REG_SP].SaveOffset,
  930. #ifdef _IMAGEHLP_SOURCE_
  931. hProcess,
  932. ReadMemory,
  933. &Succeed,
  934. #else
  935. &Source,
  936. #endif // _IMAGEHLP_SOURCE_
  937. &Nat
  938. );
  939. #ifdef _IMAGEHLP_SOURCE_
  940. if (!Succeed) {
  941. return 0;
  942. }
  943. #endif // _IMAGEHLP_SOURCE_
  944. } else {
  945. Source = ContextRecord->IntSp + UnwindContext.MiscRegs[REG_SP].SaveOffset*4;
  946. #ifdef _IMAGEHLP_SOURCE_
  947. if (!ReadMemory(hProcess, (ULONG64)(Source), &PreviousIntSp, sizeof(ULONGLONG), &Size)) {
  948. return 0;
  949. }
  950. #else
  951. PreviousIntSp = *(PULONGLONG)Source;
  952. #endif // _IMAGEHLP_SOURCE_
  953. EXTRACT_NAT_FROM_UNAT(Nat);
  954. }
  955. ContextRecord->IntNats &= ~(0x1 << STACK_POINTER_GR);
  956. ContextRecord->IntNats |= (Nat << STACK_POINTER_GR);
  957. SrPointer->MiscMask &= ~(1 << REG_SP);
  958. if (ARGUMENT_PRESENT(ContextPointers)) {
  959. CtxPtr = (ULONG64 *)((ULONG_PTR)ContextPointers +
  960. MiscContextPointersOffset[REG_SP]);
  961. *CtxPtr = Source;
  962. }
  963. PspRestored = TRUE;
  964. }
  965. if (PspRestored == FALSE) {
  966. PreviousIntSp += SrPointer->SpAdjustment * 4;
  967. }
  968. SrPointer = SrPointer->Previous;
  969. }
  970. if (AbiImmContext != 0xFF) {
  971. ContextRecord->IntSp = PreviousIntSp; // trap/context frame address
  972. NextPc = ProcessInterruptRegion(
  973. #ifdef _IMAGEHLP_SOURCE_
  974. hProcess,
  975. ReadMemory,
  976. #else
  977. ContextPointers,
  978. EstablisherFrame,
  979. #endif _IMAGEHLP_SOURCE_
  980. &UnwindContext,
  981. ContextRecord,
  982. AbiImmContext);
  983. goto FastExit;
  984. }
  985. //
  986. // Restore the contents of any preserved registers saved in this frame.
  987. //
  988. SrPointer = StateTable.Current;
  989. while (SrPointer != StateTable.Base) {
  990. Mask = SrPointer->MiscMask;
  991. UW_DEBUG(("MiscMask = 0x%x\n", Mask));
  992. for (i = 0; i < NUMBER_OF_PRESERVED_REGISTERS; i++) {
  993. Destination = (PVOID)((ULONG_PTR)ContextRecord + MiscContextOffset[i]);
  994. if (Mask & 0x1) {
  995. if (ARGUMENT_PRESENT(ContextPointers)) {
  996. CtxPtr = (ULONG64 *)((ULONG_PTR)ContextPointers +
  997. MiscContextPointersOffset[i]);
  998. Source = *CtxPtr;
  999. }
  1000. if (UnwindContext.MiscRegs[i].Where == GENERAL_REG) {
  1001. *(PULONGLONG)Destination =
  1002. RestorePreservedRegisterFromGR (
  1003. ContextRecord,
  1004. (SHORT)UnwindContext.MiscRegs[i].SaveOffset,
  1005. #ifdef _IMAGEHLP_SOURCE_
  1006. hProcess,
  1007. ReadMemory,
  1008. &Succeed,
  1009. #else
  1010. &Source,
  1011. #endif // _IMAGEHLP_SOURCE_
  1012. NULL
  1013. );
  1014. #ifdef _IMAGEHLP_SOURCE_
  1015. if (!Succeed) {
  1016. return 0;
  1017. }
  1018. #endif // _IMAGEHLP_SOURCE_
  1019. } else if (UnwindContext.MiscRegs[i].Where == BRANCH_REG) {
  1020. //
  1021. // restore return pointer from branch register
  1022. //
  1023. USHORT Offset;
  1024. Offset = (USHORT)UnwindContext.MiscRegs[i].SaveOffset-FIRST_PRESERVED_BR;
  1025. Source = (ULONG64)(&ContextRecord->BrS0 + Offset);
  1026. #ifdef _IMAGEHLP_SOURCE_
  1027. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) {
  1028. return 0;
  1029. }
  1030. #else
  1031. *(PULONGLONG)Destination = *(PULONGLONG)(Source);
  1032. #endif // _IMAGEHLP_SOURCE_
  1033. } else if (UnwindContext.MiscRegs[i].Where == PSP_RELATIVE) {
  1034. if ((SrPointer->Ecount == 0) || (UnwindContext.MiscRegs[i].SaveOffset <= (STACK_SCRATCH_AREA/sizeof(ULONG)))) {
  1035. Source = PreviousIntSp + STACK_SCRATCH_AREA
  1036. - UnwindContext.MiscRegs[i].SaveOffset*4;
  1037. if (i == REG_NATS) {
  1038. Destination = (PVOID)&IntNats;
  1039. IntNatsSource = Source;
  1040. }
  1041. #ifdef _IMAGEHLP_SOURCE_
  1042. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) {
  1043. return 0;
  1044. }
  1045. #else
  1046. *(PULONGLONG)Destination = *(PULONGLONG)(Source);
  1047. #endif // _IMAGEHLP_SOURCE_
  1048. }
  1049. } else if (UnwindContext.MiscRegs[i].Where == SP_RELATIVE) {
  1050. //
  1051. // Make the necessary adjustment depending on whether
  1052. // the preserved register is saved before or after the
  1053. // stack pointer has been adjusted in this prologue.
  1054. //
  1055. if (UnwindContext.MiscRegs[i].When >= SrPointer->SpWhen && (SrPointer->RegionLen != 0))
  1056. Source = ContextRecord->IntSp
  1057. + UnwindContext.MiscRegs[i].SaveOffset*4;
  1058. else
  1059. Source = ContextRecord->IntSp+SrPointer->SpAdjustment*4
  1060. + UnwindContext.MiscRegs[i].SaveOffset*4;
  1061. if (i == REG_NATS) {
  1062. Destination = (PVOID)&IntNats;
  1063. IntNatsSource = Source;
  1064. }
  1065. #ifdef _IMAGEHLP_SOURCE_
  1066. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) {
  1067. return 0;
  1068. }
  1069. #else
  1070. *(PULONGLONG)Destination = *(PULONGLONG)(Source);
  1071. #endif // _IMAGEHLP_SOURCE_
  1072. }
  1073. if (ARGUMENT_PRESENT(ContextPointers) && (i != REG_NATS)) {
  1074. *CtxPtr = Source;
  1075. }
  1076. } else if (Mask == 0) {
  1077. //
  1078. // No more registers to restore
  1079. //
  1080. break;
  1081. }
  1082. Mask = Mask >> 1;
  1083. }
  1084. //
  1085. // Restore preserved FRs (f2 - f5, f16 - f31)
  1086. //
  1087. Mask = SrPointer->FrMask;
  1088. Destination = (PVOID)&ContextRecord->FltS0;
  1089. CtxPtr = (ULONG64 *)&ContextPointers->FltS0;
  1090. UW_DEBUG(("FrMask = 0x%x\n", Mask));
  1091. for (i = 0; i < NUMBER_OF_PRESERVED_FR; i++) {
  1092. if (Mask & 0x1) {
  1093. if ((SrPointer->Ecount == 0) || (UnwindContext.Float[i].SaveOffset <= (STACK_SCRATCH_AREA/sizeof(ULONG)))) {
  1094. Source = PreviousIntSp + STACK_SCRATCH_AREA
  1095. - UnwindContext.Float[i].SaveOffset*4;
  1096. #ifdef _IMAGEHLP_SOURCE_
  1097. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(FLOAT128), &Size)) {
  1098. return 0;
  1099. }
  1100. #else
  1101. *(FLOAT128 *)Destination = *(FLOAT128 *)Source;
  1102. #endif // _IMAGEHLP_SOURCE_
  1103. if (ARGUMENT_PRESENT(ContextPointers)) {
  1104. *CtxPtr = Source;
  1105. }
  1106. }
  1107. } else if (Mask == 0) {
  1108. break;
  1109. }
  1110. Mask = Mask >> 1;
  1111. if (i == (NUMBER_OF_LOW_PRESERVED_FR - 1)) {
  1112. Destination = (PVOID)&ContextRecord->FltS4;
  1113. CtxPtr = (ULONG64 *)(&ContextPointers->FltS4);
  1114. } else {
  1115. Destination = (PVOID)((FLOAT128 *)Destination+1);
  1116. CtxPtr++;
  1117. }
  1118. }
  1119. //
  1120. // Restore preserved GRs (r4 - r7)
  1121. //
  1122. Mask = SrPointer->GrMask;
  1123. Destination = (PVOID)&ContextRecord->IntS0;
  1124. CtxPtr = (ULONG64 *)&ContextPointers->IntS0;
  1125. NatCtxPtr = (ULONG64 *)&ContextPointers->IntS0Nat;
  1126. UW_DEBUG(("GrMask = 0x%x\n", Mask));
  1127. for (i = 0; i < NUMBER_OF_PRESERVED_GR; i++)
  1128. {
  1129. if (Mask & 0x1) {
  1130. if ((SrPointer->Ecount == 0) || (UnwindContext.Integer[i].SaveOffset <= (STACK_SCRATCH_AREA/sizeof(ULONG)))) {
  1131. Source = PreviousIntSp + STACK_SCRATCH_AREA
  1132. - UnwindContext.Integer[i].SaveOffset*4;
  1133. #ifdef _IMAGEHLP_SOURCE_
  1134. if (!ReadMemory(hProcess, (ULONG64)(Source), Destination, sizeof(ULONGLONG), &Size)) {
  1135. return 0;
  1136. }
  1137. #else
  1138. *(PULONGLONG)Destination = *(PULONGLONG)Source;
  1139. #endif // _IMAGEHLP_SOURCE_
  1140. EXTRACT_NAT_FROM_UNAT(Nat);
  1141. Nat = (UCHAR)((IntNats >> (((ULONG_PTR)Source & 0x1F8) >> 3)) & 0x1);
  1142. ContextRecord->IntNats &= ~(0x1 << (i+FIRST_PRESERVED_GR));
  1143. ContextRecord->IntNats |= (Nat << (i+FIRST_PRESERVED_GR));
  1144. #ifndef _IMAGEHLP_SOURCE_
  1145. if (ARGUMENT_PRESENT(ContextPointers)) {
  1146. *CtxPtr = Source;
  1147. *NatCtxPtr = IntNatsSource;
  1148. }
  1149. #endif
  1150. }
  1151. } else if (Mask == 0) {
  1152. break;
  1153. }
  1154. Mask = Mask >> 1;
  1155. Destination = (PVOID)((PULONGLONG)Destination+1);
  1156. CtxPtr++;
  1157. NatCtxPtr++;
  1158. }
  1159. ContextRecord->IntSp += SrPointer->SpAdjustment * 4;
  1160. SrPointer = SrPointer->Previous;
  1161. }
  1162. ContextRecord->IntSp = PreviousIntSp;
  1163. //
  1164. // Restore the value of the epilogue count from the PFS
  1165. //
  1166. ContextRecord->ApEC = (ContextRecord->RsPFS >> PFS_EC_SHIFT) &
  1167. ~(((ULONGLONG)1 << PFS_EC_SIZE) - 1);
  1168. if (ARGUMENT_PRESENT(ContextPointers)) {
  1169. ContextPointers->ApEC = ContextPointers->RsPFS;
  1170. }
  1171. FastExit:
  1172. NOT_IMAGEHLP(*InFunction = TRUE);
  1173. if (AbiImmContext == 0xFF) {
  1174. //
  1175. // ProcessInterruptRegion fills in these values for traps.
  1176. //
  1177. NOT_IMAGEHLP(EstablisherFrame->MemoryStackFp = ContextRecord->IntSp);
  1178. NOT_IMAGEHLP(EstablisherFrame->BackingStoreFp = ContextRecord->RsBSP);
  1179. }
  1180. #ifdef _IMAGEHLP_SOURCE_
  1181. if (Descriptors)
  1182. MemFree(Descriptors);
  1183. #endif // _IMAGEHLP_SOURCE_
  1184. if (AbiImmContext == 0xFF) {
  1185. NextPc = *(&ContextRecord->BrRp + UnwindContext.AlternateRp);
  1186. #ifndef _IMAGEHLP_SOURCE_
  1187. NextPc = RtlIa64InsertIPSlotNumber((NextPc-0x10), 2);
  1188. #endif // _IMAGEHLP_SOURCE_
  1189. //
  1190. // determine the local frame size of previous frame and compute
  1191. // the new bsp.
  1192. //
  1193. OldTopRnat = RtlpRseRNatAddress (RtlpRseGrowBySOF(ContextRecord->RsBSP, ContextRecord->StIFS) - 8);
  1194. ContextRecord->StIFS = MASK(IFS_V, (ULONGLONG)1) | ContextRecord->RsPFS;
  1195. ContextRecord->RsBSP = RtlpRseShrinkBySOL(ContextRecord->RsBSP, ContextRecord->StIFS);
  1196. ContextRecord->RsBSPSTORE = ContextRecord->RsBSP;
  1197. //
  1198. // determine if the RNAT field needs to be updated.
  1199. //
  1200. NewTopRnat = RtlpRseRNatAddress(RtlpRseGrowBySOF(ContextRecord->RsBSP, ContextRecord->StIFS) - 8);
  1201. if (NewTopRnat < OldTopRnat) {
  1202. #ifdef _IMAGEHLP_SOURCE_
  1203. Destination = &ContextRecord->RsRNAT;
  1204. Source = NewTopRnat;
  1205. if (!ReadMemory(hProcess, (ULONG64)Source, Destination, 8, &Size)) {
  1206. return 0;
  1207. }
  1208. #else
  1209. ContextRecord->RsRNAT = *NewTopRnat;
  1210. #endif // _IMAGEHLP_SOURCE_
  1211. }
  1212. }
  1213. #ifdef _IMAGEHLP_SOURCE_
  1214. UW_DEBUG(("NextPc = 0x%lx, PSP = 0x%lx, BSP = 0x%lx\n",
  1215. (ULONGLONG)NextPc,
  1216. (ULONGLONG)ContextRecord->IntSp,
  1217. (ULONGLONG)ContextRecord->RsBSP));
  1218. #else
  1219. UW_DEBUG(("NextPc = 0x%lx, PSP = 0x%lx, BSP = 0x%lx\n",
  1220. (ULONGLONG)NextPc,
  1221. EstablisherFrame->MemoryStackFp,
  1222. EstablisherFrame->BackingStoreFp));
  1223. #endif // _IMAGEHLP_SOURCE_
  1224. return (NextPc);
  1225. }
  1226. UCHAR
  1227. NewParsePrologueRegionPhase0 (
  1228. IN PUNWIND_CONTEXT UwContext,
  1229. IN PSTATE_RECORD State,
  1230. IN OUT PUCHAR AbiImmContext
  1231. )
  1232. {
  1233. PUCHAR Desc = UwContext->Descriptors;
  1234. ULONG Offset;
  1235. ULONG FrameSize;
  1236. ULONG Index;
  1237. UCHAR RecType;
  1238. UCHAR FirstByte;
  1239. UCHAR SecondByte;
  1240. ULONG GrSave;
  1241. ULONG TempMask;
  1242. ULONG i;
  1243. while (UwContext->DescCount < UwContext->Size) {
  1244. FirstByte = Desc[UwContext->DescCount++];
  1245. if ( (FirstByte & P1_MASK) == P1_PREFIX) {
  1246. continue;
  1247. } else if ( (FirstByte & P2_MASK) == P2_PREFIX ) {
  1248. UwContext->DescCount++;
  1249. } else if ( (FirstByte & P3_MASK) == P3_PREFIX ) {
  1250. UwContext->DescCount++;
  1251. } else if ( (FirstByte & P4_MASK) == P4_PREFIX ) {
  1252. UwContext->DescCount += ((State->RegionLen+3) >> 2);
  1253. } else if ( (FirstByte & P5_MASK) == P5_PREFIX ) {
  1254. UwContext->DescCount += 3;
  1255. } else if ( (FirstByte & P6_MASK) == P6_PREFIX ) {
  1256. continue;
  1257. } else if ( (FirstByte & P7_MASK) == P7_PREFIX ) {
  1258. RecType = FirstByte & ~P7_MASK;
  1259. switch (RecType) {
  1260. case MEM_STACK_F:
  1261. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1262. FrameSize = ReadLEB128(Desc, &UwContext->DescCount);
  1263. if (UwContext->TargetSlot > (UwContext->SlotCount+Offset) || State->RegionLen == 0)
  1264. {
  1265. State->SpAdjustment += FrameSize*4;
  1266. State->SpWhen = Offset;
  1267. }
  1268. break;
  1269. case SPILL_BASE:
  1270. State->SpillBase = ReadLEB128(Desc, &UwContext->DescCount);
  1271. State->SpillPtr = State->SpillBase;
  1272. break;
  1273. case MEM_STACK_V:
  1274. case RP_WHEN:
  1275. case PFS_WHEN:
  1276. case PREDS_WHEN:
  1277. case LC_WHEN:
  1278. case UNAT_WHEN:
  1279. case FPSR_WHEN:
  1280. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1281. if ((State->IsTarget) &&
  1282. (UwContext->TargetSlot > (UwContext->SlotCount+Offset)))
  1283. {
  1284. Index = P7RecordTypeToRegisterIndex[RecType];
  1285. if (!(State->MiscMask & (1 << Index))) {
  1286. State->MiscMask |= MASK(Index,1);
  1287. UwContext->MiscRegs[Index].When = Offset;
  1288. } else {
  1289. UW_DEBUG(("Duplicate descriptors,"));
  1290. UW_DEBUG(("unwinder may produce incorrect result!\n"));
  1291. }
  1292. }
  1293. UW_DEBUG(("Prolog P7: type=%d slot= %d\n", RecType, Offset));
  1294. break;
  1295. case PSP_SPREL:
  1296. case RP_PSPREL:
  1297. case PFS_PSPREL:
  1298. case PREDS_PSPREL:
  1299. case LC_PSPREL:
  1300. case UNAT_PSPREL:
  1301. case FPSR_PSPREL:
  1302. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1303. break;
  1304. default:
  1305. UW_DEBUG(("Invalid record type for descriptor P7!\n"));
  1306. }
  1307. } else if ( (FirstByte & P8_MASK) == P8_PREFIX ) {
  1308. RecType = Desc[UwContext->DescCount++];
  1309. switch (RecType) {
  1310. case PSP_PSPREL:
  1311. case RP_SPREL:
  1312. case PFS_SPREL:
  1313. case PREDS_SPREL:
  1314. case LC_SPREL:
  1315. case UNAT_SPREL:
  1316. case FPSR_SPREL:
  1317. case BSP_PSPREL:
  1318. case BSP_SPREL:
  1319. case BSPSTORE_PSPREL:
  1320. case BSPSTORE_SPREL:
  1321. case RNAT_PSPREL:
  1322. case RNAT_SPREL:
  1323. case PRIUNAT_PSPREL:
  1324. case PRIUNAT_SPREL:
  1325. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1326. UW_DEBUG(("Prolog P8: type=%d slot= %d\n", RecType, Offset));
  1327. break;
  1328. case BSP_WHEN:
  1329. case BSPSTORE_WHEN:
  1330. case RNAT_WHEN:
  1331. case PRIUNAT_WHEN:
  1332. Offset = ReadLEB128(Desc, &UwContext->DescCount);
  1333. if ((State->IsTarget) &&
  1334. (UwContext->TargetSlot > (UwContext->SlotCount+Offset)))
  1335. {
  1336. Index = P7RecordTypeToRegisterIndex[RecType];
  1337. if (!(State->MiscMask & (1 << Index))) {
  1338. State->MiscMask |= MASK(Index,1);
  1339. UwContext->MiscRegs[Index].When = Offset;
  1340. } else {
  1341. UW_DEBUG(("Duplicate descriptors,"));
  1342. UW_DEBUG(("unwinder may produce incorrect result!\n"));
  1343. }
  1344. }
  1345. UW_DEBUG(("Prolog P8: type=%d slot= %d\n", RecType, Offset));
  1346. break;
  1347. default:
  1348. UW_DEBUG(("Invalid record type for descriptor P8!\n"));
  1349. }
  1350. } else if ( (FirstByte & P9_MASK) == P9_PREFIX ) {
  1351. UwContext->DescCount += 2;
  1352. VUW_DEBUG_PRINT("Format P9 not supported yet!\n");
  1353. } else if ( (FirstByte & P10_MASK) == P10_PREFIX ) {
  1354. UCHAR Abi = Desc[UwContext->DescCount++];
  1355. UCHAR Context = Desc[UwContext->DescCount++];
  1356. *AbiImmContext = Context;
  1357. if (Abi != NT_ABI) {
  1358. VUW_DEBUG_PRINT("Unknown ABI unwind descriptor\n");
  1359. }
  1360. } else {
  1361. //
  1362. // Encounter another region header record
  1363. //
  1364. break;
  1365. }
  1366. }
  1367. State->DescEnd = UwContext->DescCount - 2;
  1368. return FirstByte;
  1369. }
  1370. VOID
  1371. NewParsePrologueRegionPhase1 (
  1372. IN PUNWIND_CONTEXT UwContext,
  1373. IN PSTATE_RECORD State
  1374. )
  1375. {
  1376. ULONG FrameSize;
  1377. ULONG Offset;
  1378. ULONG GrSave;
  1379. ULONG BrBase;
  1380. ULONG Index;
  1381. ULONG Count;
  1382. UCHAR RecType;
  1383. UCHAR FirstByte, SecondByte; // 1st & 2nd bytes of a region header record
  1384. ULONG DescIndex;
  1385. ULONG ImaskBegin;
  1386. UCHAR NextBr, NextGr, NextFr;
  1387. USHORT MiscMask;
  1388. ULONG TempMask;
  1389. ULONG FrMask = 0;
  1390. UCHAR BrMask = 0;
  1391. UCHAR GrMask = 0;
  1392. PUCHAR Desc = UwContext->Descriptors;
  1393. BOOLEAN SpillMaskOmitted = TRUE;
  1394. DescIndex = State->DescBegin;
  1395. FirstByte = Desc[DescIndex];
  1396. if ((FirstByte & R2_MASK) == R2_PREFIX) {
  1397. //
  1398. // general prologue region header; need to process it first
  1399. //
  1400. ULONG GrSave, Count;
  1401. UCHAR MiscMask;
  1402. UCHAR SecondByte;
  1403. USHORT i;
  1404. DescIndex++;
  1405. SecondByte = Desc[DescIndex++];
  1406. MiscMask = ((FirstByte & 0x7) << 1) | ((SecondByte & 0x80) >> 7);
  1407. GrSave = SecondByte & 0x7F;
  1408. ReadLEB128(Desc, &DescIndex); // advance the descriptor index
  1409. if (GrSave < STATIC_REGISTER_SET_SIZE) {
  1410. UW_DEBUG(("Invalid unwind descriptor!\n"));
  1411. }
  1412. UW_DEBUG(("Region R2: rmask=%x,grsave=%d,length=%d\n",
  1413. MiscMask, GrSave, State->RegionLen));
  1414. Count = 0;
  1415. for (Index = REG_PREDS; Index <= REG_RP; Index++) {
  1416. if (MiscMask & 0x1) {
  1417. if (!(State->IsTarget) ||
  1418. (State->MiscMask & MASK(Index,1)))
  1419. {
  1420. UwContext->MiscRegs[Index].Where = GENERAL_REG;
  1421. UwContext->MiscRegs[Index].SaveOffset = GrSave+Count;
  1422. UwContext->MiscRegs[Index].When = 0;
  1423. State->MiscMask |= MASK(Index,1);
  1424. }
  1425. Count++;
  1426. }
  1427. MiscMask = MiscMask >> 1;
  1428. }
  1429. }
  1430. while (DescIndex <= State->DescEnd) {
  1431. FirstByte = Desc[DescIndex++];
  1432. if ( (FirstByte & P1_MASK) == P1_PREFIX) {
  1433. BrMask = FirstByte & ~P1_MASK;
  1434. State->MiscMask |= (BrMask << REG_BR_BASE);
  1435. UW_DEBUG(("Prolog P1: brmask=%x\n", BrMask));
  1436. for (Count = REG_BR_BASE;
  1437. Count < REG_BR_BASE+NUMBER_OF_PRESERVED_BR;
  1438. Count++)
  1439. {
  1440. if (BrMask & 0x1) {
  1441. UwContext->MiscRegs[Count].Where = PSP_RELATIVE;
  1442. UwContext->MiscRegs[Count].When = State->RegionLen;
  1443. }
  1444. BrMask = BrMask >> 1;
  1445. }
  1446. } else if ( (FirstByte & P2_MASK) == P2_PREFIX ) {
  1447. SecondByte = Desc[DescIndex++];
  1448. GrSave = SecondByte & 0x7F;
  1449. BrMask = ((FirstByte & ~P2_MASK) << 1) | ((SecondByte & 0x80) >> 7);
  1450. UW_DEBUG(("Prolog P2: brmask=%x reg base=%d\n", BrMask, GrSave));
  1451. State->MiscMask |= (BrMask << REG_BR_BASE);
  1452. for (Count = REG_BR_BASE;
  1453. Count < REG_BR_BASE+NUMBER_OF_PRESERVED_BR;
  1454. Count++)
  1455. {
  1456. if (BrMask & 0x1) {
  1457. UwContext->MiscRegs[Count].Where = GENERAL_REG;
  1458. UwContext->MiscRegs[Count].SaveOffset = GrSave++;
  1459. }
  1460. BrMask = BrMask >> 1;
  1461. }
  1462. } else if ( (FirstByte & P3_MASK) == P3_PREFIX ) {
  1463. SecondByte = Desc[DescIndex++];
  1464. RecType = ((SecondByte & 0x80) >> 7) | ((FirstByte & 0x7) << 1);
  1465. Index = P3RecordTypeToRegisterIndex[RecType];
  1466. if (RecType == RP_BR)
  1467. {
  1468. UwContext->AlternateRp = SecondByte & 0x7F;
  1469. }
  1470. else if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1471. {
  1472. UwContext->MiscRegs[Index].Where = GENERAL_REG;
  1473. UwContext->MiscRegs[Index].SaveOffset = SecondByte & 0x7F;
  1474. UwContext->MiscRegs[Index].When = 0;
  1475. State->MiscMask |= MASK(Index,1);
  1476. UW_DEBUG(("Prolog P3: type=%d reg=%d\n",
  1477. RecType, UwContext->MiscRegs[Index].SaveOffset));
  1478. }
  1479. } else if ( (FirstByte & P4_MASK) == P4_PREFIX ) {
  1480. SpillMaskOmitted = FALSE;
  1481. ImaskBegin = DescIndex;
  1482. DescIndex += ((State->RegionLen+3) >> 2);
  1483. } else if ( (FirstByte & P5_MASK) == P5_PREFIX ) {
  1484. GrMask = (Desc[DescIndex] & 0xF0) >> 4;
  1485. FrMask = ((ULONG)(Desc[DescIndex] & 0xF) << 16) |
  1486. ((ULONG)Desc[DescIndex+1] << 8) |
  1487. ((ULONG)Desc[DescIndex+2]);
  1488. DescIndex += 3; // increment the descriptor index
  1489. State->GrMask |= GrMask;
  1490. State->FrMask |= FrMask;
  1491. UW_DEBUG(("Prolog P5: grmask = %x, frmask = %x\n",
  1492. State->GrMask, State->FrMask));
  1493. } else if ( (FirstByte & P6_MASK) == P6_PREFIX ) {
  1494. if (FirstByte & 0x10) {
  1495. GrMask = FirstByte & 0xF;
  1496. State->GrMask |= GrMask;
  1497. } else {
  1498. FrMask = FirstByte & 0xF;
  1499. State->FrMask |= FrMask;
  1500. }
  1501. UW_DEBUG(("Prolog P6: is_gr = %d, mask = %x\n",
  1502. (FirstByte & 0x10) ? 1 : 0,
  1503. (FirstByte & 0x10) ? State->GrMask : State->FrMask));
  1504. } else if ( (FirstByte & P7_MASK) == P7_PREFIX ) {
  1505. RecType = FirstByte & ~P7_MASK;
  1506. switch (RecType) {
  1507. case PSP_SPREL:
  1508. //
  1509. // sp-relative location
  1510. //
  1511. Index = P7RecordTypeToRegisterIndex[RecType];
  1512. Offset = ReadLEB128(Desc, &DescIndex);
  1513. if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1514. {
  1515. UwContext->MiscRegs[Index].Where = SP_RELATIVE;
  1516. UwContext->MiscRegs[Index].SaveOffset = Offset;
  1517. if (!(State->MiscMask & MASK(Index,1))) {
  1518. UwContext->MiscRegs[Index].When = State->RegionLen;
  1519. State->MiscMask |= MASK(Index,1);
  1520. }
  1521. }
  1522. UW_DEBUG(("Prolog P7: type=%d spoff = %d\n", RecType, Offset));
  1523. break;
  1524. case RP_PSPREL:
  1525. case PFS_PSPREL:
  1526. case PREDS_PSPREL:
  1527. case LC_PSPREL:
  1528. case UNAT_PSPREL:
  1529. case FPSR_PSPREL:
  1530. //
  1531. // psp-relative location
  1532. //
  1533. Index = P7RecordTypeToRegisterIndex[RecType];
  1534. Offset = ReadLEB128(Desc, &DescIndex);
  1535. if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1536. {
  1537. UwContext->MiscRegs[Index].Where = PSP_RELATIVE;
  1538. UwContext->MiscRegs[Index].SaveOffset = Offset;
  1539. UwContext->MiscRegs[Index].When = 0;
  1540. State->MiscMask |= MASK(Index,1);
  1541. }
  1542. UW_DEBUG(("Prolog P7: type=%d pspoff= %d\n", RecType, Offset));
  1543. break;
  1544. case MEM_STACK_V:
  1545. case RP_WHEN:
  1546. case PFS_WHEN:
  1547. case PREDS_WHEN:
  1548. case LC_WHEN:
  1549. case UNAT_WHEN:
  1550. case FPSR_WHEN:
  1551. //
  1552. // Nevermind processing these descriptors because they
  1553. // have been taken care of in phase 0
  1554. //
  1555. Offset = ReadLEB128(Desc, &DescIndex);
  1556. break;
  1557. case MEM_STACK_F:
  1558. Offset = ReadLEB128(Desc, &DescIndex);
  1559. FrameSize = ReadLEB128(Desc, &DescIndex);
  1560. UW_DEBUG(("Prolog P7: type=%d Slot=%d FrameSize=%d\n",
  1561. RecType, Offset, FrameSize));
  1562. break;
  1563. case SPILL_BASE:
  1564. State->SpillBase = ReadLEB128(Desc, &DescIndex);
  1565. State->SpillPtr = State->SpillBase;
  1566. UW_DEBUG(("Prolog P7: type=%d, spillbase=%d\n",
  1567. RecType, State->SpillBase));
  1568. break;
  1569. default:
  1570. UW_DEBUG(("invalid unwind descriptors\n"));
  1571. }
  1572. } else if ( (FirstByte & P8_MASK) == P8_PREFIX ) {
  1573. RecType = Desc[DescIndex++];
  1574. switch (RecType) {
  1575. case PSP_PSPREL:
  1576. VUW_DEBUG_PRINT("Unsupported Unwind Descriptor!\n");
  1577. break;
  1578. case RP_SPREL:
  1579. case PFS_SPREL:
  1580. case PREDS_SPREL:
  1581. case LC_SPREL:
  1582. case UNAT_SPREL:
  1583. case FPSR_SPREL:
  1584. case BSP_SPREL:
  1585. case BSPSTORE_SPREL:
  1586. case RNAT_SPREL:
  1587. case PRIUNAT_SPREL:
  1588. //
  1589. // sp-relative location
  1590. //
  1591. Index = P8RecordTypeToRegisterIndex[RecType];
  1592. Offset = ReadLEB128(Desc, &DescIndex);
  1593. if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1594. {
  1595. UwContext->MiscRegs[Index].Where = SP_RELATIVE;
  1596. UwContext->MiscRegs[Index].SaveOffset = Offset;
  1597. if (!(State->MiscMask & MASK(Index,1))) {
  1598. UwContext->MiscRegs[Index].When=State->RegionLen;
  1599. State->MiscMask |= MASK(Index,1);
  1600. }
  1601. }
  1602. UW_DEBUG(("Prolog P8: type=%d spoff= %d\n", RecType, Offset));
  1603. break;
  1604. case BSP_PSPREL:
  1605. case BSPSTORE_PSPREL:
  1606. case RNAT_PSPREL:
  1607. case PRIUNAT_PSPREL:
  1608. //
  1609. // psp-relative location
  1610. //
  1611. Index = P8RecordTypeToRegisterIndex[RecType];
  1612. Offset = ReadLEB128(Desc, &DescIndex);
  1613. if (!(State->IsTarget) || (State->MiscMask & MASK(Index,1)))
  1614. {
  1615. UwContext->MiscRegs[Index].Where = PSP_RELATIVE;
  1616. UwContext->MiscRegs[Index].SaveOffset = Offset;
  1617. UwContext->MiscRegs[Index].When = 0;
  1618. State->MiscMask |= MASK(Index,1);
  1619. }
  1620. UW_DEBUG(("Prolog P8: type=%d pspoff= %d\n", RecType, Offset));
  1621. break;
  1622. case BSP_WHEN:
  1623. case BSPSTORE_WHEN:
  1624. case RNAT_WHEN:
  1625. case PRIUNAT_WHEN:
  1626. //
  1627. // Nevermind processing these descriptors because they
  1628. // have been taken care of in phase 0
  1629. //
  1630. Offset = ReadLEB128(Desc, &DescIndex);
  1631. break;
  1632. default:
  1633. UW_DEBUG(("Invalid record type for descriptor P8!\n"));
  1634. }
  1635. } else if ( (FirstByte & P9_MASK) == P9_PREFIX ) {
  1636. DescIndex += 2;
  1637. VUW_DEBUG_PRINT("Format P9 not supported yet!\n");
  1638. } else if ( (FirstByte & P10_MASK) == P10_PREFIX ) {
  1639. UCHAR Abi = Desc[DescIndex++];
  1640. UCHAR Context = Desc[DescIndex++];
  1641. } else {
  1642. UW_DEBUG(("Invalid descriptor!\n"));
  1643. }
  1644. }
  1645. GrMask = State->GrMask;
  1646. FrMask = State->FrMask;
  1647. BrMask = State->MiscMask >> REG_BR_BASE;
  1648. if (!(GrMask | FrMask | BrMask)) {
  1649. return;
  1650. } else if (SpillMaskOmitted && !(State->IsTarget)) {
  1651. //
  1652. // When spillmask is omitted, floating point registers, general
  1653. // registers, and then branch regisers are spilled in order.
  1654. // They are not modified in the prologue region; therefore, there
  1655. // is no need to restore their contents when the control ip is
  1656. // in this prologue region.
  1657. //
  1658. // 1. floating point registers
  1659. State->SpillPtr &= ~(SPILLSIZE_OF_FLOAT128_IN_DWORDS - 1);
  1660. NextFr = NUMBER_OF_PRESERVED_FR - 1;
  1661. while (FrMask & 0xFFFFF) {
  1662. if (FrMask & 0x80000) {
  1663. State->SpillPtr += SPILLSIZE_OF_FLOAT128_IN_DWORDS;
  1664. UwContext->Float[NextFr].SaveOffset = State->SpillPtr;
  1665. }
  1666. FrMask = FrMask << 1;
  1667. NextFr--;
  1668. }
  1669. // 2. branch registers
  1670. NextBr = REG_BR_BASE + NUMBER_OF_PRESERVED_BR - 1;
  1671. while (BrMask & 0x1F) {
  1672. if (BrMask & 0x10) {
  1673. if (UwContext->MiscRegs[NextBr].Where == PSP_RELATIVE) {
  1674. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1675. UwContext->MiscRegs[NextBr].SaveOffset = State->SpillPtr;
  1676. }
  1677. }
  1678. BrMask = BrMask << 1;
  1679. NextBr--;
  1680. }
  1681. // 3. general registers
  1682. NextGr = NUMBER_OF_PRESERVED_GR - 1;
  1683. while (GrMask & 0xF) {
  1684. if (GrMask & 0x8) {
  1685. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1686. UwContext->Integer[NextGr].SaveOffset = State->SpillPtr;
  1687. }
  1688. GrMask = GrMask << 1;
  1689. NextGr--;
  1690. }
  1691. } else if (SpillMaskOmitted && State->IsTarget) {
  1692. State->GrMask = 0;
  1693. State->FrMask = 0;
  1694. State->MiscMask &= MASK(REG_BR_BASE, 1) - 1;
  1695. } else if (SpillMaskOmitted == FALSE) {
  1696. ULONG Length;
  1697. if (State->IsTarget) {
  1698. //
  1699. // control ip is in the prologue region; clear the masks
  1700. // and then process the imask to determine which preserved
  1701. // Gr/Fr/Br have been saved and set the corresponding bits.
  1702. //
  1703. State->GrMask = 0;
  1704. State->FrMask = 0;
  1705. State->MiscMask &= MASK(REG_BR_BASE, 1) - 1;
  1706. Length = UwContext->TargetSlot - State->RegionBegin;
  1707. } else {
  1708. Length = State->RegionLen;
  1709. }
  1710. NextGr = NUMBER_OF_PRESERVED_GR - 1;
  1711. NextBr = NUMBER_OF_PRESERVED_BR - 1;
  1712. NextFr = NUMBER_OF_PRESERVED_FR - 1;
  1713. for (Count = 0; Count < Length; Count++) {
  1714. if ((Count % 4) == 0) {
  1715. FirstByte = Desc[ImaskBegin++];
  1716. } else {
  1717. FirstByte = FirstByte << 2;
  1718. }
  1719. switch (FirstByte & 0xC0) {
  1720. case 0x40: // 0x01 - save next fr
  1721. while ( !(FrMask & 0x80000) && (NextFr > 0) ) {
  1722. NextFr--;
  1723. FrMask = FrMask << 1;
  1724. }
  1725. UW_DEBUG(("spilled register FS%lx\n", (ULONG)NextFr));
  1726. State->FrMask |= MASK(NextFr,1);
  1727. UwContext->Float[NextFr].When = Count;
  1728. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1729. State->SpillPtr &= ~(SPILLSIZE_OF_FLOAT128_IN_DWORDS - 1);
  1730. State->SpillPtr += SPILLSIZE_OF_FLOAT128_IN_DWORDS;
  1731. UwContext->Float[NextFr].SaveOffset = State->SpillPtr;
  1732. NextFr--;
  1733. FrMask = FrMask << 1;
  1734. break;
  1735. case 0x80: // 0x10 - save next gr
  1736. while ( !(GrMask & 0x8) && (NextGr > 0) ) {
  1737. NextGr--;
  1738. GrMask = GrMask << 1;
  1739. }
  1740. UW_DEBUG(("spilled register S%lx\n", (ULONG)NextGr));
  1741. State->GrMask |= MASK(NextGr,1);
  1742. UwContext->Integer[NextGr].When = Count;
  1743. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1744. UwContext->Integer[NextGr].SaveOffset = State->SpillPtr;
  1745. NextGr--;
  1746. GrMask = GrMask << 1;
  1747. break;
  1748. case 0xC0: // 0x11 - save next br
  1749. while ( !(BrMask & 0x10) && (NextBr > 0) ) {
  1750. NextBr--;
  1751. BrMask = BrMask << 1;
  1752. }
  1753. UW_DEBUG(("spilled register BS%lx\n", (ULONG)NextBr));
  1754. Index = REG_BR_BASE + NextBr;
  1755. State->MiscMask |= MASK(Index,1);
  1756. UwContext->MiscRegs[Index].When = Count;
  1757. if (UwContext->MiscRegs[Index].Where == PSP_RELATIVE) {
  1758. State->SpillPtr += SPILLSIZE_OF_ULONGLONG_IN_DWORDS;
  1759. UwContext->MiscRegs[Index].SaveOffset = State->SpillPtr;
  1760. }
  1761. NextBr--;
  1762. BrMask = BrMask << 1;
  1763. break;
  1764. default: // 0x00 - save no register
  1765. break;
  1766. }
  1767. }
  1768. }
  1769. }