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.

536 lines
14 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)(THIS);
  12. STDMETHOD_(ULONG, Release)(THIS);
  13. };
  14. STDMETHODIMP_(ULONG)
  15. StaticEventCallbacks::AddRef(THIS)
  16. {
  17. // This class is designed to be static so
  18. // there's no true refcount.
  19. return 1;
  20. }
  21. STDMETHODIMP_(ULONG)
  22. StaticEventCallbacks::Release(THIS)
  23. {
  24. // This class is designed to be static so
  25. // there's no true refcount.
  26. return 0;
  27. }
  28. //----------------------------------------------------------------------------
  29. //
  30. // ExcepCallbacks.
  31. //
  32. //----------------------------------------------------------------------------
  33. class ExcepCallbacks : public StaticEventCallbacks
  34. {
  35. public:
  36. ExcepCallbacks(void)
  37. {
  38. m_Client = NULL;
  39. m_Control = NULL;
  40. }
  41. // IDebugEventCallbacks.
  42. STDMETHOD(GetInterestMask)(THIS_
  43. OUT PULONG Mask);
  44. STDMETHOD(Exception)(THIS_
  45. IN PEXCEPTION_RECORD64 Exception,
  46. IN ULONG FirstChance);
  47. HRESULT Initialize(PDEBUG_CLIENT Client)
  48. {
  49. HRESULT Status;
  50. m_Client = Client;
  51. m_Client->AddRef();
  52. if ((Status = m_Client->QueryInterface(__uuidof(IDebugControl),
  53. (void**)&m_Control)) == S_OK)
  54. {
  55. #if 0
  56. // Turn off default breakin on breakpoint exceptions.
  57. Status = m_Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
  58. "sxd bpe", DEBUG_EXECUTE_DEFAULT);
  59. #endif
  60. }
  61. return Status;
  62. }
  63. void Uninitialize(void)
  64. {
  65. EXT_RELEASE(m_Control);
  66. EXT_RELEASE(m_Client);
  67. }
  68. private:
  69. PDEBUG_CLIENT m_Client;
  70. PDEBUG_CONTROL m_Control;
  71. };
  72. STDMETHODIMP
  73. ExcepCallbacks::GetInterestMask(
  74. THIS_
  75. OUT PULONG Mask
  76. )
  77. {
  78. *Mask = DEBUG_EVENT_EXCEPTION;
  79. return S_OK;
  80. }
  81. STDMETHODIMP
  82. ExcepCallbacks::Exception(
  83. THIS_
  84. IN PEXCEPTION_RECORD64 Exception,
  85. IN ULONG FirstChance
  86. )
  87. {
  88. m_Control->Output(DEBUG_OUTPUT_NORMAL, "Exception %X at %p, chance %d\n",
  89. Exception->ExceptionCode, Exception->ExceptionAddress,
  90. FirstChance ? 1 : 2);
  91. return DEBUG_STATUS_GO_HANDLED;
  92. }
  93. ExcepCallbacks g_ExcepCallbacks;
  94. //----------------------------------------------------------------------------
  95. //
  96. // FnProfCallbacks.
  97. //
  98. //----------------------------------------------------------------------------
  99. class FnProfCallbacks : public StaticEventCallbacks
  100. {
  101. public:
  102. FnProfCallbacks(void)
  103. {
  104. m_Client = NULL;
  105. m_Control = NULL;
  106. }
  107. // IDebugEventCallbacks.
  108. STDMETHOD(GetInterestMask)(THIS_
  109. OUT PULONG Mask);
  110. STDMETHOD(Breakpoint)(THIS_
  111. IN PDEBUG_BREAKPOINT Bp);
  112. HRESULT Initialize(PDEBUG_CLIENT Client,
  113. PDEBUG_CONTROL Control)
  114. {
  115. m_Hits = 0;
  116. m_Client = Client;
  117. m_Client->AddRef();
  118. m_Control = Control;
  119. m_Control->AddRef();
  120. return S_OK;
  121. }
  122. void Uninitialize(void)
  123. {
  124. EXT_RELEASE(m_Control);
  125. EXT_RELEASE(m_Client);
  126. }
  127. ULONG GetHits(void)
  128. {
  129. return m_Hits;
  130. }
  131. PDEBUG_CONTROL GetControl(void)
  132. {
  133. return m_Control;
  134. }
  135. private:
  136. PDEBUG_CLIENT m_Client;
  137. PDEBUG_CONTROL m_Control;
  138. ULONG m_Hits;
  139. };
  140. STDMETHODIMP
  141. FnProfCallbacks::GetInterestMask(THIS_
  142. OUT PULONG Mask)
  143. {
  144. *Mask = DEBUG_EVENT_BREAKPOINT;
  145. return S_OK;
  146. }
  147. STDMETHODIMP
  148. FnProfCallbacks::Breakpoint(THIS_
  149. IN PDEBUG_BREAKPOINT Bp)
  150. {
  151. PDEBUG_CLIENT Client;
  152. HRESULT Status = DEBUG_STATUS_NO_CHANGE;
  153. // If this is one of our profiling breakpoints
  154. // record the function hit and continue on.
  155. if (Bp->GetAdder(&Client) == S_OK) {
  156. if (Client == m_Client) {
  157. m_Hits++;
  158. Status = DEBUG_STATUS_GO;
  159. }
  160. Client->Release();
  161. }
  162. Bp->Release();
  163. return Status;
  164. }
  165. FnProfCallbacks g_FnProfCallbacks;
  166. //----------------------------------------------------------------------------
  167. //
  168. // Extension entry points.
  169. //
  170. //----------------------------------------------------------------------------
  171. extern "C" HRESULT CALLBACK
  172. DebugExtensionInitialize(PULONG Version, PULONG Flags)
  173. {
  174. *Version = DEBUG_EXTENSION_VERSION(1, 0);
  175. *Flags = 0;
  176. return S_OK;
  177. }
  178. extern "C" void CALLBACK
  179. DebugExtensionUninitialize(void)
  180. {
  181. g_ExcepCallbacks.Uninitialize();
  182. g_FnProfCallbacks.Uninitialize();
  183. }
  184. const char* szHelp =
  185. " usage: !vtsimea [-? | function | address]\n"
  186. "\n"
  187. " where: -? displays this help\n"
  188. " function name of the function to simulate EA at\n"
  189. " address address to simulate EA at\n"
  190. "\n"
  191. " Example:\n"
  192. " !vtsimea nv4_disp!DrvBitBlt\n";
  193. const char* szErrorPrefix =
  194. " Error: ";
  195. const char* szErrorSuffix =
  196. " Use -? for help\n";
  197. const char* szSuccess = "Success.\n";
  198. HRESULT EncodeInfiniteLoopX86(ULONG64 Address)
  199. {
  200. // jmp -2
  201. unsigned char JmpOnSelf[2] = {0xEB, 0xFE};
  202. return g_ExtData->WriteVirtual(Address,
  203. &JmpOnSelf,
  204. sizeof(JmpOnSelf),
  205. NULL);
  206. }
  207. HRESULT EncodeInfiniteLoopIA64(ULONG64 Address)
  208. {
  209. // nop.m 0
  210. // nop.m 0
  211. // br.cond.sptk.many +0;;
  212. unsigned char JmpOnSelf[16] = {0x19, 0x00, 0x00, 0x00,
  213. 0x01, 0x00, 0x00, 0x00,
  214. 0x00, 0x02, 0x00, 0x00,
  215. 0x08, 0x00, 0x00, 0x40};
  216. return g_ExtData->WriteVirtual(Address,
  217. &JmpOnSelf,
  218. sizeof(JmpOnSelf),
  219. NULL);
  220. }
  221. HRESULT SimulateEA(ULONG64 Address[2])
  222. {
  223. HRESULT Status;
  224. HRESULT BpAdded[2] = {-1, -1};
  225. PDEBUG_BREAKPOINT Bp[2];
  226. ULONG BpId[2];
  227. ULONG BpSize;
  228. unsigned uBpHit = 0xFF;
  229. unsigned i, count;
  230. ExtOut("Get CPU type ... ");
  231. ULONG CpuType;
  232. Status = g_ExtControl->GetEffectiveProcessorType(&CpuType);
  233. if (Status != S_OK) {
  234. ExtErr("Failure! Can't get CPU type\n");
  235. goto CleanExit;
  236. }
  237. switch (CpuType) {
  238. case IMAGE_FILE_MACHINE_I386: BpSize = 1; break;
  239. case IMAGE_FILE_MACHINE_IA64: BpSize = 16; break;
  240. default:
  241. ExtErr("Failure! Invalid CPU type %d\n", CpuType);
  242. goto CleanExit;
  243. }
  244. ExtOut(szSuccess);
  245. count = 0;
  246. for (i = 0; Address[i] && (i < 2); ++i) {
  247. ExtOut("Set HW breakpoint at %I64lx ... ", Address[i]);
  248. Status = BpAdded[i] = g_ExtControl->AddBreakpoint(DEBUG_BREAKPOINT_DATA,
  249. DEBUG_ANY_ID,
  250. &Bp[i]);
  251. if ((Status != S_OK) ||
  252. ((Status = Bp[i]->SetDataParameters(BpSize, DEBUG_BREAK_EXECUTE)) != S_OK) ||
  253. ((Status = Bp[i]->SetOffset(Address[i])) != S_OK) ||
  254. ((Status = Bp[i]->GetId(&BpId[i])) != S_OK) ||
  255. ((Status = Bp[i]->AddFlags(DEBUG_BREAKPOINT_ENABLED)) != S_OK))
  256. {
  257. ExtOut("Failure!\n");
  258. }
  259. else {
  260. ++count;
  261. }
  262. ExtOut(szSuccess);
  263. } // for
  264. if (!count) {
  265. ExtErr("Failure! Unable to set HW breakpoints\n");
  266. goto CleanExit;
  267. }
  268. ExtOut("Continuing execution (until BP hit) ... ");
  269. Status = g_ExtControl->SetExecutionStatus(DEBUG_STATUS_GO);
  270. if (Status != S_OK) {
  271. ExtOut("Failure\n");
  272. goto CleanExit;
  273. }
  274. Status = g_ExtControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE);
  275. if (Status != S_OK) {
  276. ExtErr("Failure! Call to WaitForEvent failed\n");
  277. goto CleanExit;
  278. }
  279. ULONG EvType, ProcessId, ThreadId;
  280. DEBUG_LAST_EVENT_INFO_BREAKPOINT BpInfo;
  281. Status = g_ExtControl->GetLastEventInformation(&EvType,
  282. &ProcessId,
  283. &ThreadId,
  284. &BpInfo,
  285. sizeof(BpInfo),
  286. 0,0,0,0);
  287. if ((Status != S_OK) ||
  288. (EvType != DEBUG_EVENT_BREAKPOINT))
  289. {
  290. ExtErr("Failure! Unknown event during EA simulation\n");
  291. goto CleanExit;
  292. }
  293. for (i = 0; Address[i] && (i < 2); ++i) {
  294. if (BpInfo.Id == BpId[i]) {
  295. uBpHit = i;
  296. break;
  297. }
  298. }
  299. if (uBpHit > 1) {
  300. ExtErr("Failure! Unknown breakpoint hit during EA simulation\n");
  301. goto CleanExit;
  302. }
  303. ExtOut("\n");
  304. for (i = 0; Address[i] && (i < 2); ++i) {
  305. ExtOut("Disable HW breakpoint %d ... ", BpId[i]);
  306. Status = Bp[i]->RemoveFlags(DEBUG_BREAKPOINT_ENABLED);
  307. if (Status != S_OK) {
  308. ExtOut("Failure\n");
  309. goto CleanExit;
  310. }
  311. ExtOut(szSuccess);
  312. }
  313. ExtOut("Encoding infinite loop at %I64lx ... ", Address[uBpHit]);
  314. switch (CpuType) {
  315. case IMAGE_FILE_MACHINE_I386:
  316. Status = EncodeInfiniteLoopX86(Address[uBpHit]);
  317. break;
  318. case IMAGE_FILE_MACHINE_IA64:
  319. Status = EncodeInfiniteLoopIA64(Address[uBpHit]);
  320. break;
  321. }
  322. if (Status != S_OK) {
  323. ExtOut("Failure\n");
  324. goto CleanExit;
  325. }
  326. ExtOut(szSuccess);
  327. ExtOut("Continue execution until EA fault ...\n");
  328. Status = g_ExtControl->SetExecutionStatus(DEBUG_STATUS_GO);
  329. if (Status != S_OK) {
  330. ExtOut("Failure\n");
  331. goto CleanExit;
  332. }
  333. CleanExit:
  334. for (i = 0; Address[i] && (i < 2); ++i) {
  335. if (BpAdded[i] == S_OK) g_ExtControl->RemoveBreakpoint(Bp[i]);
  336. }
  337. return Status;
  338. }
  339. HRESULT GetAddressPair(PCSTR Args,
  340. ULONG64 Address[2],
  341. size_t* pCount)
  342. {
  343. HRESULT Status;
  344. ULONG64 h;
  345. Address[0] = Address[1] = 0;
  346. *pCount = 0;
  347. //
  348. // Symbol can't start from number so we can optimize
  349. // our resolution process
  350. //
  351. if ((Args[0] < '0') || (Args[0] > '9')) { // Guess it is just symbol
  352. //
  353. // search at least 2 to cover ia64 p-label
  354. //
  355. Status = g_ExtSymbols->StartSymbolMatch(Args, &h);
  356. if (Status != S_OK) return Status;
  357. char szName[1024];
  358. ULONG64 Offset;
  359. for(;;) {
  360. Status = g_ExtSymbols->GetNextSymbolMatch(h,
  361. szName,
  362. sizeof(szName),
  363. NULL,
  364. &Offset);
  365. if (Status != S_OK) break;
  366. if (*pCount < 2) Address[*pCount] = Offset;
  367. ++*pCount;
  368. }
  369. g_ExtSymbols->EndSymbolMatch(h);
  370. } // if
  371. if (!*pCount) { // It is not simple symbol - guess it is expression
  372. DEBUG_VALUE AddrVal;
  373. Status = g_ExtControl->Evaluate(Args, DEBUG_VALUE_INT64, &AddrVal, NULL);
  374. if (Status == S_OK) {
  375. Address[0] = AddrVal.I64;
  376. *pCount = 1;
  377. }
  378. } // if
  379. if (!*pCount) return Status;
  380. return Address[0] ? S_OK : -1;
  381. }
  382. extern "C" HRESULT CALLBACK
  383. vtsimea(PDEBUG_CLIENT pClient, PCSTR Args)
  384. {
  385. HRESULT Status;
  386. Status = ExtQuery(pClient);
  387. if (Status != S_OK) {
  388. ExtErr("Failure! Client unavailable\n");
  389. return Status;
  390. }
  391. if (!g_ExtControl ||
  392. !g_ExtData ||
  393. !g_ExtSymbols)
  394. {
  395. ExtErr(szErrorPrefix);
  396. ExtErr("Failure! Required interfaces are unavailable\n");
  397. ExtRelease();
  398. return -1;
  399. }
  400. size_t ArgsLen = Args ? strlen(Args) : 0;
  401. if (!ArgsLen) {
  402. ExtErr(szErrorSuffix);
  403. }
  404. if (ArgsLen >= 64) {
  405. ExtErr(szErrorPrefix);
  406. ExtErr("Parameters size too big\n");
  407. ExtErr(szErrorSuffix);
  408. }
  409. else if (!strcmp(Args, "-?")) {
  410. ExtOut(szHelp);
  411. }
  412. else if (strchr(Args, '*') ||
  413. strchr(Args, '?') ||
  414. strchr(Args, ' '))
  415. {
  416. ExtErr(szErrorPrefix);
  417. ExtErr("Invalid parameter or wrong parameters number\n");
  418. ExtErr(szErrorSuffix);
  419. }
  420. else {
  421. size_t Count;
  422. ULONG64 Address[2];
  423. Status = GetAddressPair(Args, Address, &Count);
  424. if (Status != S_OK) {
  425. ExtErr(szErrorPrefix);
  426. ExtErr("Can't resolve %s\n", Args);
  427. ExtErr(szErrorSuffix);
  428. }
  429. else if (Count > 2) {
  430. ExtErr(szErrorPrefix);
  431. ExtErr("Too many resolutions for %s\n", Args);
  432. ExtErr(szErrorSuffix);
  433. }
  434. else {
  435. ExtOut("Simulating fault EA at %s (%I64lx)\n", Args, Address[0]);
  436. Status = SimulateEA(Address);
  437. }
  438. }
  439. ExtRelease();
  440. return Status;
  441. }
  442. extern "C" HRESULT CALLBACK
  443. simea(PDEBUG_CLIENT pClient, PCSTR Args)
  444. {
  445. return vtsimea(pClient, Args);
  446. }