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.

2763 lines
60 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // IDebugSystemObjects implementations.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999-2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. ULONG64 g_ImplicitThreadData;
  10. BOOL g_ImplicitThreadDataIsDefault = TRUE;
  11. ULONG64 g_ImplicitProcessData;
  12. BOOL g_ImplicitProcessDataIsDefault = TRUE;
  13. //----------------------------------------------------------------------------
  14. //
  15. // Utility functions.
  16. //
  17. //----------------------------------------------------------------------------
  18. HRESULT
  19. EmulateNtSelDescriptor(MachineInfo* Machine,
  20. ULONG Selector, PDESCRIPTOR64 Desc)
  21. {
  22. // Only emulate on platforms that support segments.
  23. if (Machine->m_ExecTypes[0] != IMAGE_FILE_MACHINE_I386 &&
  24. Machine->m_ExecTypes[0] != IMAGE_FILE_MACHINE_AMD64)
  25. {
  26. return E_UNEXPECTED;
  27. }
  28. ULONG Type, Gran;
  29. //
  30. // For user mode and triage dumps, we can hardcode the selector
  31. // since we do not have it anywhere.
  32. // XXX drewb - How many should we fake? There are quite
  33. // a few KGDT entries. Which ones are valid in user mode and
  34. // which are valid for a triage dump?
  35. //
  36. switch(Selector)
  37. {
  38. case X86_KGDT_R3_TEB + 3:
  39. HRESULT Status;
  40. // In user mode fs points to the TEB so fake up
  41. // a selector for it.
  42. if ((Status = GetImplicitThreadDataTeb(&Desc->Base)) != S_OK)
  43. {
  44. return Status;
  45. }
  46. if (Machine != g_TargetMachine)
  47. {
  48. ULONG Read;
  49. // We're asking for an emulated machine's TEB.
  50. // The only case we currently handle is x86-on-IA64
  51. // for Wow64, where the 32-bit TEB pointer is
  52. // stored in NT_TIB.ExceptionList.
  53. // Conveniently, this is the very first entry.
  54. if ((Status = g_Target->ReadVirtual(Desc->Base, &Desc->Base,
  55. sizeof(ULONG), &Read)) != S_OK)
  56. {
  57. return Status;
  58. }
  59. if (Read != sizeof(ULONG))
  60. {
  61. return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  62. }
  63. Desc->Base = EXTEND64(Desc->Base);
  64. }
  65. Desc->Limit = Machine->m_PageSize - 1;
  66. Type = 0x13;
  67. Gran = 0;
  68. break;
  69. case X86_KGDT_R3_DATA + 3:
  70. Desc->Base = 0;
  71. Desc->Limit = Machine->m_Ptr64 ? 0xffffffffffffffffI64 : 0xffffffff;
  72. Type = 0x13;
  73. Gran = X86_DESC_GRANULARITY;
  74. break;
  75. default:
  76. Desc->Base = 0;
  77. Desc->Limit = Machine->m_Ptr64 ? 0xffffffffffffffffI64 : 0xffffffff;
  78. Type = 0x1b;
  79. Gran = X86_DESC_GRANULARITY |
  80. (Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_AMD64 ?
  81. X86_DESC_LONG_MODE : 0);
  82. break;
  83. }
  84. Desc->Flags = Gran | X86_DESC_DEFAULT_BIG | X86_DESC_PRESENT | Type |
  85. (IS_USER_TARGET() ?
  86. (3 << X86_DESC_PRIVILEGE_SHIFT) : (Selector & 3));
  87. return S_OK;
  88. }
  89. void
  90. X86DescriptorToDescriptor64(PX86_LDT_ENTRY X86Desc,
  91. PDESCRIPTOR64 Desc64)
  92. {
  93. Desc64->Base = EXTEND64((ULONG)X86Desc->BaseLow +
  94. ((ULONG)X86Desc->HighWord.Bits.BaseMid << 16) +
  95. ((ULONG)X86Desc->HighWord.Bytes.BaseHi << 24));
  96. Desc64->Limit = (ULONG)X86Desc->LimitLow +
  97. ((ULONG)X86Desc->HighWord.Bits.LimitHi << 16);
  98. if (X86Desc->HighWord.Bits.Granularity)
  99. {
  100. Desc64->Limit = (Desc64->Limit << X86_PAGE_SHIFT) +
  101. ((1 << X86_PAGE_SHIFT) - 1);
  102. }
  103. Desc64->Flags = (ULONG)X86Desc->HighWord.Bytes.Flags1 +
  104. (((ULONG)X86Desc->HighWord.Bytes.Flags2 >> 4) << 8);
  105. }
  106. HRESULT
  107. ReadX86Descriptor(ULONG Selector, ULONG64 Base, ULONG Limit,
  108. PDESCRIPTOR64 Desc)
  109. {
  110. ULONG Index;
  111. // Mask off irrelevant bits
  112. Index = Selector & ~0x7;
  113. // Check to make sure that the selector is within the table bounds
  114. if (Index > Limit)
  115. {
  116. return E_INVALIDARG;
  117. }
  118. HRESULT Status;
  119. X86_LDT_ENTRY X86Desc;
  120. ULONG Result;
  121. Status = g_Target->ReadVirtual(Base + Index, &X86Desc, sizeof(X86Desc),
  122. &Result);
  123. if (Status != S_OK)
  124. {
  125. return Status;
  126. }
  127. if (Result != sizeof(X86Desc))
  128. {
  129. return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  130. }
  131. X86DescriptorToDescriptor64(&X86Desc, Desc);
  132. return S_OK;
  133. }
  134. //----------------------------------------------------------------------------
  135. //
  136. // TargetInfo system object methods.
  137. //
  138. //----------------------------------------------------------------------------
  139. HRESULT
  140. TargetInfo::GetProcessorSystemDataOffset(
  141. IN ULONG Processor,
  142. IN ULONG Index,
  143. OUT PULONG64 Offset
  144. )
  145. {
  146. if (!IS_KERNEL_TARGET())
  147. {
  148. return E_UNEXPECTED;
  149. }
  150. // XXX drewb - Temporary until different OS support is
  151. // sorted out.
  152. if (g_ActualSystemVersion < NT_SVER_START ||
  153. g_ActualSystemVersion > NT_SVER_END)
  154. {
  155. return E_UNEXPECTED;
  156. }
  157. HRESULT Status;
  158. ULONG Read;
  159. if (g_TargetMachineType == IMAGE_FILE_MACHINE_I386)
  160. {
  161. DESCRIPTOR64 Entry;
  162. //
  163. // We always need the PCR address so go ahead and get it.
  164. //
  165. if (!IS_CONTEXT_ACCESSIBLE())
  166. {
  167. X86_DESCRIPTOR GdtDesc;
  168. // We can't go through the normal context segreg mapping
  169. // but all we really need is an entry from the
  170. // kernel GDT that should always be present and
  171. // constant while the system is initialized. We
  172. // can get the GDT information from the x86 control
  173. // space so do that.
  174. if ((Status = ReadControl
  175. (Processor, g_TargetMachine->m_OffsetSpecialRegisters +
  176. FIELD_OFFSET(X86_KSPECIAL_REGISTERS, Gdtr),
  177. &GdtDesc, sizeof(GdtDesc), &Read)) != S_OK ||
  178. Read != sizeof(GdtDesc) ||
  179. (Status = ReadX86Descriptor(X86_KGDT_R0_PCR,
  180. EXTEND64(GdtDesc.Base),
  181. GdtDesc.Limit, &Entry)) != S_OK)
  182. {
  183. ErrOut("Unable to read selector for PCR for processor %u\n",
  184. Processor);
  185. return Status != S_OK ?
  186. Status : HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  187. }
  188. }
  189. else
  190. {
  191. if ((Status = GetSelDescriptor(g_TargetMachine,
  192. VIRTUAL_THREAD_HANDLE(Processor),
  193. X86_KGDT_R0_PCR, &Entry)) != S_OK)
  194. {
  195. ErrOut("Unable to read selector for PCR for processor %u\n",
  196. Processor);
  197. return Status;
  198. }
  199. }
  200. switch(Index)
  201. {
  202. case DEBUG_DATA_KPCR_OFFSET:
  203. Status = ReadPointer(g_TargetMachine,
  204. Entry.Base + FIELD_OFFSET(X86_KPCR, SelfPcr),
  205. Offset);
  206. if ((Status != S_OK) || Entry.Base != *Offset)
  207. {
  208. ErrOut("KPCR is corrupted !");
  209. }
  210. *Offset = Entry.Base;
  211. break;
  212. case DEBUG_DATA_KPRCB_OFFSET:
  213. case DEBUG_DATA_KTHREAD_OFFSET:
  214. Status = ReadPointer(g_TargetMachine,
  215. Entry.Base + FIELD_OFFSET(X86_KPCR, Prcb),
  216. Offset);
  217. if (Status != S_OK)
  218. {
  219. return Status;
  220. }
  221. if (Index == DEBUG_DATA_KPRCB_OFFSET)
  222. {
  223. break;
  224. }
  225. Status = ReadPointer(g_TargetMachine,
  226. *Offset + KPRCB_CURRENT_THREAD_OFFSET_32,
  227. Offset);
  228. if (Status != S_OK)
  229. {
  230. return Status;
  231. }
  232. break;
  233. }
  234. }
  235. else
  236. {
  237. ULONG ReadSize = g_TargetMachine->m_Ptr64 ?
  238. sizeof(ULONG64) : sizeof(ULONG);
  239. ULONG64 Address;
  240. switch(g_TargetMachineType)
  241. {
  242. case IMAGE_FILE_MACHINE_ALPHA:
  243. case IMAGE_FILE_MACHINE_AXP64:
  244. switch(Index)
  245. {
  246. case DEBUG_DATA_KPCR_OFFSET:
  247. Index = ALPHA_DEBUG_CONTROL_SPACE_PCR;
  248. break;
  249. case DEBUG_DATA_KPRCB_OFFSET:
  250. Index = ALPHA_DEBUG_CONTROL_SPACE_PRCB;
  251. break;
  252. case DEBUG_DATA_KTHREAD_OFFSET:
  253. Index = ALPHA_DEBUG_CONTROL_SPACE_THREAD;
  254. break;
  255. }
  256. break;
  257. case IMAGE_FILE_MACHINE_IA64:
  258. switch(Index)
  259. {
  260. case DEBUG_DATA_KPCR_OFFSET:
  261. Index = IA64_DEBUG_CONTROL_SPACE_PCR;
  262. break;
  263. case DEBUG_DATA_KPRCB_OFFSET:
  264. Index = IA64_DEBUG_CONTROL_SPACE_PRCB;
  265. break;
  266. case DEBUG_DATA_KTHREAD_OFFSET:
  267. Index = IA64_DEBUG_CONTROL_SPACE_THREAD;
  268. break;
  269. }
  270. break;
  271. case IMAGE_FILE_MACHINE_AMD64:
  272. switch(Index)
  273. {
  274. case DEBUG_DATA_KPCR_OFFSET:
  275. Index = AMD64_DEBUG_CONTROL_SPACE_PCR;
  276. break;
  277. case DEBUG_DATA_KPRCB_OFFSET:
  278. Index = AMD64_DEBUG_CONTROL_SPACE_PRCB;
  279. break;
  280. case DEBUG_DATA_KTHREAD_OFFSET:
  281. Index = AMD64_DEBUG_CONTROL_SPACE_THREAD;
  282. break;
  283. }
  284. break;
  285. }
  286. Status = ReadControl(Processor, Index, &Address, ReadSize, &Read);
  287. if (Status != S_OK)
  288. {
  289. return Status;
  290. }
  291. else if (Read != ReadSize)
  292. {
  293. return HRESULT_FROM_WIN32(ERROR_READ_FAULT);
  294. }
  295. if (!g_TargetMachine->m_Ptr64)
  296. {
  297. Address = EXTEND64(Address);
  298. }
  299. *Offset = Address;
  300. }
  301. return S_OK;
  302. }
  303. HRESULT
  304. TargetInfo::GetTargetSegRegDescriptors(ULONG64 Thread,
  305. ULONG Start, ULONG Count,
  306. PDESCRIPTOR64 Descs)
  307. {
  308. while (Count-- > 0)
  309. {
  310. Descs->Flags = SEGDESC_INVALID;
  311. Descs++;
  312. }
  313. return S_OK;
  314. }
  315. HRESULT
  316. TargetInfo::GetTargetSpecialRegisters
  317. (ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  318. {
  319. HRESULT Status;
  320. ULONG Done;
  321. Status = ReadControl(VIRTUAL_THREAD_INDEX(Thread),
  322. g_TargetMachine->m_OffsetSpecialRegisters,
  323. Special, g_TargetMachine->m_SizeKspecialRegisters,
  324. &Done);
  325. if (Status != S_OK)
  326. {
  327. return Status;
  328. }
  329. return Done == g_TargetMachine->m_SizeKspecialRegisters ? S_OK : E_FAIL;
  330. }
  331. HRESULT
  332. TargetInfo::SetTargetSpecialRegisters
  333. (ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  334. {
  335. HRESULT Status;
  336. ULONG Done;
  337. Status = WriteControl(VIRTUAL_THREAD_INDEX(Thread),
  338. g_TargetMachine->m_OffsetSpecialRegisters,
  339. Special, g_TargetMachine->m_SizeKspecialRegisters,
  340. &Done);
  341. if (Status != S_OK)
  342. {
  343. return Status;
  344. }
  345. return Done == g_TargetMachine->m_SizeKspecialRegisters ? S_OK : E_FAIL;
  346. }
  347. void
  348. TargetInfo::InvalidateTargetContext(void)
  349. {
  350. // Nothing to do.
  351. }
  352. HRESULT
  353. TargetInfo::GetContext(
  354. ULONG64 Thread,
  355. PCROSS_PLATFORM_CONTEXT Context
  356. )
  357. {
  358. if (g_TargetMachine == NULL)
  359. {
  360. return E_UNEXPECTED;
  361. }
  362. HRESULT Status;
  363. CROSS_PLATFORM_CONTEXT TargetContextBuffer;
  364. PCROSS_PLATFORM_CONTEXT TargetContext;
  365. if (g_TargetMachine->m_SverCanonicalContext <= g_SystemVersion)
  366. {
  367. TargetContext = Context;
  368. }
  369. else
  370. {
  371. TargetContext = &TargetContextBuffer;
  372. g_TargetMachine->InitializeContextFlags(TargetContext,
  373. g_SystemVersion);
  374. }
  375. Status = GetTargetContext(Thread, TargetContext);
  376. if (Status == S_OK && TargetContext == &TargetContextBuffer)
  377. {
  378. Status = g_TargetMachine->
  379. ConvertContextFrom(Context, g_SystemVersion,
  380. g_TargetMachine->m_SizeTargetContext,
  381. TargetContext);
  382. // Conversion should always succeed since the size is
  383. // known to be valid.
  384. DBG_ASSERT(Status == S_OK);
  385. }
  386. return Status;
  387. }
  388. HRESULT
  389. TargetInfo::SetContext(
  390. ULONG64 Thread,
  391. PCROSS_PLATFORM_CONTEXT Context
  392. )
  393. {
  394. if (g_TargetMachine == NULL)
  395. {
  396. return E_UNEXPECTED;
  397. }
  398. CROSS_PLATFORM_CONTEXT TargetContextBuffer;
  399. PCROSS_PLATFORM_CONTEXT TargetContext;
  400. if (g_TargetMachine->m_SverCanonicalContext <= g_SystemVersion)
  401. {
  402. TargetContext = Context;
  403. }
  404. else
  405. {
  406. TargetContext = &TargetContextBuffer;
  407. HRESULT Status = g_TargetMachine->
  408. ConvertContextTo(Context, g_SystemVersion,
  409. g_TargetMachine->m_SizeTargetContext,
  410. TargetContext);
  411. // Conversion should always succeed since the size is
  412. // known to be valid.
  413. DBG_ASSERT(Status == S_OK);
  414. }
  415. return SetTargetContext(Thread, TargetContext);
  416. }
  417. HRESULT
  418. TargetInfo::KdGetThreadInfoDataOffset(PTHREAD_INFO Thread,
  419. ULONG64 ThreadHandle,
  420. PULONG64 Offset)
  421. {
  422. if (Thread != NULL && Thread->DataOffset != 0)
  423. {
  424. *Offset = Thread->DataOffset;
  425. return S_OK;
  426. }
  427. ULONG Processor;
  428. if (Thread != NULL)
  429. {
  430. ThreadHandle = Thread->Handle;
  431. }
  432. Processor = VIRTUAL_THREAD_INDEX(ThreadHandle);
  433. HRESULT Status;
  434. Status = GetProcessorSystemDataOffset(Processor,
  435. DEBUG_DATA_KTHREAD_OFFSET,
  436. Offset);
  437. if (Status == S_OK && Thread != NULL)
  438. {
  439. Thread->DataOffset = *Offset;
  440. }
  441. return Status;
  442. }
  443. HRESULT
  444. TargetInfo::KdGetProcessInfoDataOffset(PTHREAD_INFO Thread,
  445. ULONG Processor,
  446. ULONG64 ThreadData,
  447. PULONG64 Offset)
  448. {
  449. // Process data offsets are not cached for kernel mode
  450. // since the only PROCESS_INFO is for kernel space.
  451. ULONG64 ProcessAddr;
  452. HRESULT Status;
  453. if (ThreadData == 0)
  454. {
  455. Status = GetThreadInfoDataOffset(Thread,
  456. VIRTUAL_THREAD_HANDLE(Processor),
  457. &ThreadData);
  458. if (Status != S_OK)
  459. {
  460. return Status;
  461. }
  462. }
  463. ThreadData += g_TargetMachine->m_OffsetKThreadApcProcess;
  464. Status = ReadPointer(g_TargetMachine, ThreadData, &ProcessAddr);
  465. if (Status != S_OK)
  466. {
  467. ErrOut("Unable to read KTHREAD address %p\n", ThreadData);
  468. }
  469. else
  470. {
  471. *Offset = ProcessAddr;
  472. }
  473. return Status;
  474. }
  475. HRESULT
  476. TargetInfo::KdGetThreadInfoTeb(PTHREAD_INFO Thread,
  477. ULONG ThreadIndex,
  478. ULONG64 ThreadData,
  479. PULONG64 Offset)
  480. {
  481. ULONG64 TebAddr;
  482. HRESULT Status;
  483. if (ThreadData == 0)
  484. {
  485. Status = GetThreadInfoDataOffset(Thread,
  486. VIRTUAL_THREAD_HANDLE(ThreadIndex),
  487. &ThreadData);
  488. if (Status != S_OK)
  489. {
  490. return Status;
  491. }
  492. }
  493. ThreadData += g_TargetMachine->m_OffsetKThreadTeb;
  494. Status = ReadPointer(g_TargetMachine, ThreadData, &TebAddr);
  495. if (Status != S_OK)
  496. {
  497. ErrOut("Could not read KTHREAD address %p\n", ThreadData);
  498. }
  499. else
  500. {
  501. *Offset = TebAddr;
  502. }
  503. return Status;
  504. }
  505. HRESULT
  506. TargetInfo::KdGetProcessInfoPeb(PTHREAD_INFO Thread,
  507. ULONG Processor,
  508. ULONG64 ThreadData,
  509. PULONG64 Offset)
  510. {
  511. HRESULT Status;
  512. ULONG64 Process, PebAddr;
  513. Status = GetProcessInfoDataOffset(Thread, Processor,
  514. ThreadData, &Process);
  515. if (Status != S_OK)
  516. {
  517. return Status;
  518. }
  519. Process += g_TargetMachine->m_OffsetEprocessPeb;
  520. Status = ReadPointer(g_TargetMachine, Process, &PebAddr);
  521. if (Status != S_OK)
  522. {
  523. ErrOut("Could not read KPROCESS address %p\n", Process);
  524. }
  525. else
  526. {
  527. *Offset = PebAddr;
  528. }
  529. return Status;
  530. }
  531. #define SELECTOR_CACHE_LENGTH 6
  532. typedef struct _sc
  533. {
  534. struct _sc *nextYoungest;
  535. struct _sc *nextOldest;
  536. ULONG Processor;
  537. ULONG Selector;
  538. DESCRIPTOR64 Desc;
  539. } SELCACHEENTRY;
  540. SELCACHEENTRY SelectorCache[SELECTOR_CACHE_LENGTH], *selYoungest, *selOldest;
  541. void
  542. InitSelCache(void)
  543. {
  544. int i;
  545. for (i = 0; i < SELECTOR_CACHE_LENGTH; i++)
  546. {
  547. SelectorCache[i].nextYoungest = &SelectorCache[i+1];
  548. SelectorCache[i].nextOldest = &SelectorCache[i-1];
  549. SelectorCache[i].Processor = (LONG) -1;
  550. SelectorCache[i].Selector = 0;
  551. }
  552. SelectorCache[--i].nextYoungest = NULL;
  553. SelectorCache[0].nextOldest = NULL;
  554. selYoungest = &SelectorCache[i];
  555. selOldest = &SelectorCache[0];
  556. }
  557. BOOL
  558. FindSelector(ULONG Processor, ULONG Selector, PDESCRIPTOR64 Desc)
  559. {
  560. int i;
  561. for (i = 0; i < SELECTOR_CACHE_LENGTH; i++)
  562. {
  563. if (SelectorCache[i].Selector == Selector &&
  564. SelectorCache[i].Processor == Processor)
  565. {
  566. *Desc = SelectorCache[i].Desc;
  567. return TRUE;
  568. }
  569. }
  570. return FALSE;
  571. }
  572. void
  573. PutSelector(ULONG Processor, ULONG Selector, PDESCRIPTOR64 Desc)
  574. {
  575. selOldest->Processor = Processor;
  576. selOldest->Selector = Selector;
  577. selOldest->Desc = *Desc;
  578. (selOldest->nextYoungest)->nextOldest = NULL;
  579. selOldest->nextOldest = selYoungest;
  580. selYoungest->nextYoungest = selOldest;
  581. selYoungest = selOldest;
  582. selOldest = selOldest->nextYoungest;
  583. }
  584. HRESULT
  585. TargetInfo::KdGetSelDescriptor(MachineInfo* Machine,
  586. ULONG64 Thread, ULONG Selector,
  587. PDESCRIPTOR64 Desc)
  588. {
  589. ULONG Processor = VIRTUAL_THREAD_INDEX(Thread);
  590. if (FindSelector(Processor, Selector, Desc))
  591. {
  592. return S_OK;
  593. }
  594. PTHREAD_INFO CtxThread, ProcThread;
  595. ProcThread = FindThreadByHandle(g_CurrentProcess, Thread);
  596. if (ProcThread == NULL)
  597. {
  598. return E_INVALIDARG;
  599. }
  600. CtxThread = g_RegContextThread;
  601. ChangeRegContext(ProcThread);
  602. ULONG TableReg;
  603. DESCRIPTOR64 Table;
  604. HRESULT Status;
  605. // Find out whether this is a GDT or LDT selector
  606. if (Selector & 0x4)
  607. {
  608. TableReg = SEGREG_LDT;
  609. }
  610. else
  611. {
  612. TableReg = SEGREG_GDT;
  613. }
  614. //
  615. // Fetch the address and limit of the appropriate descriptor table,
  616. // then look up the selector entry.
  617. //
  618. if ((Status = Machine->GetSegRegDescriptor(TableReg, &Table)) != S_OK)
  619. {
  620. goto Exit;
  621. }
  622. Status = ReadX86Descriptor(Selector, Table.Base, (ULONG)Table.Limit, Desc);
  623. if (Status == S_OK)
  624. {
  625. PutSelector(Processor, Selector, Desc);
  626. }
  627. Exit:
  628. ChangeRegContext(CtxThread);
  629. return Status;
  630. }
  631. //----------------------------------------------------------------------------
  632. //
  633. // LiveKernelTargetInfo system object methods.
  634. //
  635. //----------------------------------------------------------------------------
  636. HRESULT
  637. LiveKernelTargetInfo::GetThreadIdByProcessor(
  638. IN ULONG Processor,
  639. OUT PULONG Id
  640. )
  641. {
  642. *Id = VIRTUAL_THREAD_ID(Processor);
  643. return S_OK;
  644. }
  645. HRESULT
  646. LiveKernelTargetInfo::GetThreadInfoDataOffset(PTHREAD_INFO Thread,
  647. ULONG64 ThreadHandle,
  648. PULONG64 Offset)
  649. {
  650. return KdGetThreadInfoDataOffset(Thread, ThreadHandle, Offset);
  651. }
  652. HRESULT
  653. LiveKernelTargetInfo::GetProcessInfoDataOffset(PTHREAD_INFO Thread,
  654. ULONG Processor,
  655. ULONG64 ThreadData,
  656. PULONG64 Offset)
  657. {
  658. return KdGetProcessInfoDataOffset(Thread, Processor, ThreadData, Offset);
  659. }
  660. HRESULT
  661. LiveKernelTargetInfo::GetThreadInfoTeb(PTHREAD_INFO Thread,
  662. ULONG ThreadIndex,
  663. ULONG64 ThreadData,
  664. PULONG64 Offset)
  665. {
  666. return KdGetThreadInfoTeb(Thread, ThreadIndex, ThreadData, Offset);
  667. }
  668. HRESULT
  669. LiveKernelTargetInfo::GetProcessInfoPeb(PTHREAD_INFO Thread,
  670. ULONG Processor,
  671. ULONG64 ThreadData,
  672. PULONG64 Offset)
  673. {
  674. return KdGetProcessInfoPeb(Thread, Processor, ThreadData, Offset);
  675. }
  676. HRESULT
  677. LiveKernelTargetInfo::GetSelDescriptor(MachineInfo* Machine,
  678. ULONG64 Thread, ULONG Selector,
  679. PDESCRIPTOR64 Desc)
  680. {
  681. return KdGetSelDescriptor(Machine, Thread, Selector, Desc);
  682. }
  683. //----------------------------------------------------------------------------
  684. //
  685. // ConnLiveKernelTargetInfo system object methods.
  686. //
  687. //----------------------------------------------------------------------------
  688. HRESULT
  689. ConnLiveKernelTargetInfo::GetTargetContext(
  690. ULONG64 Thread,
  691. PVOID Context
  692. )
  693. {
  694. NTSTATUS Status = DbgKdGetContext((USHORT)VIRTUAL_THREAD_INDEX(Thread),
  695. (PCROSS_PLATFORM_CONTEXT)Context);
  696. return CONV_NT_STATUS(Status);
  697. }
  698. HRESULT
  699. ConnLiveKernelTargetInfo::SetTargetContext(
  700. ULONG64 Thread,
  701. PVOID Context
  702. )
  703. {
  704. NTSTATUS Status = DbgKdSetContext((USHORT)VIRTUAL_THREAD_INDEX(Thread),
  705. (PCROSS_PLATFORM_CONTEXT)Context);
  706. return CONV_NT_STATUS(Status);
  707. }
  708. //----------------------------------------------------------------------------
  709. //
  710. // LocalLiveKernelTargetInfo system object methods.
  711. //
  712. //----------------------------------------------------------------------------
  713. HRESULT
  714. LocalLiveKernelTargetInfo::GetTargetContext(
  715. ULONG64 Thread,
  716. PVOID Context
  717. )
  718. {
  719. // There really isn't any way to make
  720. // this work in a meaningful way unless the system
  721. // is paused.
  722. return E_NOTIMPL;
  723. }
  724. HRESULT
  725. LocalLiveKernelTargetInfo::SetTargetContext(
  726. ULONG64 Thread,
  727. PVOID Context
  728. )
  729. {
  730. // There really isn't any way to make
  731. // this work in a meaningful way unless the system
  732. // is paused.
  733. return E_NOTIMPL;
  734. }
  735. //----------------------------------------------------------------------------
  736. //
  737. // ExdiLiveKernelTargetInfo system object methods.
  738. //
  739. //----------------------------------------------------------------------------
  740. HRESULT
  741. ExdiLiveKernelTargetInfo::GetProcessorSystemDataOffset(
  742. IN ULONG Processor,
  743. IN ULONG Index,
  744. OUT PULONG64 Offset
  745. )
  746. {
  747. if (m_KdSupport != EXDI_KD_GS_PCR ||
  748. g_TargetMachineType != IMAGE_FILE_MACHINE_AMD64)
  749. {
  750. return LiveKernelTargetInfo::
  751. GetProcessorSystemDataOffset(Processor, Index, Offset);
  752. }
  753. HRESULT Status;
  754. DESCRIPTOR64 GsDesc;
  755. if ((Status =
  756. GetTargetSegRegDescriptors(0, SEGREG_GS, 1, &GsDesc)) != S_OK)
  757. {
  758. return Status;
  759. }
  760. switch(Index)
  761. {
  762. case DEBUG_DATA_KPCR_OFFSET:
  763. *Offset = GsDesc.Base;
  764. break;
  765. case DEBUG_DATA_KPRCB_OFFSET:
  766. case DEBUG_DATA_KTHREAD_OFFSET:
  767. Status = ReadPointer(g_TargetMachine,
  768. GsDesc.Base +
  769. FIELD_OFFSET(AMD64_KPCR, CurrentPrcb),
  770. Offset);
  771. if (Status != S_OK)
  772. {
  773. return Status;
  774. }
  775. if (Index == DEBUG_DATA_KPRCB_OFFSET)
  776. {
  777. break;
  778. }
  779. Status = ReadPointer(g_TargetMachine,
  780. *Offset + KPRCB_CURRENT_THREAD_OFFSET_64,
  781. Offset);
  782. if (Status != S_OK)
  783. {
  784. return Status;
  785. }
  786. break;
  787. }
  788. return S_OK;
  789. }
  790. HRESULT
  791. ExdiLiveKernelTargetInfo::GetTargetContext(
  792. ULONG64 Thread,
  793. PVOID Context
  794. )
  795. {
  796. if (!m_ContextValid)
  797. {
  798. HRESULT Status;
  799. if ((Status = g_TargetMachine->
  800. GetExdiContext(m_Context, &m_ContextData)) != S_OK)
  801. {
  802. return Status;
  803. }
  804. m_ContextValid = TRUE;
  805. }
  806. g_TargetMachine->ConvertExdiContextToContext
  807. (&m_ContextData, (PCROSS_PLATFORM_CONTEXT)Context);
  808. return S_OK;
  809. }
  810. HRESULT
  811. ExdiLiveKernelTargetInfo::SetTargetContext(
  812. ULONG64 Thread,
  813. PVOID Context
  814. )
  815. {
  816. if (!m_ContextValid)
  817. {
  818. HRESULT Status;
  819. if ((Status = g_TargetMachine->
  820. GetExdiContext(m_Context, &m_ContextData)) != S_OK)
  821. {
  822. return Status;
  823. }
  824. m_ContextValid = TRUE;
  825. }
  826. g_TargetMachine->ConvertExdiContextFromContext
  827. ((PCROSS_PLATFORM_CONTEXT)Context, &m_ContextData);
  828. return g_TargetMachine->SetExdiContext(m_Context, &m_ContextData);
  829. }
  830. HRESULT
  831. ExdiLiveKernelTargetInfo::GetTargetSegRegDescriptors(ULONG64 Thread,
  832. ULONG Start, ULONG Count,
  833. PDESCRIPTOR64 Descs)
  834. {
  835. if (!m_ContextValid)
  836. {
  837. HRESULT Status;
  838. if ((Status = g_TargetMachine->
  839. GetExdiContext(m_Context, &m_ContextData)) != S_OK)
  840. {
  841. return Status;
  842. }
  843. m_ContextValid = TRUE;
  844. }
  845. g_TargetMachine->ConvertExdiContextToSegDescs(&m_ContextData, Start,
  846. Count, Descs);
  847. return S_OK;
  848. }
  849. void
  850. ExdiLiveKernelTargetInfo::InvalidateTargetContext(void)
  851. {
  852. m_ContextValid = FALSE;
  853. }
  854. HRESULT
  855. ExdiLiveKernelTargetInfo::GetTargetSpecialRegisters
  856. (ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  857. {
  858. if (!m_ContextValid)
  859. {
  860. HRESULT Status;
  861. if ((Status = g_TargetMachine->
  862. GetExdiContext(m_Context, &m_ContextData)) != S_OK)
  863. {
  864. return Status;
  865. }
  866. m_ContextValid = TRUE;
  867. }
  868. g_TargetMachine->ConvertExdiContextToSpecial(&m_ContextData, Special);
  869. return S_OK;
  870. }
  871. HRESULT
  872. ExdiLiveKernelTargetInfo::SetTargetSpecialRegisters
  873. (ULONG64 Thread, PCROSS_PLATFORM_KSPECIAL_REGISTERS Special)
  874. {
  875. if (!m_ContextValid)
  876. {
  877. HRESULT Status;
  878. if ((Status = g_TargetMachine->
  879. GetExdiContext(m_Context, &m_ContextData)) != S_OK)
  880. {
  881. return Status;
  882. }
  883. m_ContextValid = TRUE;
  884. }
  885. g_TargetMachine->ConvertExdiContextFromSpecial(Special, &m_ContextData);
  886. return g_TargetMachine->SetExdiContext(m_Context, &m_ContextData);
  887. }
  888. //----------------------------------------------------------------------------
  889. //
  890. // UserTargetInfo system object methods.
  891. //
  892. //----------------------------------------------------------------------------
  893. HRESULT
  894. UserTargetInfo::GetTargetContext(
  895. ULONG64 Thread,
  896. PVOID Context
  897. )
  898. {
  899. return m_Services->
  900. // g_TargetMachine should be used because of Wx86 debugging
  901. GetContext(Thread,
  902. *(PULONG)((PUCHAR)Context +
  903. g_TargetMachine->m_OffsetTargetContextFlags),
  904. g_TargetMachine->m_OffsetTargetContextFlags,
  905. Context,
  906. g_TargetMachine->m_SizeTargetContext, NULL);
  907. }
  908. HRESULT
  909. UserTargetInfo::SetTargetContext(
  910. ULONG64 Thread,
  911. PVOID Context
  912. )
  913. {
  914. return m_Services->SetContext(Thread, Context,
  915. // g_TargetMachine should be used because of Wx86 debugging
  916. g_TargetMachine->m_SizeTargetContext, NULL);
  917. }
  918. HRESULT
  919. UserTargetInfo::GetThreadInfoDataOffset(PTHREAD_INFO Thread,
  920. ULONG64 ThreadHandle,
  921. PULONG64 Offset)
  922. {
  923. if (Thread != NULL && Thread->DataOffset != 0)
  924. {
  925. *Offset = Thread->DataOffset;
  926. return S_OK;
  927. }
  928. if (Thread != NULL)
  929. {
  930. ThreadHandle = Thread->Handle;
  931. }
  932. else if (ThreadHandle == NULL)
  933. {
  934. ThreadHandle = g_CurrentProcess->CurrentThread->Handle;
  935. }
  936. HRESULT Status = m_Services->
  937. GetThreadDataOffset(ThreadHandle, Offset);
  938. if (Status == S_OK)
  939. {
  940. if (Thread != NULL)
  941. {
  942. Thread->DataOffset = *Offset;
  943. }
  944. }
  945. return Status;
  946. }
  947. HRESULT
  948. UserTargetInfo::GetProcessInfoDataOffset(PTHREAD_INFO Thread,
  949. ULONG Processor,
  950. ULONG64 ThreadData,
  951. PULONG64 Offset)
  952. {
  953. HRESULT Status;
  954. PPROCESS_INFO Process;
  955. // Processor isn't any use so default to the current thread.
  956. if (Thread == NULL)
  957. {
  958. Process = g_CurrentProcess;
  959. }
  960. else
  961. {
  962. Process = Thread->Process;
  963. }
  964. if (ThreadData == 0 && Process->DataOffset != 0)
  965. {
  966. *Offset = Process->DataOffset;
  967. return S_OK;
  968. }
  969. if (ThreadData != 0)
  970. {
  971. if (g_DebuggerPlatformId == VER_PLATFORM_WIN32_NT)
  972. {
  973. ThreadData += g_TargetMachine->m_Ptr64 ?
  974. PEB_FROM_TEB64 : PEB_FROM_TEB32;
  975. Status = ReadPointer(g_TargetMachine, ThreadData, Offset);
  976. }
  977. else
  978. {
  979. Status = E_NOTIMPL;
  980. }
  981. }
  982. else
  983. {
  984. Status = m_Services->GetProcessDataOffset(Process->FullHandle, Offset);
  985. }
  986. if (Status == S_OK)
  987. {
  988. if (ThreadData == 0)
  989. {
  990. Process->DataOffset = *Offset;
  991. }
  992. }
  993. return Status;
  994. }
  995. HRESULT
  996. UserTargetInfo::GetThreadInfoTeb(PTHREAD_INFO Thread,
  997. ULONG Processor,
  998. ULONG64 ThreadData,
  999. PULONG64 Offset)
  1000. {
  1001. return GetThreadInfoDataOffset(Thread, ThreadData, Offset);
  1002. }
  1003. HRESULT
  1004. UserTargetInfo::GetProcessInfoPeb(PTHREAD_INFO Thread,
  1005. ULONG Processor,
  1006. ULONG64 ThreadData,
  1007. PULONG64 Offset)
  1008. {
  1009. // Thread data is not useful.
  1010. return GetProcessInfoDataOffset(Thread, 0, 0, Offset);
  1011. }
  1012. HRESULT
  1013. UserTargetInfo::GetSelDescriptor(MachineInfo* Machine,
  1014. ULONG64 Thread, ULONG Selector,
  1015. PDESCRIPTOR64 Desc)
  1016. {
  1017. HRESULT Status;
  1018. ULONG Used;
  1019. X86_LDT_ENTRY X86Desc;
  1020. if ((Status = m_Services->
  1021. DescribeSelector(Thread, Selector, &X86Desc, sizeof(X86Desc),
  1022. &Used)) != S_OK)
  1023. {
  1024. return Status;
  1025. }
  1026. if (Used != sizeof(X86Desc))
  1027. {
  1028. return E_FAIL;
  1029. }
  1030. X86DescriptorToDescriptor64(&X86Desc, Desc);
  1031. return S_OK;
  1032. }
  1033. //----------------------------------------------------------------------------
  1034. //
  1035. // IDebugSystemObjects methods.
  1036. //
  1037. //----------------------------------------------------------------------------
  1038. STDMETHODIMP
  1039. DebugClient::GetEventThread(
  1040. THIS_
  1041. OUT PULONG Id
  1042. )
  1043. {
  1044. ENTER_ENGINE();
  1045. HRESULT Status;
  1046. if (g_EventThread == NULL)
  1047. {
  1048. Status = E_UNEXPECTED;
  1049. }
  1050. else
  1051. {
  1052. *Id = g_EventThread->UserId;
  1053. Status = S_OK;
  1054. }
  1055. LEAVE_ENGINE();
  1056. return Status;
  1057. }
  1058. STDMETHODIMP
  1059. DebugClient::GetEventProcess(
  1060. THIS_
  1061. OUT PULONG Id
  1062. )
  1063. {
  1064. ENTER_ENGINE();
  1065. HRESULT Status;
  1066. if (g_EventProcess == NULL)
  1067. {
  1068. Status = E_UNEXPECTED;
  1069. }
  1070. else
  1071. {
  1072. *Id = g_EventProcess->UserId;
  1073. Status = S_OK;
  1074. }
  1075. LEAVE_ENGINE();
  1076. return Status;
  1077. }
  1078. STDMETHODIMP
  1079. DebugClient::GetCurrentThreadId(
  1080. THIS_
  1081. OUT PULONG Id
  1082. )
  1083. {
  1084. HRESULT Status;
  1085. ENTER_ENGINE();
  1086. if (g_CurrentProcess == NULL ||
  1087. g_CurrentProcess->CurrentThread == NULL)
  1088. {
  1089. Status = E_UNEXPECTED;
  1090. }
  1091. else
  1092. {
  1093. *Id = g_CurrentProcess->CurrentThread->UserId;
  1094. Status = S_OK;
  1095. }
  1096. LEAVE_ENGINE();
  1097. return Status;
  1098. }
  1099. STDMETHODIMP
  1100. DebugClient::SetCurrentThreadId(
  1101. THIS_
  1102. IN ULONG Id
  1103. )
  1104. {
  1105. ENTER_ENGINE();
  1106. HRESULT Status;
  1107. PTHREAD_INFO Thread = FindThreadByUserId(NULL, Id);
  1108. if (Thread != NULL)
  1109. {
  1110. SetCurrentThread(Thread, FALSE);
  1111. ResetCurrentScopeLazy();
  1112. Status = S_OK;
  1113. }
  1114. else
  1115. {
  1116. Status = E_NOINTERFACE;
  1117. }
  1118. LEAVE_ENGINE();
  1119. return Status;
  1120. }
  1121. STDMETHODIMP
  1122. DebugClient::GetCurrentProcessId(
  1123. THIS_
  1124. OUT PULONG Id
  1125. )
  1126. {
  1127. HRESULT Status;
  1128. ENTER_ENGINE();
  1129. if (g_CurrentProcess == NULL)
  1130. {
  1131. Status = E_UNEXPECTED;
  1132. }
  1133. else
  1134. {
  1135. *Id = g_CurrentProcess->UserId;
  1136. Status = S_OK;
  1137. }
  1138. LEAVE_ENGINE();
  1139. return Status;
  1140. }
  1141. STDMETHODIMP
  1142. DebugClient::SetCurrentProcessId(
  1143. THIS_
  1144. IN ULONG Id
  1145. )
  1146. {
  1147. ENTER_ENGINE();
  1148. HRESULT Status;
  1149. PPROCESS_INFO Process = FindProcessByUserId(Id);
  1150. if (Process != NULL)
  1151. {
  1152. if (Process->CurrentThread == NULL)
  1153. {
  1154. Process->CurrentThread = Process->ThreadHead;
  1155. }
  1156. if (Process->CurrentThread == NULL)
  1157. {
  1158. Status = E_FAIL;
  1159. }
  1160. else
  1161. {
  1162. SetCurrentThread(Process->CurrentThread, FALSE);
  1163. ResetCurrentScopeLazy();
  1164. Status = S_OK;
  1165. }
  1166. }
  1167. else
  1168. {
  1169. Status = E_NOINTERFACE;
  1170. }
  1171. LEAVE_ENGINE();
  1172. return Status;
  1173. }
  1174. STDMETHODIMP
  1175. DebugClient::GetNumberThreads(
  1176. THIS_
  1177. OUT PULONG Number
  1178. )
  1179. {
  1180. HRESULT Status;
  1181. ENTER_ENGINE();
  1182. if (g_CurrentProcess == NULL)
  1183. {
  1184. Status = E_UNEXPECTED;
  1185. }
  1186. else
  1187. {
  1188. *Number = g_CurrentProcess->NumberThreads;
  1189. Status = S_OK;
  1190. }
  1191. LEAVE_ENGINE();
  1192. return Status;
  1193. }
  1194. STDMETHODIMP
  1195. DebugClient::GetTotalNumberThreads(
  1196. THIS_
  1197. OUT PULONG Total,
  1198. OUT PULONG LargestProcess
  1199. )
  1200. {
  1201. ENTER_ENGINE();
  1202. *Total = g_TotalNumberThreads;
  1203. *LargestProcess = g_MaxThreadsInProcess;
  1204. LEAVE_ENGINE();
  1205. return S_OK;
  1206. }
  1207. STDMETHODIMP
  1208. DebugClient::GetThreadIdsByIndex(
  1209. THIS_
  1210. IN ULONG Start,
  1211. IN ULONG Count,
  1212. OUT OPTIONAL /* size_is(Count) */ PULONG Ids,
  1213. OUT OPTIONAL /* size_is(Count) */ PULONG SysIds
  1214. )
  1215. {
  1216. HRESULT Status;
  1217. ENTER_ENGINE();
  1218. if (g_CurrentProcess == NULL)
  1219. {
  1220. Status = E_UNEXPECTED;
  1221. }
  1222. else
  1223. {
  1224. PTHREAD_INFO Thread;
  1225. ULONG Index;
  1226. if (Start >= g_CurrentProcess->NumberThreads ||
  1227. Start + Count > g_CurrentProcess->NumberThreads)
  1228. {
  1229. Status = E_INVALIDARG;
  1230. }
  1231. else
  1232. {
  1233. Index = 0;
  1234. for (Thread = g_CurrentProcess->ThreadHead;
  1235. Thread != NULL;
  1236. Thread = Thread->Next)
  1237. {
  1238. if (Index >= Start && Index < Start + Count)
  1239. {
  1240. if (Ids != NULL)
  1241. {
  1242. *Ids++ = Thread->UserId;
  1243. }
  1244. if (SysIds != NULL)
  1245. {
  1246. *SysIds++ = Thread->SystemId;
  1247. }
  1248. }
  1249. Index++;
  1250. }
  1251. Status = S_OK;
  1252. }
  1253. }
  1254. LEAVE_ENGINE();
  1255. return Status;
  1256. }
  1257. STDMETHODIMP
  1258. DebugClient::GetThreadIdByProcessor(
  1259. THIS_
  1260. IN ULONG Processor,
  1261. OUT PULONG Id
  1262. )
  1263. {
  1264. HRESULT Status;
  1265. ENTER_ENGINE();
  1266. if (g_CurrentProcess == NULL)
  1267. {
  1268. Status = E_UNEXPECTED;
  1269. }
  1270. else
  1271. {
  1272. ULONG SysId;
  1273. Status = g_Target->GetThreadIdByProcessor(Processor, &SysId);
  1274. if (Status == S_OK)
  1275. {
  1276. PTHREAD_INFO Thread =
  1277. FindThreadBySystemId(g_CurrentProcess, SysId);
  1278. if (Thread != NULL)
  1279. {
  1280. *Id = Thread->UserId;
  1281. }
  1282. else
  1283. {
  1284. Status = E_NOINTERFACE;
  1285. }
  1286. }
  1287. }
  1288. LEAVE_ENGINE();
  1289. return Status;
  1290. }
  1291. STDMETHODIMP
  1292. DebugClient::GetCurrentThreadDataOffset(
  1293. THIS_
  1294. OUT PULONG64 Offset
  1295. )
  1296. {
  1297. HRESULT Status;
  1298. ENTER_ENGINE();
  1299. if (g_CurrentProcess == NULL)
  1300. {
  1301. Status = E_UNEXPECTED;
  1302. }
  1303. else
  1304. {
  1305. Status = g_Target->
  1306. GetThreadInfoDataOffset(g_CurrentProcess->CurrentThread,
  1307. 0, Offset);
  1308. }
  1309. LEAVE_ENGINE();
  1310. return Status;
  1311. }
  1312. STDMETHODIMP
  1313. DebugClient::GetThreadIdByDataOffset(
  1314. THIS_
  1315. IN ULONG64 Offset,
  1316. OUT PULONG Id
  1317. )
  1318. {
  1319. HRESULT Status;
  1320. ENTER_ENGINE();
  1321. if (g_CurrentProcess == NULL)
  1322. {
  1323. Status = E_UNEXPECTED;
  1324. }
  1325. else
  1326. {
  1327. PTHREAD_INFO Thread;
  1328. Status = E_NOINTERFACE;
  1329. for (Thread = g_CurrentProcess->ThreadHead;
  1330. Thread != NULL;
  1331. Thread = Thread->Next)
  1332. {
  1333. HRESULT Status;
  1334. ULONG64 DataOffset;
  1335. Status = g_Target->GetThreadInfoDataOffset(Thread, 0, &DataOffset);
  1336. if (Status != S_OK)
  1337. {
  1338. break;
  1339. }
  1340. if (DataOffset == Offset)
  1341. {
  1342. *Id = Thread->UserId;
  1343. Status = S_OK;
  1344. break;
  1345. }
  1346. }
  1347. }
  1348. LEAVE_ENGINE();
  1349. return Status;
  1350. }
  1351. STDMETHODIMP
  1352. DebugClient::GetCurrentThreadTeb(
  1353. THIS_
  1354. OUT PULONG64 Offset
  1355. )
  1356. {
  1357. HRESULT Status;
  1358. ENTER_ENGINE();
  1359. if (g_CurrentProcess == NULL)
  1360. {
  1361. Status = E_UNEXPECTED;
  1362. }
  1363. else
  1364. {
  1365. Status = g_Target->GetThreadInfoTeb(g_CurrentProcess->CurrentThread,
  1366. 0, 0, Offset);
  1367. }
  1368. LEAVE_ENGINE();
  1369. return Status;
  1370. }
  1371. STDMETHODIMP
  1372. DebugClient::GetThreadIdByTeb(
  1373. THIS_
  1374. IN ULONG64 Offset,
  1375. OUT PULONG Id
  1376. )
  1377. {
  1378. HRESULT Status;
  1379. ENTER_ENGINE();
  1380. if (g_CurrentProcess == NULL)
  1381. {
  1382. Status = E_UNEXPECTED;
  1383. }
  1384. else
  1385. {
  1386. PTHREAD_INFO Thread;
  1387. Status = E_NOINTERFACE;
  1388. for (Thread = g_CurrentProcess->ThreadHead;
  1389. Thread != NULL;
  1390. Thread = Thread->Next)
  1391. {
  1392. HRESULT Status;
  1393. ULONG64 Teb;
  1394. Status = g_Target->GetThreadInfoTeb(Thread, 0, 0, &Teb);
  1395. if (Status != S_OK)
  1396. {
  1397. break;
  1398. }
  1399. if (Teb == Offset)
  1400. {
  1401. *Id = Thread->UserId;
  1402. Status = S_OK;
  1403. break;
  1404. }
  1405. }
  1406. }
  1407. LEAVE_ENGINE();
  1408. return Status;
  1409. }
  1410. STDMETHODIMP
  1411. DebugClient::GetCurrentThreadSystemId(
  1412. THIS_
  1413. OUT PULONG SysId
  1414. )
  1415. {
  1416. if (IS_KERNEL_TARGET())
  1417. {
  1418. return E_NOTIMPL;
  1419. }
  1420. HRESULT Status;
  1421. ENTER_ENGINE();
  1422. if (g_CurrentProcess == NULL)
  1423. {
  1424. Status = E_UNEXPECTED;
  1425. }
  1426. else
  1427. {
  1428. *SysId = g_CurrentProcess->CurrentThread->SystemId;
  1429. Status = S_OK;
  1430. }
  1431. LEAVE_ENGINE();
  1432. return Status;
  1433. }
  1434. STDMETHODIMP
  1435. DebugClient::GetThreadIdBySystemId(
  1436. THIS_
  1437. IN ULONG SysId,
  1438. OUT PULONG Id
  1439. )
  1440. {
  1441. HRESULT Status;
  1442. ENTER_ENGINE();
  1443. if (IS_KERNEL_TARGET())
  1444. {
  1445. Status = E_NOTIMPL;
  1446. }
  1447. else if (g_CurrentProcess == NULL)
  1448. {
  1449. Status = E_UNEXPECTED;
  1450. }
  1451. else
  1452. {
  1453. PTHREAD_INFO Thread = FindThreadBySystemId(g_CurrentProcess, SysId);
  1454. if (Thread != NULL)
  1455. {
  1456. *Id = Thread->UserId;
  1457. Status = S_OK;
  1458. }
  1459. else
  1460. {
  1461. Status = E_NOINTERFACE;
  1462. }
  1463. }
  1464. LEAVE_ENGINE();
  1465. return Status;
  1466. }
  1467. STDMETHODIMP
  1468. DebugClient::GetCurrentThreadHandle(
  1469. THIS_
  1470. OUT PULONG64 Handle
  1471. )
  1472. {
  1473. HRESULT Status;
  1474. ENTER_ENGINE();
  1475. if (g_CurrentProcess == NULL)
  1476. {
  1477. Status = E_UNEXPECTED;
  1478. }
  1479. else
  1480. {
  1481. *Handle = g_CurrentProcess->CurrentThread->Handle;
  1482. Status = S_OK;
  1483. }
  1484. LEAVE_ENGINE();
  1485. return Status;
  1486. }
  1487. STDMETHODIMP
  1488. DebugClient::GetThreadIdByHandle(
  1489. THIS_
  1490. IN ULONG64 Handle,
  1491. OUT PULONG Id
  1492. )
  1493. {
  1494. HRESULT Status;
  1495. ENTER_ENGINE();
  1496. if (g_CurrentProcess == NULL)
  1497. {
  1498. Status = E_UNEXPECTED;
  1499. }
  1500. else
  1501. {
  1502. PTHREAD_INFO Thread = FindThreadByHandle(g_CurrentProcess, Handle);
  1503. if (Thread != NULL)
  1504. {
  1505. *Id = Thread->UserId;
  1506. Status = S_OK;
  1507. }
  1508. else
  1509. {
  1510. Status = E_NOINTERFACE;
  1511. }
  1512. }
  1513. LEAVE_ENGINE();
  1514. return Status;
  1515. }
  1516. STDMETHODIMP
  1517. DebugClient::GetNumberProcesses(
  1518. THIS_
  1519. OUT PULONG Number
  1520. )
  1521. {
  1522. if (!IS_TARGET_SET())
  1523. {
  1524. return E_UNEXPECTED;
  1525. }
  1526. ENTER_ENGINE();
  1527. *Number = g_NumberProcesses;
  1528. LEAVE_ENGINE();
  1529. return S_OK;
  1530. }
  1531. STDMETHODIMP
  1532. DebugClient::GetProcessIdsByIndex(
  1533. THIS_
  1534. IN ULONG Start,
  1535. IN ULONG Count,
  1536. OUT OPTIONAL /* size_is(Count) */ PULONG Ids,
  1537. OUT OPTIONAL /* size_is(Count) */ PULONG SysIds
  1538. )
  1539. {
  1540. if (!IS_TARGET_SET())
  1541. {
  1542. return E_UNEXPECTED;
  1543. }
  1544. HRESULT Status;
  1545. ENTER_ENGINE();
  1546. PPROCESS_INFO Process;
  1547. ULONG Index;
  1548. if (Start >= g_NumberProcesses ||
  1549. Start + Count > g_NumberProcesses)
  1550. {
  1551. Status = E_INVALIDARG;
  1552. goto EH_Exit;
  1553. }
  1554. Index = 0;
  1555. for (Process = g_ProcessHead;
  1556. Process != NULL;
  1557. Process = Process->Next)
  1558. {
  1559. if (Index >= Start && Index < Start + Count)
  1560. {
  1561. if (Ids != NULL)
  1562. {
  1563. *Ids++ = Process->UserId;
  1564. }
  1565. if (SysIds != NULL)
  1566. {
  1567. *SysIds++ = Process->SystemId;
  1568. }
  1569. }
  1570. Index++;
  1571. }
  1572. Status = S_OK;
  1573. EH_Exit:
  1574. LEAVE_ENGINE();
  1575. return Status;
  1576. }
  1577. STDMETHODIMP
  1578. DebugClient::GetCurrentProcessDataOffset(
  1579. THIS_
  1580. OUT PULONG64 Offset
  1581. )
  1582. {
  1583. HRESULT Status;
  1584. ENTER_ENGINE();
  1585. if (g_CurrentProcess == NULL)
  1586. {
  1587. Status = E_UNEXPECTED;
  1588. }
  1589. else
  1590. {
  1591. Status = g_Target->
  1592. GetProcessInfoDataOffset(g_CurrentProcess->CurrentThread,
  1593. 0, 0, Offset);
  1594. }
  1595. LEAVE_ENGINE();
  1596. return Status;
  1597. }
  1598. STDMETHODIMP
  1599. DebugClient::GetProcessIdByDataOffset(
  1600. THIS_
  1601. IN ULONG64 Offset,
  1602. OUT PULONG Id
  1603. )
  1604. {
  1605. if (!IS_TARGET_SET())
  1606. {
  1607. return E_UNEXPECTED;
  1608. }
  1609. if (IS_KERNEL_TARGET())
  1610. {
  1611. return E_NOTIMPL;
  1612. }
  1613. HRESULT Status;
  1614. PPROCESS_INFO Process;
  1615. ENTER_ENGINE();
  1616. Status = E_NOINTERFACE;
  1617. for (Process = g_ProcessHead;
  1618. Process != NULL;
  1619. Process = Process->Next)
  1620. {
  1621. ULONG64 DataOffset;
  1622. Status = g_Target->
  1623. GetProcessInfoDataOffset(Process->ThreadHead, 0, 0, &DataOffset);
  1624. if (Status != S_OK)
  1625. {
  1626. break;
  1627. }
  1628. if (DataOffset == Offset)
  1629. {
  1630. *Id = Process->UserId;
  1631. Status = S_OK;
  1632. break;
  1633. }
  1634. }
  1635. LEAVE_ENGINE();
  1636. return Status;
  1637. }
  1638. STDMETHODIMP
  1639. DebugClient::GetCurrentProcessPeb(
  1640. THIS_
  1641. OUT PULONG64 Offset
  1642. )
  1643. {
  1644. HRESULT Status;
  1645. ENTER_ENGINE();
  1646. if (g_CurrentProcess == NULL)
  1647. {
  1648. Status = E_UNEXPECTED;
  1649. }
  1650. else
  1651. {
  1652. Status = g_Target->GetProcessInfoPeb(g_CurrentProcess->CurrentThread,
  1653. 0, 0, Offset);
  1654. }
  1655. LEAVE_ENGINE();
  1656. return Status;
  1657. }
  1658. STDMETHODIMP
  1659. DebugClient::GetProcessIdByPeb(
  1660. THIS_
  1661. IN ULONG64 Offset,
  1662. OUT PULONG Id
  1663. )
  1664. {
  1665. if (!IS_TARGET_SET())
  1666. {
  1667. return E_UNEXPECTED;
  1668. }
  1669. if (IS_KERNEL_TARGET())
  1670. {
  1671. return E_NOTIMPL;
  1672. }
  1673. HRESULT Status;
  1674. PPROCESS_INFO Process;
  1675. ENTER_ENGINE();
  1676. Status = E_NOINTERFACE;
  1677. for (Process = g_ProcessHead;
  1678. Process != NULL;
  1679. Process = Process->Next)
  1680. {
  1681. ULONG64 Peb;
  1682. Status = g_Target->GetProcessInfoPeb(Process->ThreadHead, 0, 0, &Peb);
  1683. if (Status != S_OK)
  1684. {
  1685. break;
  1686. }
  1687. if (Peb == Offset)
  1688. {
  1689. *Id = Process->UserId;
  1690. Status = S_OK;
  1691. break;
  1692. }
  1693. }
  1694. LEAVE_ENGINE();
  1695. return Status;
  1696. }
  1697. STDMETHODIMP
  1698. DebugClient::GetCurrentProcessSystemId(
  1699. THIS_
  1700. OUT PULONG SysId
  1701. )
  1702. {
  1703. if (IS_KERNEL_TARGET())
  1704. {
  1705. return E_NOTIMPL;
  1706. }
  1707. HRESULT Status;
  1708. ENTER_ENGINE();
  1709. if (g_CurrentProcess == NULL)
  1710. {
  1711. Status = E_UNEXPECTED;
  1712. }
  1713. else
  1714. {
  1715. *SysId = g_CurrentProcess->SystemId;
  1716. Status = S_OK;
  1717. }
  1718. LEAVE_ENGINE();
  1719. return Status;
  1720. }
  1721. STDMETHODIMP
  1722. DebugClient::GetProcessIdBySystemId(
  1723. THIS_
  1724. IN ULONG SysId,
  1725. OUT PULONG Id
  1726. )
  1727. {
  1728. if (!IS_TARGET_SET())
  1729. {
  1730. return E_UNEXPECTED;
  1731. }
  1732. if (IS_KERNEL_TARGET())
  1733. {
  1734. return E_NOTIMPL;
  1735. }
  1736. HRESULT Status;
  1737. ENTER_ENGINE();
  1738. PPROCESS_INFO Process = FindProcessBySystemId(SysId);
  1739. if (Process != NULL)
  1740. {
  1741. *Id = Process->UserId;
  1742. Status = S_OK;
  1743. }
  1744. else
  1745. {
  1746. Status = E_NOINTERFACE;
  1747. }
  1748. LEAVE_ENGINE();
  1749. return Status;
  1750. }
  1751. STDMETHODIMP
  1752. DebugClient::GetCurrentProcessHandle(
  1753. THIS_
  1754. OUT PULONG64 Handle
  1755. )
  1756. {
  1757. HRESULT Status;
  1758. ENTER_ENGINE();
  1759. if (g_CurrentProcess == NULL)
  1760. {
  1761. Status = E_UNEXPECTED;
  1762. }
  1763. else
  1764. {
  1765. *Handle = (ULONG64)g_CurrentProcess->Handle;
  1766. Status = S_OK;
  1767. }
  1768. LEAVE_ENGINE();
  1769. return Status;
  1770. }
  1771. STDMETHODIMP
  1772. DebugClient::GetProcessIdByHandle(
  1773. THIS_
  1774. IN ULONG64 Handle,
  1775. OUT PULONG Id
  1776. )
  1777. {
  1778. if (!IS_TARGET_SET())
  1779. {
  1780. return E_UNEXPECTED;
  1781. }
  1782. HRESULT Status;
  1783. ENTER_ENGINE();
  1784. PPROCESS_INFO Process = FindProcessByHandle(Handle);
  1785. if (Process != NULL)
  1786. {
  1787. *Id = Process->UserId;
  1788. Status = S_OK;
  1789. }
  1790. else
  1791. {
  1792. Status = E_NOINTERFACE;
  1793. }
  1794. LEAVE_ENGINE();
  1795. return Status;
  1796. }
  1797. STDMETHODIMP
  1798. DebugClient::GetCurrentProcessExecutableName(
  1799. THIS_
  1800. OUT OPTIONAL PSTR Buffer,
  1801. IN ULONG BufferSize,
  1802. OUT OPTIONAL PULONG ExeSize
  1803. )
  1804. {
  1805. HRESULT Status;
  1806. ENTER_ENGINE();
  1807. if (g_CurrentProcess == NULL)
  1808. {
  1809. Status = E_UNEXPECTED;
  1810. }
  1811. else if (g_CurrentProcess->ExecutableImage == NULL)
  1812. {
  1813. Status = E_NOINTERFACE;
  1814. }
  1815. else
  1816. {
  1817. Status = FillStringBuffer(g_CurrentProcess->ExecutableImage->ImagePath,
  1818. 0, Buffer, BufferSize, ExeSize);
  1819. }
  1820. LEAVE_ENGINE();
  1821. return Status;
  1822. }
  1823. STDMETHODIMP
  1824. DebugClient::GetCurrentProcessUpTime(
  1825. THIS_
  1826. OUT PULONG UpTime
  1827. )
  1828. {
  1829. HRESULT Status;
  1830. ENTER_ENGINE();
  1831. if (!IS_LIVE_USER_TARGET() || g_CurrentProcess == NULL)
  1832. {
  1833. Status = E_UNEXPECTED;
  1834. }
  1835. else
  1836. {
  1837. ULONG64 LongUpTime;
  1838. LongUpTime = g_Target->GetProcessUpTimeN(g_CurrentProcess->FullHandle);
  1839. if (LongUpTime == 0)
  1840. {
  1841. Status = E_NOINTERFACE;
  1842. }
  1843. else
  1844. {
  1845. *UpTime = FileTimeToTime(LongUpTime);
  1846. Status = S_OK;
  1847. }
  1848. }
  1849. LEAVE_ENGINE();
  1850. return Status;
  1851. }
  1852. HRESULT
  1853. GetContextFromThreadStack(
  1854. ULONG64 ThreadBase,
  1855. PCROSS_PLATFORM_CONTEXT Context,
  1856. PDEBUG_STACK_FRAME StkFrame,
  1857. BOOL Verbose
  1858. )
  1859. {
  1860. DBG_ASSERT(ThreadBase && Context != NULL);
  1861. if (!IS_KERNEL_TARGET())
  1862. {
  1863. return E_UNEXPECTED;
  1864. }
  1865. HRESULT Status;
  1866. CROSS_PLATFORM_THREAD ThreadContents;
  1867. DEBUG_STACK_FRAME LocalStkFrame;
  1868. ULONG Proc;
  1869. if (!StkFrame)
  1870. {
  1871. StkFrame = &LocalStkFrame;
  1872. }
  1873. ZeroMemory(StkFrame, sizeof(*StkFrame));
  1874. if ((Status = g_Target->ReadAllVirtual
  1875. (ThreadBase, &ThreadContents,
  1876. g_TargetMachine->m_SizePartialKThread)) != S_OK)
  1877. {
  1878. {
  1879. ErrOut("Cannot read thread contents @ %s, %s\n",
  1880. FormatAddr64(ThreadBase), FormatStatusCode(Status));
  1881. }
  1882. return Status;
  1883. }
  1884. if (*((PCHAR) &ThreadContents) != 6)
  1885. {
  1886. ErrOut("Invalid thread @ %s type - context unchanged.\n",
  1887. FormatAddr64(ThreadBase));
  1888. return E_INVALIDARG;
  1889. }
  1890. Status = g_TargetMachine->GetContextFromThreadStack
  1891. (ThreadBase, &ThreadContents, Context, StkFrame, &Proc);
  1892. if (Status == S_FALSE)
  1893. {
  1894. // Get the processor context if it's a valid processor.
  1895. if (Proc < g_TargetNumberProcessors)
  1896. {
  1897. // This get may be getting the context of the thread
  1898. // currently cached by the register code. Make sure
  1899. // the cache is flushed.
  1900. FlushRegContext();
  1901. g_TargetMachine->InitializeContextFlags(Context, g_SystemVersion);
  1902. if ((Status = g_Target->GetContext(VIRTUAL_THREAD_HANDLE(Proc),
  1903. Context)) != S_OK)
  1904. {
  1905. ErrOut("Unable to get context for thread "
  1906. "running on processor %d, %s\n",
  1907. Proc, FormatStatusCode(Status));
  1908. return Status;
  1909. }
  1910. }
  1911. else
  1912. {
  1913. if (Verbose)
  1914. {
  1915. ErrOut("Thread running on invalid processor %d\n", Proc);
  1916. }
  1917. return E_INVALIDARG;
  1918. }
  1919. }
  1920. else if (Status != S_OK)
  1921. {
  1922. if (Verbose)
  1923. {
  1924. ErrOut("Can't retrieve thread context, %s\n",
  1925. FormatStatusCode(Status));
  1926. }
  1927. return Status;
  1928. }
  1929. return S_OK;
  1930. }
  1931. HRESULT
  1932. SetContextFromThreadData(ULONG64 ThreadBase, BOOL Verbose)
  1933. {
  1934. if (!ThreadBase)
  1935. {
  1936. if (GetCurrentScopeContext())
  1937. {
  1938. ResetCurrentScope();
  1939. }
  1940. return S_OK;
  1941. }
  1942. HRESULT Status;
  1943. DEBUG_STACK_FRAME StkFrame = {0};
  1944. CROSS_PLATFORM_CONTEXT Context = {0};
  1945. if ((Status = GetContextFromThreadStack(ThreadBase, &Context,
  1946. &StkFrame, FALSE)) != S_OK)
  1947. {
  1948. return Status;
  1949. }
  1950. SetCurrentScope(&StkFrame, &Context, sizeof(Context));
  1951. if (StackTrace(StkFrame.FrameOffset, StkFrame.StackOffset,
  1952. StkFrame.InstructionOffset,
  1953. &StkFrame, 1, 0, 0, FALSE) != 1)
  1954. {
  1955. if (Verbose)
  1956. {
  1957. ErrOut("Scope can't be set for thread %s\n",
  1958. FormatAddr64(ThreadBase));
  1959. }
  1960. ResetCurrentScope();
  1961. return E_FAIL;
  1962. }
  1963. return S_OK;
  1964. }
  1965. HRESULT
  1966. GetImplicitThreadData(PULONG64 Offset)
  1967. {
  1968. HRESULT Status;
  1969. if (g_ImplicitThreadData == 0)
  1970. {
  1971. Status = SetImplicitThreadData(0, FALSE);
  1972. }
  1973. else
  1974. {
  1975. Status = S_OK;
  1976. }
  1977. *Offset = g_ImplicitThreadData;
  1978. return Status;
  1979. }
  1980. HRESULT
  1981. GetImplicitThreadDataTeb(PULONG64 Offset)
  1982. {
  1983. if (IS_USER_TARGET())
  1984. {
  1985. // In user mode the thread data is the TEB.
  1986. return GetImplicitThreadData(Offset);
  1987. }
  1988. else
  1989. {
  1990. return g_Target->ReadImplicitThreadInfoPointer
  1991. (g_TargetMachine->m_OffsetKThreadTeb, Offset);
  1992. }
  1993. }
  1994. HRESULT
  1995. SetImplicitThreadData(ULONG64 Offset, BOOL Verbose)
  1996. {
  1997. HRESULT Status;
  1998. BOOL Default = FALSE;
  1999. if (Offset == 0)
  2000. {
  2001. if ((Status = g_Target->
  2002. GetThreadInfoDataOffset(g_CurrentProcess->CurrentThread,
  2003. 0, &Offset)) != S_OK)
  2004. {
  2005. if (Verbose)
  2006. {
  2007. ErrOut("Unable to get the current thread data\n");
  2008. }
  2009. return Status;
  2010. }
  2011. if (Offset == 0)
  2012. {
  2013. if (Verbose)
  2014. {
  2015. ErrOut("Current thread data is NULL\n");
  2016. }
  2017. return E_FAIL;
  2018. }
  2019. Default = TRUE;
  2020. }
  2021. if (IS_KERNEL_TARGET() &&
  2022. (Status = SetContextFromThreadData(Default ? 0 : Offset,
  2023. Verbose)) != S_OK)
  2024. {
  2025. return Status;
  2026. }
  2027. g_ImplicitThreadData = Offset;
  2028. g_ImplicitThreadDataIsDefault = Default;
  2029. return S_OK;
  2030. }
  2031. STDMETHODIMP
  2032. DebugClient::GetImplicitThreadDataOffset(
  2033. THIS_
  2034. OUT PULONG64 Offset
  2035. )
  2036. {
  2037. HRESULT Status;
  2038. ENTER_ENGINE();
  2039. if (!IS_MACHINE_ACCESSIBLE())
  2040. {
  2041. Status = E_UNEXPECTED;
  2042. }
  2043. else
  2044. {
  2045. Status = ::GetImplicitThreadData(Offset);
  2046. }
  2047. LEAVE_ENGINE();
  2048. return Status;
  2049. }
  2050. STDMETHODIMP
  2051. DebugClient::SetImplicitThreadDataOffset(
  2052. THIS_
  2053. IN ULONG64 Offset
  2054. )
  2055. {
  2056. HRESULT Status;
  2057. ENTER_ENGINE();
  2058. if (!IS_MACHINE_ACCESSIBLE())
  2059. {
  2060. Status = E_UNEXPECTED;
  2061. }
  2062. else
  2063. {
  2064. Status = ::SetImplicitThreadData(Offset, FALSE);
  2065. }
  2066. LEAVE_ENGINE();
  2067. return Status;
  2068. }
  2069. HRESULT
  2070. GetImplicitProcessData(PULONG64 Offset)
  2071. {
  2072. HRESULT Status;
  2073. if (g_ImplicitProcessData == 0)
  2074. {
  2075. Status = SetImplicitProcessData(0, FALSE);
  2076. }
  2077. else
  2078. {
  2079. Status = S_OK;
  2080. }
  2081. *Offset = g_ImplicitProcessData;
  2082. return Status;
  2083. }
  2084. HRESULT
  2085. GetImplicitProcessDataPeb(PULONG64 Offset)
  2086. {
  2087. if (IS_USER_TARGET())
  2088. {
  2089. // In user mode the process data is the PEB.
  2090. return GetImplicitProcessData(Offset);
  2091. }
  2092. else
  2093. {
  2094. return g_Target->ReadImplicitProcessInfoPointer
  2095. (g_TargetMachine->m_OffsetEprocessPeb, Offset);
  2096. }
  2097. }
  2098. HRESULT
  2099. SetImplicitProcessData(ULONG64 Offset, BOOL Verbose)
  2100. {
  2101. HRESULT Status;
  2102. BOOL Default = FALSE;
  2103. if (Offset == 0)
  2104. {
  2105. if ((Status = g_Target->
  2106. GetProcessInfoDataOffset(g_CurrentProcess->CurrentThread,
  2107. 0, 0, &Offset)) != S_OK)
  2108. {
  2109. if (Verbose)
  2110. {
  2111. ErrOut("Unable to get the current process data\n");
  2112. }
  2113. return Status;
  2114. }
  2115. if (Offset == 0)
  2116. {
  2117. if (Verbose)
  2118. {
  2119. ErrOut("Current process data is NULL\n");
  2120. }
  2121. return E_FAIL;
  2122. }
  2123. Default = TRUE;
  2124. }
  2125. ULONG64 Old = g_ImplicitProcessData;
  2126. BOOL OldDefault = g_ImplicitProcessDataIsDefault;
  2127. g_ImplicitProcessData = Offset;
  2128. g_ImplicitProcessDataIsDefault = Default;
  2129. if (IS_KERNEL_TARGET() &&
  2130. (Status = g_TargetMachine->
  2131. SetDefaultPageDirectories(PAGE_DIR_ALL)) != S_OK)
  2132. {
  2133. g_ImplicitProcessData = Old;
  2134. g_ImplicitProcessDataIsDefault = OldDefault;
  2135. if (Verbose)
  2136. {
  2137. ErrOut("Process %s has invalid page directories\n",
  2138. FormatAddr64(Offset));
  2139. }
  2140. return Status;
  2141. }
  2142. return S_OK;
  2143. }
  2144. STDMETHODIMP
  2145. DebugClient::GetImplicitProcessDataOffset(
  2146. THIS_
  2147. OUT PULONG64 Offset
  2148. )
  2149. {
  2150. HRESULT Status;
  2151. ENTER_ENGINE();
  2152. if (!IS_MACHINE_ACCESSIBLE())
  2153. {
  2154. Status = E_UNEXPECTED;
  2155. }
  2156. else
  2157. {
  2158. Status = ::GetImplicitProcessData(Offset);
  2159. }
  2160. LEAVE_ENGINE();
  2161. return Status;
  2162. }
  2163. STDMETHODIMP
  2164. DebugClient::SetImplicitProcessDataOffset(
  2165. THIS_
  2166. IN ULONG64 Offset
  2167. )
  2168. {
  2169. HRESULT Status;
  2170. ENTER_ENGINE();
  2171. if (!IS_MACHINE_ACCESSIBLE())
  2172. {
  2173. Status = E_UNEXPECTED;
  2174. }
  2175. else
  2176. {
  2177. Status = ::SetImplicitProcessData(Offset, FALSE);
  2178. }
  2179. LEAVE_ENGINE();
  2180. return Status;
  2181. }
  2182. void
  2183. ResetImplicitData(void)
  2184. {
  2185. g_ImplicitThreadData = 0;
  2186. g_ImplicitThreadDataIsDefault = TRUE;
  2187. g_ImplicitProcessData = 0;
  2188. g_ImplicitProcessDataIsDefault = TRUE;
  2189. }
  2190. void
  2191. ParseSetImplicitThread(void)
  2192. {
  2193. ULONG64 Base = 0;
  2194. if (PeekChar() && *g_CurCmd != ';')
  2195. {
  2196. Base = GetExpression();
  2197. }
  2198. if (SetImplicitThreadData(Base, TRUE) == S_OK)
  2199. {
  2200. dprintf("Implicit thread is now %s\n",
  2201. FormatAddr64(g_ImplicitThreadData));
  2202. }
  2203. }
  2204. HRESULT
  2205. KernelPageIn(ULONG64 Process, ULONG64 Data)
  2206. {
  2207. HRESULT Status;
  2208. ULONG work;
  2209. ULONG Size;
  2210. ULONG64 ExpDebuggerProcessAttach = 0;
  2211. ULONG64 ExpDebuggerPageIn = 0;
  2212. ULONG64 ExpDebuggerWork = 0;
  2213. if (!IS_LIVE_KERNEL_TARGET())
  2214. {
  2215. ErrOut("This operation only works on live kernel debug sessions\n");
  2216. return E_NOTIMPL;
  2217. }
  2218. GetOffsetFromSym("nt!ExpDebuggerProcessAttach", &ExpDebuggerProcessAttach, NULL);
  2219. GetOffsetFromSym("nt!ExpDebuggerPageIn", &ExpDebuggerPageIn, NULL);
  2220. GetOffsetFromSym("nt!ExpDebuggerWork", &ExpDebuggerWork, NULL);
  2221. if (!ExpDebuggerProcessAttach ||
  2222. !ExpDebuggerPageIn ||
  2223. !ExpDebuggerWork)
  2224. {
  2225. ErrOut("Symbols are wrong or this version of the operating system"
  2226. "does not support this command\n");
  2227. return E_NOTIMPL;
  2228. }
  2229. Status = g_Target->ReadVirtual(ExpDebuggerWork, &work, sizeof(work), &Size);
  2230. if ((Status != S_OK) || Size != sizeof(work))
  2231. {
  2232. ErrOut("Could not determine status or debugger worker thread\n");
  2233. return HRESULT_FROM_WIN32(ERROR_BUSY);
  2234. }
  2235. else if (work > 1)
  2236. {
  2237. ErrOut("Debugger worker thread has pending command\n");
  2238. return HRESULT_FROM_WIN32(ERROR_BUSY);
  2239. }
  2240. Status = g_Target->WritePointer(g_Machine, ExpDebuggerProcessAttach,
  2241. Process);
  2242. if (Status == S_OK)
  2243. {
  2244. Status = g_Target->WritePointer(g_Machine, ExpDebuggerPageIn,
  2245. Data);
  2246. }
  2247. if (Status == S_OK)
  2248. {
  2249. work = 1;
  2250. Status = g_Target->WriteVirtual(ExpDebuggerWork, &work,
  2251. sizeof(work), &Size);
  2252. }
  2253. if (Status != S_OK)
  2254. {
  2255. ErrOut("Could not queue operation to debugger worker thread\n");
  2256. }
  2257. return Status;
  2258. }
  2259. void
  2260. ParseSetImplicitProcess(void)
  2261. {
  2262. ULONG64 Base = 0;
  2263. BOOL Ptes = FALSE;
  2264. BOOL Invasive = FALSE;
  2265. BOOL OldPtes = g_VirtualCache.m_ForceDecodePTEs;
  2266. while (PeekChar() == '-' || *g_CurCmd == '/')
  2267. {
  2268. switch(*(++g_CurCmd))
  2269. {
  2270. case 'p':
  2271. Ptes = TRUE;
  2272. break;
  2273. case 'i':
  2274. Invasive = TRUE;
  2275. break;
  2276. default:
  2277. dprintf("Unknown option '%c'\n", *g_CurCmd);
  2278. break;
  2279. }
  2280. g_CurCmd++;
  2281. }
  2282. if (PeekChar() && *g_CurCmd != ';')
  2283. {
  2284. Base = GetExpression();
  2285. }
  2286. if (Invasive)
  2287. {
  2288. if (S_OK == KernelPageIn(Base, 0))
  2289. {
  2290. dprintf("You need to continue execution (press 'g' <enter>) for "
  2291. "the context to be switched. When the debugger breaks "
  2292. "in again, you will be in the new process context.\n");
  2293. }
  2294. return;
  2295. }
  2296. if (Ptes && !Base)
  2297. {
  2298. // If the user has requested a reset to the default
  2299. // process with no translations we need to turn
  2300. // off translations immediately so that any
  2301. // existing base doesn't interfere with determining
  2302. // the default process.
  2303. g_VirtualCache.SetForceDecodePtes(FALSE);
  2304. }
  2305. if (SetImplicitProcessData(Base, TRUE) == S_OK)
  2306. {
  2307. dprintf("Implicit process is now %s\n",
  2308. FormatAddr64(g_ImplicitProcessData));
  2309. if (Ptes)
  2310. {
  2311. if (Base)
  2312. {
  2313. g_VirtualCache.SetForceDecodePtes(TRUE);
  2314. }
  2315. dprintf(".cache %sforcedecodeptes done\n",
  2316. Base != 0 ? "" : "no");
  2317. }
  2318. if (Base && !g_VirtualCache.m_ForceDecodePTEs)
  2319. {
  2320. WarnOut("WARNING: .cache forcedecodeptes is not enabled\n");
  2321. }
  2322. }
  2323. else if (Ptes && !Base && OldPtes)
  2324. {
  2325. // Restore settings to the way they were.
  2326. g_VirtualCache.SetForceDecodePtes(TRUE);
  2327. }
  2328. }
  2329. void
  2330. ParsePageIn(void)
  2331. {
  2332. ULONG64 Process = 0;
  2333. ULONG64 Data = 0;
  2334. while (PeekChar() == '-' || *g_CurCmd == '/')
  2335. {
  2336. switch(*(++g_CurCmd))
  2337. {
  2338. case 'p':
  2339. g_CurCmd++;
  2340. Process = GetExpression();
  2341. break;
  2342. default:
  2343. g_CurCmd++;
  2344. dprintf("Unknown option '%c'\n", *g_CurCmd);
  2345. break;
  2346. }
  2347. }
  2348. if (PeekChar() && *g_CurCmd != ';')
  2349. {
  2350. Data = GetExpression();
  2351. }
  2352. if (!Data)
  2353. {
  2354. ErrOut("Pagein requires an address to be specified\n");
  2355. return;
  2356. }
  2357. //
  2358. // Modify kernel state to do the pagein
  2359. //
  2360. if (S_OK != KernelPageIn(Process, Data))
  2361. {
  2362. ErrOut("PageIn for address %s, process %s failed\n",
  2363. FormatAddr64(Data),
  2364. FormatAddr64(Process));
  2365. }
  2366. else
  2367. {
  2368. dprintf("You need to continue execution (press 'g' <enter>) for "
  2369. "the pagein to be brought in. When the debugger breaks in "
  2370. "again, the page will be present.\n");
  2371. }
  2372. }