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

1080 lines
30 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Stack walking support.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997-2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. IMAGE_IA64_RUNTIME_FUNCTION_ENTRY g_EpcRfeBuffer;
  10. PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY g_EpcRfe;
  11. PFPO_DATA
  12. SynthesizeKnownFpo(PSTR Symbol, ULONG64 OffStart, ULONG64 Disp)
  13. {
  14. static ULONG64 s_Nr2, s_Lu2, s_Eh3, s_Kuit;
  15. if (!s_Nr2 || !s_Lu2 || !s_Eh3 || !s_Kuit)
  16. {
  17. GetOffsetFromSym("nt!_NLG_Return2", &s_Nr2, NULL);
  18. GetOffsetFromSym("nt!_local_unwind2", &s_Lu2, NULL);
  19. GetOffsetFromSym("nt!_except_handler3", &s_Eh3, NULL);
  20. GetOffsetFromSym("nt!KiUnexpectedInterruptTail", &s_Kuit, NULL);
  21. }
  22. if (OffStart == s_Nr2 || OffStart == s_Lu2)
  23. {
  24. static FPO_DATA s_Lu2Fpo;
  25. s_Lu2Fpo.ulOffStart = (ULONG)OffStart;
  26. s_Lu2Fpo.cbProcSize = 0x68;
  27. s_Lu2Fpo.cdwLocals = 4;
  28. s_Lu2Fpo.cdwParams = 0;
  29. s_Lu2Fpo.cbProlog = 0;
  30. s_Lu2Fpo.cbRegs = 3;
  31. s_Lu2Fpo.fHasSEH = 0;
  32. s_Lu2Fpo.fUseBP = 0;
  33. s_Lu2Fpo.reserved = 0;
  34. s_Lu2Fpo.cbFrame = FRAME_FPO;
  35. return &s_Lu2Fpo;
  36. }
  37. else if (OffStart == s_Eh3)
  38. {
  39. static FPO_DATA s_Eh3Fpo;
  40. s_Eh3Fpo.ulOffStart = (ULONG)OffStart;
  41. s_Eh3Fpo.cbProcSize = 0xbd;
  42. s_Eh3Fpo.cdwLocals = 2;
  43. s_Eh3Fpo.cdwParams = 4;
  44. s_Eh3Fpo.cbProlog = 3;
  45. s_Eh3Fpo.cbRegs = 4;
  46. s_Eh3Fpo.fHasSEH = 0;
  47. s_Eh3Fpo.fUseBP = 0;
  48. s_Eh3Fpo.reserved = 0;
  49. s_Eh3Fpo.cbFrame = FRAME_NONFPO;
  50. return &s_Eh3Fpo;
  51. }
  52. else if (OffStart == s_Kuit)
  53. {
  54. //
  55. // KiUnexpectedInterruptTail has three special stubs
  56. // following it for CommonDispatchException[0-2]Args.
  57. // These stubs set up for the appropriate number of
  58. // arguments and then call CommonDispatchException.
  59. // They do not have symbols or FPO data so fake some
  60. // up if we're in the region immediately after KUIT.
  61. //
  62. PFPO_DATA KuitData = (PFPO_DATA)
  63. SymFunctionTableAccess(g_CurrentProcess->Handle, OffStart);
  64. if (KuitData != NULL &&
  65. Disp >= (ULONG64)KuitData->cbProcSize &&
  66. Disp < (ULONG64)KuitData->cbProcSize + 0x20)
  67. {
  68. static FPO_DATA s_CdeStubFpo;
  69. s_CdeStubFpo.ulOffStart = (ULONG)OffStart;
  70. s_CdeStubFpo.cbProcSize = 0x10;
  71. s_CdeStubFpo.cdwLocals = 0;
  72. s_CdeStubFpo.cdwParams = 0;
  73. s_CdeStubFpo.cbProlog = 0;
  74. s_CdeStubFpo.cbRegs = 0;
  75. s_CdeStubFpo.fHasSEH = 0;
  76. s_CdeStubFpo.fUseBP = 0;
  77. s_CdeStubFpo.reserved = 0;
  78. s_CdeStubFpo.cbFrame = FRAME_TRAP;
  79. return &s_CdeStubFpo;
  80. }
  81. }
  82. return NULL;
  83. }
  84. PFPO_DATA
  85. SynthesizeFpoDataForModule(DWORD64 PCAddr)
  86. {
  87. DWORD64 Offset;
  88. USHORT StdCallArgs;
  89. CHAR symbuf[MAX_SYMBOL_LEN];
  90. GetSymbolStdCall( PCAddr,
  91. symbuf,
  92. sizeof(symbuf),
  93. &Offset,
  94. &StdCallArgs);
  95. if (Offset == PCAddr)
  96. {
  97. // No symbol.
  98. return NULL;
  99. }
  100. PFPO_DATA KnownFpo =
  101. SynthesizeKnownFpo(symbuf, PCAddr - Offset, Offset);
  102. if (KnownFpo != NULL)
  103. {
  104. return KnownFpo;
  105. }
  106. if (StdCallArgs == 0xffff)
  107. {
  108. return NULL;
  109. }
  110. static FPO_DATA s_SynthFpo;
  111. s_SynthFpo.ulOffStart = (ULONG)(PCAddr - Offset);
  112. s_SynthFpo.cbProcSize = (ULONG)(Offset + 10);
  113. s_SynthFpo.cdwLocals = 0;
  114. s_SynthFpo.cdwParams = StdCallArgs;
  115. s_SynthFpo.cbProlog = 0;
  116. s_SynthFpo.cbRegs = 0;
  117. s_SynthFpo.fHasSEH = 0;
  118. s_SynthFpo.fUseBP = 0;
  119. s_SynthFpo.reserved = 0;
  120. s_SynthFpo.cbFrame = FRAME_NONFPO;
  121. return &s_SynthFpo;
  122. }
  123. PFPO_DATA
  124. SynthesizeFpoDataForFastSyscall(ULONG64 Offset)
  125. {
  126. static FPO_DATA s_FastFpo;
  127. // XXX drewb - Temporary until the fake user-shared
  128. // module is worked out.
  129. s_FastFpo.ulOffStart = (ULONG)Offset;
  130. s_FastFpo.cbProcSize = X86_SHARED_SYSCALL_SIZE;
  131. s_FastFpo.cdwLocals = 0;
  132. s_FastFpo.cdwParams = 0;
  133. s_FastFpo.cbProlog = 0;
  134. s_FastFpo.cbRegs = 0;
  135. s_FastFpo.fHasSEH = 0;
  136. s_FastFpo.fUseBP = 0;
  137. s_FastFpo.reserved = 0;
  138. s_FastFpo.cbFrame = FRAME_FPO;
  139. return &s_FastFpo;
  140. }
  141. PFPO_DATA
  142. ModifyFpoRecord(PDEBUG_IMAGE_INFO Image, PFPO_DATA FpoData)
  143. {
  144. if (FpoData->cdwLocals == 80)
  145. {
  146. static ULONG64 s_CommonDispatchException;
  147. // Some versions of CommonDispatchException have
  148. // the wrong locals size, which screws up stack
  149. // traces. Detect and fix up these problems.
  150. if (s_CommonDispatchException == 0)
  151. {
  152. GetOffsetFromSym("nt!CommonDispatchException",
  153. &s_CommonDispatchException,
  154. NULL);
  155. }
  156. if (Image->BaseOfImage + FpoData->ulOffStart ==
  157. s_CommonDispatchException)
  158. {
  159. static FPO_DATA s_CdeFpo;
  160. s_CdeFpo = *FpoData;
  161. s_CdeFpo.cdwLocals = 20;
  162. FpoData = &s_CdeFpo;
  163. }
  164. }
  165. else if (FpoData->cdwLocals == 0 && FpoData->cdwParams == 0 &&
  166. FpoData->cbRegs == 3)
  167. {
  168. static ULONG64 s_KiSwapThread;
  169. // KiSwapThread has shrink-wrapping so that three registers
  170. // are pushed in only a portion of the code. Unfortunately,
  171. // the most important place in the code -- the call to
  172. // KiSwapContext -- is outside of this region and therefore
  173. // the register count is wrong much more often than it's
  174. // correct. Switch the register count to two to make it
  175. // correct more often than wrong.
  176. if (s_KiSwapThread == 0)
  177. {
  178. GetOffsetFromSym("nt!KiSwapThread", &s_KiSwapThread, NULL);
  179. }
  180. if (Image->BaseOfImage + FpoData->ulOffStart ==
  181. s_KiSwapThread)
  182. {
  183. static FPO_DATA s_KstFpo;
  184. s_KstFpo = *FpoData;
  185. s_KstFpo.cbRegs = 2;
  186. FpoData = &s_KstFpo;
  187. }
  188. }
  189. else if (FpoData->fHasSEH)
  190. {
  191. static FPO_DATA s_SehFpo;
  192. s_SehFpo = *FpoData;
  193. s_SehFpo.cbFrame = FRAME_NONFPO;
  194. FpoData = &s_SehFpo;
  195. }
  196. return FpoData;
  197. }
  198. PFPO_DATA
  199. FindFpoDataForModule(DWORD64 PCAddr)
  200. /*++
  201. Routine Description:
  202. Locates the fpo data structure in the process's linked list for the
  203. requested module.
  204. Arguments:
  205. PCAddr - address contained in the program counter
  206. Return Value:
  207. null - could not locate the entry
  208. valid address - found the entry at the adress retured
  209. --*/
  210. {
  211. PPROCESS_INFO Process;
  212. PDEBUG_IMAGE_INFO Image;
  213. PFPO_DATA FpoData;
  214. Process = g_CurrentProcess;
  215. Image = Process->ImageHead;
  216. FpoData = 0;
  217. while (Image)
  218. {
  219. if ((PCAddr >= Image->BaseOfImage) &&
  220. (PCAddr < Image->BaseOfImage + Image->SizeOfImage))
  221. {
  222. FpoData = (PFPO_DATA)
  223. SymFunctionTableAccess(g_CurrentProcess->Handle, PCAddr);
  224. if (!FpoData)
  225. {
  226. FpoData = SynthesizeFpoDataForModule(PCAddr);
  227. }
  228. else
  229. {
  230. FpoData = ModifyFpoRecord(Image, FpoData);
  231. }
  232. return FpoData;
  233. }
  234. Image = Image->Next;
  235. }
  236. ULONG64 FscBase;
  237. switch(IsInFastSyscall(PCAddr, &FscBase))
  238. {
  239. case FSC_FOUND:
  240. return SynthesizeFpoDataForFastSyscall(FscBase);
  241. }
  242. // the function is not part of any known loaded image
  243. return NULL;
  244. }
  245. LPVOID
  246. SwFunctionTableAccess(
  247. HANDLE hProcess,
  248. ULONG64 AddrBase
  249. )
  250. {
  251. static IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY s_Axp32;
  252. static IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY s_Axp64;
  253. static IMAGE_IA64_RUNTIME_FUNCTION_ENTRY s_Ia64;
  254. static _IMAGE_RUNTIME_FUNCTION_ENTRY s_Amd64;
  255. PVOID pife;
  256. if (g_EffMachine == IMAGE_FILE_MACHINE_I386)
  257. {
  258. return (LPVOID)FindFpoDataForModule( AddrBase );
  259. }
  260. pife = SymFunctionTableAccess64(hProcess, AddrBase);
  261. switch (g_EffMachine)
  262. {
  263. case IMAGE_FILE_MACHINE_AXP64:
  264. if (!pife)
  265. {
  266. return NULL;
  267. }
  268. s_Axp64.BeginAddress =
  269. ((PIMAGE_FUNCTION_ENTRY64)pife)->StartingAddress;
  270. s_Axp64.EndAddress =
  271. ((PIMAGE_FUNCTION_ENTRY64)pife)->EndingAddress;
  272. s_Axp64.ExceptionHandler = 0;
  273. s_Axp64.HandlerData = 0;
  274. s_Axp64.PrologEndAddress =
  275. ((PIMAGE_FUNCTION_ENTRY64)pife)->EndOfPrologue;
  276. return &s_Axp64;
  277. case IMAGE_FILE_MACHINE_ALPHA:
  278. if (!pife)
  279. {
  280. return NULL;
  281. }
  282. s_Axp32.BeginAddress =
  283. ((PIMAGE_FUNCTION_ENTRY)pife)->StartingAddress;
  284. s_Axp32.EndAddress =
  285. ((PIMAGE_FUNCTION_ENTRY)pife)->EndingAddress;
  286. s_Axp32.ExceptionHandler = 0;
  287. s_Axp32.HandlerData = 0;
  288. s_Axp32.PrologEndAddress =
  289. ((PIMAGE_FUNCTION_ENTRY)pife)->EndOfPrologue;
  290. return &s_Axp32;
  291. case IMAGE_FILE_MACHINE_IA64:
  292. if (pife)
  293. {
  294. s_Ia64 = *(PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY)pife;
  295. return &s_Ia64;
  296. }
  297. else
  298. {
  299. if (IS_KERNEL_TARGET() &&
  300. (AddrBase >= IA64_MM_EPC_VA) &&
  301. (AddrBase < (IA64_MM_EPC_VA + IA64_PAGE_SIZE)))
  302. {
  303. return g_EpcRfe;
  304. }
  305. else
  306. {
  307. return NULL;
  308. }
  309. }
  310. break;
  311. case IMAGE_FILE_MACHINE_AMD64:
  312. if (pife)
  313. {
  314. s_Amd64 = *(_PIMAGE_RUNTIME_FUNCTION_ENTRY)pife;
  315. return &s_Amd64;
  316. }
  317. break;
  318. }
  319. return NULL;
  320. }
  321. DWORD64
  322. SwTranslateAddress(
  323. HANDLE hProcess,
  324. HANDLE hThread,
  325. LPADDRESS64 lpaddress
  326. )
  327. {
  328. //
  329. // don't support 16bit stacks
  330. //
  331. return 0;
  332. }
  333. BOOL
  334. SwReadMemory32(
  335. HANDLE hProcess,
  336. ULONG dwBaseAddress,
  337. LPVOID lpBuffer,
  338. DWORD nSize,
  339. LPDWORD lpNumberOfBytesRead
  340. )
  341. {
  342. return SwReadMemory(hProcess,
  343. EXTEND64(dwBaseAddress),
  344. lpBuffer,
  345. nSize,
  346. lpNumberOfBytesRead);
  347. }
  348. BOOL
  349. SwReadMemory(
  350. HANDLE hProcess,
  351. ULONG64 BaseAddress,
  352. LPVOID lpBuffer,
  353. DWORD nSize,
  354. LPDWORD lpNumberOfBytesRead
  355. )
  356. {
  357. DBG_ASSERT(hProcess == g_CurrentProcess->Handle);
  358. if (IS_KERNEL_TARGET())
  359. {
  360. DWORD BytesRead;
  361. HRESULT Status;
  362. if ((LONG_PTR)lpNumberOfBytesRead == -1)
  363. {
  364. if (g_TargetMachineType == IMAGE_FILE_MACHINE_I386)
  365. {
  366. BaseAddress += g_TargetMachine->m_SizeTargetContext;
  367. }
  368. Status = g_Target->ReadControl(CURRENT_PROC,
  369. (ULONG)BaseAddress,
  370. lpBuffer,
  371. nSize,
  372. &BytesRead);
  373. return Status == S_OK;
  374. }
  375. }
  376. if (g_Target->ReadVirtual(BaseAddress, lpBuffer, nSize,
  377. lpNumberOfBytesRead) != S_OK)
  378. {
  379. // Make sure bytes read is zero.
  380. if (lpNumberOfBytesRead != NULL)
  381. {
  382. *lpNumberOfBytesRead = 0;
  383. }
  384. return FALSE;
  385. }
  386. else
  387. {
  388. return TRUE;
  389. }
  390. }
  391. DWORD64
  392. SwGetModuleBase(
  393. HANDLE hProcess,
  394. ULONG64 Address
  395. )
  396. {
  397. PDEBUG_IMAGE_INFO Image = g_CurrentProcess->ImageHead;
  398. if (g_EffMachine == IMAGE_FILE_MACHINE_IA64 &&
  399. IS_KERNEL_TARGET() &&
  400. (Address >= IA64_MM_EPC_VA) &&
  401. (Address < (IA64_MM_EPC_VA + IA64_PAGE_SIZE)))
  402. {
  403. Address -= (IA64_MM_EPC_VA - g_SystemCallVirtualAddress);
  404. }
  405. while (Image)
  406. {
  407. if ((Address >= Image->BaseOfImage) &&
  408. (Address < (Image->BaseOfImage + Image->SizeOfImage)))
  409. {
  410. return Image->BaseOfImage;
  411. }
  412. Image = Image->Next;
  413. }
  414. // If no regular module was found we need to look in
  415. // the dynamic function tables to see if an entry
  416. // there matches.
  417. ULONG64 DynBase = g_Target->
  418. GetDynamicFunctionTableBase(g_Machine, Address);
  419. if (DynBase)
  420. {
  421. return DynBase;
  422. }
  423. if (IS_KERNEL_TARGET())
  424. {
  425. // If no modules have been loaded there's still a possibility
  426. // of getting a kernel stack trace (without symbols) by going
  427. // after the module base directly. This also makes it possible
  428. // to get a stack trace when there are no symbols available.
  429. if (g_CurrentProcess->ImageHead == NULL)
  430. {
  431. return GetKernelModuleBase( Address );
  432. }
  433. }
  434. return 0;
  435. }
  436. DWORD
  437. SwGetModuleBase32(
  438. HANDLE hProcess,
  439. DWORD Address
  440. )
  441. {
  442. return (DWORD)SwGetModuleBase(hProcess, Address);
  443. }
  444. void
  445. PrintStackTraceHeaderLine(
  446. ULONG Flags
  447. )
  448. {
  449. if ( (Flags & DEBUG_STACK_COLUMN_NAMES) == 0 )
  450. {
  451. return;
  452. }
  453. StartOutLine(DEBUG_OUTPUT_NORMAL, OUT_LINE_NO_TIMESTAMP);
  454. if (Flags & DEBUG_STACK_FRAME_NUMBERS)
  455. {
  456. dprintf(" # ");
  457. }
  458. if (Flags & DEBUG_STACK_FRAME_ADDRESSES)
  459. {
  460. g_Machine->PrintStackFrameAddressesTitle(Flags);
  461. }
  462. if (Flags & DEBUG_STACK_ARGUMENTS)
  463. {
  464. g_Machine->PrintStackArgumentsTitle(Flags);
  465. }
  466. g_Machine->PrintStackCallSiteTitle(Flags);
  467. dprintf("\n");
  468. }
  469. VOID
  470. PrintStackFrame(
  471. PDEBUG_STACK_FRAME StackFrame,
  472. ULONG Flags
  473. )
  474. {
  475. DWORD64 displacement;
  476. CHAR symbuf[MAX_SYMBOL_LEN];
  477. USHORT StdCallArgs;
  478. ULONG64 InstructionOffset = StackFrame->InstructionOffset;
  479. if (g_EffMachine == IMAGE_FILE_MACHINE_IA64 &&
  480. IS_KERNEL_TARGET() &&
  481. (InstructionOffset >= IA64_MM_EPC_VA) &&
  482. (InstructionOffset < (IA64_MM_EPC_VA + IA64_PAGE_SIZE)))
  483. {
  484. InstructionOffset = InstructionOffset -
  485. (IA64_MM_EPC_VA - g_SystemCallVirtualAddress);
  486. }
  487. GetSymbolStdCall(InstructionOffset,
  488. symbuf,
  489. sizeof(symbuf),
  490. &displacement,
  491. &StdCallArgs);
  492. StartOutLine(DEBUG_OUTPUT_NORMAL, OUT_LINE_NO_TIMESTAMP);
  493. if (Flags & DEBUG_STACK_FRAME_NUMBERS)
  494. {
  495. dprintf("%02lx ", StackFrame->FrameNumber);
  496. }
  497. if (Flags & DEBUG_STACK_FRAME_ADDRESSES)
  498. {
  499. g_Machine->PrintStackFrameAddresses(Flags, StackFrame);
  500. }
  501. if (Flags & DEBUG_STACK_ARGUMENTS)
  502. {
  503. g_Machine->PrintStackArguments(Flags, StackFrame);
  504. }
  505. g_Machine->PrintStackCallSite(Flags, StackFrame,
  506. symbuf, displacement,
  507. StdCallArgs);
  508. if (Flags & DEBUG_STACK_SOURCE_LINE)
  509. {
  510. OutputLineAddr(InstructionOffset, " [%s @ %d]");
  511. }
  512. dprintf( "\n" );
  513. }
  514. VOID
  515. PrintStackTrace(
  516. ULONG NumFrames,
  517. PDEBUG_STACK_FRAME StackFrames,
  518. ULONG Flags
  519. )
  520. {
  521. ULONG i;
  522. PrintStackTraceHeaderLine(Flags);
  523. for (i = 0; i < NumFrames; i++)
  524. {
  525. PrintStackFrame(StackFrames + i, Flags);
  526. }
  527. }
  528. void
  529. GetStkTraceArgsForCurrentScope(
  530. PULONG64 FramePointer,
  531. PULONG64 StackPointer,
  532. PULONG64 InstructionPointer,
  533. PCROSS_PLATFORM_CONTEXT ContextCopyPointer
  534. )
  535. {
  536. PCROSS_PLATFORM_CONTEXT ScopeContext = GetCurrentScopeContext();
  537. if (ScopeContext != NULL)
  538. {
  539. g_Machine->PushContext(ScopeContext);
  540. switch (g_EffMachine)
  541. {
  542. case IMAGE_FILE_MACHINE_I386:
  543. if (*InstructionPointer == 0)
  544. {
  545. *InstructionPointer = g_Machine->GetReg64(X86_EIP);
  546. }
  547. if (*StackPointer == 0)
  548. {
  549. *StackPointer = g_Machine->GetReg64(X86_ESP);
  550. }
  551. if (*FramePointer == 0)
  552. {
  553. *FramePointer = g_Machine->GetReg64(X86_EBP);
  554. }
  555. break;
  556. case IMAGE_FILE_MACHINE_IA64:
  557. *InstructionPointer = g_Machine->GetReg64(STIIP);
  558. *StackPointer = g_Machine->GetReg64(INTSP);
  559. *FramePointer = g_Machine->GetReg64(RSBSP);
  560. break;
  561. case IMAGE_FILE_MACHINE_AXP64:
  562. case IMAGE_FILE_MACHINE_ALPHA:
  563. *InstructionPointer = g_Machine->GetReg64(ALPHA_FIR);
  564. *StackPointer = g_Machine->GetReg64(SP_REG);
  565. *FramePointer = g_Machine->GetReg64(FP_REG);
  566. break;
  567. case IMAGE_FILE_MACHINE_AMD64:
  568. *InstructionPointer = g_Machine->GetReg64(AMD64_RIP);
  569. *StackPointer = g_Machine->GetReg64(AMD64_RSP);
  570. *FramePointer = g_Machine->GetReg64(AMD64_RBP);
  571. break;
  572. default:
  573. break;
  574. }
  575. if (ContextCopyPointer)
  576. {
  577. *ContextCopyPointer = g_Machine->m_Context;
  578. }
  579. g_Machine->PopContext();
  580. }
  581. else
  582. {
  583. if (ContextCopyPointer)
  584. {
  585. *ContextCopyPointer = g_Machine->m_Context;
  586. }
  587. }
  588. }
  589. DWORD
  590. StackTrace(
  591. ULONG64 FramePointer,
  592. ULONG64 StackPointer,
  593. ULONG64 InstructionPointer,
  594. PDEBUG_STACK_FRAME StackFrames,
  595. ULONG NumFrames,
  596. ULONG64 ExtThread,
  597. ULONG Flags,
  598. BOOL EstablishingScope
  599. )
  600. {
  601. STACKFRAME64 VirtualFrame;
  602. DWORD i;
  603. CROSS_PLATFORM_CONTEXT Context;
  604. PVOID FunctionEntry;
  605. ULONG64 Value;
  606. ULONG result;
  607. BOOL SymWarning = FALSE;
  608. ULONG X86Ebp;
  609. if (!EstablishingScope)
  610. {
  611. RequireCurrentScope();
  612. }
  613. //
  614. // let's start clean
  615. //
  616. ZeroMemory( StackFrames, sizeof(StackFrames[0]) * NumFrames );
  617. ZeroMemory( &VirtualFrame, sizeof(VirtualFrame) );
  618. if (g_Machine->GetContextState(MCTX_FULL) != S_OK)
  619. {
  620. return 0;
  621. }
  622. ULONG Seg;
  623. if ((!FramePointer && !InstructionPointer && !StackPointer) ||
  624. (g_EffMachine == IMAGE_FILE_MACHINE_I386))
  625. {
  626. // Do the default stack trace for current debug context
  627. // For x86, set these if any of them is 0
  628. GetStkTraceArgsForCurrentScope(&FramePointer, &StackPointer,
  629. &InstructionPointer, &Context);
  630. }
  631. if (IS_KERNEL_TARGET())
  632. {
  633. //
  634. // if debugger was initialized at boot, usermode addresses needed for
  635. // stack traces on IA64 were not available. Try it now:
  636. //
  637. if (g_EffMachine == IMAGE_FILE_MACHINE_IA64 &&
  638. !KdDebuggerData.KeUserCallbackDispatcher)
  639. {
  640. VerifyKernelBase (FALSE);
  641. }
  642. ULONG64 ThreadData;
  643. // If no explicit thread is given then we use the
  644. // current thread. However, the current thread is only
  645. // valid if the current thread is the event thread since
  646. // tracing back into user mode requires that the appropriate
  647. // user-mode memory state be active.
  648. if (ExtThread != 0)
  649. {
  650. ThreadData = ExtThread;
  651. }
  652. else if (g_CurrentProcess->CurrentThread != g_EventThread ||
  653. g_CurrentProcess != g_EventProcess ||
  654. GetImplicitThreadData(&ThreadData) != S_OK)
  655. {
  656. ThreadData = 0;
  657. }
  658. VirtualFrame.KdHelp.Thread = ThreadData;
  659. VirtualFrame.KdHelp.ThCallbackStack = ThreadData ?
  660. KdDebuggerData.ThCallbackStack : 0;
  661. VirtualFrame.KdHelp.KiCallUserMode = KdDebuggerData.KiCallUserMode;
  662. VirtualFrame.KdHelp.NextCallback = KdDebuggerData.NextCallback;
  663. VirtualFrame.KdHelp.KeUserCallbackDispatcher =
  664. KdDebuggerData.KeUserCallbackDispatcher;
  665. VirtualFrame.KdHelp.FramePointer = KdDebuggerData.FramePointer;
  666. VirtualFrame.KdHelp.SystemRangeStart = g_SystemRangeStart;
  667. }
  668. //
  669. // setup the program counter
  670. //
  671. if (!InstructionPointer)
  672. {
  673. if (g_EffMachine == IMAGE_FILE_MACHINE_I386)
  674. {
  675. ADDR Addr;
  676. VirtualFrame.AddrPC.Mode = AddrModeFlat;
  677. g_Machine->GetPC(&Addr);
  678. VirtualFrame.AddrPC.Segment = Addr.seg;
  679. VirtualFrame.AddrPC.Offset = Flat(Addr);
  680. }
  681. }
  682. else
  683. {
  684. VirtualFrame.AddrPC.Mode = AddrModeFlat;
  685. Seg = g_Machine->GetSegRegNum(SEGREG_CODE);
  686. VirtualFrame.AddrPC.Segment =
  687. Seg ? (WORD)GetRegVal32(Seg) : 0;
  688. VirtualFrame.AddrPC.Offset = InstructionPointer;
  689. }
  690. //
  691. // setup the frame pointer
  692. //
  693. if (!FramePointer)
  694. {
  695. if (g_EffMachine == IMAGE_FILE_MACHINE_I386)
  696. {
  697. ADDR Addr;
  698. VirtualFrame.AddrFrame.Mode = AddrModeFlat;
  699. g_Machine->GetFP(&Addr);
  700. VirtualFrame.AddrFrame.Segment = Addr.seg;
  701. VirtualFrame.AddrFrame.Offset = Flat(Addr);
  702. }
  703. }
  704. else
  705. {
  706. VirtualFrame.AddrFrame.Mode = AddrModeFlat;
  707. Seg = g_Machine->GetSegRegNum(SEGREG_STACK);
  708. VirtualFrame.AddrFrame.Segment =
  709. Seg ? (WORD)GetRegVal32(Seg) : 0;
  710. VirtualFrame.AddrFrame.Offset = FramePointer;
  711. }
  712. VirtualFrame.AddrBStore = VirtualFrame.AddrFrame;
  713. if (g_EffMachine == IMAGE_FILE_MACHINE_I386)
  714. {
  715. X86Ebp = (ULONG) VirtualFrame.AddrFrame.Offset;
  716. }
  717. //
  718. // setup the stack pointer
  719. //
  720. if (!StackPointer)
  721. {
  722. if (g_EffMachine == IMAGE_FILE_MACHINE_I386)
  723. {
  724. ADDR Addr;
  725. VirtualFrame.AddrStack.Mode = AddrModeFlat;
  726. g_Machine->GetSP(&Addr);
  727. VirtualFrame.AddrStack.Segment = Addr.seg;
  728. VirtualFrame.AddrStack.Offset = Flat(Addr);
  729. }
  730. }
  731. else
  732. {
  733. VirtualFrame.AddrStack.Mode = AddrModeFlat;
  734. Seg = g_Machine->GetSegRegNum(SEGREG_STACK);
  735. VirtualFrame.AddrStack.Segment =
  736. Seg ? (WORD)GetRegVal32(Seg) : 0;
  737. VirtualFrame.AddrStack.Offset = StackPointer;
  738. }
  739. if (g_EffMachine == IMAGE_FILE_MACHINE_IA64 &&
  740. IS_KERNEL_TARGET() &&
  741. g_SystemCallVirtualAddress)
  742. {
  743. PVOID functionEntry;
  744. ULONG numberOfBytesRead;
  745. functionEntry = SwFunctionTableAccess (g_CurrentProcess->Handle,
  746. g_SystemCallVirtualAddress);
  747. if (functionEntry != NULL)
  748. {
  749. RtlCopyMemory(&g_EpcRfeBuffer, functionEntry,
  750. sizeof(IMAGE_IA64_RUNTIME_FUNCTION_ENTRY));
  751. g_EpcRfe = &g_EpcRfeBuffer;
  752. }
  753. else
  754. {
  755. g_EpcRfe = NULL;
  756. }
  757. }
  758. for (i = 0; i < NumFrames; i++)
  759. {
  760. // SwReadMemory doesn't currently use the thread handle
  761. // but send in something reasonable in case of future changes.
  762. if (!StackWalk64(g_EffMachine,
  763. g_CurrentProcess->Handle,
  764. OS_HANDLE(g_CurrentProcess->CurrentThread->Handle),
  765. &VirtualFrame,
  766. &Context,
  767. SwReadMemory,
  768. SwFunctionTableAccess,
  769. SwGetModuleBase,
  770. SwTranslateAddress))
  771. {
  772. break;
  773. }
  774. StackFrames[i].InstructionOffset = VirtualFrame.AddrPC.Offset;
  775. StackFrames[i].ReturnOffset = VirtualFrame.AddrReturn.Offset;
  776. StackFrames[i].FrameOffset = VirtualFrame.AddrFrame.Offset;
  777. StackFrames[i].StackOffset = VirtualFrame.AddrStack.Offset;
  778. StackFrames[i].FuncTableEntry = (ULONG64)VirtualFrame.FuncTableEntry;
  779. StackFrames[i].Virtual = VirtualFrame.Virtual;
  780. StackFrames[i].FrameNumber = i;
  781. // NOTE - we have more reserved space in the DEBUG_STACK_FRAME
  782. memcpy(StackFrames[i].Reserved, VirtualFrame.Reserved,
  783. sizeof(VirtualFrame.Reserved));
  784. memcpy(StackFrames[i].Params, VirtualFrame.Params,
  785. sizeof(VirtualFrame.Params));
  786. if (g_EffMachine == IMAGE_FILE_MACHINE_IA64 &&
  787. IS_KERNEL_TARGET())
  788. {
  789. if ((VirtualFrame.AddrPC.Offset >= IA64_MM_EPC_VA) &&
  790. (VirtualFrame.AddrPC.Offset <
  791. (IA64_MM_EPC_VA + IA64_PAGE_SIZE)))
  792. {
  793. VirtualFrame.AddrPC.Offset -=
  794. (IA64_MM_EPC_VA - g_SystemCallVirtualAddress);
  795. }
  796. if ((i != 0) &&
  797. (StackFrames[i - 1].InstructionOffset >= IA64_MM_EPC_VA) &&
  798. (VirtualFrame.AddrPC.Offset <
  799. (IA64_MM_EPC_VA + IA64_PAGE_SIZE)))
  800. {
  801. StackFrames[i - 1].ReturnOffset =
  802. VirtualFrame.AddrPC.Offset;
  803. }
  804. } else if (g_EffMachine == IMAGE_FILE_MACHINE_I386)
  805. {
  806. if (StackFrames[i].FuncTableEntry)
  807. {
  808. PFPO_DATA FpoData = (PFPO_DATA)StackFrames[i].FuncTableEntry;
  809. if (FpoData->cbFrame == FRAME_FPO &&
  810. !FpoData->fUseBP)
  811. {
  812. SAVE_EBP(&StackFrames[i]) = (ULONG64) (LONG64) (LONG) X86Ebp;
  813. }
  814. }
  815. X86Ebp = Context.X86Context.Ebp;
  816. }
  817. if (Flags && i == 0)
  818. {
  819. PrintStackTraceHeaderLine(Flags);
  820. }
  821. IMAGEHLP_MODULE64 Mod;
  822. // If the current frame's PC is in a loaded module and
  823. // that module does not have symbols it's very possible
  824. // that the stack trace will be incorrect since the
  825. // debugger has to guess about how to unwind the stack.
  826. // Non-x86 architectures have unwind info in the images
  827. // themselves so restrict this check to x86.
  828. Mod.SizeOfStruct = sizeof(Mod);
  829. if (!SymWarning &&
  830. NumFrames > 1 &&
  831. g_EffMachine == IMAGE_FILE_MACHINE_I386 &&
  832. StackFrames[i].InstructionOffset != -1 &&
  833. SymGetModuleInfo64(g_CurrentProcess->Handle,
  834. StackFrames[i].InstructionOffset, &Mod) &&
  835. (Mod.SymType == SymNone || Mod.SymType == SymExport ||
  836. Mod.SymType == SymDeferred))
  837. {
  838. WarnOut("WARNING: Stack unwind information not available. "
  839. "Following frames may be wrong.\n");
  840. // Only show one warning per trace.
  841. SymWarning = TRUE;
  842. }
  843. if (Flags)
  844. {
  845. PrintStackFrame(StackFrames + i, Flags);
  846. if (Flags & DEBUG_STACK_NONVOLATILE_REGISTERS)
  847. {
  848. g_Machine->PrintStackNonvolatileRegisters(Flags,
  849. StackFrames + i,
  850. &Context, i);
  851. }
  852. }
  853. }
  854. return i;
  855. }
  856. #define BASIC_STACK \
  857. (DEBUG_STACK_COLUMN_NAMES | DEBUG_STACK_FRAME_ADDRESSES | \
  858. DEBUG_STACK_SOURCE_LINE)
  859. ULONG g_StackTraceTypeFlags[STACK_TRACE_TYPE_MAX] =
  860. {
  861. BASIC_STACK, // Default
  862. BASIC_STACK | DEBUG_STACK_ARGUMENTS, // kb
  863. BASIC_STACK | DEBUG_STACK_ARGUMENTS | DEBUG_STACK_FUNCTION_INFO |
  864. DEBUG_STACK_NONVOLATILE_REGISTERS, // kv
  865. 0, // kd
  866. BASIC_STACK | DEBUG_STACK_PARAMETERS, // kp
  867. BASIC_STACK | DEBUG_STACK_FRAME_NUMBERS, // kn
  868. BASIC_STACK | DEBUG_STACK_ARGUMENTS | DEBUG_STACK_FRAME_NUMBERS, // kbn
  869. BASIC_STACK | DEBUG_STACK_ARGUMENTS | DEBUG_STACK_FUNCTION_INFO |
  870. DEBUG_STACK_NONVOLATILE_REGISTERS | DEBUG_STACK_FRAME_NUMBERS,// kvn
  871. DEBUG_STACK_FRAME_NUMBERS, // kdn
  872. BASIC_STACK | DEBUG_STACK_PARAMETERS | DEBUG_STACK_FRAME_NUMBERS // kpn
  873. };
  874. VOID
  875. DoStackTrace(
  876. ULONG64 FramePointer,
  877. ULONG64 StackPointer,
  878. ULONG64 InstructionPointer,
  879. ULONG NumFrames,
  880. STACK_TRACE_TYPE TraceType
  881. )
  882. {
  883. PDEBUG_STACK_FRAME StackFrames;
  884. ULONG NumFramesToRead;
  885. DWORD FrameCount;
  886. if (NumFrames == 0)
  887. {
  888. NumFrames = g_DefaultStackTraceDepth;
  889. }
  890. if (TraceType == STACK_TRACE_TYPE_KD)
  891. {
  892. NumFramesToRead = 1;
  893. }
  894. else
  895. {
  896. NumFramesToRead = NumFrames;
  897. }
  898. StackFrames = (PDEBUG_STACK_FRAME)
  899. malloc( sizeof(StackFrames[0]) * NumFramesToRead );
  900. if (!StackFrames)
  901. {
  902. ErrOut( "could not allocate memory for stack trace\n" );
  903. return;
  904. }
  905. ULONG Flags = g_StackTraceTypeFlags[TraceType];
  906. if ((TraceType == STACK_TRACE_TYPE_KB) && g_Machine->m_Ptr64)
  907. {
  908. Flags |= DEBUG_STACK_FRAME_ADDRESSES_RA_ONLY;
  909. }
  910. FrameCount = StackTrace( FramePointer,
  911. StackPointer,
  912. InstructionPointer,
  913. StackFrames,
  914. NumFramesToRead,
  915. 0,
  916. Flags,
  917. FALSE
  918. );
  919. if (FrameCount == 0)
  920. {
  921. ErrOut( "could not fetch any stack frames\n" );
  922. free(StackFrames);
  923. return;
  924. }
  925. if (TraceType == STACK_TRACE_TYPE_KD)
  926. {
  927. // Starting with the stack pointer, dump NumFrames DWORD's
  928. // and the symbol if possible.
  929. ADDR startAddr;
  930. ADDRFLAT(&startAddr, StackFrames[0].FrameOffset);
  931. fnDumpDwordMemory(&startAddr, NumFrames, TRUE);
  932. }
  933. free( StackFrames );
  934. }