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.

1122 lines
32 KiB

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