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.

1346 lines
32 KiB

  1. #include <engexts.h>
  2. //----------------------------------------------------------------------------
  3. //
  4. // StaticEventCallbacks.
  5. //
  6. //----------------------------------------------------------------------------
  7. class StaticEventCallbacks : public DebugBaseEventCallbacks
  8. {
  9. public:
  10. // IUnknown.
  11. STDMETHOD_(ULONG, AddRef)(
  12. THIS
  13. );
  14. STDMETHOD_(ULONG, Release)(
  15. THIS
  16. );
  17. };
  18. STDMETHODIMP_(ULONG)
  19. StaticEventCallbacks::AddRef(
  20. THIS
  21. )
  22. {
  23. // This class is designed to be static so
  24. // there's no true refcount.
  25. return 1;
  26. }
  27. STDMETHODIMP_(ULONG)
  28. StaticEventCallbacks::Release(
  29. THIS
  30. )
  31. {
  32. // This class is designed to be static so
  33. // there's no true refcount.
  34. return 0;
  35. }
  36. //----------------------------------------------------------------------------
  37. //
  38. // ExcepCallbacks.
  39. //
  40. //----------------------------------------------------------------------------
  41. class ExcepCallbacks : public StaticEventCallbacks
  42. {
  43. public:
  44. ExcepCallbacks(void)
  45. {
  46. m_Client = NULL;
  47. m_Control = NULL;
  48. }
  49. // IDebugEventCallbacks.
  50. STDMETHOD(GetInterestMask)(
  51. THIS_
  52. OUT PULONG Mask
  53. );
  54. STDMETHOD(Exception)(
  55. THIS_
  56. IN PEXCEPTION_RECORD64 Exception,
  57. IN ULONG FirstChance
  58. );
  59. HRESULT Initialize(PDEBUG_CLIENT Client)
  60. {
  61. HRESULT Status;
  62. m_Client = Client;
  63. m_Client->AddRef();
  64. if ((Status = m_Client->QueryInterface(__uuidof(IDebugControl),
  65. (void**)&m_Control)) == S_OK)
  66. {
  67. // Turn off default breakin on breakpoint exceptions.
  68. Status = m_Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
  69. "sxd bpe", DEBUG_EXECUTE_DEFAULT);
  70. }
  71. return Status;
  72. }
  73. void Uninitialize(void)
  74. {
  75. EXT_RELEASE(m_Control);
  76. EXT_RELEASE(m_Client);
  77. }
  78. private:
  79. PDEBUG_CLIENT m_Client;
  80. PDEBUG_CONTROL m_Control;
  81. };
  82. STDMETHODIMP
  83. ExcepCallbacks::GetInterestMask(
  84. THIS_
  85. OUT PULONG Mask
  86. )
  87. {
  88. *Mask = DEBUG_EVENT_EXCEPTION;
  89. return S_OK;
  90. }
  91. STDMETHODIMP
  92. ExcepCallbacks::Exception(
  93. THIS_
  94. IN PEXCEPTION_RECORD64 Exception,
  95. IN ULONG FirstChance
  96. )
  97. {
  98. m_Control->Output(DEBUG_OUTPUT_NORMAL, "Exception %X at %p, chance %d\n",
  99. Exception->ExceptionCode, Exception->ExceptionAddress,
  100. FirstChance ? 1 : 2);
  101. return DEBUG_STATUS_GO_HANDLED;
  102. }
  103. ExcepCallbacks g_ExcepCallbacks;
  104. //----------------------------------------------------------------------------
  105. //
  106. // FnProfCallbacks.
  107. //
  108. //----------------------------------------------------------------------------
  109. class FnProfCallbacks : public StaticEventCallbacks
  110. {
  111. public:
  112. FnProfCallbacks(void)
  113. {
  114. m_Client = NULL;
  115. m_Control = NULL;
  116. }
  117. // IDebugEventCallbacks.
  118. STDMETHOD(GetInterestMask)(
  119. THIS_
  120. OUT PULONG Mask
  121. );
  122. STDMETHOD(Breakpoint)(
  123. THIS_
  124. IN PDEBUG_BREAKPOINT Bp
  125. );
  126. HRESULT Initialize(PDEBUG_CLIENT Client, PDEBUG_CONTROL Control)
  127. {
  128. m_Hits = 0;
  129. m_Client = Client;
  130. m_Client->AddRef();
  131. m_Control = Control;
  132. m_Control->AddRef();
  133. return S_OK;
  134. }
  135. void Uninitialize(void)
  136. {
  137. EXT_RELEASE(m_Control);
  138. EXT_RELEASE(m_Client);
  139. }
  140. ULONG GetHits(void)
  141. {
  142. return m_Hits;
  143. }
  144. PDEBUG_CONTROL GetControl(void)
  145. {
  146. return m_Control;
  147. }
  148. private:
  149. PDEBUG_CLIENT m_Client;
  150. PDEBUG_CONTROL m_Control;
  151. ULONG m_Hits;
  152. };
  153. STDMETHODIMP
  154. FnProfCallbacks::GetInterestMask(
  155. THIS_
  156. OUT PULONG Mask
  157. )
  158. {
  159. *Mask = DEBUG_EVENT_BREAKPOINT;
  160. return S_OK;
  161. }
  162. STDMETHODIMP
  163. FnProfCallbacks::Breakpoint(
  164. THIS_
  165. IN PDEBUG_BREAKPOINT Bp
  166. )
  167. {
  168. PDEBUG_CLIENT Client;
  169. HRESULT Status = DEBUG_STATUS_NO_CHANGE;
  170. // If this is one of our profiling breakpoints
  171. // record the function hit and continue on.
  172. if (Bp->GetAdder(&Client) == S_OK)
  173. {
  174. if (Client == m_Client)
  175. {
  176. m_Hits++;
  177. Status = DEBUG_STATUS_GO;
  178. }
  179. Client->Release();
  180. }
  181. Bp->Release();
  182. return Status;
  183. }
  184. FnProfCallbacks g_FnProfCallbacks;
  185. //----------------------------------------------------------------------------
  186. //
  187. // Extension entry points.
  188. //
  189. //----------------------------------------------------------------------------
  190. extern "C" HRESULT CALLBACK
  191. DebugExtensionInitialize(PULONG Version, PULONG Flags)
  192. {
  193. *Version = DEBUG_EXTENSION_VERSION(1, 0);
  194. *Flags = 0;
  195. return S_OK;
  196. }
  197. extern "C" void CALLBACK
  198. DebugExtensionUninitialize(void)
  199. {
  200. g_ExcepCallbacks.Uninitialize();
  201. g_FnProfCallbacks.Uninitialize();
  202. }
  203. #if 0
  204. extern "C" HRESULT CALLBACK
  205. teb(PDEBUG_CLIENT Client, PCSTR Args)
  206. {
  207. HRESULT Status;
  208. ULONG64 DataOffset;
  209. if ((Status = ExtQuery(Client)) != S_OK)
  210. {
  211. return Status;
  212. }
  213. if (*Args)
  214. {
  215. sscanf(Args, "%I64x", &DataOffset);
  216. }
  217. else
  218. {
  219. g_ExtSystem->GetCurrentThreadDataOffset(&DataOffset);
  220. }
  221. ExtOut("TEB at %I64x\n", DataOffset);
  222. TEB Teb;
  223. Status = g_ExtData->ReadVirtual(DataOffset, &Teb, sizeof(Teb), NULL);
  224. if (Status != S_OK)
  225. {
  226. ExtErr("* Unable to read TEB\n");
  227. }
  228. else
  229. {
  230. ExtOut(" ExceptionList: %x\n", Teb.NtTib.ExceptionList);
  231. ExtOut(" Stack Base: %x\n", Teb.NtTib.StackBase);
  232. ExtOut(" Stack Limit: %x\n", Teb.NtTib.StackLimit);
  233. ExtOut(" SubSystemTib: %x\n", Teb.NtTib.SubSystemTib);
  234. ExtOut(" FiberData: %x\n", Teb.NtTib.FiberData);
  235. ExtOut(" ArbitraryUser: %x\n", Teb.NtTib.ArbitraryUserPointer);
  236. ExtOut(" Self: %x\n", Teb.NtTib.Self);
  237. ExtOut(" EnvironmentPtr: %x\n", Teb.EnvironmentPointer);
  238. ExtOut(" ClientId: %x.%x\n",
  239. Teb.ClientId.UniqueProcess, Teb.ClientId.UniqueThread);
  240. if (Teb.ClientId.UniqueProcess != Teb.RealClientId.UniqueProcess ||
  241. Teb.ClientId.UniqueThread != Teb.RealClientId.UniqueThread)
  242. {
  243. ExtOut(" Real ClientId: %x.%x\n",
  244. Teb.RealClientId.UniqueProcess,
  245. Teb.RealClientId.UniqueThread);
  246. }
  247. ExtOut(" Real ClientId: %x.%x\n",
  248. Teb.RealClientId.UniqueProcess,
  249. Teb.RealClientId.UniqueThread);
  250. ExtOut(" RpcHandle: %x\n", Teb.ActiveRpcHandle);
  251. ExtOut(" Tls Storage: %x\n", Teb.ThreadLocalStoragePointer);
  252. ExtOut(" PEB Address: %x\n", Teb.ProcessEnvironmentBlock);
  253. ExtOut(" LastErrorValue: %u\n", Teb.LastErrorValue);
  254. ExtOut(" LastStatusValue: %x\n", Teb.LastStatusValue);
  255. ExtOut(" Count Owned Locks:%u\n", Teb.CountOfOwnedCriticalSections);
  256. ExtOut(" HardErrorMode: %u\n", Teb.HardErrorMode);
  257. Status = S_OK;
  258. }
  259. ExtRelease();
  260. return Status;
  261. }
  262. #endif
  263. extern "C" HRESULT CALLBACK
  264. outreg(PDEBUG_CLIENT Client, PCSTR Args)
  265. {
  266. HRESULT Status;
  267. if ((Status = ExtQuery(Client)) != S_OK)
  268. {
  269. return Status;
  270. }
  271. g_ExtRegisters->OutputRegisters(DEBUG_OUTCTL_ALL_CLIENTS,
  272. DEBUG_REGISTERS_ALL);
  273. ExtRelease();
  274. return Status;
  275. }
  276. extern "C" HRESULT CALLBACK
  277. enumreg(PDEBUG_CLIENT Client, PCSTR Args)
  278. {
  279. HRESULT Status;
  280. if ((Status = ExtQuery(Client)) != S_OK)
  281. {
  282. return Status;
  283. }
  284. ULONG Num;
  285. g_ExtRegisters->GetNumberRegisters(&Num);
  286. ExtOut("%d registers\n", Num);
  287. ULONG i;
  288. char Name[64];
  289. DEBUG_REGISTER_DESCRIPTION Desc;
  290. ULONG Reax, Rebx, Refl, Rsf, Rst0;
  291. ULONG RegFound = 0;
  292. for (i = 0; i < Num; i++)
  293. {
  294. g_ExtRegisters->GetDescription(i, Name, sizeof(Name), NULL, &Desc);
  295. ExtOut(" %2d: \"%s\", type %d, flags %X\n",
  296. i, Name, Desc.Type, Desc.Flags);
  297. if (Desc.Flags & DEBUG_REGISTER_SUB_REGISTER)
  298. {
  299. ExtOut(" sub to %d, len %d, mask %I64X, shift %d\n",
  300. Desc.SubregMaster, Desc.SubregLength,
  301. Desc.SubregMask, Desc.SubregShift);
  302. }
  303. // XXX drewb - Hack for testing purposes.
  304. if (!_strcmpi(Name, "eax"))
  305. {
  306. Reax = i;
  307. RegFound++;
  308. }
  309. else if (!_strcmpi(Name, "ebx"))
  310. {
  311. Rebx = i;
  312. RegFound++;
  313. }
  314. else if (!_strcmpi(Name, "efl"))
  315. {
  316. Refl = i;
  317. RegFound++;
  318. }
  319. else if (!_strcmpi(Name, "sf"))
  320. {
  321. Rsf = i;
  322. RegFound++;
  323. }
  324. else if (!_strcmpi(Name, "st0"))
  325. {
  326. Rst0 = i;
  327. RegFound++;
  328. }
  329. }
  330. ULONG ProcType;
  331. g_ExtControl->GetExecutingProcessorType(&ProcType);
  332. ExtOut("Processor type %d\n", ProcType);
  333. if (ProcType == IMAGE_FILE_MACHINE_I386)
  334. {
  335. DEBUG_VALUE Val;
  336. DEBUG_VALUE Coerce;
  337. if (RegFound != 5)
  338. {
  339. ExtErr("** Only found %d registers\n", RegFound);
  340. }
  341. Val.Type = DEBUG_VALUE_INT32;
  342. Val.I32 = 0x12345678;
  343. g_ExtRegisters->SetValue(Reax, &Val);
  344. Val.I32 = 12345678;
  345. g_ExtRegisters->SetValue(Rst0, &Val);
  346. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
  347. "r eax,st0", DEBUG_EXECUTE_NOT_LOGGED);
  348. Val.Type = DEBUG_VALUE_FLOAT32;
  349. Val.F32 = 1.2345f;
  350. g_ExtRegisters->SetValue(Rst0, &Val);
  351. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
  352. "r st0", DEBUG_EXECUTE_NOT_LOGGED);
  353. g_ExtRegisters->GetValue(Rst0, &Val);
  354. ExtOut("st0 type is %d\n", Val.Type);
  355. g_ExtControl->CoerceValue(&Val, DEBUG_VALUE_FLOAT32, &Coerce);
  356. Coerce.F32 *= 2.0f;
  357. ExtOut("coerce type is %d, val*2 %hf\n", Coerce.Type, Coerce.F32);
  358. g_ExtRegisters->SetValue(Reax, &Val);
  359. g_ExtRegisters->SetValue(Rebx, &Coerce);
  360. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
  361. "r eax,ebx", DEBUG_EXECUTE_NOT_LOGGED);
  362. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
  363. "r efl", DEBUG_EXECUTE_NOT_LOGGED);
  364. g_ExtRegisters->GetValue(Rsf, &Val);
  365. ExtOut("sf type is %d, val %d\n", Val.Type, Val.I32);
  366. Val.I32 ^= 1;
  367. g_ExtRegisters->SetValue(Rsf, &Val);
  368. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
  369. "r efl", DEBUG_EXECUTE_NOT_LOGGED);
  370. g_ExtRegisters->GetValue(Rsf, &Val);
  371. ExtOut("sf type is %d, val %d\n", Val.Type, Val.I32);
  372. Val.I32 ^= 1;
  373. g_ExtRegisters->SetValue(Rsf, &Val);
  374. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
  375. "r efl", DEBUG_EXECUTE_NOT_LOGGED);
  376. }
  377. ExtRelease();
  378. return Status;
  379. }
  380. extern "C" HRESULT CALLBACK
  381. symnear(PDEBUG_CLIENT Client, PCSTR Args)
  382. {
  383. HRESULT Status;
  384. if ((Status = ExtQuery(Client)) != S_OK)
  385. {
  386. return Status;
  387. }
  388. LONG Delta;
  389. Delta = 0;
  390. sscanf(Args, "%d", &Delta);
  391. ULONG64 Instr;
  392. char Name[128];
  393. ULONG64 Disp;
  394. g_ExtRegisters->GetInstructionOffset(&Instr);
  395. if (g_ExtSymbols->GetNearNameByOffset(Instr, Delta,
  396. Name, sizeof(Name), NULL,
  397. &Disp) == S_OK)
  398. {
  399. ExtOut("Symbol %d away from %p is:\n %s + 0x%I64x\n",
  400. Delta, Instr, Name, Disp);
  401. if (g_ExtSymbols->GetOffsetByName(Name, &Instr) == S_OK)
  402. {
  403. ExtOut("Symbol %s has offset %p\n", Name, Instr);
  404. }
  405. else
  406. {
  407. ExtOut("Symbol %s has no offset\n", Name);
  408. }
  409. }
  410. else
  411. {
  412. ExtOut("No symbol %d away from %p\n", Delta, Instr);
  413. }
  414. ExtRelease();
  415. return Status;
  416. }
  417. extern "C" HRESULT CALLBACK
  418. symname(PDEBUG_CLIENT Client, PCSTR Args)
  419. {
  420. HRESULT Status;
  421. if ((Status = ExtQuery(Client)) != S_OK)
  422. {
  423. return Status;
  424. }
  425. ULONG64 Offs;
  426. if (g_ExtSymbols->GetOffsetByName(Args, &Offs) == S_OK)
  427. {
  428. ExtOut("Symbol %s has offset %I64x\n",
  429. Args, Offs);
  430. }
  431. else
  432. {
  433. ExtOut("Symbol %s has no offset\n", Args);
  434. }
  435. ExtRelease();
  436. return Status;
  437. }
  438. extern "C" HRESULT CALLBACK
  439. line(PDEBUG_CLIENT Client, PCSTR Args)
  440. {
  441. HRESULT Status;
  442. if ((Status = ExtQuery(Client)) != S_OK)
  443. {
  444. return Status;
  445. }
  446. ULONG64 Instr;
  447. ULONG Line;
  448. char File[128];
  449. ULONG64 Disp;
  450. g_ExtRegisters->GetInstructionOffset(&Instr);
  451. if (g_ExtSymbols->GetLineByOffset(Instr, &Line,
  452. File, sizeof(File), NULL, &Disp) == S_OK)
  453. {
  454. ExtOut("Line at %p is:\n %s(%d) + 0x%I64x\n",
  455. Instr, File, Line, Disp);
  456. if (g_ExtSymbols->GetOffsetByLine(Line, File, &Instr) == S_OK)
  457. {
  458. ExtOut("Line %s(%d) has offset %p\n", File, Line, Instr);
  459. }
  460. else
  461. {
  462. ExtOut("Line %s(%d) has no offset\n", File, Line);
  463. }
  464. }
  465. else
  466. {
  467. ExtOut("No line information for %p\n", Instr);
  468. }
  469. ExtRelease();
  470. return Status;
  471. }
  472. extern "C" HRESULT CALLBACK
  473. sympat(PDEBUG_CLIENT Client, PCSTR Args)
  474. {
  475. HRESULT Status;
  476. if ((Status = ExtQuery(Client)) != S_OK)
  477. {
  478. return Status;
  479. }
  480. ULONG64 Match;
  481. char Name[128];
  482. ULONG64 Offset;
  483. PCSTR Pattern;
  484. while (*Args == ' ' || *Args == '\t')
  485. {
  486. Args++;
  487. }
  488. if (*Args)
  489. {
  490. Pattern = Args;
  491. }
  492. else
  493. {
  494. Pattern = "*";
  495. }
  496. Status = g_ExtSymbols->StartSymbolMatch(Pattern, &Match);
  497. if (Status != S_OK)
  498. {
  499. ExtErr("Unable to match on '%s'\n", Pattern);
  500. }
  501. else
  502. {
  503. for (;;)
  504. {
  505. Status = g_ExtSymbols->
  506. GetNextSymbolMatch(Match, Name, sizeof(Name), NULL, &Offset);
  507. if (Status != S_OK)
  508. {
  509. break;
  510. }
  511. ExtOut("%p - %s\n", Offset, Name);
  512. if (g_ExtControl->GetInterrupt() == S_OK)
  513. {
  514. ExtOut("** interrupt\n");
  515. break;
  516. }
  517. }
  518. g_ExtSymbols->EndSymbolMatch(Match);
  519. }
  520. ExtRelease();
  521. return Status;
  522. }
  523. extern "C" HRESULT CALLBACK
  524. stack(PDEBUG_CLIENT Client, PCSTR Args)
  525. {
  526. HRESULT Status;
  527. if ((Status = ExtQuery(Client)) != S_OK)
  528. {
  529. return Status;
  530. }
  531. ULONG Flags;
  532. while (*Args == ' ' || *Args == '\t')
  533. {
  534. Args++;
  535. }
  536. if (*Args)
  537. {
  538. sscanf(Args, "%d", &Flags);
  539. }
  540. else
  541. {
  542. Flags = 0;
  543. }
  544. DEBUG_STACK_FRAME Frames[4];
  545. ULONG64 FrameOff, StackOff, InstrOff;
  546. ULONG Filled;
  547. g_ExtRegisters->GetFrameOffset(&FrameOff);
  548. g_ExtRegisters->GetStackOffset(&StackOff);
  549. g_ExtRegisters->GetInstructionOffset(&InstrOff);
  550. if (g_ExtControl->GetStackTrace(FrameOff, StackOff, InstrOff,
  551. Frames, sizeof(Frames) / sizeof(Frames[0]),
  552. &Filled) != S_OK)
  553. {
  554. ExtErr("Unable to get stack trace\n");
  555. }
  556. else
  557. {
  558. ExtOut("Filled %d frames at %p\n", Filled, InstrOff);
  559. g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS,
  560. Frames, Filled, Flags);
  561. }
  562. ExtOut("\nDirect:\n");
  563. g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS,
  564. NULL, 20, Flags);
  565. ExtRelease();
  566. return Status;
  567. }
  568. extern "C" HRESULT CALLBACK
  569. tyid(PDEBUG_CLIENT Client, PCSTR Args)
  570. {
  571. HRESULT Status;
  572. if ((Status = ExtQuery(Client)) != S_OK)
  573. {
  574. return Status;
  575. }
  576. ULONG TypeId;
  577. char Type[256];
  578. ULONG TypeSize;
  579. ULONG64 Module;
  580. while (*Args == ' ' || *Args == '\t')
  581. {
  582. Args++;
  583. }
  584. if (*Args >= '0' && *Args <= '9')
  585. {
  586. DEBUG_VALUE IntVal;
  587. g_ExtControl->Evaluate(Args, DEBUG_VALUE_INT64, &IntVal, NULL);
  588. Status = g_ExtSymbols->GetOffsetTypeId(IntVal.I64, &TypeId, &Module);
  589. }
  590. else
  591. {
  592. Status = g_ExtSymbols->GetSymbolTypeId(Args, &TypeId, &Module);
  593. }
  594. if (Status == S_OK)
  595. {
  596. ExtOut("Type ID of '%s' is %d\n", Args, TypeId);
  597. }
  598. else
  599. {
  600. ExtErr("Unable to get type ID, %X\n", Status);
  601. }
  602. ExtRelease();
  603. return Status;
  604. }
  605. extern "C" HRESULT CALLBACK
  606. typeof(PDEBUG_CLIENT Client, PCSTR Args)
  607. {
  608. HRESULT Status;
  609. if ((Status = ExtQuery(Client)) != S_OK)
  610. {
  611. return Status;
  612. }
  613. ULONG TypeId;
  614. char Type[256];
  615. ULONG TypeSize;
  616. ULONG64 Module;
  617. while (*Args == ' ' || *Args == '\t')
  618. {
  619. Args++;
  620. }
  621. if (*Args >= '0' && *Args <= '9')
  622. {
  623. DEBUG_VALUE IntVal;
  624. g_ExtControl->Evaluate(Args, DEBUG_VALUE_INT64, &IntVal, NULL);
  625. Status = g_ExtSymbols->GetOffsetTypeId(IntVal.I64, &TypeId, &Module);
  626. }
  627. else
  628. {
  629. Status = g_ExtSymbols->GetSymbolTypeId(Args, &TypeId, &Module);
  630. }
  631. if (Status == S_OK)
  632. {
  633. Status = g_ExtSymbols->GetTypeName(Module, TypeId, Type, sizeof(Type),
  634. &TypeSize);
  635. }
  636. if (Status == S_OK)
  637. {
  638. ExtOut("Type of '%s' is '%s':%d (%d chars)\n",
  639. Args, Type, TypeId, TypeSize);
  640. }
  641. else
  642. {
  643. ExtErr("Unable to get type, %X\n", Status);
  644. }
  645. ExtRelease();
  646. return Status;
  647. }
  648. extern "C" HRESULT CALLBACK
  649. tsizeof(PDEBUG_CLIENT Client, PCSTR Args)
  650. {
  651. HRESULT Status;
  652. if ((Status = ExtQuery(Client)) != S_OK)
  653. {
  654. return Status;
  655. }
  656. PCSTR TypeName;
  657. ULONG TypeId;
  658. ULONG TypeSize;
  659. while (*Args == ' ' || *Args == '\t')
  660. {
  661. Args++;
  662. }
  663. TypeName = strchr(Args, '!');
  664. if (TypeName == NULL)
  665. {
  666. ExtErr("Must specify Module!Type\n");
  667. Status = E_INVALIDARG;
  668. }
  669. else
  670. {
  671. ULONG64 Module;
  672. Status = g_ExtSymbols->GetSymbolModule(Args, &Module);
  673. if (Status == S_OK)
  674. {
  675. Status = g_ExtSymbols->GetTypeId(Module, TypeName, &TypeId);
  676. }
  677. if (Status == S_OK)
  678. {
  679. Status = g_ExtSymbols->GetTypeSize(Module, TypeId, &TypeSize);
  680. }
  681. if (Status == S_OK)
  682. {
  683. ExtOut("Type '%s':%d is %d bytes\n",
  684. Args, TypeId, TypeSize);
  685. }
  686. else
  687. {
  688. ExtErr("Unable to get type size, %X\n", Status);
  689. }
  690. }
  691. ExtRelease();
  692. return Status;
  693. }
  694. extern "C" HRESULT CALLBACK
  695. foff(PDEBUG_CLIENT Client, PCSTR Args)
  696. {
  697. HRESULT Status;
  698. if ((Status = ExtQuery(Client)) != S_OK)
  699. {
  700. return Status;
  701. }
  702. ULONG TypeId;
  703. char Type[256];
  704. PCSTR Bang, Dot;
  705. ULONG Offset;
  706. while (*Args == ' ' || *Args == '\t')
  707. {
  708. Args++;
  709. }
  710. Bang = strchr(Args, '!');
  711. if (Bang != NULL)
  712. {
  713. Dot = strchr(Bang + 1, '.');
  714. }
  715. if (Bang == NULL || Dot == NULL)
  716. {
  717. ExtErr("Syntax is Module!Type.Field\n");
  718. Status = E_INVALIDARG;
  719. }
  720. else
  721. {
  722. ULONG64 Module;
  723. memcpy(Type, Bang + 1, Dot - (Bang + 1));
  724. Type[Dot - (Bang + 1)] = 0;
  725. Dot++;
  726. Status = g_ExtSymbols->GetSymbolModule(Args, &Module);
  727. if (Status == S_OK)
  728. {
  729. Status = g_ExtSymbols->GetTypeId(Module, Type, &TypeId);
  730. }
  731. if (Status == S_OK)
  732. {
  733. Status = g_ExtSymbols->GetFieldOffset(Module, TypeId, Dot,
  734. &Offset);
  735. }
  736. if (Status == S_OK)
  737. {
  738. ExtOut("Offset of %s is %d bytes\n",
  739. Args, Offset);
  740. }
  741. else
  742. {
  743. ExtErr("Unable to get field offset, %X\n", Status);
  744. }
  745. }
  746. ExtRelease();
  747. return Status;
  748. }
  749. extern "C" HRESULT CALLBACK
  750. otype(PDEBUG_CLIENT Client, PCSTR Args)
  751. {
  752. HRESULT Status;
  753. if ((Status = ExtQuery(Client)) != S_OK)
  754. {
  755. return Status;
  756. }
  757. ULONG TypeId;
  758. char Type[256];
  759. PCSTR Bang, Space;
  760. while (*Args == ' ' || *Args == '\t')
  761. {
  762. Args++;
  763. }
  764. Bang = strchr(Args, '!');
  765. if (Bang != NULL)
  766. {
  767. Space = strchr(Bang + 1, ' ');
  768. }
  769. if (Bang == NULL || Space == NULL)
  770. {
  771. ExtErr("Syntax is Module!Type Address\n");
  772. Status = E_INVALIDARG;
  773. }
  774. else
  775. {
  776. memcpy(Type, Bang + 1, Space - (Bang + 1));
  777. Type[Space - (Bang + 1)] = 0;
  778. Space++;
  779. ULONG64 Module;
  780. ULONG Flags = DEBUG_OUTTYPE_RECURSION_LEVEL(15);
  781. DEBUG_VALUE IntVal;
  782. g_ExtControl->Evaluate(Space, DEBUG_VALUE_INT64, &IntVal, NULL);
  783. Status = g_ExtSymbols->GetSymbolModule(Args, &Module);
  784. if (Status == S_OK)
  785. {
  786. Status = g_ExtSymbols->GetTypeId(Module, Type, &TypeId);
  787. }
  788. if (Status == S_OK)
  789. {
  790. Status = g_ExtSymbols->
  791. OutputTypedDataVirtual(DEBUG_OUTCTL_ALL_CLIENTS,
  792. IntVal.I64, Module, TypeId, Flags);
  793. if (Status != S_OK)
  794. {
  795. ExtErr("Unable to output data, %X\n", Status);
  796. }
  797. }
  798. else
  799. {
  800. ExtErr("Unable to get type ID, %X\n", Status);
  801. }
  802. }
  803. ExtRelease();
  804. return Status;
  805. }
  806. extern "C" HRESULT CALLBACK
  807. vsearch(PDEBUG_CLIENT Client, PCSTR Args)
  808. {
  809. HRESULT Status;
  810. if ((Status = ExtQuery(Client)) != S_OK)
  811. {
  812. return Status;
  813. }
  814. ULONG Start = 0, Len = 0;
  815. ULONG Chars;
  816. sscanf(Args, "%x %x%n", &Start, &Len, &Chars);
  817. if (Start == 0 || Len == 0)
  818. {
  819. ExtErr("Syntax is Start Len Byte+\n");
  820. Status = E_INVALIDARG;
  821. }
  822. else
  823. {
  824. UCHAR Pattern[32];
  825. ULONG PatLen;
  826. Args += Chars;
  827. PatLen = 0;
  828. for (;;)
  829. {
  830. while (*Args == ' ' || *Args == '\t')
  831. {
  832. Args++;
  833. }
  834. if (*Args == 0)
  835. {
  836. break;
  837. }
  838. sscanf(Args, "%x", &Pattern[PatLen]);
  839. PatLen++;
  840. while (*Args != 0 && *Args != ' ' && *Args != '\t')
  841. {
  842. Args++;
  843. }
  844. }
  845. ULONG64 Match;
  846. Status = g_ExtData->SearchVirtual(Start, Len, Pattern, PatLen, 1,
  847. &Match);
  848. if (Status == S_OK)
  849. {
  850. ExtOut("Match at %p\n", Match);
  851. }
  852. else
  853. {
  854. ExtErr("Search failed, 0x%X\n", Status);
  855. }
  856. }
  857. ExtRelease();
  858. return Status;
  859. }
  860. extern "C" HRESULT CALLBACK
  861. vread(PDEBUG_CLIENT Client, PCSTR Args)
  862. {
  863. HRESULT Status;
  864. if ((Status = ExtQuery(Client)) != S_OK)
  865. {
  866. return Status;
  867. }
  868. ULONG Start = 0, Len = 0;
  869. sscanf(Args, "%x %x", &Start, &Len);
  870. if (Start == 0 || Len == 0)
  871. {
  872. ExtErr("Syntax is Start Len\n");
  873. Status = E_INVALIDARG;
  874. }
  875. else
  876. {
  877. UCHAR Buffer[16384];
  878. ULONG Read;
  879. if (Len > sizeof(Buffer))
  880. {
  881. ExtWarn("Buffer is only %X bytes, clamping\n", sizeof(Buffer));
  882. Len = sizeof(Buffer);
  883. }
  884. Status = g_ExtData->ReadVirtual(Start, Buffer, Len, &Read);
  885. if (Status == S_OK)
  886. {
  887. ExtOut("Read %X bytes\n", Read);
  888. }
  889. else
  890. {
  891. ExtErr("Read failed, 0x%X\n", Status);
  892. }
  893. }
  894. ExtRelease();
  895. return Status;
  896. }
  897. extern "C" HRESULT CALLBACK
  898. watch(PDEBUG_CLIENT Client, PCSTR Args)
  899. {
  900. HRESULT Status;
  901. PDEBUG_CLIENT Watcher = NULL;
  902. if ((Status = Client->CreateClient(&Watcher)) != S_OK)
  903. {
  904. goto Exit;
  905. }
  906. if ((Status = Watcher->SetEventCallbacks(&g_ExcepCallbacks)) != S_OK)
  907. {
  908. goto Exit;
  909. }
  910. g_ExcepCallbacks.Uninitialize();
  911. Status = g_ExcepCallbacks.Initialize(Watcher);
  912. Exit:
  913. EXT_RELEASE(Watcher);
  914. if (Status != S_OK)
  915. {
  916. ExtErr("Unable to watch, 0x%X\n", Status);
  917. g_ExcepCallbacks.Uninitialize();
  918. }
  919. return Status;
  920. }
  921. extern "C" HRESULT CALLBACK
  922. fnprof(PDEBUG_CLIENT Client, PCSTR Args)
  923. {
  924. HRESULT Status;
  925. PDEBUG_CLIENT Profiler = NULL;
  926. PDEBUG_CONTROL ProfCtrl = NULL;
  927. PDEBUG_BREAKPOINT Bp = NULL;
  928. static ULONG s_BpId = DEBUG_ANY_ID;
  929. if ((Status = ExtQuery(Client)) != S_OK)
  930. {
  931. return Status;
  932. }
  933. while (*Args == ' ' || *Args == '\t')
  934. {
  935. Args++;
  936. }
  937. if (!*Args)
  938. {
  939. goto Exit;
  940. }
  941. if (!_strcmpi(Args, "-end"))
  942. {
  943. ULONG64 Offset;
  944. char OffsetExpr[512];
  945. if (s_BpId == DEBUG_ANY_ID)
  946. {
  947. Status = E_UNEXPECTED;
  948. goto Exit;
  949. }
  950. if ((Status = g_FnProfCallbacks.GetControl()->
  951. GetBreakpointById(s_BpId, &Bp)) != S_OK)
  952. {
  953. goto Exit;
  954. }
  955. if ((Status = Bp->GetOffset(&Offset)) != S_OK)
  956. {
  957. Offset = DEBUG_INVALID_OFFSET;
  958. }
  959. if ((Status = Bp->GetOffsetExpression(OffsetExpr,
  960. sizeof(OffsetExpr),
  961. NULL)) != S_OK)
  962. {
  963. goto Exit;
  964. }
  965. ExtOut("%s ", OffsetExpr);
  966. if (Offset != DEBUG_INVALID_OFFSET)
  967. {
  968. ExtOut("(%p) ", Offset);
  969. }
  970. ExtOut("was hit %d times\n", g_FnProfCallbacks.GetHits());
  971. g_FnProfCallbacks.GetControl()->RemoveBreakpoint(Bp);
  972. Bp = NULL;
  973. s_BpId = DEBUG_ANY_ID;
  974. g_FnProfCallbacks.Uninitialize();
  975. }
  976. else
  977. {
  978. if (s_BpId != DEBUG_ANY_ID)
  979. {
  980. Status = E_UNEXPECTED;
  981. goto Exit;
  982. }
  983. if ((Status = Client->CreateClient(&Profiler)) != S_OK)
  984. {
  985. goto Exit;
  986. }
  987. if ((Status = Profiler->SetEventCallbacks(&g_FnProfCallbacks)) != S_OK)
  988. {
  989. goto Exit;
  990. }
  991. if ((Status = Profiler->QueryInterface(__uuidof(IDebugControl),
  992. (void **)&ProfCtrl)) != S_OK)
  993. {
  994. goto Exit;
  995. }
  996. if ((Status = ProfCtrl->AddBreakpoint(DEBUG_BREAKPOINT_CODE,
  997. DEBUG_ANY_ID, &Bp)) != S_OK)
  998. {
  999. goto Exit;
  1000. }
  1001. if ((Status = Bp->SetOffsetExpression(Args)) != S_OK)
  1002. {
  1003. goto Exit;
  1004. }
  1005. if ((Status = Bp->AddFlags(DEBUG_BREAKPOINT_ADDER_ONLY |
  1006. DEBUG_BREAKPOINT_ENABLED)) != S_OK)
  1007. {
  1008. goto Exit;
  1009. }
  1010. if ((Status = Bp->GetId(&s_BpId)) != S_OK)
  1011. {
  1012. goto Exit;
  1013. }
  1014. g_FnProfCallbacks.Uninitialize();
  1015. if ((Status = g_FnProfCallbacks.Initialize(Profiler,
  1016. ProfCtrl)) != S_OK)
  1017. {
  1018. goto Exit;
  1019. }
  1020. ExtOut("Added breakpoint %d on %s\n", s_BpId, Args);
  1021. Bp = NULL;
  1022. }
  1023. Exit:
  1024. if (Bp != NULL)
  1025. {
  1026. if (ProfCtrl != NULL)
  1027. {
  1028. ProfCtrl->RemoveBreakpoint(Bp);
  1029. }
  1030. else
  1031. {
  1032. Bp->Release();
  1033. }
  1034. }
  1035. EXT_RELEASE(ProfCtrl);
  1036. EXT_RELEASE(Profiler);
  1037. if (Status != S_OK)
  1038. {
  1039. ExtErr("Unable to profile, 0x%X\n", Status);
  1040. g_FnProfCallbacks.Uninitialize();
  1041. }
  1042. ExtRelease();
  1043. return Status;
  1044. }
  1045. extern "C" HRESULT CALLBACK
  1046. vtrans(PDEBUG_CLIENT Client, PCSTR Args)
  1047. {
  1048. HRESULT Status;
  1049. if ((Status = ExtQuery(Client)) != S_OK)
  1050. {
  1051. return Status;
  1052. }
  1053. if (g_ExtData2 != NULL)
  1054. {
  1055. ULONG64 PhysOffs[8];
  1056. ULONG Levels;
  1057. DEBUG_VALUE Virt;
  1058. if ((Status = g_ExtControl->
  1059. Evaluate(Args, DEBUG_VALUE_INT64, &Virt, NULL)) == S_OK)
  1060. {
  1061. Status = g_ExtData2->
  1062. GetVirtualTranslationPhysicalOffsets(Virt.I64, PhysOffs,
  1063. sizeof(PhysOffs) /
  1064. sizeof(PhysOffs[0]),
  1065. &Levels);
  1066. if (SUCCEEDED(Status))
  1067. {
  1068. ULONG i;
  1069. ExtOut("%I64X translates in %d levels:\n",
  1070. Virt.I64, Levels);
  1071. for (i = 0; i < Levels; i++)
  1072. {
  1073. ExtOut(" %I64X\n", PhysOffs[i]);
  1074. }
  1075. }
  1076. else
  1077. {
  1078. ExtErr("Unable to translate %I64X, 0x%X\n",
  1079. Virt.I64, Status);
  1080. }
  1081. }
  1082. else
  1083. {
  1084. ExtErr("Unable to evaluate '%s', 0x%X\n", Args, Status);
  1085. }
  1086. }
  1087. else
  1088. {
  1089. ExtErr("Debugger does not support IDebugDataSpaces2\n");
  1090. }
  1091. ExtRelease();
  1092. return Status;
  1093. }
  1094. extern "C" HRESULT CALLBACK
  1095. enummod(PDEBUG_CLIENT Client, PCSTR Args)
  1096. {
  1097. HRESULT Status;
  1098. if ((Status = ExtQuery(Client)) != S_OK)
  1099. {
  1100. return Status;
  1101. }
  1102. ULONG Num[2];
  1103. ULONG Type, i, Index;
  1104. DEBUG_MODULE_PARAMETERS Params;
  1105. if ((Status = g_ExtSymbols->GetNumberModules(&Num[0],
  1106. &Num[1])) != S_OK)
  1107. {
  1108. ExtErr("GetNumberModules failed, 0x%X\n", Status);
  1109. goto Exit;
  1110. }
  1111. ExtOut("%d modules, %d unloaded modules\n", Num[0], Num[1]);
  1112. Index = -1;
  1113. for (Type = 0; Type < 2; Type++)
  1114. {
  1115. if (!Num[Type])
  1116. {
  1117. continue;
  1118. }
  1119. switch(Type)
  1120. {
  1121. case 0:
  1122. ExtOut("Loaded:\n");
  1123. ExtOut("-------\n");
  1124. break;
  1125. case 1:
  1126. ExtOut("Unloaded:\n");
  1127. ExtOut("---------\n");
  1128. break;
  1129. }
  1130. for (i = 0; i < Num[Type]; i++)
  1131. {
  1132. if ((Status = g_ExtSymbols->
  1133. GetModuleParameters(1, NULL, ++Index, &Params)) != S_OK)
  1134. {
  1135. ExtErr(" GetModuleParameters failed, 0x%X\n", Status);
  1136. continue;
  1137. }
  1138. ExtOut(" Base %p, size %08x\n", Params.Base, Params.Size);
  1139. ExtOut(" Flags %08x\n", Params.Flags);
  1140. }
  1141. }
  1142. Exit:
  1143. ExtRelease();
  1144. return Status;
  1145. }