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.

1444 lines
47 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. walkamd64.c
  5. Abstract:
  6. This file implements the AMD64 stack walking api.
  7. Author:
  8. Environment:
  9. User Mode
  10. --*/
  11. #define _IMAGEHLP_SOURCE_
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include "private.h"
  16. #define NOEXTAPI
  17. #include "wdbgexts.h"
  18. #include "ntdbg.h"
  19. #include "symbols.h"
  20. #include <stdlib.h>
  21. #include <globals.h>
  22. #define WDB(Args) SdbOut Args
  23. //
  24. // Lookup table providing the number of slots used by each unwind code.
  25. //
  26. UCHAR RtlpUnwindOpSlotTableAmd64[] = {
  27. 1, // UWOP_PUSH_NONVOL
  28. 2, // UWOP_ALLOC_LARGE (or 3, special cased in lookup code)
  29. 1, // UWOP_ALLOC_SMALL
  30. 1, // UWOP_SET_FPREG
  31. 2, // UWOP_SAVE_NONVOL
  32. 3, // UWOP_SAVE_NONVOL_FAR
  33. 2, // UWOP_SAVE_XMM
  34. 3, // UWOP_SAVE_XMM_FAR
  35. 2, // UWOP_SAVE_XMM128
  36. 3, // UWOP_SAVE_XMM128_FAR
  37. 1 // UWOP_PUSH_MACHFRAME
  38. };
  39. BOOL
  40. WalkAmd64Init(
  41. HANDLE Process,
  42. LPSTACKFRAME64 StackFrame,
  43. PAMD64_CONTEXT Context,
  44. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
  45. PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
  46. PGET_MODULE_BASE_ROUTINE64 GetModuleBase
  47. );
  48. BOOL
  49. WalkAmd64Next(
  50. HANDLE Process,
  51. LPSTACKFRAME64 StackFrame,
  52. PAMD64_CONTEXT Context,
  53. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
  54. PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
  55. PGET_MODULE_BASE_ROUTINE64 GetModuleBase
  56. );
  57. BOOL
  58. UnwindStackFrameAmd64(
  59. HANDLE Process,
  60. PULONG64 ReturnAddress,
  61. PULONG64 StackPointer,
  62. PULONG64 FramePointer,
  63. PAMD64_CONTEXT Context,
  64. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  65. PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccess,
  66. PGET_MODULE_BASE_ROUTINE64 GetModuleBase
  67. );
  68. PAMD64_UNWIND_INFO
  69. ReadUnwindInfoAmd64(ULONG64 ImageBase, ULONG Offset,
  70. BOOL ReadCodes, HANDLE Process,
  71. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  72. PVOID StaticBuffer, ULONG StaticBufferSize)
  73. {
  74. ULONG Done;
  75. ULONG UnwindInfoSize;
  76. PAMD64_UNWIND_INFO UnwindInfo;
  77. PVOID SymInfo = NULL;
  78. ULONG SymInfoSize;
  79. ULONG64 MemOffset = ImageBase + Offset;
  80. // Static buffer should at least be large enough to read the
  81. // basic structure.
  82. if (StaticBufferSize < sizeof(*UnwindInfo)) {
  83. return NULL;
  84. }
  85. UnwindInfo = (PAMD64_UNWIND_INFO)StaticBuffer;
  86. // First read just the basic structure since the information
  87. // is needed to compute the complete size.
  88. if (!ReadMemory(Process, MemOffset,
  89. UnwindInfo, sizeof(*UnwindInfo), &Done) ||
  90. Done != sizeof(*UnwindInfo)) {
  91. WDB((1, "Unable to read unwind info at %I64X\n", MemOffset));
  92. SymInfo = GetUnwindInfoFromSymbols(Process, ImageBase, Offset,
  93. &SymInfoSize);
  94. if (!SymInfo || SymInfoSize < sizeof(*UnwindInfo)) {
  95. WDB((1, "Unable to get symbol unwind info at %I64X:%X\n",
  96. ImageBase, Offset));
  97. return NULL;
  98. }
  99. memcpy(UnwindInfo, SymInfo, sizeof(*UnwindInfo));
  100. }
  101. if (!ReadCodes) {
  102. return UnwindInfo;
  103. }
  104. // Compute the size of all the data.
  105. UnwindInfoSize = sizeof(*UnwindInfo) +
  106. (UnwindInfo->CountOfCodes - 1) * sizeof(AMD64_UNWIND_CODE);
  107. // An extra alignment code and pointer may be added on to handle
  108. // the chained info case where the chain pointer is just
  109. // beyond the end of the normal code array.
  110. if ((UnwindInfo->Flags & AMD64_UNW_FLAG_CHAININFO) != 0) {
  111. if ((UnwindInfo->CountOfCodes & 1) != 0) {
  112. UnwindInfoSize += sizeof(AMD64_UNWIND_CODE);
  113. }
  114. UnwindInfoSize += sizeof(ULONG64);
  115. }
  116. if (UnwindInfoSize > 0xffff) {
  117. // Too large to be valid data, assume it's garbage.
  118. WDB((1, "Invalid unwind info at %I64X\n", MemOffset));
  119. return NULL;
  120. }
  121. if (SymInfo && UnwindInfoSize > SymInfoSize) {
  122. WDB((1, "Insufficient unwind info in symbols for %I64X:%X\n",
  123. ImageBase, Offset));
  124. return NULL;
  125. }
  126. if (UnwindInfoSize > StaticBufferSize) {
  127. UnwindInfo = (PAMD64_UNWIND_INFO)MemAlloc(UnwindInfoSize);
  128. if (UnwindInfo == NULL) {
  129. WDB((1, "Unable to allocate memory for unwind info\n"));
  130. return NULL;
  131. }
  132. }
  133. // Now read all the data.
  134. if (SymInfo) {
  135. memcpy(UnwindInfo, SymInfo, UnwindInfoSize);
  136. } else if (!ReadMemory(Process, MemOffset, UnwindInfo, UnwindInfoSize,
  137. &Done) ||
  138. Done != UnwindInfoSize) {
  139. if ((PVOID)UnwindInfo != StaticBuffer) {
  140. MemFree(UnwindInfo);
  141. }
  142. WDB((1, "Unable to read unwind info at %I64X\n", MemOffset));
  143. return NULL;
  144. }
  145. return UnwindInfo;
  146. }
  147. //
  148. // ****** temp - defin elsewhere ******
  149. //
  150. #define SIZE64_PREFIX 0x48
  151. #define ADD_IMM8_OP 0x83
  152. #define ADD_IMM32_OP 0x81
  153. #define JMP_IMM8_OP 0xeb
  154. #define JMP_IMM32_OP 0xe9
  155. #define LEA_OP 0x8d
  156. #define POP_OP 0x58
  157. #define RET_OP 0xc3
  158. BOOLEAN
  159. RtlpUnwindPrologueAmd64 (
  160. IN ULONG64 ImageBase,
  161. IN ULONG64 ControlPc,
  162. IN ULONG64 FrameBase,
  163. IN _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry,
  164. IN OUT PAMD64_CONTEXT ContextRecord,
  165. IN HANDLE Process,
  166. IN PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory
  167. )
  168. /*++
  169. Routine Description:
  170. This function processes unwind codes and reverses the state change
  171. effects of a prologue. If the specified unwind information contains
  172. chained unwind information, then that prologue is unwound recursively.
  173. As the prologue is unwound state changes are recorded in the specified
  174. context structure and optionally in the specified context pointers
  175. structures.
  176. Arguments:
  177. ImageBase - Supplies the base address of the image that contains the
  178. function being unwound.
  179. ControlPc - Supplies the address where control left the specified
  180. function.
  181. FrameBase - Supplies the base of the stack frame subject function stack
  182. frame.
  183. FunctionEntry - Supplies the address of the function table entry for the
  184. specified function.
  185. ContextRecord - Supplies the address of a context record.
  186. --*/
  187. {
  188. ULONG64 FloatingAddress;
  189. PAMD64_M128 FloatingRegister;
  190. ULONG FrameOffset;
  191. ULONG Index;
  192. ULONG64 IntegerAddress;
  193. PULONG64 IntegerRegister;
  194. BOOLEAN MachineFrame;
  195. ULONG OpInfo;
  196. ULONG PrologOffset;
  197. PULONG64 RegisterAddress;
  198. ULONG64 ReturnAddress;
  199. ULONG64 StackAddress;
  200. PAMD64_UNWIND_CODE UnwindCode;
  201. ULONG64 UnwindInfoBuffer[32];
  202. PAMD64_UNWIND_INFO UnwindInfo;
  203. ULONG Done;
  204. ULONG UnwindOp;
  205. //
  206. // Process the unwind codes.
  207. //
  208. FloatingRegister = &ContextRecord->Xmm0;
  209. IntegerRegister = &ContextRecord->Rax;
  210. Index = 0;
  211. MachineFrame = FALSE;
  212. PrologOffset = (ULONG)(ControlPc - (FunctionEntry->BeginAddress + ImageBase));
  213. WDB((1, "Prol: RIP %I64X, 0x%X bytes in function at %I64X\n",
  214. ControlPc, PrologOffset, FunctionEntry->BeginAddress + ImageBase));
  215. WDB((1, "Prol: Read unwind info at %I64X\n",
  216. FunctionEntry->UnwindInfoAddress + ImageBase));
  217. UnwindInfo =
  218. ReadUnwindInfoAmd64(ImageBase, FunctionEntry->UnwindInfoAddress,
  219. TRUE, Process, ReadMemory, UnwindInfoBuffer,
  220. sizeof(UnwindInfoBuffer));
  221. if (UnwindInfo == NULL) {
  222. WDB((1, "Prol: Unable to read unwind info\n"));
  223. return FALSE;
  224. }
  225. WDB((1, " Unwind info has 0x%X codes\n", UnwindInfo->CountOfCodes));
  226. while (Index < UnwindInfo->CountOfCodes) {
  227. WDB((1, " %02X: Code %X offs %03X, RSP %I64X\n",
  228. Index, UnwindInfo->UnwindCode[Index].UnwindOp,
  229. UnwindInfo->UnwindCode[Index].CodeOffset,
  230. ContextRecord->Rsp));
  231. //
  232. // If the prologue offset is greater than the next unwind code offset,
  233. // then simulate the effect of the unwind code.
  234. //
  235. UnwindOp = UnwindInfo->UnwindCode[Index].UnwindOp;
  236. OpInfo = UnwindInfo->UnwindCode[Index].OpInfo;
  237. if (PrologOffset >= UnwindInfo->UnwindCode[Index].CodeOffset) {
  238. switch (UnwindOp) {
  239. //
  240. // Push nonvolatile integer register.
  241. //
  242. // The operation information is the register number of the
  243. // register than was pushed.
  244. //
  245. case AMD64_UWOP_PUSH_NONVOL:
  246. IntegerAddress = ContextRecord->Rsp;
  247. if (!ReadMemory(Process, IntegerAddress,
  248. &IntegerRegister[OpInfo], sizeof(ULONG64),
  249. &Done) ||
  250. Done != sizeof(ULONG64)) {
  251. goto Fail;
  252. }
  253. ContextRecord->Rsp += 8;
  254. break;
  255. //
  256. // Allocate a large sized area on the stack.
  257. //
  258. // The operation information determines if the size is
  259. // 16- or 32-bits.
  260. //
  261. case AMD64_UWOP_ALLOC_LARGE:
  262. Index += 1;
  263. FrameOffset = UnwindInfo->UnwindCode[Index].FrameOffset;
  264. if (OpInfo != 0) {
  265. Index += 1;
  266. FrameOffset += (UnwindInfo->UnwindCode[Index].FrameOffset << 16);
  267. } else {
  268. // The 16-bit form is scaled.
  269. FrameOffset *= 8;
  270. }
  271. ContextRecord->Rsp += FrameOffset;
  272. break;
  273. //
  274. // Allocate a small sized area on the stack.
  275. //
  276. // The operation information is the size of the unscaled
  277. // allocation size (8 is the scale factor) minus 8.
  278. //
  279. case AMD64_UWOP_ALLOC_SMALL:
  280. ContextRecord->Rsp += (OpInfo * 8) + 8;
  281. break;
  282. //
  283. // Establish the the frame pointer register.
  284. //
  285. // The operation information is not used.
  286. //
  287. case AMD64_UWOP_SET_FPREG:
  288. ContextRecord->Rsp = IntegerRegister[UnwindInfo->FrameRegister];
  289. ContextRecord->Rsp -= UnwindInfo->FrameOffset * 16;
  290. break;
  291. //
  292. // Save nonvolatile integer register on the stack using a
  293. // 16-bit displacment.
  294. //
  295. // The operation information is the register number.
  296. //
  297. case AMD64_UWOP_SAVE_NONVOL:
  298. Index += 1;
  299. FrameOffset = UnwindInfo->UnwindCode[Index].FrameOffset * 8;
  300. IntegerAddress = FrameBase + FrameOffset;
  301. if (!ReadMemory(Process, IntegerAddress,
  302. &IntegerRegister[OpInfo], sizeof(ULONG64),
  303. &Done) ||
  304. Done != sizeof(ULONG64)) {
  305. goto Fail;
  306. }
  307. break;
  308. //
  309. // Save nonvolatile integer register on the stack using a
  310. // 32-bit displacment.
  311. //
  312. // The operation information is the register number.
  313. //
  314. case AMD64_UWOP_SAVE_NONVOL_FAR:
  315. Index += 2;
  316. FrameOffset = UnwindInfo->UnwindCode[Index - 1].FrameOffset;
  317. FrameOffset += (UnwindInfo->UnwindCode[Index].FrameOffset << 16);
  318. IntegerAddress = FrameBase + FrameOffset;
  319. if (!ReadMemory(Process, IntegerAddress,
  320. &IntegerRegister[OpInfo], sizeof(ULONG64),
  321. &Done) ||
  322. Done != sizeof(ULONG64)) {
  323. goto Fail;
  324. }
  325. break;
  326. //
  327. // Save a nonvolatile XMM(64) register on the stack using a
  328. // 16-bit displacement.
  329. //
  330. // The operation information is the register number.
  331. //
  332. case AMD64_UWOP_SAVE_XMM:
  333. Index += 1;
  334. FrameOffset = UnwindInfo->UnwindCode[Index].FrameOffset * 8;
  335. FloatingAddress = FrameBase + FrameOffset;
  336. FloatingRegister[OpInfo].High = 0;
  337. if (!ReadMemory(Process, FloatingAddress,
  338. &FloatingRegister[OpInfo].Low, sizeof(ULONG64),
  339. &Done) ||
  340. Done != sizeof(ULONG64)) {
  341. goto Fail;
  342. }
  343. break;
  344. //
  345. // Save a nonvolatile XMM(64) register on the stack using a
  346. // 32-bit displacement.
  347. //
  348. // The operation information is the register number.
  349. //
  350. case AMD64_UWOP_SAVE_XMM_FAR:
  351. Index += 2;
  352. FrameOffset = UnwindInfo->UnwindCode[Index - 1].FrameOffset;
  353. FrameOffset += (UnwindInfo->UnwindCode[Index].FrameOffset << 16);
  354. FloatingAddress = FrameBase + FrameOffset;
  355. FloatingRegister[OpInfo].High = 0;
  356. if (!ReadMemory(Process, FloatingAddress,
  357. &FloatingRegister[OpInfo].Low, sizeof(ULONG64),
  358. &Done) ||
  359. Done != sizeof(ULONG64)) {
  360. goto Fail;
  361. }
  362. break;
  363. //
  364. // Save a nonvolatile XMM(128) register on the stack using a
  365. // 16-bit displacement.
  366. //
  367. // The operation information is the register number.
  368. //
  369. case AMD64_UWOP_SAVE_XMM128:
  370. Index += 1;
  371. FrameOffset = UnwindInfo->UnwindCode[Index].FrameOffset * 16;
  372. FloatingAddress = FrameBase + FrameOffset;
  373. if (!ReadMemory(Process, FloatingAddress,
  374. &FloatingRegister[OpInfo], sizeof(AMD64_M128),
  375. &Done) ||
  376. Done != sizeof(AMD64_M128)) {
  377. goto Fail;
  378. }
  379. break;
  380. //
  381. // Save a nonvolatile XMM(128) register on the stack using a
  382. // 32-bit displacement.
  383. //
  384. // The operation information is the register number.
  385. //
  386. case AMD64_UWOP_SAVE_XMM128_FAR:
  387. Index += 2;
  388. FrameOffset = UnwindInfo->UnwindCode[Index - 1].FrameOffset;
  389. FrameOffset += (UnwindInfo->UnwindCode[Index].FrameOffset << 16);
  390. FloatingAddress = FrameBase + FrameOffset;
  391. if (!ReadMemory(Process, FloatingAddress,
  392. &FloatingRegister[OpInfo], sizeof(AMD64_M128),
  393. &Done) ||
  394. Done != sizeof(AMD64_M128)) {
  395. goto Fail;
  396. }
  397. break;
  398. //
  399. // Push a machine frame on the stack.
  400. //
  401. // The operation information determines whether the machine
  402. // frame contains an error code or not.
  403. //
  404. case AMD64_UWOP_PUSH_MACHFRAME:
  405. MachineFrame = TRUE;
  406. ReturnAddress = ContextRecord->Rsp;
  407. StackAddress = ContextRecord->Rsp + (3 * 8);
  408. if (OpInfo != 0) {
  409. ReturnAddress += 8;
  410. StackAddress += 8;
  411. }
  412. if (!ReadMemory(Process, ReturnAddress,
  413. &ContextRecord->Rip, sizeof(ULONG64),
  414. &Done) ||
  415. Done != sizeof(ULONG64)) {
  416. goto Fail;
  417. }
  418. if (!ReadMemory(Process, StackAddress,
  419. &ContextRecord->Rsp, sizeof(ULONG64),
  420. &Done) ||
  421. Done != sizeof(ULONG64)) {
  422. goto Fail;
  423. }
  424. break;
  425. //
  426. // Unused codes.
  427. //
  428. default:
  429. break;
  430. }
  431. Index += 1;
  432. } else {
  433. //
  434. // Skip this unwind operation by advancing the slot index by the
  435. // number of slots consumed by this operation.
  436. //
  437. Index += RtlpUnwindOpSlotTableAmd64[UnwindOp];
  438. //
  439. // Special case any unwind operations that can consume a variable
  440. // number of slots.
  441. //
  442. switch (UnwindOp) {
  443. //
  444. // A non-zero operation information indicates that an
  445. // additional slot is consumed.
  446. //
  447. case AMD64_UWOP_ALLOC_LARGE:
  448. if (OpInfo != 0) {
  449. Index += 1;
  450. }
  451. break;
  452. //
  453. // No other special cases.
  454. //
  455. default:
  456. break;
  457. }
  458. }
  459. }
  460. //
  461. // If chained unwind information is specified, then recursively unwind
  462. // the chained information. Otherwise, determine the return address if
  463. // a machine frame was not encountered during the scan of the unwind
  464. // codes.
  465. //
  466. if ((UnwindInfo->Flags & AMD64_UNW_FLAG_CHAININFO) != 0) {
  467. Index = UnwindInfo->CountOfCodes;
  468. if ((Index & 1) != 0) {
  469. Index += 1;
  470. }
  471. ULONG64 ChainEntryAddr =
  472. *(PULONG64)(&UnwindInfo->UnwindCode[Index]) + ImageBase;
  473. if (UnwindInfo != (PAMD64_UNWIND_INFO)UnwindInfoBuffer) {
  474. MemFree(UnwindInfo);
  475. }
  476. _IMAGE_RUNTIME_FUNCTION_ENTRY ChainEntry;
  477. WDB((1, " Chain to entry at %I64X\n", ChainEntryAddr));
  478. if (!ReadMemory(Process, ChainEntryAddr,
  479. &ChainEntry, sizeof(ChainEntry), &Done) ||
  480. Done != sizeof(ChainEntry)) {
  481. WDB((1, " Unable to read entry\n"));
  482. return FALSE;
  483. }
  484. return RtlpUnwindPrologueAmd64(ImageBase,
  485. ControlPc,
  486. FrameBase,
  487. &ChainEntry,
  488. ContextRecord,
  489. Process,
  490. ReadMemory);
  491. } else {
  492. if (UnwindInfo != (PAMD64_UNWIND_INFO)UnwindInfoBuffer) {
  493. MemFree(UnwindInfo);
  494. }
  495. if (MachineFrame == FALSE) {
  496. if (!ReadMemory(Process, ContextRecord->Rsp,
  497. &ContextRecord->Rip, sizeof(ULONG64),
  498. &Done) ||
  499. Done != sizeof(ULONG64)) {
  500. return FALSE;
  501. }
  502. ContextRecord->Rsp += 8;
  503. }
  504. WDB((1, "Prol: Returning with RIP %I64X, RSP %I64X\n",
  505. ContextRecord->Rip, ContextRecord->Rsp));
  506. return TRUE;
  507. }
  508. Fail:
  509. if (UnwindInfo != (PAMD64_UNWIND_INFO)UnwindInfoBuffer) {
  510. MemFree(UnwindInfo);
  511. }
  512. WDB((1, "Prol: Unwind failed\n"));
  513. return FALSE;
  514. }
  515. BOOLEAN
  516. RtlVirtualUnwindAmd64 (
  517. IN ULONG64 ImageBase,
  518. IN ULONG64 ControlPc,
  519. IN _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry,
  520. IN OUT PAMD64_CONTEXT ContextRecord,
  521. OUT PULONG64 EstablisherFrame,
  522. IN HANDLE Process,
  523. IN PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory
  524. )
  525. /*++
  526. Routine Description:
  527. This function virtually unwinds the specified function by executing its
  528. prologue code backward or its epilogue code forward.
  529. If a context pointers record is specified, then the address where each
  530. nonvolatile registers is restored from is recorded in the appropriate
  531. element of the context pointers record.
  532. Arguments:
  533. ImageBase - Supplies the base address of the image that contains the
  534. function being unwound.
  535. ControlPc - Supplies the address where control left the specified
  536. function.
  537. FunctionEntry - Supplies the address of the function table entry for the
  538. specified function.
  539. ContextRecord - Supplies the address of a context record.
  540. EstablisherFrame - Supplies a pointer to a variable that receives the
  541. the establisher frame pointer value.
  542. --*/
  543. {
  544. ULONG64 BranchTarget;
  545. LONG Displacement;
  546. ULONG FrameRegister;
  547. ULONG Index;
  548. LOGICAL InEpilogue;
  549. PULONG64 IntegerRegister;
  550. PUCHAR NextByte;
  551. ULONG PrologOffset;
  552. ULONG RegisterNumber;
  553. PAMD64_UNWIND_INFO UnwindInfo;
  554. ULONG64 UnwindInfoBuffer[8];
  555. ULONG Done;
  556. UCHAR InstrBuffer[32];
  557. ULONG InstrBytes;
  558. ULONG Bytes;
  559. ULONG UnwindFrameReg;
  560. //
  561. // If the specified function does not use a frame pointer, then the
  562. // establisher frame is the contents of the stack pointer. This may
  563. // not actually be the real establisher frame if control left the
  564. // function from within the prologue. In this case the establisher
  565. // frame may be not required since control has not actually entered
  566. // the function and prologue entries cannot refer to the establisher
  567. // frame before it has been established, i.e., if it has not been
  568. // established, then no save unwind codes should be encountered during
  569. // the unwind operation.
  570. //
  571. // If the specified function uses a frame pointer and control left the
  572. // function outside of the prologue or the unwind information contains
  573. // a chained information structure, then the establisher frame is the
  574. // contents of the frame pointer.
  575. //
  576. // If the specified function uses a frame pointer and control left the
  577. // function from within the prologue, then the set frame pointer unwind
  578. // code must be looked up in the unwind codes to detetermine if the
  579. // contents of the stack pointer or the contents of the frame pointer
  580. // should be used for the establisher frame. This may not atually be
  581. // the real establisher frame. In this case the establisher frame may
  582. // not be required since control has not actually entered the function
  583. // and prologue entries cannot refer to the establisher frame before it
  584. // has been established, i.e., if it has not been established, then no
  585. // save unwind codes should be encountered during the unwind operation.
  586. //
  587. // N.B. The correctness of these assumptions is based on the ordering of
  588. // unwind codes.
  589. //
  590. UnwindInfo =
  591. ReadUnwindInfoAmd64(ImageBase, FunctionEntry->UnwindInfoAddress,
  592. FALSE, Process, ReadMemory, UnwindInfoBuffer,
  593. sizeof(UnwindInfoBuffer));
  594. if (UnwindInfo == NULL) {
  595. return FALSE;
  596. }
  597. PrologOffset = (ULONG)(ControlPc - (FunctionEntry->BeginAddress + ImageBase));
  598. UnwindFrameReg = UnwindInfo->FrameRegister;
  599. if (UnwindFrameReg == 0) {
  600. *EstablisherFrame = ContextRecord->Rsp;
  601. } else if ((PrologOffset >= UnwindInfo->SizeOfProlog) ||
  602. ((UnwindInfo->Flags & AMD64_UNW_FLAG_CHAININFO) != 0)) {
  603. *EstablisherFrame = (&ContextRecord->Rax)[UnwindFrameReg];
  604. *EstablisherFrame -= UnwindInfo->FrameOffset * 16;
  605. } else {
  606. // Read all the data.
  607. UnwindInfo = ReadUnwindInfoAmd64(ImageBase,
  608. FunctionEntry->UnwindInfoAddress,
  609. TRUE, Process, ReadMemory,
  610. UnwindInfoBuffer,
  611. sizeof(UnwindInfoBuffer));
  612. if (UnwindInfo == NULL) {
  613. return FALSE;
  614. }
  615. Index = 0;
  616. while (Index < UnwindInfo->CountOfCodes) {
  617. if (UnwindInfo->UnwindCode[Index].UnwindOp == AMD64_UWOP_SET_FPREG) {
  618. break;
  619. }
  620. Index += 1;
  621. }
  622. if (PrologOffset >= UnwindInfo->UnwindCode[Index].CodeOffset) {
  623. *EstablisherFrame = (&ContextRecord->Rax)[UnwindFrameReg];
  624. *EstablisherFrame -= UnwindInfo->FrameOffset * 16;
  625. } else {
  626. *EstablisherFrame = ContextRecord->Rsp;
  627. }
  628. if (UnwindInfo != (PAMD64_UNWIND_INFO)UnwindInfoBuffer) {
  629. MemFree(UnwindInfo);
  630. }
  631. }
  632. if (!ReadMemory(Process, ControlPc, InstrBuffer, sizeof(InstrBuffer),
  633. &InstrBytes)) {
  634. WDB((1, "Unable to read instruction stream at %I64X\n", ControlPc));
  635. return FALSE;
  636. }
  637. //
  638. // Check for epilogue.
  639. //
  640. // If the point at which control left the specified function is in an
  641. // epilogue, then emulate the execution of the epilogue forward and
  642. // return no exception handler.
  643. //
  644. IntegerRegister = &ContextRecord->Rax;
  645. NextByte = InstrBuffer;
  646. Bytes = InstrBytes;
  647. //
  648. // Check for one of:
  649. //
  650. // add rsp, imm8
  651. // or
  652. // add rsp, imm32
  653. // or
  654. // lea rsp, -disp8[fp]
  655. // or
  656. // lea rsp, -disp32[fp]
  657. //
  658. if (Bytes >= 4 &&
  659. (NextByte[0] == SIZE64_PREFIX) &&
  660. (NextByte[1] == ADD_IMM8_OP) &&
  661. (NextByte[2] == 0xc4)) {
  662. //
  663. // add rsp, imm8.
  664. //
  665. NextByte += 4;
  666. Bytes -= 4;
  667. } else if (Bytes >= 7 &&
  668. (NextByte[0] == SIZE64_PREFIX) &&
  669. (NextByte[1] == ADD_IMM32_OP) &&
  670. (NextByte[2] == 0xc4)) {
  671. //
  672. // add rsp, imm32.
  673. //
  674. NextByte += 7;
  675. Bytes -= 7;
  676. } else if (Bytes >= 4 &&
  677. ((NextByte[0] & 0xf8) == SIZE64_PREFIX) &&
  678. (NextByte[1] == LEA_OP)) {
  679. FrameRegister = ((NextByte[0] & 0x7) << 3) | (NextByte[2] & 0x7);
  680. if ((FrameRegister != 0) &&
  681. (FrameRegister == UnwindFrameReg)) {
  682. if ((NextByte[2] & 0xf8) == 0x60) {
  683. //
  684. // lea rsp, disp8[fp].
  685. //
  686. NextByte += 4;
  687. Bytes -= 4;
  688. } else if (Bytes >= 7 &&
  689. (NextByte[2] &0xf8) == 0xa0) {
  690. //
  691. // lea rsp, disp32[fp].
  692. //
  693. NextByte += 7;
  694. Bytes -= 7;
  695. }
  696. }
  697. }
  698. //
  699. // Check for any number of:
  700. //
  701. // pop nonvolatile-integer-register[0..15].
  702. //
  703. while (TRUE) {
  704. if (Bytes >= 1 &&
  705. (NextByte[0] & 0xf8) == POP_OP) {
  706. NextByte += 1;
  707. Bytes -= 1;
  708. } else if (Bytes >= 2 &&
  709. ((NextByte[0] & 0xf8) == SIZE64_PREFIX) &&
  710. ((NextByte[1] & 0xf8) == POP_OP)) {
  711. NextByte += 2;
  712. Bytes -= 2;
  713. } else {
  714. break;
  715. }
  716. }
  717. //
  718. // If the next instruction is a return, then control is currently in
  719. // an epilogue and execution of the epilogue should be emulated.
  720. // Otherwise, execution is not in an epilogue and the prologue should
  721. // be unwound.
  722. //
  723. InEpilogue = FALSE;
  724. if (Bytes >= 1 &&
  725. NextByte[0] == RET_OP) {
  726. //
  727. // A return is an unambiguous indication of an epilogue
  728. //
  729. InEpilogue = TRUE;
  730. } else if ((Bytes >= 2 && NextByte[0] == JMP_IMM8_OP) ||
  731. (Bytes >= 5 && NextByte[0] == JMP_IMM32_OP)) {
  732. //
  733. // An unconditional branch to a target that is equal to the start of
  734. // or outside of this routine is logically a call to another function.
  735. //
  736. BranchTarget = (ULONG64)(NextByte - InstrBuffer) + ControlPc - ImageBase;
  737. if (NextByte[0] == JMP_IMM8_OP) {
  738. BranchTarget += 2 + (CHAR)NextByte[1];
  739. } else {
  740. BranchTarget += 5 + *((LONG UNALIGNED *)&NextByte[1]);
  741. }
  742. //
  743. // Now determine whether the branch target refers to code within this
  744. // function. If not then it is an epilogue indicator.
  745. //
  746. if (BranchTarget <= FunctionEntry->BeginAddress ||
  747. BranchTarget > FunctionEntry->EndAddress) {
  748. InEpilogue = TRUE;
  749. }
  750. }
  751. if (InEpilogue != FALSE) {
  752. NextByte = InstrBuffer;
  753. Bytes = InstrBytes;
  754. //
  755. // Emulate one of (if any):
  756. //
  757. // add rsp, imm8
  758. // or
  759. // add rsp, imm32
  760. // or
  761. // lea rsp, disp8[frame-register]
  762. // or
  763. // lea rsp, disp32[frame-register]
  764. //
  765. if (Bytes >= 4 &&
  766. NextByte[1] == ADD_IMM8_OP) {
  767. //
  768. // add rsp, imm8.
  769. //
  770. ContextRecord->Rsp += (CHAR)NextByte[3];
  771. NextByte += 4;
  772. Bytes -= 4;
  773. } else if (Bytes >= 7 &&
  774. NextByte[1] == ADD_IMM32_OP) {
  775. //
  776. // add rsp, imm32.
  777. //
  778. Displacement = NextByte[3] | (NextByte[4] << 8);
  779. Displacement |= (NextByte[5] << 16) | (NextByte[6] << 24);
  780. ContextRecord->Rsp += Displacement;
  781. NextByte += 7;
  782. Bytes -= 7;
  783. } else if (Bytes >= 4 &&
  784. NextByte[1] == LEA_OP) {
  785. if ((NextByte[2] & 0xf8) == 0x60) {
  786. //
  787. // lea rsp, disp8[frame-register].
  788. //
  789. ContextRecord->Rsp = IntegerRegister[FrameRegister];
  790. ContextRecord->Rsp += (CHAR)NextByte[3];
  791. NextByte += 4;
  792. Bytes -= 4;
  793. } else if (Bytes >= 7 &&
  794. (NextByte[2] & 0xf8) == 0xa0) {
  795. //
  796. // lea rsp, disp32[frame-register].
  797. //
  798. Displacement = NextByte[3] | (NextByte[4] << 8);
  799. Displacement |= (NextByte[5] << 16) | (NextByte[6] << 24);
  800. ContextRecord->Rsp = IntegerRegister[FrameRegister];
  801. ContextRecord->Rsp += Displacement;
  802. NextByte += 7;
  803. Bytes -= 7;
  804. }
  805. }
  806. //
  807. // Emulate any number of (if any):
  808. //
  809. // pop nonvolatile-integer-register.
  810. //
  811. while (TRUE) {
  812. if (Bytes >= 1 &&
  813. (NextByte[0] & 0xf8) == POP_OP) {
  814. //
  815. // pop nonvolatile-integer-register[0..7]
  816. //
  817. RegisterNumber = NextByte[0] & 0x7;
  818. if (!ReadMemory(Process, ContextRecord->Rsp,
  819. &IntegerRegister[RegisterNumber],
  820. sizeof(ULONG64), &Done) ||
  821. Done != sizeof(ULONG64)) {
  822. WDB((1, "Unable to read stack at %I64X\n",
  823. ContextRecord->Rsp));
  824. return FALSE;
  825. }
  826. ContextRecord->Rsp += 8;
  827. NextByte += 1;
  828. Bytes -= 1;
  829. } else if (Bytes >= 2 &&
  830. (NextByte[0] & 0xf8) == SIZE64_PREFIX &&
  831. (NextByte[1] & 0xf8) == POP_OP) {
  832. //
  833. // pop nonvolatile-integer-register[8..15]
  834. //
  835. RegisterNumber = ((NextByte[0] & 1) << 3) | (NextByte[1] & 0x7);
  836. if (!ReadMemory(Process, ContextRecord->Rsp,
  837. &IntegerRegister[RegisterNumber],
  838. sizeof(ULONG64), &Done) ||
  839. Done != sizeof(ULONG64)) {
  840. WDB((1, "Unable to read stack at %I64X\n",
  841. ContextRecord->Rsp));
  842. return FALSE;
  843. }
  844. ContextRecord->Rsp += 8;
  845. NextByte += 2;
  846. Bytes -= 2;
  847. } else {
  848. break;
  849. }
  850. }
  851. //
  852. // Emulate return and return null exception handler.
  853. //
  854. // Note: this instruction might in fact be a jmp, however
  855. // we want to emulate a return regardless.
  856. //
  857. if (!ReadMemory(Process, ContextRecord->Rsp,
  858. &ContextRecord->Rip, sizeof(ULONG64),
  859. &Done) ||
  860. Done != sizeof(ULONG64)) {
  861. WDB((1, "Unable to read stack at %I64X\n",
  862. ContextRecord->Rsp));
  863. return FALSE;
  864. }
  865. ContextRecord->Rsp += 8;
  866. return TRUE;
  867. }
  868. //
  869. // Control left the specified function outside an epilogue. Unwind the
  870. // subject function and any chained unwind information.
  871. //
  872. return RtlpUnwindPrologueAmd64(ImageBase,
  873. ControlPc,
  874. *EstablisherFrame,
  875. FunctionEntry,
  876. ContextRecord,
  877. Process,
  878. ReadMemory);
  879. }
  880. BOOL
  881. WalkAmd64(
  882. HANDLE Process,
  883. LPSTACKFRAME64 StackFrame,
  884. PVOID ContextRecord,
  885. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  886. PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccess,
  887. PGET_MODULE_BASE_ROUTINE64 GetModuleBase
  888. )
  889. {
  890. BOOL rval;
  891. PAMD64_CONTEXT Context = (PAMD64_CONTEXT)ContextRecord;
  892. WDB((2, "WalkAmd64 in: PC %I64X, SP %I64X, FP %I64X, RA %I64X\n",
  893. StackFrame->AddrPC.Offset,
  894. StackFrame->AddrStack.Offset,
  895. StackFrame->AddrFrame.Offset,
  896. StackFrame->AddrReturn.Offset));
  897. if (StackFrame->Virtual) {
  898. rval = WalkAmd64Next( Process,
  899. StackFrame,
  900. Context,
  901. ReadMemory,
  902. FunctionTableAccess,
  903. GetModuleBase
  904. );
  905. } else {
  906. rval = WalkAmd64Init( Process,
  907. StackFrame,
  908. Context,
  909. ReadMemory,
  910. FunctionTableAccess,
  911. GetModuleBase
  912. );
  913. }
  914. WDB((2, "WalkAmd64 out: succ %d, PC %I64X, SP %I64X, FP %I64X, RA %I64X\n",
  915. rval,
  916. StackFrame->AddrPC.Offset,
  917. StackFrame->AddrStack.Offset,
  918. StackFrame->AddrFrame.Offset,
  919. StackFrame->AddrReturn.Offset));
  920. return rval;
  921. }
  922. BOOL
  923. UnwindStackFrameAmd64(
  924. IN HANDLE Process,
  925. IN OUT PULONG64 ReturnAddress,
  926. IN OUT PULONG64 StackPointer,
  927. IN OUT PULONG64 FramePointer,
  928. IN PAMD64_CONTEXT Context, // Context members could be modified.
  929. IN PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  930. IN PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccess,
  931. IN PGET_MODULE_BASE_ROUTINE64 GetModuleBase
  932. )
  933. {
  934. _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry;
  935. ULONG64 RetAddr;
  936. BOOL Succ = TRUE;
  937. FunctionEntry = (_PIMAGE_RUNTIME_FUNCTION_ENTRY)
  938. FunctionTableAccess( Process, *ReturnAddress );
  939. if (FunctionEntry != NULL) {
  940. ULONG64 ImageBase;
  941. // Initialized to quiet a PREfix warning.
  942. ULONG64 EstablisherFrame = 0;
  943. //
  944. // The return value coming out of mainCRTStartup is set by some
  945. // run-time routine to be 0; this serves to cause an error if someone
  946. // actually does a return from the mainCRTStartup frame.
  947. //
  948. ImageBase = GetModuleBase(Process, *ReturnAddress);
  949. if (!RtlVirtualUnwindAmd64(ImageBase, *ReturnAddress, FunctionEntry,
  950. Context, &EstablisherFrame,
  951. Process, ReadMemory) ||
  952. Context->Rip == 0 ||
  953. (Context->Rip == *ReturnAddress &&
  954. EstablisherFrame == *FramePointer)) {
  955. Succ = FALSE;
  956. }
  957. *ReturnAddress = Context->Rip;
  958. *StackPointer = Context->Rsp;
  959. // The frame pointer is an artificial value set
  960. // to a pointer below the return address. This
  961. // matches an RBP-chain style of frame while
  962. // also allowing easy access to the return
  963. // address and homed arguments above it.
  964. *FramePointer = Context->Rsp - 2 * sizeof(ULONG64);
  965. } else {
  966. ULONG Done;
  967. // If there's no function entry for a function
  968. // we assume that it's a leaf and that ESP points
  969. // directly to the return address. There's no
  970. // stored frame pointer so we actually need to
  971. // set a virtual frame pointer deeper in the stack
  972. // so that arguments can correctly be read at
  973. // two ULONG64's up from it.
  974. *FramePointer = Context->Rsp - 8;
  975. *StackPointer = Context->Rsp + 8;
  976. Succ = ReadMemory(Process, Context->Rsp,
  977. ReturnAddress, sizeof(*ReturnAddress), &Done) &&
  978. Done == sizeof(*ReturnAddress);
  979. // Update the context values to what they should be in
  980. // the caller.
  981. if (Succ) {
  982. Context->Rsp += 8;
  983. Context->Rip = *ReturnAddress;
  984. }
  985. }
  986. if (Succ) {
  987. ULONG64 CallOffset;
  988. _PIMAGE_RUNTIME_FUNCTION_ENTRY CallFunc;
  989. //
  990. // Calls of __declspec(noreturn) functions may not have any
  991. // code after them to return to since the compiler knows
  992. // that the function will not return. This can confuse
  993. // stack traces because the return address will lie outside
  994. // of the function's address range and FPO data will not
  995. // be looked up correctly. Check and see if the return
  996. // address falls outside of the calling function and, if so,
  997. // adjust the return address back by one byte. It'd be
  998. // better to adjust it back to the call itself so that
  999. // the return address points to valid code but
  1000. // backing up in X86 assembly is more or less impossible.
  1001. //
  1002. CallOffset = *ReturnAddress - 1;
  1003. CallFunc = (_PIMAGE_RUNTIME_FUNCTION_ENTRY)
  1004. FunctionTableAccess(Process, CallOffset);
  1005. if (CallFunc != NULL) {
  1006. _IMAGE_RUNTIME_FUNCTION_ENTRY SaveCallFunc = *CallFunc;
  1007. _PIMAGE_RUNTIME_FUNCTION_ENTRY RetFunc =
  1008. (_PIMAGE_RUNTIME_FUNCTION_ENTRY)
  1009. FunctionTableAccess(Process, *ReturnAddress);
  1010. if (RetFunc == NULL ||
  1011. memcmp(&SaveCallFunc, RetFunc, sizeof(SaveCallFunc))) {
  1012. *ReturnAddress = CallOffset;
  1013. }
  1014. }
  1015. }
  1016. return Succ;
  1017. }
  1018. BOOL
  1019. ReadFrameArgsAmd64(
  1020. LPADDRESS64 FrameOffset,
  1021. HANDLE Process,
  1022. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  1023. PULONG64 Args
  1024. )
  1025. {
  1026. ULONG Done;
  1027. if (!ReadMemory(Process, FrameOffset->Offset + 2 * sizeof(ULONG64),
  1028. Args, 4 * sizeof(ULONG64), &Done)) {
  1029. Done = 0;
  1030. }
  1031. ZeroMemory((PUCHAR)Args + Done, 4 * sizeof(ULONG64) - Done);
  1032. return Done > 0;
  1033. }
  1034. BOOL
  1035. WalkAmd64Init(
  1036. HANDLE Process,
  1037. LPSTACKFRAME64 StackFrame,
  1038. PAMD64_CONTEXT Context,
  1039. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  1040. PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccess,
  1041. PGET_MODULE_BASE_ROUTINE64 GetModuleBase
  1042. )
  1043. {
  1044. AMD64_CONTEXT ContextSave;
  1045. DWORD64 PcOffset;
  1046. DWORD64 StackOffset;
  1047. DWORD64 FrameOffset;
  1048. ZeroMemory( &StackFrame->AddrBStore, sizeof(StackFrame->AddrBStore) );
  1049. StackFrame->FuncTableEntry = NULL;
  1050. ZeroMemory( StackFrame->Params, sizeof(StackFrame->Params) );
  1051. StackFrame->Far = FALSE;
  1052. StackFrame->Virtual = TRUE;
  1053. ZeroMemory( StackFrame->Reserved, sizeof(StackFrame->Reserved) );
  1054. if (!StackFrame->AddrPC.Offset) {
  1055. StackFrame->AddrPC.Offset = Context->Rip;
  1056. StackFrame->AddrPC.Mode = AddrModeFlat;
  1057. }
  1058. if (!StackFrame->AddrStack.Offset) {
  1059. StackFrame->AddrStack.Offset = Context->Rsp;
  1060. StackFrame->AddrStack.Mode = AddrModeFlat;
  1061. }
  1062. if (!StackFrame->AddrFrame.Offset) {
  1063. StackFrame->AddrFrame.Offset = Context->Rbp;
  1064. StackFrame->AddrFrame.Mode = AddrModeFlat;
  1065. }
  1066. if ((StackFrame->AddrPC.Mode != AddrModeFlat) ||
  1067. (StackFrame->AddrStack.Mode != AddrModeFlat) ||
  1068. (StackFrame->AddrFrame.Mode != AddrModeFlat)) {
  1069. return FALSE;
  1070. }
  1071. PcOffset = StackFrame->AddrPC.Offset;
  1072. StackOffset = StackFrame->AddrStack.Offset;
  1073. FrameOffset = StackFrame->AddrFrame.Offset;
  1074. ContextSave = *Context;
  1075. ContextSave.Rip = PcOffset;
  1076. ContextSave.Rsp = StackOffset;
  1077. ContextSave.Rbp = FrameOffset;
  1078. if (!UnwindStackFrameAmd64( Process,
  1079. &PcOffset,
  1080. &StackOffset,
  1081. &FrameOffset,
  1082. &ContextSave,
  1083. ReadMemory,
  1084. FunctionTableAccess,
  1085. GetModuleBase)) {
  1086. return FALSE;
  1087. }
  1088. StackFrame->AddrReturn.Offset = PcOffset;
  1089. StackFrame->AddrReturn.Mode = AddrModeFlat;
  1090. StackFrame->AddrFrame.Offset = FrameOffset;
  1091. ReadFrameArgsAmd64(&StackFrame->AddrFrame, Process,
  1092. ReadMemory, StackFrame->Params);
  1093. return TRUE;
  1094. }
  1095. BOOL
  1096. WalkAmd64Next(
  1097. HANDLE Process,
  1098. LPSTACKFRAME64 StackFrame,
  1099. PAMD64_CONTEXT Context,
  1100. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory,
  1101. PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccess,
  1102. PGET_MODULE_BASE_ROUTINE64 GetModuleBase
  1103. )
  1104. {
  1105. DWORD Done;
  1106. BOOL Succ = TRUE;
  1107. DWORD64 StackAddress;
  1108. _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry;
  1109. if (!UnwindStackFrameAmd64( Process,
  1110. &StackFrame->AddrPC.Offset,
  1111. &StackFrame->AddrStack.Offset,
  1112. &StackFrame->AddrFrame.Offset,
  1113. Context,
  1114. ReadMemory,
  1115. FunctionTableAccess,
  1116. GetModuleBase)) {
  1117. Succ = FALSE;
  1118. //
  1119. // If the frame could not be unwound or is terminal, see if
  1120. // there is a callback frame:
  1121. //
  1122. if (g.AppVersion.Revision >= 4 && CALLBACK_STACK(StackFrame)) {
  1123. DWORD64 ImageBase;
  1124. if (CALLBACK_STACK(StackFrame) & 0x80000000) {
  1125. //
  1126. // it is the pointer to the stack frame that we want
  1127. //
  1128. StackAddress = CALLBACK_STACK(StackFrame);
  1129. } else {
  1130. //
  1131. // if it is a positive integer, it is the offset to
  1132. // the address in the thread.
  1133. // Look up the pointer:
  1134. //
  1135. Succ = ReadMemory(Process,
  1136. (CALLBACK_THREAD(StackFrame) +
  1137. CALLBACK_STACK(StackFrame)),
  1138. &StackAddress,
  1139. sizeof(StackAddress),
  1140. &Done);
  1141. if (!Succ || Done != sizeof(StackAddress) ||
  1142. StackAddress == 0) {
  1143. StackAddress = (DWORD64)-1;
  1144. CALLBACK_STACK(StackFrame) = (DWORD)-1;
  1145. }
  1146. }
  1147. if ((StackAddress == (DWORD64)-1) ||
  1148. (!(FunctionEntry = (_PIMAGE_RUNTIME_FUNCTION_ENTRY)
  1149. FunctionTableAccess(Process, CALLBACK_FUNC(StackFrame))) ||
  1150. !(ImageBase = GetModuleBase(Process,
  1151. CALLBACK_FUNC(StackFrame))))) {
  1152. Succ = FALSE;
  1153. } else {
  1154. if (!ReadMemory(Process,
  1155. (StackAddress + CALLBACK_NEXT(StackFrame)),
  1156. &CALLBACK_STACK(StackFrame),
  1157. sizeof(DWORD64),
  1158. &Done) ||
  1159. Done != sizeof(DWORD64)) {
  1160. Succ = FALSE;
  1161. } else {
  1162. StackFrame->AddrPC.Offset =
  1163. ImageBase + FunctionEntry->BeginAddress;
  1164. StackFrame->AddrStack.Offset = StackAddress;
  1165. Context->Rsp = StackAddress;
  1166. Succ = TRUE;
  1167. }
  1168. }
  1169. }
  1170. }
  1171. if (Succ) {
  1172. AMD64_CONTEXT ContextSave;
  1173. ULONG64 StackOffset = 0;
  1174. ULONG64 FrameOffset = 0;
  1175. //
  1176. // Get the return address.
  1177. //
  1178. ContextSave = *Context;
  1179. StackFrame->AddrReturn.Offset = StackFrame->AddrPC.Offset;
  1180. if (!UnwindStackFrameAmd64( Process,
  1181. &StackFrame->AddrReturn.Offset,
  1182. &StackOffset,
  1183. &FrameOffset,
  1184. &ContextSave,
  1185. ReadMemory,
  1186. FunctionTableAccess,
  1187. GetModuleBase)) {
  1188. StackFrame->AddrReturn.Offset = 0;
  1189. }
  1190. StackFrame->AddrFrame.Offset = FrameOffset;
  1191. ReadFrameArgsAmd64(&StackFrame->AddrFrame, Process, ReadMemory,
  1192. StackFrame->Params);
  1193. }
  1194. return Succ;
  1195. }