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.

1032 lines
24 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Abstraction of processor-specific information.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999-2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. ULONG g_EffMachine = IMAGE_FILE_MACHINE_UNKNOWN;
  10. MachineIndex g_EffMachineIndex = MACHIDX_COUNT;
  11. MachineInfo* g_Machine = NULL;
  12. MachineInfo* g_TargetMachine;
  13. // Leave one extra slot at the end so indexing
  14. // MACHIDX_COUNT returns NULL for the undefined case.
  15. MachineInfo* g_AllMachines[MACHIDX_COUNT + 1];
  16. // TRUE when symbol prefixing should be done.
  17. BOOL g_PrefixSymbols;
  18. // TRUE if context changed while processing
  19. BOOL g_ContextChanged;
  20. DEBUG_PROCESSOR_IDENTIFICATION_ALL g_InitProcessorId;
  21. //----------------------------------------------------------------------------
  22. //
  23. // MachineInfo.
  24. //
  25. //----------------------------------------------------------------------------
  26. HRESULT
  27. MachineInfo::InitializeConstants(void)
  28. {
  29. m_TraceMode = TRACE_NONE;
  30. m_ContextState = MCTX_NONE;
  31. m_ContextIsReadOnly = FALSE;
  32. m_NumberRegs = 0;
  33. // Every machine supports basic integer and FP registers.
  34. m_AllMaskBits = DEBUG_REGISTERS_ALL;
  35. m_SymPrefixLen = m_SymPrefix != NULL ? strlen(m_SymPrefix) : 0;
  36. ZeroMemory(m_PageDirectories, sizeof(m_PageDirectories));
  37. m_Translating = FALSE;
  38. ULONG i;
  39. for (i = 0; i < SEGREG_COUNT; i++)
  40. {
  41. m_SegRegDesc[i].Flags = SEGDESC_INVALID;
  42. }
  43. return S_OK;
  44. }
  45. HRESULT
  46. MachineInfo::InitializeForTarget(void)
  47. {
  48. InitializeContextFlags(&m_Context, m_SverCanonicalContext);
  49. return S_OK;
  50. }
  51. HRESULT
  52. MachineInfo::InitializeForProcessor(void)
  53. {
  54. DBG_ASSERT(m_MaxDataBreakpoints <= MAX_DATA_BREAKS);
  55. // Count register definitions.
  56. RegisterGroup* Group;
  57. for (Group = m_Groups; Group != NULL; Group = Group->Next)
  58. {
  59. Group->NumberRegs = 0;
  60. REGDEF* Def = Group->Regs;
  61. while (Def->psz != NULL)
  62. {
  63. Group->NumberRegs++;
  64. Def++;
  65. }
  66. m_NumberRegs += Group->NumberRegs;
  67. REGALLDESC* Desc = Group->AllExtraDesc;
  68. if (Desc != NULL)
  69. {
  70. while (Desc->Bit != 0)
  71. {
  72. m_AllMaskBits |= Desc->Bit;
  73. Desc++;
  74. }
  75. }
  76. }
  77. return S_OK;
  78. }
  79. HRESULT
  80. MachineInfo::GetContextState(ULONG State)
  81. {
  82. if (g_RegContextThread == NULL)
  83. {
  84. // No error message here as this can get hit during
  85. // Reload("NT") initialization when accessing paged-out memory.
  86. // It's also noisy in other failure cases, so rely
  87. // on higher-level error output.
  88. return E_UNEXPECTED;
  89. }
  90. if (State == MCTX_DIRTY)
  91. {
  92. g_ContextChanged = TRUE;
  93. }
  94. if (m_ContextState >= State)
  95. {
  96. return S_OK;
  97. }
  98. HRESULT Status = E_UNEXPECTED;
  99. // Dump support is built into the Ud/Kd routines.
  100. if (IS_USER_TARGET())
  101. {
  102. Status = UdGetContextState(State);
  103. }
  104. else if (IS_KERNEL_TARGET())
  105. {
  106. Status = KdGetContextState(State);
  107. }
  108. if (Status != S_OK)
  109. {
  110. ErrOut("GetContextState failed, 0x%X\n", Status);
  111. return Status;
  112. }
  113. if (State == MCTX_DIRTY)
  114. {
  115. DBG_ASSERT(m_ContextState >= MCTX_FULL);
  116. m_ContextState = State;
  117. }
  118. DBG_ASSERT(State <= m_ContextState);
  119. return S_OK;
  120. }
  121. HRESULT
  122. MachineInfo::SetContext(void)
  123. {
  124. if (m_ContextState != MCTX_DIRTY)
  125. {
  126. // Nothing to write.
  127. return S_OK;
  128. }
  129. if (g_RegContextThread == NULL)
  130. {
  131. ErrOut("No current thread in SetContext\n");
  132. return E_UNEXPECTED;
  133. }
  134. if (m_ContextIsReadOnly)
  135. {
  136. ErrOut("Context cannot be modified\n");
  137. return E_UNEXPECTED;
  138. }
  139. HRESULT Status = E_UNEXPECTED;
  140. if (IS_DUMP_TARGET())
  141. {
  142. ErrOut("Can't set dump file contexts\n");
  143. return E_UNEXPECTED;
  144. }
  145. else if (IS_USER_TARGET())
  146. {
  147. Status = UdSetContext();
  148. }
  149. else if (IS_KERNEL_TARGET())
  150. {
  151. Status = KdSetContext();
  152. }
  153. if (Status != S_OK)
  154. {
  155. ErrOut("SetContext failed, 0x%X\n", Status);
  156. return Status;
  157. }
  158. // No longer dirty.
  159. m_ContextState = MCTX_FULL;
  160. return S_OK;
  161. }
  162. HRESULT
  163. MachineInfo::UdGetContextState(ULONG State)
  164. {
  165. // MCTX_CONTEXT and MCTX_FULL are the same in user mode.
  166. if (State >= MCTX_CONTEXT && m_ContextState < MCTX_FULL)
  167. {
  168. HRESULT Status = g_Target->GetContext(g_RegContextThread->Handle,
  169. &m_Context);
  170. if (Status != S_OK)
  171. {
  172. return Status;
  173. }
  174. Status = g_Target->GetTargetSegRegDescriptors
  175. (g_RegContextThread->Handle, 0, SEGREG_COUNT, m_SegRegDesc);
  176. if (Status != S_OK)
  177. {
  178. return Status;
  179. }
  180. m_ContextState = MCTX_FULL;
  181. }
  182. return S_OK;
  183. }
  184. HRESULT
  185. MachineInfo::UdSetContext(void)
  186. {
  187. return g_Target->SetContext(g_RegContextThread->Handle, &m_Context);
  188. }
  189. void
  190. MachineInfo::InvalidateContext(void)
  191. {
  192. m_ContextState = MCTX_NONE;
  193. g_Target->InvalidateTargetContext();
  194. ULONG i;
  195. for (i = 0; i < SEGREG_COUNT; i++)
  196. {
  197. m_SegRegDesc[i].Flags = SEGDESC_INVALID;
  198. }
  199. }
  200. HRESULT
  201. MachineInfo::GetExdiContext(IUnknown* Exdi, PEXDI_CONTEXT Context)
  202. {
  203. return E_NOTIMPL;
  204. }
  205. HRESULT
  206. MachineInfo::SetExdiContext(IUnknown* Exdi, PEXDI_CONTEXT Context)
  207. {
  208. return E_NOTIMPL;
  209. }
  210. void
  211. MachineInfo::ConvertExdiContextFromContext(PCROSS_PLATFORM_CONTEXT Context,
  212. PEXDI_CONTEXT ExdiContext)
  213. {
  214. // Nothing to do.
  215. }
  216. void
  217. MachineInfo::ConvertExdiContextToContext(PEXDI_CONTEXT ExdiContext,
  218. PCROSS_PLATFORM_CONTEXT Context)
  219. {
  220. // Nothing to do.
  221. }
  222. void
  223. MachineInfo::ConvertExdiContextToSegDescs(PEXDI_CONTEXT ExdiContext,
  224. ULONG Start, ULONG Count,
  225. PDESCRIPTOR64 Descs)
  226. {
  227. // Nothing to do.
  228. }
  229. void
  230. MachineInfo::ConvertExdiContextFromSpecial
  231. (PCROSS_PLATFORM_KSPECIAL_REGISTERS Special,
  232. PEXDI_CONTEXT ExdiContext)
  233. {
  234. // Nothing to do.
  235. }
  236. void
  237. MachineInfo::ConvertExdiContextToSpecial
  238. (PEXDI_CONTEXT ExdiContext,
  239. PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  240. {
  241. // Nothing to do.
  242. }
  243. ULONG
  244. MachineInfo::GetSegRegNum(ULONG SegReg)
  245. {
  246. return 0;
  247. }
  248. HRESULT
  249. MachineInfo::GetSegRegDescriptor(ULONG SegReg, PDESCRIPTOR64 Desc)
  250. {
  251. return E_UNEXPECTED;
  252. }
  253. void
  254. MachineInfo::KdUpdateControlSet(PDBGKD_ANY_CONTROL_SET ControlSet)
  255. {
  256. // Nothing to do.
  257. }
  258. void
  259. MachineInfo::KdSaveProcessorState(
  260. void
  261. )
  262. {
  263. m_SavedContext = m_Context;
  264. m_SavedContextState = m_ContextState;
  265. memcpy(m_SavedSegRegDesc, m_SegRegDesc, sizeof(m_SegRegDesc));
  266. m_ContextState = MCTX_NONE;
  267. g_Target->InvalidateTargetContext();
  268. }
  269. void
  270. MachineInfo::KdRestoreProcessorState(
  271. void
  272. )
  273. {
  274. DBG_ASSERT(m_ContextState != MCTX_DIRTY);
  275. m_Context = m_SavedContext;
  276. m_ContextState = m_SavedContextState;
  277. memcpy(m_SegRegDesc, m_SavedSegRegDesc, sizeof(m_SegRegDesc));
  278. g_Target->InvalidateTargetContext();
  279. }
  280. HRESULT
  281. MachineInfo::SetDefaultPageDirectories(ULONG Mask)
  282. {
  283. HRESULT Status;
  284. ULONG i;
  285. ULONG64 OldDirs[PAGE_DIR_COUNT];
  286. memcpy(OldDirs, m_PageDirectories, sizeof(m_PageDirectories));
  287. i = 0;
  288. while (i < PAGE_DIR_COUNT)
  289. {
  290. // Pass on the set to machine-specific code.
  291. if (Mask & (1 << i))
  292. {
  293. if ((Status = SetPageDirectory(i, 0, &i)) != S_OK)
  294. {
  295. memcpy(m_PageDirectories, OldDirs, sizeof(m_PageDirectories));
  296. return Status;
  297. }
  298. }
  299. else
  300. {
  301. i++;
  302. }
  303. }
  304. // Try and validate that the new kernel page directory is
  305. // valid by checking an address that should always
  306. // be available.
  307. if ((Mask & (1 << PAGE_DIR_KERNEL)) &&
  308. IS_KERNEL_TARGET() && KdDebuggerData.PsLoadedModuleList)
  309. {
  310. LIST_ENTRY64 List;
  311. if ((Status = g_Target->
  312. ReadListEntry(this, KdDebuggerData.PsLoadedModuleList,
  313. &List)) != S_OK)
  314. {
  315. // This page directory doesn't seem valid so restore
  316. // the previous setting and fail.
  317. memcpy(m_PageDirectories, OldDirs, sizeof(m_PageDirectories));
  318. }
  319. }
  320. return Status;
  321. }
  322. HRESULT
  323. MachineInfo::NewBreakpoint(DebugClient* Client,
  324. ULONG Type,
  325. ULONG Id,
  326. Breakpoint** RetBp)
  327. {
  328. return E_NOINTERFACE;
  329. }
  330. void
  331. MachineInfo::InsertAllDataBreakpoints(void)
  332. {
  333. // Nothing to do.
  334. }
  335. void
  336. MachineInfo::RemoveAllDataBreakpoints(void)
  337. {
  338. // Nothing to do.
  339. }
  340. ULONG
  341. MachineInfo::IsBreakpointOrStepException(PEXCEPTION_RECORD64 Record,
  342. ULONG FirstChance,
  343. PADDR BpAddr,
  344. PADDR RelAddr)
  345. {
  346. return Record->ExceptionCode == STATUS_BREAKPOINT ?
  347. EXBS_BREAKPOINT_ANY : EXBS_NONE;
  348. }
  349. void
  350. MachineInfo::GetRetAddr(PADDR Addr)
  351. {
  352. DEBUG_STACK_FRAME StackFrame;
  353. if (StackTrace(0, 0, 0, &StackFrame, 1, 0, 0, FALSE) > 0)
  354. {
  355. ADDRFLAT(Addr, StackFrame.ReturnOffset);
  356. }
  357. else
  358. {
  359. ErrOut("StackTrace failed\n");
  360. ADDRFLAT(Addr, 0);
  361. }
  362. }
  363. BOOL
  364. MachineInfo::GetPrefixedSymbolOffset(ULONG64 SymOffset,
  365. ULONG Flags,
  366. PULONG64 PrefixedSymOffset)
  367. {
  368. DBG_ASSERT(m_SymPrefix == NULL);
  369. // This routine should never be called since there's no prefix.
  370. return FALSE;
  371. }
  372. HRESULT
  373. MachineInfo::ReadDynamicFunctionTable(ULONG64 Table,
  374. PULONG64 NextTable,
  375. PULONG64 MinAddress,
  376. PULONG64 MaxAddress,
  377. PULONG64 BaseAddress,
  378. PULONG64 TableData,
  379. PULONG TableSize,
  380. PWSTR OutOfProcessDll,
  381. PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE RawTable)
  382. {
  383. // No dynamic function table support.
  384. return E_UNEXPECTED;
  385. }
  386. PVOID
  387. MachineInfo::FindDynamicFunctionEntry(PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE Table,
  388. ULONG64 Address,
  389. PVOID TableData,
  390. ULONG TableSize)
  391. {
  392. // No dynamic function tables so no match.
  393. return NULL;
  394. }
  395. void
  396. MachineInfo::FlushPerExecutionCaches(void)
  397. {
  398. ZeroMemory(m_PageDirectories, sizeof(m_PageDirectories));
  399. m_Translating = FALSE;
  400. }
  401. void
  402. MachineInfo::FormAddr(ULONG SegOrReg, ULONG64 Off,
  403. ULONG Flags, PADDR Address)
  404. {
  405. PDESCRIPTOR64 SegDesc = NULL;
  406. DESCRIPTOR64 Desc;
  407. Address->off = Off;
  408. if (Flags & FORM_SEGREG)
  409. {
  410. ULONG SegRegNum = GetSegRegNum(SegOrReg);
  411. if (SegRegNum)
  412. {
  413. Address->seg = GetReg16(SegRegNum);
  414. }
  415. else
  416. {
  417. Address->seg = 0;
  418. }
  419. }
  420. else
  421. {
  422. Address->seg = (USHORT)SegOrReg;
  423. }
  424. if (Flags & FORM_VM86)
  425. {
  426. Address->type = ADDR_V86;
  427. }
  428. else if (Address->seg == 0)
  429. {
  430. // A segment wasn't used or segmentation doesn't exist.
  431. Address->type = ADDR_FLAT;
  432. }
  433. else
  434. {
  435. HRESULT Status;
  436. if (Flags & FORM_SEGREG)
  437. {
  438. Status = GetSegRegDescriptor(SegOrReg, &Desc);
  439. }
  440. else
  441. {
  442. Status = g_Target->
  443. GetSelDescriptor(this, g_CurrentProcess->CurrentThread->Handle,
  444. SegOrReg, &Desc);
  445. }
  446. if (Status == S_OK)
  447. {
  448. static USHORT MainCodeSeg = 0;
  449. SegDesc = &Desc;
  450. if (((Flags & FORM_CODE) && (Desc.Flags & X86_DESC_LONG_MODE)) ||
  451. ((Flags & FORM_CODE) == 0 && g_Amd64InCode64))
  452. {
  453. Address->type = ADDR_1664;
  454. }
  455. else if (Desc.Flags & X86_DESC_DEFAULT_BIG)
  456. {
  457. Address->type = ADDR_1632;
  458. }
  459. else
  460. {
  461. Address->type = ADDR_16;
  462. }
  463. if ((Flags & FORM_CODE) &&
  464. ((g_EffMachine == IMAGE_FILE_MACHINE_I386 &&
  465. Address->type == ADDR_1632) ||
  466. (g_EffMachine == IMAGE_FILE_MACHINE_AMD64 &&
  467. Address->type == ADDR_1664)))
  468. {
  469. if ( MainCodeSeg == 0 )
  470. {
  471. if ( Desc.Base == 0 )
  472. {
  473. MainCodeSeg = Address->seg;
  474. }
  475. }
  476. if ( Address->seg == MainCodeSeg )
  477. {
  478. Address->type = ADDR_FLAT;
  479. }
  480. }
  481. }
  482. else
  483. {
  484. Address->type = ADDR_16;
  485. }
  486. }
  487. ComputeFlatAddress(Address, SegDesc);
  488. }
  489. void
  490. MachineInfo::PrintStackFrameAddressesTitle(ULONG Flags)
  491. {
  492. if (!(Flags & DEBUG_STACK_FRAME_ADDRESSES_RA_ONLY))
  493. {
  494. PrintMultiPtrTitle("Child-SP", 1);
  495. }
  496. PrintMultiPtrTitle("RetAddr", 1);
  497. }
  498. void
  499. MachineInfo::PrintStackFrameAddresses(ULONG Flags,
  500. PDEBUG_STACK_FRAME StackFrame)
  501. {
  502. if (!(Flags & DEBUG_STACK_FRAME_ADDRESSES_RA_ONLY))
  503. {
  504. dprintf("%s ", FormatAddr64(StackFrame->StackOffset));
  505. }
  506. dprintf("%s ", FormatAddr64(StackFrame->ReturnOffset));
  507. }
  508. void
  509. MachineInfo::PrintStackArgumentsTitle(ULONG Flags)
  510. {
  511. dprintf(": ");
  512. PrintMultiPtrTitle("Args to Child", 4);
  513. dprintf(": ");
  514. }
  515. void
  516. MachineInfo::PrintStackArguments(ULONG Flags,
  517. PDEBUG_STACK_FRAME StackFrame)
  518. {
  519. dprintf(": %s %s %s %s : ",
  520. FormatAddr64(StackFrame->Params[0]),
  521. FormatAddr64(StackFrame->Params[1]),
  522. FormatAddr64(StackFrame->Params[2]),
  523. FormatAddr64(StackFrame->Params[3]));
  524. }
  525. void
  526. MachineInfo::PrintStackCallSiteTitle(ULONG Flags)
  527. {
  528. dprintf("Call Site");
  529. }
  530. void
  531. MachineInfo::PrintStackCallSite(ULONG Flags,
  532. PDEBUG_STACK_FRAME StackFrame,
  533. CHAR SymBuf[],
  534. DWORD64 Displacement,
  535. USHORT StdCallArgs)
  536. {
  537. if (*SymBuf)
  538. {
  539. dprintf("%s", SymBuf);
  540. if (!(Flags & DEBUG_STACK_PARAMETERS) ||
  541. !ShowFunctionParameters(StackFrame, SymBuf, Displacement))
  542. {
  543. // We dont see the parameters
  544. }
  545. if (Displacement)
  546. {
  547. dprintf("+");
  548. }
  549. }
  550. if (Displacement || !*SymBuf)
  551. {
  552. dprintf("0x%s", FormatDisp64(Displacement));
  553. }
  554. }
  555. void
  556. MachineInfo::PrintStackNonvolatileRegisters(ULONG Flags,
  557. PDEBUG_STACK_FRAME StackFrame,
  558. PCROSS_PLATFORM_CONTEXT Context,
  559. ULONG FrameNum)
  560. {
  561. // Empty base implementation.
  562. }
  563. //----------------------------------------------------------------------------
  564. //
  565. // Functions.
  566. //
  567. //----------------------------------------------------------------------------
  568. HRESULT
  569. InitializeMachines(ULONG TargetMachine)
  570. {
  571. HRESULT Status;
  572. ULONG i;
  573. if (DbgKdApi64 != (g_SystemVersion > NT_SVER_NT4))
  574. {
  575. WarnOut("Debug API version does not match system version\n");
  576. }
  577. if (IsImageMachineType64(TargetMachine) && !DbgKdApi64)
  578. {
  579. WarnOut("64-bit machine not using 64-bit API\n");
  580. }
  581. memset(g_AllMachines, 0, sizeof(g_AllMachines));
  582. // There are several different X86 machines due to
  583. // the emulations available on various systems and CPUs.
  584. switch(TargetMachine)
  585. {
  586. case IMAGE_FILE_MACHINE_IA64:
  587. g_AllMachines[MACHIDX_I386] = &g_X86OnIa64Machine;
  588. break;
  589. default:
  590. g_AllMachines[MACHIDX_I386] = &g_X86Machine;
  591. break;
  592. }
  593. g_AllMachines[MACHIDX_ALPHA] = &g_Axp32Machine;
  594. g_AllMachines[MACHIDX_AXP64] = &g_Axp64Machine;
  595. g_AllMachines[MACHIDX_IA64] = &g_Ia64Machine;
  596. g_AllMachines[MACHIDX_AMD64] = &g_Amd64Machine;
  597. g_TargetMachineType = TargetMachine;
  598. g_TargetMachine = MachineTypeInfo(TargetMachine);
  599. ZeroMemory(&g_InitProcessorId, sizeof(g_InitProcessorId));
  600. for (i = 0; i < MACHIDX_COUNT; i++)
  601. {
  602. DBG_ASSERT(g_AllMachines[i] != NULL);
  603. if ((Status = g_AllMachines[i]->InitializeConstants()) != S_OK)
  604. {
  605. return Status;
  606. }
  607. }
  608. if (!IS_TARGET_SET())
  609. {
  610. return S_OK;
  611. }
  612. for (i = 0; i < MACHIDX_COUNT; i++)
  613. {
  614. if ((Status = g_AllMachines[i]->InitializeForTarget()) != S_OK)
  615. {
  616. return Status;
  617. }
  618. }
  619. if (g_TargetMachineType == IMAGE_FILE_MACHINE_UNKNOWN)
  620. {
  621. return S_OK;
  622. }
  623. // Get the base processor ID for determing what
  624. // kind of features a processor supports. The
  625. // assumption is that the processors in a machine
  626. // will be similar enough that retrieving this
  627. // for one processor is sufficient.
  628. // If this fails we continue on without a processor ID.
  629. if (!IS_DUMP_TARGET())
  630. {
  631. g_Target->GetProcessorId(0, &g_InitProcessorId);
  632. }
  633. for (i = 0; i < MACHIDX_COUNT; i++)
  634. {
  635. if ((Status = g_AllMachines[i]->InitializeForProcessor()) != S_OK)
  636. {
  637. return Status;
  638. }
  639. }
  640. return S_OK;
  641. }
  642. void
  643. SetEffMachine(ULONG Machine, BOOL Notify)
  644. {
  645. BOOL Changed = g_EffMachine != Machine;
  646. if (Changed &&
  647. g_EffMachine != IMAGE_FILE_MACHINE_UNKNOWN &&
  648. g_EffMachine != g_TargetMachineType)
  649. {
  650. // If the previous machine was not the target machine
  651. // it may be an emulated machine that uses the
  652. // target machine's context. In that case we need to
  653. // make sure that any dirty registers it has get flushed
  654. // so that if the new effective machine is the target
  655. // machine it'll show changes due to changes through
  656. // the emulated machine.
  657. if (g_Machine->SetContext() != S_OK)
  658. {
  659. // Error already displayed.
  660. return;
  661. }
  662. }
  663. g_EffMachine = Machine;
  664. g_EffMachineIndex = MachineTypeIndex(Machine);
  665. DBG_ASSERT(g_EffMachineIndex <= MACHIDX_COUNT);
  666. g_Machine = g_AllMachines[g_EffMachineIndex];
  667. if (Changed && Notify)
  668. {
  669. NotifyChangeEngineState(DEBUG_CES_EFFECTIVE_PROCESSOR,
  670. g_EffMachine, TRUE);
  671. }
  672. }
  673. MachineIndex
  674. MachineTypeIndex(ULONG Machine)
  675. {
  676. switch(Machine)
  677. {
  678. case IMAGE_FILE_MACHINE_I386:
  679. return MACHIDX_I386;
  680. case IMAGE_FILE_MACHINE_ALPHA:
  681. return MACHIDX_ALPHA;
  682. case IMAGE_FILE_MACHINE_AXP64:
  683. return MACHIDX_AXP64;
  684. case IMAGE_FILE_MACHINE_IA64:
  685. return MACHIDX_IA64;
  686. case IMAGE_FILE_MACHINE_AMD64:
  687. return MACHIDX_AMD64;
  688. default:
  689. return MACHIDX_COUNT;
  690. }
  691. }
  692. void
  693. CacheReportInstructions(ULONG64 Pc, ULONG Count, PUCHAR Stream)
  694. {
  695. // There was a long-standing bug in the kernel
  696. // where it didn't properly remove all breakpoints
  697. // present in the instruction stream reported to
  698. // the debugger. If this kernel suffers from the
  699. // problem just ignore the stream contents.
  700. if (Count == 0 || g_TargetBuildNumber < 2300)
  701. {
  702. return;
  703. }
  704. g_VirtualCache.Add(Pc, Stream, Count);
  705. }
  706. void
  707. FlushMachinePerExecutionCaches(void)
  708. {
  709. ULONG i;
  710. for (i = 0; i < MACHIDX_COUNT; i++)
  711. {
  712. g_AllMachines[i]->FlushPerExecutionCaches();
  713. }
  714. }
  715. //----------------------------------------------------------------------------
  716. //
  717. // Common code and constants.
  718. //
  719. //----------------------------------------------------------------------------
  720. /* OutputHex - output hex value
  721. *
  722. * Purpose:
  723. * Output the value in outvalue into the buffer
  724. * pointed by *pBuf. The value may be signed
  725. * or unsigned depending on the value fSigned.
  726. *
  727. * Input:
  728. * outvalue - value to output
  729. * length - length in digits
  730. * fSigned - TRUE if signed else FALSE
  731. *
  732. * Output:
  733. * None.
  734. *
  735. ***********************************************************************/
  736. UCHAR g_HexDigit[16] =
  737. {
  738. '0', '1', '2', '3', '4', '5', '6', '7',
  739. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
  740. };
  741. void
  742. MachineInfo::BufferHex (
  743. ULONG64 outvalue,
  744. ULONG length,
  745. BOOL fSigned
  746. )
  747. {
  748. UCHAR digit[32];
  749. LONG index = 0;
  750. DBG_ASSERT(length <= 32);
  751. if (fSigned && (LONGLONG)outvalue < 0)
  752. {
  753. *m_Buf++ = '-';
  754. outvalue = - (LONGLONG)outvalue;
  755. }
  756. do
  757. {
  758. digit[index++] = g_HexDigit[outvalue & 0xf];
  759. outvalue >>= 4;
  760. }
  761. while ((fSigned && outvalue) || (!fSigned && index < (LONG)length));
  762. while (--index >= 0)
  763. {
  764. *m_Buf++ = digit[index];
  765. }
  766. }
  767. /* BlankFill - blank-fill buffer
  768. *
  769. * Purpose:
  770. * To fill the buffer at *pBuf with blanks until
  771. * position count is reached.
  772. *
  773. * Input:
  774. * None.
  775. *
  776. * Output:
  777. * None.
  778. *
  779. ***********************************************************************/
  780. void
  781. MachineInfo::BufferBlanks(ULONG count)
  782. {
  783. do
  784. {
  785. *m_Buf++ = ' ';
  786. }
  787. while (m_Buf < m_BufStart + count);
  788. }
  789. /* OutputString - output string
  790. *
  791. * Purpose:
  792. * Copy the string into the buffer pointed by pBuf.
  793. *
  794. * Input:
  795. * *pStr - pointer to string
  796. *
  797. * Output:
  798. * None.
  799. *
  800. ***********************************************************************/
  801. void
  802. MachineInfo::BufferString(PCSTR String)
  803. {
  804. while (*String)
  805. {
  806. *m_Buf++ = *String++;
  807. }
  808. }
  809. void
  810. MachineInfo::PrintMultiPtrTitle(const CHAR* Title, USHORT PtrNum)
  811. {
  812. size_t PtrLen = (strlen(FormatAddr64(0)) + 1) * PtrNum;
  813. size_t TitleLen = strlen(Title);
  814. if (PtrLen < TitleLen)
  815. {
  816. // Extremly rare case so keep it simple while slow
  817. for (size_t i = 0; i < PtrLen - 1; ++i)
  818. {
  819. dprintf("%c", Title[i]);
  820. }
  821. dprintf(" ");
  822. }
  823. else
  824. {
  825. dprintf(Title);
  826. if (PtrLen > TitleLen)
  827. {
  828. char Format[16];
  829. _snprintf(Format, sizeof(Format) - 1,
  830. "%% %ds", PtrLen - TitleLen);
  831. dprintf(Format, "");
  832. }
  833. }
  834. }
  835. CHAR g_F0[] = "f0";
  836. CHAR g_F1[] = "f1";
  837. CHAR g_F2[] = "f2";
  838. CHAR g_F3[] = "f3";
  839. CHAR g_F4[] = "f4";
  840. CHAR g_F5[] = "f5";
  841. CHAR g_F6[] = "f6";
  842. CHAR g_F7[] = "f7";
  843. CHAR g_F8[] = "f8";
  844. CHAR g_F9[] = "f9";
  845. CHAR g_F10[] = "f10";
  846. CHAR g_F11[] = "f11";
  847. CHAR g_F12[] = "f12";
  848. CHAR g_F13[] = "f13";
  849. CHAR g_F14[] = "f14";
  850. CHAR g_F15[] = "f15";
  851. CHAR g_F16[] = "f16";
  852. CHAR g_F17[] = "f17";
  853. CHAR g_F18[] = "f18";
  854. CHAR g_F19[] = "f19";
  855. CHAR g_F20[] = "f20";
  856. CHAR g_F21[] = "f21";
  857. CHAR g_F22[] = "f22";
  858. CHAR g_F23[] = "f23";
  859. CHAR g_F24[] = "f24";
  860. CHAR g_F25[] = "f25";
  861. CHAR g_F26[] = "f26";
  862. CHAR g_F27[] = "f27";
  863. CHAR g_F28[] = "f28";
  864. CHAR g_F29[] = "f29";
  865. CHAR g_F30[] = "f30";
  866. CHAR g_F31[] = "f31";
  867. CHAR g_R0[] = "r0";
  868. CHAR g_R1[] = "r1";
  869. CHAR g_R2[] = "r2";
  870. CHAR g_R3[] = "r3";
  871. CHAR g_R4[] = "r4";
  872. CHAR g_R5[] = "r5";
  873. CHAR g_R6[] = "r6";
  874. CHAR g_R7[] = "r7";
  875. CHAR g_R8[] = "r8";
  876. CHAR g_R9[] = "r9";
  877. CHAR g_R10[] = "r10";
  878. CHAR g_R11[] = "r11";
  879. CHAR g_R12[] = "r12";
  880. CHAR g_R13[] = "r13";
  881. CHAR g_R14[] = "r14";
  882. CHAR g_R15[] = "r15";
  883. CHAR g_R16[] = "r16";
  884. CHAR g_R17[] = "r17";
  885. CHAR g_R18[] = "r18";
  886. CHAR g_R19[] = "r19";
  887. CHAR g_R20[] = "r20";
  888. CHAR g_R21[] = "r21";
  889. CHAR g_R22[] = "r22";
  890. CHAR g_R23[] = "r23";
  891. CHAR g_R24[] = "r24";
  892. CHAR g_R25[] = "r25";
  893. CHAR g_R26[] = "r26";
  894. CHAR g_R27[] = "r27";
  895. CHAR g_R28[] = "r28";
  896. CHAR g_R29[] = "r29";
  897. CHAR g_R30[] = "r30";
  898. CHAR g_R31[] = "r31";