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.

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