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.

5246 lines
159 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Event waiting and processing.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. // Special exception code used by the system when generating dumps
  10. // from apps which seem to be hung.
  11. #define STATUS_APPLICATION_HANG 0xcfffffff
  12. // An event can be signalled on certain events for
  13. // synchronizing other programs with the debugger.
  14. HANDLE g_EventToSignal;
  15. // When both creating a debuggee process and attaching
  16. // the debuggee is left suspended until the attach
  17. // succeeds. At that point the created process's thread
  18. // is resumed.
  19. ULONG64 g_ThreadToResume;
  20. PUSER_DEBUG_SERVICES g_ThreadToResumeServices;
  21. ULONG g_ExecutionStatusRequest = DEBUG_STATUS_NO_CHANGE;
  22. // Currently in seconds.
  23. ULONG g_PendingBreakInTimeoutLimit = 30;
  24. char g_OutputCommandRedirectPrefix[MAX_PATH];
  25. ULONG g_OutputCommandRedirectPrefixLen;
  26. // Set when events occur. Can't always be retrieved from
  27. // g_Event{Process|Thread}->SystemId since the events may be creation events
  28. // where the info structures haven't been created yet.
  29. ULONG g_EventThreadSysId;
  30. ULONG g_EventProcessSysId;
  31. ULONG g_LastEventType;
  32. char g_LastEventDesc[MAX_IMAGE_PATH + 64];
  33. PVOID g_LastEventExtraData;
  34. ULONG g_LastEventExtraDataSize;
  35. LAST_EVENT_INFO g_LastEventInfo;
  36. // Set when lookups are done during event handling.
  37. TargetInfo* g_EventTarget;
  38. ProcessInfo* g_EventProcess;
  39. ThreadInfo* g_EventThread;
  40. MachineInfo* g_EventMachine;
  41. // This is zero for events without a PC.
  42. ULONG64 g_TargetEventPc;
  43. // PC for current suspended event.
  44. ADDR g_EventPc;
  45. // Stored PC from the last resumed event.
  46. ADDR g_PrevEventPc;
  47. // An interesting related PC for the current event, such
  48. // as the source of a branch when branch tracing.
  49. ADDR g_PrevRelatedPc;
  50. PDEBUG_EXCEPTION_FILTER_PARAMETERS g_EventExceptionFilter;
  51. ULONG g_ExceptionFirstChance;
  52. ULONG g_SystemErrorOutput = SLE_ERROR;
  53. ULONG g_SystemErrorBreak = SLE_ERROR;
  54. ULONG g_SuspendedExecutionStatus;
  55. CHAR g_SuspendedCmdState;
  56. PDBGKD_ANY_CONTROL_REPORT g_ControlReport;
  57. PCHAR g_StateChangeData;
  58. CHAR g_StateChangeBuffer[2 * PACKET_MAX_SIZE];
  59. DBGKD_ANY_WAIT_STATE_CHANGE g_StateChange;
  60. DBGKD_ANY_CONTROL_SET g_ControlSet;
  61. char g_CreateProcessBreakName[FILTER_MAX_ARGUMENT];
  62. char g_ExitProcessBreakName[FILTER_MAX_ARGUMENT];
  63. char g_LoadDllBreakName[FILTER_MAX_ARGUMENT];
  64. char g_UnloadDllBaseName[FILTER_MAX_ARGUMENT];
  65. ULONG64 g_UnloadDllBase;
  66. char g_OutEventFilterPattern[FILTER_MAX_ARGUMENT];
  67. DEBUG_EXCEPTION_FILTER_PARAMETERS
  68. g_OtherExceptionList[OTHER_EXCEPTION_LIST_MAX];
  69. EVENT_COMMAND g_OtherExceptionCommands[OTHER_EXCEPTION_LIST_MAX];
  70. ULONG g_NumOtherExceptions;
  71. char g_EventLog[1024];
  72. PSTR g_EventLogEnd = g_EventLog;
  73. EVENT_FILTER g_EventFilters[] =
  74. {
  75. //
  76. // Debug events.
  77. //
  78. "Create thread", "ct", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  79. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, 0,
  80. NULL, NULL, NULL, 0, 0, NULL, 0,
  81. "Exit thread", "et", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  82. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, 0,
  83. NULL, NULL, NULL, 0, 0, NULL, 0,
  84. "Create process", "cpr", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  85. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, 0,
  86. NULL, NULL, NULL, 0, 0, g_CreateProcessBreakName, 0,
  87. "Exit process", "epr", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  88. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, 0,
  89. NULL, NULL, NULL, 0, 0, g_ExitProcessBreakName, 0,
  90. "Load module", "ld", NULL, NULL, 0, DEBUG_FILTER_OUTPUT,
  91. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, 0,
  92. NULL, NULL, NULL, 0, 0, g_LoadDllBreakName, 0,
  93. "Unload module", "ud", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  94. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, 0,
  95. NULL, NULL, NULL, 0, 0, g_UnloadDllBaseName, 0,
  96. "System error", "ser", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  97. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, 0,
  98. NULL, NULL, NULL, 0, 0, NULL, 0,
  99. "Initial breakpoint", "ibp", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  100. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, 0,
  101. NULL, NULL, NULL, 0, 0, NULL, 0,
  102. "Initial module load", "iml", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  103. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, 0,
  104. NULL, NULL, NULL, 0, 0, NULL, 0,
  105. "Debuggee output", "out", NULL, NULL, 0, DEBUG_FILTER_OUTPUT,
  106. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, 0,
  107. NULL, NULL, NULL, 0, 0, g_OutEventFilterPattern, 0,
  108. // Default exception filter.
  109. "Unknown exception", NULL, NULL, NULL, 0, DEBUG_FILTER_SECOND_CHANCE_BREAK,
  110. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, 0,
  111. NULL, NULL, NULL, 0, 0, NULL, 0,
  112. //
  113. // Specific exceptions.
  114. //
  115. "Access violation", "av", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  116. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_ACCESS_VIOLATION,
  117. NULL, NULL, NULL, 0, 0, NULL, 0,
  118. "Application hang", "aph", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  119. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_APPLICATION_HANG,
  120. NULL, NULL, NULL, 0, 0, NULL, 0,
  121. "Break instruction exception", "bpe", "bpec", NULL, 0, DEBUG_FILTER_BREAK,
  122. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, STATUS_BREAKPOINT,
  123. NULL, NULL, NULL, 0, 0, NULL, 0,
  124. "C++ EH exception", "eh", NULL, NULL, 0, DEBUG_FILTER_SECOND_CHANCE_BREAK,
  125. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_CPP_EH_EXCEPTION,
  126. NULL, NULL, NULL, 0, 0, NULL, 0,
  127. "Control-Break exception", "cce", "cc", NULL, 0, DEBUG_FILTER_BREAK,
  128. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, DBG_CONTROL_BREAK,
  129. NULL, NULL, NULL, 0, 0, NULL, 0,
  130. "Control-C exception", "cce", "cc", NULL, 0, DEBUG_FILTER_BREAK,
  131. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, DBG_CONTROL_C,
  132. NULL, NULL, NULL, 0, 0, NULL, 0,
  133. "Data misaligned", "dm", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  134. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_DATATYPE_MISALIGNMENT,
  135. NULL, NULL, NULL, 0, 0, NULL, 0,
  136. "Debugger command exception", "dbce", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  137. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, DBG_COMMAND_EXCEPTION,
  138. NULL, NULL, NULL, 0, 0, NULL, 0,
  139. "Guard page violation", "gp", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  140. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_GUARD_PAGE_VIOLATION,
  141. NULL, NULL, NULL, 0, 0, NULL, 0,
  142. "Illegal instruction", "ii", NULL, NULL, 0, DEBUG_FILTER_SECOND_CHANCE_BREAK,
  143. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_ILLEGAL_INSTRUCTION,
  144. NULL, NULL, NULL, 0, 0, NULL, 0,
  145. "In-page I/O error", "ip", NULL, " %I64x", 2, DEBUG_FILTER_BREAK,
  146. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_IN_PAGE_ERROR,
  147. NULL, NULL, NULL, 0, 0, NULL, 0,
  148. "Integer divide-by-zero", "dz", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  149. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_INTEGER_DIVIDE_BY_ZERO,
  150. NULL, NULL, NULL, 0, 0, NULL, 0,
  151. "Integer overflow", "iov", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  152. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_INTEGER_OVERFLOW,
  153. NULL, NULL, NULL, 0, 0, NULL, 0,
  154. "Invalid handle", "ch", "hc", NULL, 0, DEBUG_FILTER_BREAK,
  155. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_INVALID_HANDLE,
  156. NULL, NULL, NULL, 0, 0, NULL, 0,
  157. "Invalid lock sequence", "lsq", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  158. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_INVALID_LOCK_SEQUENCE,
  159. NULL, NULL, NULL, 0, 0, NULL, 0,
  160. "Invalid system call", "isc", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  161. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_INVALID_SYSTEM_SERVICE,
  162. NULL, NULL, NULL, 0, 0, NULL, 0,
  163. "Port disconnected", "3c", NULL, NULL, 0, DEBUG_FILTER_SECOND_CHANCE_BREAK,
  164. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_PORT_DISCONNECTED,
  165. NULL, NULL, NULL, 0, 0, NULL, 0,
  166. "Single step exception", "sse", "ssec", NULL, 0, DEBUG_FILTER_BREAK,
  167. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, STATUS_SINGLE_STEP,
  168. NULL, NULL, NULL, 0, 0, NULL, 0,
  169. "Stack buffer overflow", "sbo", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  170. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_STACK_BUFFER_OVERRUN,
  171. NULL, NULL, NULL, 0, 0, NULL, 0,
  172. "Stack overflow", "sov", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  173. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_STACK_OVERFLOW,
  174. NULL, NULL, NULL, 0, 0, NULL, 0,
  175. "Visual C++ exception", "vcpp", NULL, NULL, 0, DEBUG_FILTER_IGNORE,
  176. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, STATUS_VCPP_EXCEPTION,
  177. NULL, NULL, NULL, 0, 0, NULL, 0,
  178. "Wake debugger", "wkd", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  179. DEBUG_FILTER_GO_NOT_HANDLED, 0, 0, 0, STATUS_WAKE_SYSTEM_DEBUGGER,
  180. NULL, NULL, NULL, 0, 0, NULL, 0,
  181. "WOW64 breakpoint", "wob", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  182. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, STATUS_WX86_BREAKPOINT,
  183. NULL, NULL, NULL, 0, 0, NULL, 0,
  184. "WOW64 single step exception", "wos", NULL, NULL, 0, DEBUG_FILTER_BREAK,
  185. DEBUG_FILTER_GO_HANDLED, 0, 0, 0, STATUS_WX86_SINGLE_STEP,
  186. NULL, NULL, NULL, 0, 0, NULL, 0,
  187. };
  188. void
  189. ClearEventLog(void)
  190. {
  191. g_EventLogEnd = g_EventLog;
  192. *g_EventLogEnd = 0;
  193. }
  194. void
  195. DotEventLog(PDOT_COMMAND Cmd, DebugClient* Client)
  196. {
  197. if (g_EventLogEnd > g_EventLog)
  198. {
  199. dprintf("%s", g_EventLog);
  200. }
  201. else
  202. {
  203. dprintf("Event log is empty\n");
  204. }
  205. dprintf("Last event: %s\n", g_LastEventDesc);
  206. }
  207. void
  208. LogEventDesc(PSTR Desc, ULONG ProcId, ULONG ThreadId)
  209. {
  210. // Extra space for newline and terminator.
  211. int Len = strlen(Desc) + 2;
  212. if (IS_USER_TARGET(g_EventTarget))
  213. {
  214. // Space for process and thread IDs.
  215. Len += 16;
  216. }
  217. if (Len > sizeof(g_EventLog))
  218. {
  219. Len = sizeof(g_EventLog);
  220. }
  221. int Avail = (int)(sizeof(g_EventLog) - (g_EventLogEnd - g_EventLog));
  222. if (g_EventLogEnd > g_EventLog && Len > Avail)
  223. {
  224. PSTR Save = g_EventLog;
  225. int Need = Len - Avail;
  226. while (Need > 0)
  227. {
  228. PSTR Scan = strchr(Save, '\n');
  229. if (Scan == NULL)
  230. {
  231. break;
  232. }
  233. Scan++;
  234. Need -= (int)(Scan - Save);
  235. Save = Scan;
  236. }
  237. if (Need > 0)
  238. {
  239. // Couldn't make enough space so throw
  240. // everything away.
  241. g_EventLogEnd = g_EventLog;
  242. *g_EventLogEnd = 0;
  243. }
  244. else
  245. {
  246. Need = strlen(Save);
  247. memmove(g_EventLog, Save, Need + 1);
  248. g_EventLogEnd = g_EventLog + Need;
  249. }
  250. }
  251. Avail = (int)(sizeof(g_EventLog) - (g_EventLogEnd - g_EventLog));
  252. if (IS_USER_TARGET(g_EventTarget))
  253. {
  254. sprintf(g_EventLogEnd, "%04x.%04x: ", ProcId, ThreadId);
  255. Avail -= strlen(g_EventLogEnd);
  256. g_EventLogEnd += strlen(g_EventLogEnd);
  257. }
  258. CopyString(g_EventLogEnd, Desc, Avail - 2);
  259. g_EventLogEnd += strlen(g_EventLogEnd);
  260. *g_EventLogEnd++ = '\n';
  261. *g_EventLogEnd = 0;
  262. }
  263. void
  264. DiscardLastEventInfo(void)
  265. {
  266. if (g_EventThread)
  267. {
  268. g_EventThread->ClearEventStrings();
  269. }
  270. if (g_LastEventDesc[0])
  271. {
  272. LogEventDesc(g_LastEventDesc, g_EventProcessSysId, g_EventThreadSysId);
  273. }
  274. g_LastEventType = 0;
  275. g_LastEventDesc[0] = 0;
  276. g_LastEventExtraData = NULL;
  277. g_LastEventExtraDataSize = 0;
  278. }
  279. void
  280. DiscardLastEvent(void)
  281. {
  282. // Do this before clearing the other information so
  283. // it's available for the log.
  284. DiscardLastEventInfo();
  285. g_EventProcessSysId = 0;
  286. g_EventThreadSysId = 0;
  287. g_TargetEventPc = 0;
  288. // Clear any cached memory read during the last event.
  289. InvalidateAllMemoryCaches();
  290. }
  291. BOOL
  292. AnyEventsPossible(void)
  293. {
  294. TargetInfo* Target;
  295. ForAllLayersToTarget()
  296. {
  297. ULONG DesiredTimeout;
  298. if (Target->
  299. WaitInitialize(DEBUG_WAIT_DEFAULT, INFINITE,
  300. WINIT_TEST, &DesiredTimeout) == S_OK &&
  301. Target->m_EventPossible)
  302. {
  303. break;
  304. }
  305. }
  306. return Target != NULL;
  307. }
  308. void
  309. NotifyDebuggeeActivation(void)
  310. {
  311. StackSaveLayers Save;
  312. //
  313. // Now that all initialization is done, send initial
  314. // notification that a debuggee exists. Make sure
  315. // that the basic target, system and machine globals
  316. // are set up so that queries can be made during
  317. // the callbacks.
  318. //
  319. SetLayersFromTarget(g_EventTarget);
  320. g_EventTarget->AddSpecificExtensions();
  321. NotifySessionStatus(DEBUG_SESSION_ACTIVE);
  322. NotifyChangeDebuggeeState(DEBUG_CDS_ALL, 0);
  323. NotifyExtensions(DEBUG_NOTIFY_SESSION_ACTIVE, 0);
  324. }
  325. ULONG
  326. EventStatusToContinue(ULONG EventStatus)
  327. {
  328. switch(EventStatus)
  329. {
  330. case DEBUG_STATUS_GO_NOT_HANDLED:
  331. return DBG_EXCEPTION_NOT_HANDLED;
  332. case DEBUG_STATUS_GO_HANDLED:
  333. return DBG_EXCEPTION_HANDLED;
  334. case DEBUG_STATUS_NO_CHANGE:
  335. case DEBUG_STATUS_IGNORE_EVENT:
  336. case DEBUG_STATUS_GO:
  337. case DEBUG_STATUS_STEP_OVER:
  338. case DEBUG_STATUS_STEP_INTO:
  339. case DEBUG_STATUS_STEP_BRANCH:
  340. return DBG_CONTINUE;
  341. default:
  342. DBG_ASSERT(FALSE);
  343. return DBG_CONTINUE;
  344. }
  345. }
  346. HRESULT
  347. PrepareForWait(ULONG Flags, PULONG ContinueStatus)
  348. {
  349. HRESULT Status;
  350. Status = PrepareForExecution(g_ExecutionStatusRequest);
  351. if (Status != S_OK)
  352. {
  353. // If S_FALSE, we're at a hard breakpoint so the only thing that
  354. // happens is that the PC is adjusted and the "wait"
  355. // can succeed immediately.
  356. // Otherwise we failed execution preparation. Either way
  357. // we need to try and prepare for calls.
  358. PrepareForCalls(0);
  359. return FAILED(Status) ? Status : S_OK;
  360. }
  361. *ContinueStatus = EventStatusToContinue(g_ExecutionStatusRequest);
  362. g_EngStatus |= ENG_STATUS_WAITING;
  363. return S_OK;
  364. }
  365. DWORD
  366. GetContinueStatus(ULONG FirstChance, ULONG Continue)
  367. {
  368. if (!FirstChance || Continue == DEBUG_FILTER_GO_HANDLED)
  369. {
  370. return DBG_EXCEPTION_HANDLED;
  371. }
  372. else
  373. {
  374. return DBG_EXCEPTION_NOT_HANDLED;
  375. }
  376. }
  377. void
  378. ProcessDeferredWork(PULONG ContinueStatus)
  379. {
  380. if (g_EngDefer & ENG_DEFER_SET_EVENT)
  381. {
  382. // This event signalling is used by the system
  383. // to synchronize with the debugger when starting
  384. // the debugger via AeDebug. The -e parameter
  385. // to ntsd sets this value.
  386. // It could potentially be used in other situations.
  387. if (g_EventToSignal != NULL)
  388. {
  389. SetEvent(g_EventToSignal);
  390. g_EventToSignal = NULL;
  391. }
  392. g_EngDefer &= ~ENG_DEFER_SET_EVENT;
  393. }
  394. if (g_EngDefer & ENG_DEFER_RESUME_THREAD)
  395. {
  396. DBG_ASSERT(g_ThreadToResumeServices);
  397. g_ThreadToResumeServices->
  398. ResumeThreads(1, &g_ThreadToResume, NULL);
  399. g_ThreadToResume = 0;
  400. g_ThreadToResumeServices = NULL;
  401. g_EngDefer &= ~ENG_DEFER_RESUME_THREAD;
  402. }
  403. if (g_EngDefer & ENG_DEFER_EXCEPTION_HANDLING)
  404. {
  405. if (*ContinueStatus == DBG_CONTINUE)
  406. {
  407. if (g_EventExceptionFilter != NULL)
  408. {
  409. // A user-visible exception occurred so check on how it
  410. // should be handled.
  411. *ContinueStatus =
  412. GetContinueStatus(g_ExceptionFirstChance,
  413. g_EventExceptionFilter->ContinueOption);
  414. }
  415. else
  416. {
  417. // An internal exception occurred, such as a single-step.
  418. // Force the continue status.
  419. *ContinueStatus = g_ExceptionFirstChance;
  420. }
  421. }
  422. g_EngDefer &= ~ENG_DEFER_EXCEPTION_HANDLING;
  423. }
  424. // If output was deferred but the wait was exited anyway
  425. // a stale defer flag will be left. Make sure it's cleared.
  426. g_EngDefer &= ~ENG_DEFER_OUTPUT_CURRENT_INFO;
  427. // Clear at-initial flags. If the incoming event
  428. // turns out to be one of them it'll turn on the flag.
  429. g_EngStatus &= ~(ENG_STATUS_AT_INITIAL_BREAK |
  430. ENG_STATUS_AT_INITIAL_MODULE_LOAD);
  431. }
  432. BOOL
  433. SuspendExecution(void)
  434. {
  435. if (g_EngStatus & ENG_STATUS_SUSPENDED)
  436. {
  437. // Nothing to do.
  438. return FALSE;
  439. }
  440. g_LastSelector = -1; // Prevent stale selector values
  441. SuspendAllThreads();
  442. // Don't notify on any state changes as
  443. // PrepareForCalls will do a blanket notify later.
  444. g_EngNotify++;
  445. // If we have an event thread select it.
  446. if (g_EventThread != NULL)
  447. {
  448. DBG_ASSERT(g_EventTarget->m_RegContextThread == NULL);
  449. g_EventTarget->ChangeRegContext(g_EventThread);
  450. }
  451. // First set the effective machine to the true
  452. // processor type so that real processor information
  453. // can be examined to determine any possible
  454. // alternate execution states.
  455. // No need to notify here as another SetEffMachine
  456. // is coming up.
  457. g_EventTarget->SetEffMachine(g_EventTarget->m_MachineType, FALSE);
  458. if (g_EngStatus & ENG_STATUS_STATE_CHANGED)
  459. {
  460. g_EventTarget->m_EffMachine->
  461. InitializeContext(g_TargetEventPc, g_ControlReport);
  462. g_EngStatus &= ~ENG_STATUS_STATE_CHANGED;
  463. }
  464. // If this is a live user target that's being examined
  465. // instead of truly debugged we do not want to set the
  466. // trace mode as we can't track events. If we did
  467. // set the trace mode here it could cause context writeback
  468. // which could generate an exception that nobody expects.
  469. if (g_EventProcess &&
  470. !IS_DUMP_TARGET(g_EventTarget) &&
  471. (!IS_LIVE_USER_TARGET(g_EventTarget) ||
  472. !(g_EventProcess->m_Flags & ENG_PROC_EXAMINED)))
  473. {
  474. g_EventTarget->m_EffMachine->QuietSetTraceMode(TRACE_NONE);
  475. }
  476. // Now determine the executing code type and
  477. // make that the effective machine.
  478. if (IS_CONTEXT_POSSIBLE(g_EventTarget))
  479. {
  480. g_EventMachine = MachineTypeInfo(g_EventTarget,
  481. g_EventTarget->m_EffMachine->
  482. ExecutingMachine());
  483. }
  484. else
  485. {
  486. // Local kernel debugging doesn't deal with contexts
  487. // as everything would be in the context of the debugger.
  488. // It's safe to just assume the executing machine
  489. // is the target machine, plus this avoids unwanted
  490. // context access.
  491. g_EventMachine = g_EventTarget->m_Machine;
  492. }
  493. g_EventTarget->SetEffMachine(g_EventMachine->m_ExecTypes[0], TRUE);
  494. g_Machine = g_EventMachine;
  495. // Trace flag should always be clear at this point.
  496. g_EngDefer &= ~ENG_DEFER_HARDWARE_TRACING;
  497. g_EngNotify--;
  498. g_EngStatus |= ENG_STATUS_SUSPENDED;
  499. g_SuspendedExecutionStatus = GetExecutionStatus();
  500. g_SuspendedCmdState = g_CmdState;
  501. g_ContextChanged = FALSE;
  502. return TRUE;
  503. }
  504. HRESULT
  505. ResumeExecution(void)
  506. {
  507. TargetInfo* Target;
  508. if ((g_EngStatus & ENG_STATUS_SUSPENDED) == 0)
  509. {
  510. // Nothing to do.
  511. return S_OK;
  512. }
  513. if (g_EventTarget &&
  514. g_EventTarget->m_EffMachine->GetTraceMode() != TRACE_NONE)
  515. {
  516. g_EngDefer |= ENG_DEFER_HARDWARE_TRACING;
  517. }
  518. if (!SPECIAL_EXECUTION(g_CmdState) &&
  519. IS_REMOTE_KERNEL_TARGET(g_EventTarget))
  520. {
  521. g_EventTarget->m_Machine->KdUpdateControlSet(&g_ControlSet);
  522. g_EngDefer |= ENG_DEFER_UPDATE_CONTROL_SET;
  523. }
  524. ForAllLayersToTarget()
  525. {
  526. Target->PrepareForExecution();
  527. }
  528. if (!ResumeAllThreads())
  529. {
  530. if (g_EventTarget)
  531. {
  532. g_EventTarget->ChangeRegContext(g_EventThread);
  533. }
  534. return E_FAIL;
  535. }
  536. g_EngStatus &= ~ENG_STATUS_SUSPENDED;
  537. return S_OK;
  538. }
  539. void
  540. PrepareForCalls(ULONG64 ExtraStatusFlags)
  541. {
  542. BOOL HardBrkpt = FALSE;
  543. ADDR PcAddr;
  544. BOOL Changed = FALSE;
  545. // If there's no event then execution didn't really
  546. // occur so there's no need to suspend. This will happen
  547. // when a debuggee exits or during errors on execution
  548. // preparation.
  549. if (g_EventThreadSysId != 0)
  550. {
  551. if (SuspendExecution())
  552. {
  553. Changed = TRUE;
  554. }
  555. }
  556. else
  557. {
  558. g_CmdState = 'c';
  559. // Force notification in this case to ensure
  560. // that clients know the engine is not running.
  561. Changed = TRUE;
  562. }
  563. if (RemoveBreakpoints() == S_OK)
  564. {
  565. Changed = TRUE;
  566. }
  567. if (!IS_EVENT_CONTEXT_ACCESSIBLE())
  568. {
  569. ADDRFLAT(&PcAddr, 0);
  570. ClearAddr(&g_EventPc);
  571. }
  572. else
  573. {
  574. g_EventMachine->GetPC(&PcAddr);
  575. g_EventPc = PcAddr;
  576. }
  577. if (g_CmdState != 'c')
  578. {
  579. g_CmdState = 'c';
  580. Changed = TRUE;
  581. g_DumpDefault = g_UnasmDefault = g_AssemDefault = PcAddr;
  582. if (IS_EVENT_CONTEXT_ACCESSIBLE() &&
  583. IS_KERNEL_TARGET(g_EventTarget))
  584. {
  585. HardBrkpt = g_EventMachine->
  586. IsBreakpointInstruction(g_EventProcess, &PcAddr);
  587. }
  588. }
  589. g_EngStatus |= ENG_STATUS_PREPARED_FOR_CALLS;
  590. if (Changed)
  591. {
  592. if (IS_EVENT_CONTEXT_ACCESSIBLE())
  593. {
  594. ResetCurrentScopeLazy();
  595. }
  596. // This can produce many notifications. Callers should
  597. // suppress notification when they can to avoid multiple
  598. // notifications during a single operation.
  599. NotifyChangeEngineState(DEBUG_CES_EXECUTION_STATUS,
  600. DEBUG_STATUS_BREAK | ExtraStatusFlags, TRUE);
  601. NotifyChangeEngineState(DEBUG_CES_CURRENT_THREAD,
  602. g_Thread ? g_Thread->m_UserId : DEBUG_ANY_ID,
  603. TRUE);
  604. NotifyChangeDebuggeeState(DEBUG_CDS_ALL, 0);
  605. NotifyExtensions(DEBUG_NOTIFY_SESSION_ACCESSIBLE, 0);
  606. }
  607. else if (ExtraStatusFlags == 0)
  608. {
  609. // We're exiting a wait so force the current execution
  610. // status to be sent to let everybody know that a
  611. // wait is finishing.
  612. NotifyChangeEngineState(DEBUG_CES_EXECUTION_STATUS,
  613. DEBUG_STATUS_BREAK, TRUE);
  614. }
  615. // IA64 reports a plabel in the structure, so we need to compare
  616. // against the real function address.
  617. if (HardBrkpt)
  618. {
  619. ULONG64 Address = Flat(PcAddr);
  620. ULONG64 StatusRoutine =
  621. g_EventTarget->m_KdDebuggerData.BreakpointWithStatus;
  622. if (g_EventMachine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_IA64)
  623. {
  624. g_EventTarget->ReadPointer(g_EventProcess, g_EventMachine,
  625. StatusRoutine, &StatusRoutine);
  626. StatusRoutine &= ~0xf;
  627. Address &= ~0xf;
  628. }
  629. if (Address && Address == StatusRoutine)
  630. {
  631. HandleBPWithStatus();
  632. }
  633. }
  634. else
  635. {
  636. // Some kernel dumps don't show up as hard breakpoints
  637. // Call !analyze if we have kernel dump target
  638. if (IS_EVENT_CONTEXT_ACCESSIBLE() &&
  639. g_EventTarget->m_Class == DEBUG_CLASS_KERNEL &&
  640. (g_EventTarget->m_ClassQualifier == DEBUG_DUMP_SMALL ||
  641. g_EventTarget->m_ClassQualifier == DEBUG_DUMP_DEFAULT ||
  642. g_EventTarget->m_ClassQualifier == DEBUG_DUMP_FULL))
  643. {
  644. CallBugCheckExtension(NULL);
  645. }
  646. }
  647. }
  648. HRESULT
  649. PrepareForExecution(ULONG NewStatus)
  650. {
  651. ADDR PcAddr;
  652. BOOL AtHardBrkpt = FALSE;
  653. ThreadInfo* StepThread = NULL;
  654. ClearAddr(&g_PrevRelatedPc);
  655. StepAgain:
  656. // Remember the event PC for later.
  657. g_PrevEventPc = g_EventPc;
  658. // Display current information on intermediate steps where
  659. // the debugger UI isn't even invoked.
  660. if ((g_EngDefer & ENG_DEFER_OUTPUT_CURRENT_INFO) &&
  661. (g_EngStatus & ENG_STATUS_STOP_SESSION) == 0)
  662. {
  663. OutCurInfo(OCI_SYMBOL | OCI_DISASM | OCI_ALLOW_EA |
  664. OCI_ALLOW_REG | OCI_ALLOW_SOURCE | OCI_IGNORE_STATE,
  665. g_Machine->m_AllMask, DEBUG_OUTPUT_PROMPT_REGISTERS);
  666. g_EngDefer &= ~ENG_DEFER_OUTPUT_CURRENT_INFO;
  667. }
  668. // Don't notify on any state changes as
  669. // PrepareForCalls will do a blanket notify later.
  670. g_EngNotify++;
  671. if (g_EventTarget && (g_EngStatus & ENG_STATUS_SUSPENDED))
  672. {
  673. if (!SPECIAL_EXECUTION(g_CmdState))
  674. {
  675. if (NewStatus != DEBUG_STATUS_IGNORE_EVENT)
  676. {
  677. SetExecutionStatus(NewStatus);
  678. DBG_ASSERT((g_EngStatus & ENG_STATUS_STOP_SESSION) ||
  679. IS_RUNNING(g_CmdState));
  680. }
  681. else
  682. {
  683. NewStatus = g_SuspendedExecutionStatus;
  684. g_CmdState = g_SuspendedCmdState;
  685. }
  686. }
  687. if (!(g_EngStatus & ENG_STATUS_STOP_SESSION) &&
  688. !SPECIAL_EXECUTION(g_CmdState) &&
  689. (g_StepTraceBp->m_Flags & DEBUG_BREAKPOINT_ENABLED) &&
  690. g_StepTraceBp->m_MatchThread)
  691. {
  692. StepThread = g_StepTraceBp->m_MatchThread;
  693. // Check and see if we need to fake a step/trace
  694. // event when artificially moving beyond a hard-coded
  695. // break instruction.
  696. if (!StepThread->m_Process->m_Exited)
  697. {
  698. StackSaveLayers SaveLayers;
  699. MachineInfo* Machine =
  700. MachineTypeInfo(StepThread->m_Process->m_Target,
  701. g_Machine->m_ExecTypes[0]);
  702. SetLayersFromThread(StepThread);
  703. StepThread->m_Process->m_Target->ChangeRegContext(StepThread);
  704. Machine->GetPC(&PcAddr);
  705. AtHardBrkpt = Machine->
  706. IsBreakpointInstruction(g_Process, &PcAddr);
  707. if (AtHardBrkpt)
  708. {
  709. g_WatchBeginCurFunc = 1;
  710. Machine->AdjustPCPastBreakpointInstruction
  711. (&PcAddr, DEBUG_BREAKPOINT_CODE);
  712. if (Flat(*g_StepTraceBp->GetAddr()) != OFFSET_TRACE)
  713. {
  714. ULONG NextMachine;
  715. Machine->GetNextOffset(g_Process,
  716. g_StepTraceCmdState == 'p',
  717. g_StepTraceBp->GetAddr(),
  718. &NextMachine);
  719. g_StepTraceBp->SetProcType(NextMachine);
  720. }
  721. GetCurrentMemoryOffsets(&g_StepTraceInRangeStart,
  722. &g_StepTraceInRangeEnd);
  723. if (StepTracePass(&PcAddr))
  724. {
  725. // If the step was passed over go back
  726. // and update things based on the adjusted PC.
  727. g_EngNotify--;
  728. g_EventPc = PcAddr;
  729. goto StepAgain;
  730. }
  731. }
  732. }
  733. }
  734. // If the last event was a hard-coded breakpoint exception
  735. // we need to move the event thread beyond the break instruction.
  736. // Note that if we continued stepping on that thread it was
  737. // handled above, so we only do this if it's a different
  738. // thread or we're not stepping.
  739. // If the continuation status is not-handled then
  740. // we need to let the int3 get hit again. If we're
  741. // exiting, though, we don't want to do this.
  742. if (g_EventThread != NULL &&
  743. !g_EventThread->m_Process->m_Exited &&
  744. g_EventTarget->m_DynamicEvents &&
  745. !SPECIAL_EXECUTION(g_CmdState) &&
  746. g_EventThread != StepThread &&
  747. (NewStatus != DEBUG_STATUS_GO_NOT_HANDLED ||
  748. (g_EngStatus & ENG_STATUS_STOP_SESSION)))
  749. {
  750. StackSaveLayers SaveLayers;
  751. SetLayersFromThread(g_EventThread);
  752. g_EventTarget->ChangeRegContext(g_EventThread);
  753. g_EventMachine->GetPC(&PcAddr);
  754. if (g_EventMachine->
  755. IsBreakpointInstruction(g_EventProcess, &PcAddr))
  756. {
  757. g_EventMachine->AdjustPCPastBreakpointInstruction
  758. (&PcAddr, DEBUG_BREAKPOINT_CODE);
  759. }
  760. if (StepThread != NULL)
  761. {
  762. StepThread->m_Process->m_Target->
  763. ChangeRegContext(StepThread);
  764. }
  765. }
  766. }
  767. HRESULT Status;
  768. if ((g_EngStatus & ENG_STATUS_STOP_SESSION) ||
  769. SPECIAL_EXECUTION(g_CmdState))
  770. {
  771. // If we're stopping don't insert breakpoints in
  772. // case we're detaching from the process. In
  773. // that case we want threads to run normally.
  774. Status = S_OK;
  775. }
  776. else
  777. {
  778. Status = InsertBreakpoints();
  779. }
  780. // Resume notification now that modifications are done.
  781. g_EngNotify--;
  782. if (Status != S_OK)
  783. {
  784. return Status;
  785. }
  786. if ((Status = ResumeExecution()) != S_OK)
  787. {
  788. return Status;
  789. }
  790. g_EngStatus &= ~ENG_STATUS_PREPARED_FOR_CALLS;
  791. if (!SPECIAL_EXECUTION(g_CmdState))
  792. {
  793. // Now that we've resumed execution notify about the change.
  794. NotifyChangeEngineState(DEBUG_CES_EXECUTION_STATUS,
  795. NewStatus, TRUE);
  796. NotifyExtensions(DEBUG_NOTIFY_SESSION_INACCESSIBLE, 0);
  797. }
  798. if (AtHardBrkpt && StepThread != NULL)
  799. {
  800. // We're stepping over a hard breakpoint. This is
  801. // done entirely by the debugger so no debug event
  802. // is associated with it. Instead we simply update
  803. // the PC and return from the Wait without actually waiting.
  804. // Step/trace events have empty event info.
  805. DiscardLastEventInfo();
  806. g_EventThreadSysId = StepThread->m_SystemId;
  807. g_EventProcessSysId = StepThread->m_Process->m_SystemId;
  808. FindEventProcessThread();
  809. // Clear left-overs from the true event so they're
  810. // not used during initialization.
  811. g_TargetEventPc = 0;
  812. g_ControlReport = NULL;
  813. SuspendExecution();
  814. if (IS_EVENT_CONTEXT_ACCESSIBLE())
  815. {
  816. g_EventMachine->GetPC(&g_EventPc);
  817. }
  818. else
  819. {
  820. ClearAddr(&g_EventPc);
  821. }
  822. return S_FALSE;
  823. }
  824. // Once we resume execution the processes and threads
  825. // can change so we must flush our notion of what's current.
  826. g_Process = NULL;
  827. g_Thread = NULL;
  828. g_EventProcess = NULL;
  829. g_EventThread = NULL;
  830. g_EventMachine = NULL;
  831. if (g_EngDefer & ENG_DEFER_DELETE_EXITED)
  832. {
  833. // Reap any threads and processes that have terminated since
  834. // we last executed.
  835. DeleteAllExitedInfos();
  836. g_EngDefer &= ~ENG_DEFER_DELETE_EXITED;
  837. }
  838. return S_OK;
  839. }
  840. HRESULT
  841. PrepareForSeparation(void)
  842. {
  843. HRESULT Status;
  844. ULONG OldStop = g_EngStatus & ENG_STATUS_STOP_SESSION;
  845. //
  846. // The debugger is going to separate from the
  847. // debuggee, such as during a detach operation.
  848. // Get the debuggee running again so that it
  849. // will go on without the debugger.
  850. //
  851. g_EngStatus |= ENG_STATUS_STOP_SESSION;
  852. Status = PrepareForExecution(DEBUG_STATUS_GO_HANDLED);
  853. g_EngStatus = (g_EngStatus & ~ENG_STATUS_STOP_SESSION) | OldStop;
  854. return Status;
  855. }
  856. void
  857. FindEventProcessThread(void)
  858. {
  859. //
  860. // If these lookups fail other processes and
  861. // threads cannot be substituted for the correct
  862. // ones as that may cause modifications to the
  863. // wrong data structures. For example, if a
  864. // thread exit comes in it cannot be processed
  865. // with any other process or thread as that would
  866. // delete the wrong thread.
  867. //
  868. g_EventProcess = g_EventTarget->FindProcessBySystemId(g_EventProcessSysId);
  869. if (g_EventProcess == NULL)
  870. {
  871. ErrOut("ERROR: Unable to find system process %X\n",
  872. g_EventProcessSysId);
  873. ErrOut("ERROR: The process being debugged has either exited "
  874. "or cannot be accessed\n");
  875. ErrOut("ERROR: Many commands will not work properly\n");
  876. }
  877. else
  878. {
  879. g_EventThread = g_EventProcess->
  880. FindThreadBySystemId(g_EventThreadSysId);
  881. if (g_EventThread == NULL)
  882. {
  883. ErrOut("ERROR: Unable to find system thread %X\n",
  884. g_EventThreadSysId);
  885. ErrOut("ERROR: The thread being debugged has either exited "
  886. "or cannot be accessed\n");
  887. ErrOut("ERROR: Many commands will not work properly\n");
  888. }
  889. }
  890. DBG_ASSERT((g_EventThread == NULL ||
  891. g_EventThread->m_Process == g_EventProcess) &&
  892. (g_EventProcess == NULL ||
  893. g_EventProcess->m_Target == g_EventTarget));
  894. g_Thread = g_EventThread;
  895. g_Process = g_EventProcess;
  896. if (g_Process)
  897. {
  898. g_Process->m_CurrentThread = g_Thread;
  899. }
  900. g_Target = g_EventTarget;
  901. if (g_Target)
  902. {
  903. g_Target->m_CurrentProcess = g_Process;
  904. }
  905. }
  906. static int VoteWeight[] =
  907. {
  908. 0, // DEBUG_STATUS_NO_CHANGE
  909. 2, // DEBUG_STATUS_GO
  910. 3, // DEBUG_STATUS_GO_HANDLED
  911. 4, // DEBUG_STATUS_GO_NOT_HANDLED
  912. 6, // DEBUG_STATUS_STEP_OVER
  913. 7, // DEBUG_STATUS_STEP_INTO
  914. 8, // DEBUG_STATUS_BREAK
  915. 9, // DEBUG_STATUS_NO_DEBUGGEE
  916. 5, // DEBUG_STATUS_STEP_BRANCH
  917. 1, // DEBUG_STATUS_IGNORE_EVENT
  918. };
  919. ULONG
  920. MergeVotes(ULONG Cur, ULONG Vote)
  921. {
  922. // If the vote is actually an error code display a message.
  923. if (FAILED(Vote))
  924. {
  925. ErrOut("Callback failed with %X\n", Vote);
  926. return Cur;
  927. }
  928. // Ignore invalid votes.
  929. if (
  930. (
  931. #if DEBUG_STATUS_NO_CHANGE > 0
  932. Vote < DEBUG_STATUS_NO_CHANGE ||
  933. #endif
  934. Vote > DEBUG_STATUS_BREAK) &&
  935. (Vote < DEBUG_STATUS_STEP_BRANCH ||
  936. Vote > DEBUG_STATUS_IGNORE_EVENT))
  937. {
  938. ErrOut("Callback returned invalid vote %X\n", Vote);
  939. return Cur;
  940. }
  941. // Votes are biased towards executing as little
  942. // as possible.
  943. // Break overrides all other votes.
  944. // Step into overrides step over.
  945. // Step over overrides step branch.
  946. // Step branch overrides go.
  947. // Go not-handled overrides go handled.
  948. // Go handled overrides plain go.
  949. // Plain go overrides ignore event.
  950. // Anything overrides no change.
  951. if (VoteWeight[Vote] > VoteWeight[Cur])
  952. {
  953. Cur = Vote;
  954. }
  955. return Cur;
  956. }
  957. ULONG
  958. ProcessBreakpointOrStepException(PEXCEPTION_RECORD64 Record,
  959. ULONG FirstChance)
  960. {
  961. ADDR BpAddr;
  962. ULONG BreakType;
  963. ULONG EventStatus;
  964. SuspendExecution();
  965. // Default breakpoint address to the current PC as that's
  966. // where the majority are at.
  967. g_EventMachine->GetPC(&BpAddr);
  968. // Check whether the exception is a breakpoint.
  969. BreakType = g_EventMachine->
  970. IsBreakpointOrStepException(Record, FirstChance,
  971. &BpAddr, &g_PrevRelatedPc);
  972. if (BreakType & EXBS_BREAKPOINT_ANY)
  973. {
  974. // It's a breakpoint of some kind.
  975. EventOut("*** breakpoint exception\n");
  976. EventStatus = CheckBreakpointOrStepTrace(&BpAddr, BreakType);
  977. }
  978. else
  979. {
  980. // It's a true single step or taken branch exception.
  981. // We still need to check breakpoints as we may have stepped
  982. // to an instruction which has a breakpoint.
  983. EventOut("*** single step or taken branch exception\n");
  984. EventStatus = CheckBreakpointOrStepTrace(&BpAddr, EXBS_BREAKPOINT_ANY);
  985. }
  986. if (EventStatus == DEBUG_STATUS_NO_CHANGE)
  987. {
  988. // The break/step exception wasn't recognized
  989. // as a debugger-specific event so handle it as
  990. // a regular exception. The default states for
  991. // break/step exceptions are to break in so
  992. // this will do the right thing, plus it allows
  993. // people to ignore or notify for them if they want.
  994. EventStatus = NotifyExceptionEvent(Record, FirstChance, FALSE);
  995. }
  996. else
  997. {
  998. // Force the exception to be handled.
  999. g_EngDefer |= ENG_DEFER_EXCEPTION_HANDLING;
  1000. g_EventExceptionFilter = NULL;
  1001. g_ExceptionFirstChance = DBG_EXCEPTION_HANDLED;
  1002. }
  1003. return EventStatus;
  1004. }
  1005. ULONG
  1006. CheckBreakpointOrStepTrace(PADDR BpAddr, ULONG BreakType)
  1007. {
  1008. ULONG EventStatus;
  1009. Breakpoint* Bp;
  1010. ULONG BreakHitType;
  1011. BOOL BpHit;
  1012. BpHit = FALSE;
  1013. Bp = NULL;
  1014. EventStatus = DEBUG_STATUS_NO_CHANGE;
  1015. // Multiple breakpoints can be hit at the same address.
  1016. // Process all possible hits. Do not do notifications
  1017. // while walking the list as the callbacks may modify
  1018. // the list. Instead just mark the breakpoint as
  1019. // needing notification in the next pass.
  1020. for (;;)
  1021. {
  1022. Bp = CheckBreakpointHit(g_EventProcess, Bp, BpAddr, BreakType, -1,
  1023. g_CmdState != 'g' ?
  1024. DEBUG_BREAKPOINT_GO_ONLY : 0,
  1025. &BreakHitType, TRUE);
  1026. if (Bp == NULL)
  1027. {
  1028. break;
  1029. }
  1030. if (BreakHitType == BREAKPOINT_HIT)
  1031. {
  1032. Bp->m_Flags |= BREAKPOINT_NOTIFY;
  1033. }
  1034. else
  1035. {
  1036. // This breakpoint was hit but the hit was ignored.
  1037. // Vote to continue execution.
  1038. EventStatus = MergeVotes(EventStatus, DEBUG_STATUS_IGNORE_EVENT);
  1039. }
  1040. BpHit = TRUE;
  1041. Bp = Bp->m_Next;
  1042. if (Bp == NULL)
  1043. {
  1044. break;
  1045. }
  1046. }
  1047. if (!BpHit)
  1048. {
  1049. // If no breakpoints were recognized check for an internal
  1050. // breakpoint.
  1051. EventStatus = CheckStepTrace(BpAddr, EventStatus);
  1052. //
  1053. // If the breakpoint wasn't for a step/trace
  1054. // it's a hard breakpoint and should be
  1055. // handled as a normal exception.
  1056. //
  1057. if (!g_EventProcess->m_InitialBreakDone)
  1058. {
  1059. g_EngStatus |= ENG_STATUS_AT_INITIAL_BREAK;
  1060. }
  1061. // We've seen the initial break for this process.
  1062. g_EventProcess->m_InitialBreakDone = TRUE;
  1063. // If we were waiting for a break-in exception we've got it.
  1064. g_EngStatus &= ~ENG_STATUS_PENDING_BREAK_IN;
  1065. if (EventStatus == DEBUG_STATUS_NO_CHANGE)
  1066. {
  1067. if (!g_EventProcess->m_InitialBreak)
  1068. {
  1069. // Refresh breakpoints even though we're not
  1070. // stopping. This gives saved breakpoints
  1071. // a chance to become active.
  1072. RemoveBreakpoints();
  1073. EventStatus = DEBUG_STATUS_GO;
  1074. g_EventProcess->m_InitialBreak = TRUE;
  1075. }
  1076. else if (IS_USER_TARGET(g_EventTarget) &&
  1077. (!g_EventProcess->m_InitialBreakWx86) &&
  1078. (g_EventTarget->m_MachineType !=
  1079. g_EventTarget->m_EffMachineType) &&
  1080. (g_EventTarget->
  1081. m_EffMachineType == IMAGE_FILE_MACHINE_I386))
  1082. {
  1083. // Allow skipping of both the target machine
  1084. // initial break and emulated machine initial breaks.
  1085. RemoveBreakpoints();
  1086. EventStatus = DEBUG_STATUS_GO;
  1087. g_EventProcess->m_InitialBreakWx86 = TRUE;
  1088. }
  1089. }
  1090. }
  1091. else
  1092. {
  1093. // A breakpoint was recognized. We need to
  1094. // refresh the breakpoint status since we'll
  1095. // probably need to defer the reinsertion of
  1096. // the breakpoint we're sitting on.
  1097. RemoveBreakpoints();
  1098. // Now do event callbacks for any breakpoints that need it.
  1099. EventStatus = NotifyHitBreakpoints(EventStatus);
  1100. }
  1101. if (g_ThreadToResume != 0)
  1102. {
  1103. g_EngDefer |= ENG_DEFER_RESUME_THREAD;
  1104. }
  1105. return EventStatus;
  1106. }
  1107. ULONG
  1108. CheckStepTrace(PADDR PcAddr, ULONG DefaultStatus)
  1109. {
  1110. BOOL WatchStepOver = FALSE;
  1111. ULONG uOciFlags;
  1112. ULONG NextMachine;
  1113. if ((g_StepTraceBp->m_Flags & DEBUG_BREAKPOINT_ENABLED) &&
  1114. Flat(*g_StepTraceBp->GetAddr()) != OFFSET_TRACE)
  1115. {
  1116. NotFlat(*g_StepTraceBp->GetAddr());
  1117. ComputeFlatAddress(g_StepTraceBp->GetAddr(), NULL);
  1118. }
  1119. // We do not check ENG_THREAD_TRACE_SET here because
  1120. // this event detection is only for proper user-initiated
  1121. // step/trace events. Such an event must occur immediately
  1122. // after the t/p/b, otherwise we cannot be sure that
  1123. // it's actually a debugger event and not an app-generated
  1124. // single-step exception.
  1125. // In user mode we restrict the step/trace state
  1126. // to a single thread to try and be as precise
  1127. // as possible. This isn't done in kernel mode
  1128. // since kernel mode "threads" are currently
  1129. // just placeholders for processors. It is
  1130. // possible for a context switch to occur at any
  1131. // time while stepping, meaning a true system
  1132. // thread could move from one processor to another.
  1133. // The processor state, including the single-step
  1134. // flag, will be moved with the thread so single
  1135. // step exceptions will come from the new processor
  1136. // rather than this one, meaning we would ignore
  1137. // it if we used "thread" restrictions. Instead,
  1138. // just assume any single-step exception while in
  1139. // p/t mode is a debugger step.
  1140. if ((g_StepTraceBp->m_Flags & DEBUG_BREAKPOINT_ENABLED) &&
  1141. g_StepTraceBp->m_Process == g_EventProcess &&
  1142. ((IS_KERNEL_TARGET(g_EventTarget) && IS_STEP_TRACE(g_CmdState)) ||
  1143. g_StepTraceBp->m_MatchThread == g_EventThread) &&
  1144. (Flat(*g_StepTraceBp->GetAddr()) == OFFSET_TRACE ||
  1145. AddrEqu(*g_StepTraceBp->GetAddr(), *PcAddr)))
  1146. {
  1147. ADDR CurrentSP;
  1148. // step/trace event occurred
  1149. // Update breakpoint status since we may need to step
  1150. // again and step/trace is updated when breakpoints
  1151. // are inserted.
  1152. RemoveBreakpoints();
  1153. uOciFlags = OCI_DISASM | OCI_ALLOW_REG | OCI_ALLOW_SOURCE |
  1154. OCI_ALLOW_EA;
  1155. if (g_EngStatus & (ENG_STATUS_PENDING_BREAK_IN |
  1156. ENG_STATUS_USER_INTERRUPT))
  1157. {
  1158. g_WatchFunctions.End(PcAddr);
  1159. return DEBUG_STATUS_BREAK;
  1160. }
  1161. if (IS_KERNEL_TARGET(g_EventTarget) && g_WatchInitialSP)
  1162. {
  1163. g_EventMachine->GetSP(&CurrentSP);
  1164. if ((Flat(CurrentSP) + 0x1500 < g_WatchInitialSP) ||
  1165. (g_WatchInitialSP + 0x1500 < Flat(CurrentSP)))
  1166. {
  1167. return DEBUG_STATUS_IGNORE_EVENT;
  1168. }
  1169. }
  1170. if (g_StepTraceInRangeStart != -1 &&
  1171. Flat(*PcAddr) >= g_StepTraceInRangeStart &&
  1172. Flat(*PcAddr) < g_StepTraceInRangeEnd)
  1173. {
  1174. // test if step/trace range active
  1175. // if so, compute the next offset and pass through
  1176. g_EventMachine->GetNextOffset(g_EventProcess,
  1177. g_StepTraceCmdState == 'p',
  1178. g_StepTraceBp->GetAddr(),
  1179. &NextMachine);
  1180. g_StepTraceBp->SetProcType(NextMachine);
  1181. if (g_WatchWhole)
  1182. {
  1183. g_WatchBeginCurFunc = Flat(*g_StepTraceBp->GetAddr());
  1184. g_WatchEndCurFunc = 0;
  1185. }
  1186. return DEBUG_STATUS_IGNORE_EVENT;
  1187. }
  1188. // active step/trace event - note event if count is zero
  1189. if (!StepTracePass(PcAddr) ||
  1190. (g_WatchFunctions.IsStarted() && AddrEqu(g_WatchTarget, *PcAddr) &&
  1191. (!IS_KERNEL_TARGET(g_EventTarget) ||
  1192. Flat(CurrentSP) >= g_WatchInitialSP)))
  1193. {
  1194. g_WatchFunctions.End(PcAddr);
  1195. return DEBUG_STATUS_BREAK;
  1196. }
  1197. if (g_WatchFunctions.IsStarted())
  1198. {
  1199. if (g_WatchTrace)
  1200. {
  1201. g_EventTarget->
  1202. ProcessWatchTraceEvent((PDBGKD_TRACE_DATA)
  1203. g_StateChangeData,
  1204. PcAddr,
  1205. &WatchStepOver);
  1206. }
  1207. goto skipit;
  1208. }
  1209. if (g_SrcOptions & SRCOPT_STEP_SOURCE)
  1210. {
  1211. goto skipit;
  1212. }
  1213. // more remaining events to occur, but output
  1214. // the instruction (optionally with registers)
  1215. // compute the step/trace address for next event
  1216. OutCurInfo(uOciFlags, g_EventMachine->m_AllMask,
  1217. DEBUG_OUTPUT_PROMPT_REGISTERS);
  1218. skipit:
  1219. g_EventMachine->
  1220. GetNextOffset(g_EventProcess,
  1221. g_StepTraceCmdState == 'p' || WatchStepOver,
  1222. g_StepTraceBp->GetAddr(),
  1223. &NextMachine);
  1224. g_StepTraceBp->SetProcType(NextMachine);
  1225. GetCurrentMemoryOffsets(&g_StepTraceInRangeStart,
  1226. &g_StepTraceInRangeEnd);
  1227. return DEBUG_STATUS_IGNORE_EVENT;
  1228. }
  1229. // Carry out deferred breakpoint work if necessary.
  1230. // We need to check the thread deferred-bp flag here as
  1231. // other events may occur before the thread with deferred
  1232. // work gets to execute again, in which case the setting
  1233. // of g_DeferDefined may have changed.
  1234. if ((g_EventThread != NULL &&
  1235. (g_EventThread->m_Flags & ENG_THREAD_DEFER_BP_TRACE)) ||
  1236. (g_DeferDefined &&
  1237. g_DeferBp->m_Process == g_EventProcess &&
  1238. (Flat(*g_DeferBp->GetAddr()) == OFFSET_TRACE ||
  1239. AddrEqu(*g_DeferBp->GetAddr(), *PcAddr))))
  1240. {
  1241. if ((g_EngOptions & DEBUG_ENGOPT_SYNCHRONIZE_BREAKPOINTS) &&
  1242. IS_USER_TARGET(g_EventTarget) &&
  1243. IsSelectedExecutionThread(g_EventThread,
  1244. SELTHREAD_INTERNAL_THREAD))
  1245. {
  1246. // The engine internally restricted execution to
  1247. // this particular thread in order to manage
  1248. // breakpoints in multithreaded conditions.
  1249. // The deferred work will be finished before
  1250. // we resume so we can drop the lock.
  1251. SelectExecutionThread(NULL, SELTHREAD_ANY);
  1252. }
  1253. // Deferred breakpoints are refreshed on breakpoint
  1254. // insertion so make sure that insertion happens
  1255. // when things restart.
  1256. RemoveBreakpoints();
  1257. return DEBUG_STATUS_IGNORE_EVENT;
  1258. }
  1259. // If the event was unrecognized return the default status.
  1260. return DefaultStatus;
  1261. }
  1262. void
  1263. AnalyzeDeadlock(PEXCEPTION_RECORD64 Record, ULONG FirstChance)
  1264. {
  1265. CHAR Symbol[MAX_SYMBOL_LEN];
  1266. DWORD64 Displacement;
  1267. ThreadInfo* ThreadOwner = NULL;
  1268. DWORD Tid = 0;
  1269. RTL_CRITICAL_SECTION CritSec;
  1270. // poking around inside NT's user-mode RTL_CRITICAL_SECTION and
  1271. // RTL_RESOURCE structures.
  1272. //
  1273. // Get the symbolic name of the routine which
  1274. // raised the exception to see if it matches
  1275. // one of the expected ones in ntdll.
  1276. //
  1277. GetSymbol((ULONG64)Record->ExceptionAddress,
  1278. Symbol, DIMA(Symbol), &Displacement);
  1279. if (!_stricmp("ntdll!RtlpWaitForCriticalSection", Symbol))
  1280. {
  1281. //
  1282. // If the first parameter is a pointer to the critsect as it
  1283. // should be, switch to the owning thread before bringing
  1284. // up the prompt. This way it's obvious where the problem
  1285. // is.
  1286. //
  1287. if (Record->ExceptionInformation[0])
  1288. {
  1289. if (g_EventTarget->
  1290. ReadAllVirtual(g_EventProcess, Record->ExceptionInformation[0],
  1291. &CritSec, sizeof(CritSec)) == S_OK)
  1292. {
  1293. if (NULL == CritSec.DebugInfo)
  1294. {
  1295. dprintf("Critsec %s was deleted or "
  1296. "was never initialized.\n",
  1297. FormatAddr64(Record->ExceptionInformation[0]));
  1298. }
  1299. else if (CritSec.LockCount < -1)
  1300. {
  1301. dprintf("Critsec %s was left when not owned, corrupted.\n",
  1302. FormatAddr64(Record->ExceptionInformation[0]));
  1303. }
  1304. else
  1305. {
  1306. Tid = (DWORD)((ULONG_PTR)CritSec.OwningThread);
  1307. ThreadOwner = g_Process->FindThreadBySystemId(Tid);
  1308. }
  1309. }
  1310. }
  1311. if (ThreadOwner)
  1312. {
  1313. dprintf("Critsec %s owned by thread %d (.%x) "
  1314. "caused thread %d (.%x)\n"
  1315. " to timeout entering it. "
  1316. "Breaking in on owner thread, ask\n"
  1317. " yourself why it has held this "
  1318. "critsec long enough to deadlock.\n"
  1319. " Use `~%ds` to switch back to timeout thread.\n",
  1320. FormatAddr64(Record->ExceptionInformation[0]),
  1321. ThreadOwner->m_UserId,
  1322. ThreadOwner->m_SystemId,
  1323. g_Thread->m_UserId,
  1324. g_Thread->m_SystemId,
  1325. g_Thread->m_UserId);
  1326. g_EventThread = ThreadOwner;
  1327. SetPromptThread(ThreadOwner, 0);
  1328. }
  1329. else if (Tid)
  1330. {
  1331. dprintf("Critsec %s ABANDONED owner thread ID is .%x, "
  1332. "no such thread.\n",
  1333. FormatAddr64(Record->ExceptionInformation[0]),
  1334. Tid);
  1335. }
  1336. if (!FirstChance)
  1337. {
  1338. dprintf("!!! second chance !!!\n");
  1339. }
  1340. //
  1341. // do a !critsec for them
  1342. //
  1343. if (Record->ExceptionInformation[0])
  1344. {
  1345. char CritsecAddr[64];
  1346. HRESULT Status;
  1347. sprintf(CritsecAddr, "%s",
  1348. FormatAddr64(Record->ExceptionInformation[0]));
  1349. dprintf("!critsec %s\n", CritsecAddr);
  1350. CallAnyExtension(NULL, NULL, "critsec", CritsecAddr,
  1351. FALSE, FALSE, &Status);
  1352. }
  1353. }
  1354. else if (!_stricmp("ntdll!RtlAcquireResourceShared", Symbol) ||
  1355. !_stricmp("ntdll!RtlAcquireResourceExclusive", Symbol) ||
  1356. !_stricmp("ntdll!RtlConvertSharedToExclusive", Symbol))
  1357. {
  1358. dprintf("deadlock in %s ", 1 + strstr(Symbol, "!"));
  1359. GetSymbol(Record->ExceptionInformation[0],
  1360. Symbol, sizeof(Symbol), &Displacement);
  1361. dprintf("Resource %s", Symbol);
  1362. if (Displacement)
  1363. {
  1364. dprintf("+%s", FormatDisp64(Displacement));
  1365. }
  1366. dprintf(" (%s)\n",
  1367. FormatAddr64(Record->ExceptionInformation[0]));
  1368. if (!FirstChance)
  1369. {
  1370. dprintf("!!! second chance !!!\n");
  1371. }
  1372. // Someone who uses RTL_RESOURCEs might write a !resource
  1373. // for ntsdexts.dll like !critsec.
  1374. }
  1375. else
  1376. {
  1377. dprintf("Possible Deadlock in %s ", Symbol);
  1378. GetSymbol(Record->ExceptionInformation[0],
  1379. Symbol, sizeof(Symbol), &Displacement);
  1380. dprintf("Lock %s", Symbol);
  1381. if (Displacement)
  1382. {
  1383. dprintf("+%s", FormatDisp64(Displacement));
  1384. }
  1385. dprintf(" (%s)\n",
  1386. FormatAddr64(Record->ExceptionInformation[0]));
  1387. if (!FirstChance)
  1388. {
  1389. dprintf("!!! second chance !!!\n");
  1390. }
  1391. }
  1392. }
  1393. void
  1394. OutputDeadlock(PEXCEPTION_RECORD64 Record, ULONG FirstChance)
  1395. {
  1396. CHAR Symbol[MAX_SYMBOL_LEN];
  1397. DWORD64 Displacement;
  1398. GetSymbol(Record->ExceptionInformation[0],
  1399. Symbol, sizeof(Symbol), &Displacement);
  1400. dprintf("Possible Deadlock Lock %s+%s at %s\n",
  1401. Symbol,
  1402. FormatDisp64(Displacement),
  1403. FormatAddr64(Record->ExceptionInformation[0]));
  1404. if (!FirstChance)
  1405. {
  1406. dprintf("!!! second chance !!!\n");
  1407. }
  1408. }
  1409. void
  1410. GetEventName(ULONG64 ImageFile, ULONG64 ImageBase,
  1411. ULONG64 NamePtr, WORD Unicode,
  1412. PSTR NameBuffer, ULONG BufferSize)
  1413. {
  1414. char TempName[MAX_IMAGE_PATH];
  1415. if (!g_EventProcess)
  1416. {
  1417. return;
  1418. }
  1419. if (NamePtr != 0)
  1420. {
  1421. if (g_EventTarget->ReadPointer(g_EventProcess,
  1422. g_EventTarget->m_Machine,
  1423. NamePtr, &NamePtr) != S_OK)
  1424. {
  1425. NamePtr = 0;
  1426. }
  1427. }
  1428. if (NamePtr != 0)
  1429. {
  1430. ULONG Done;
  1431. if (g_EventTarget->ReadVirtual(g_EventProcess,
  1432. NamePtr, TempName, sizeof(TempName),
  1433. &Done) != S_OK ||
  1434. Done < (Unicode ? 2 * sizeof(WCHAR) : 2))
  1435. {
  1436. NamePtr = 0;
  1437. }
  1438. else
  1439. {
  1440. TempName[sizeof(TempName) - 1] = 0;
  1441. TempName[sizeof(TempName) - 2] = 0;
  1442. }
  1443. }
  1444. if (NamePtr != 0)
  1445. {
  1446. //
  1447. // We have a name.
  1448. //
  1449. if (Unicode)
  1450. {
  1451. if (!WideCharToMultiByte(
  1452. CP_ACP,
  1453. WC_COMPOSITECHECK,
  1454. (LPWSTR)TempName,
  1455. -1,
  1456. NameBuffer,
  1457. BufferSize,
  1458. NULL,
  1459. NULL
  1460. ))
  1461. {
  1462. //
  1463. // Unicode -> ANSI conversion failed.
  1464. //
  1465. NameBuffer[0] = 0;
  1466. }
  1467. }
  1468. else
  1469. {
  1470. CopyString(NameBuffer, TempName, BufferSize);
  1471. }
  1472. }
  1473. else
  1474. {
  1475. //
  1476. // We don't have a name, so look in the image.
  1477. // A file handle will only be provided here in the
  1478. // local case so it's safe to case to HANDLE.
  1479. //
  1480. if (!GetModnameFromImage(g_EventProcess,
  1481. ImageBase, OS_HANDLE(ImageFile),
  1482. NameBuffer, BufferSize, TRUE))
  1483. {
  1484. NameBuffer[0] = 0;
  1485. }
  1486. }
  1487. if (!NameBuffer[0])
  1488. {
  1489. if (!GetModNameFromLoaderList(g_EventThread,
  1490. g_EventTarget->m_Machine, 0,
  1491. ImageBase, NameBuffer, BufferSize,
  1492. TRUE))
  1493. {
  1494. PrintString(NameBuffer, BufferSize,
  1495. "image%p", (PVOID)(ULONG_PTR)ImageBase);
  1496. }
  1497. }
  1498. else
  1499. {
  1500. // If the name given doesn't have a full path try
  1501. // and locate a full path in the loader list.
  1502. if ((((NameBuffer[0] < 'a' || NameBuffer[0] > 'z') &&
  1503. (NameBuffer[0] < 'A' || NameBuffer[0] > 'Z')) ||
  1504. NameBuffer[1] != ':') &&
  1505. (NameBuffer[0] != '\\' || NameBuffer[1] != '\\'))
  1506. {
  1507. GetModNameFromLoaderList(g_EventThread,
  1508. g_EventTarget->m_Machine, 0,
  1509. ImageBase, NameBuffer, BufferSize,
  1510. TRUE);
  1511. }
  1512. }
  1513. }
  1514. //----------------------------------------------------------------------------
  1515. //
  1516. // ConnLiveKernelTargetInfo wait methods.
  1517. //
  1518. //----------------------------------------------------------------------------
  1519. NTSTATUS
  1520. ConnLiveKernelTargetInfo::KdContinue(ULONG ContinueStatus,
  1521. PDBGKD_ANY_CONTROL_SET ControlSet)
  1522. {
  1523. DBGKD_MANIPULATE_STATE64 m;
  1524. DBG_ASSERT(ContinueStatus == DBG_EXCEPTION_HANDLED ||
  1525. ContinueStatus == DBG_EXCEPTION_NOT_HANDLED ||
  1526. ContinueStatus == DBG_CONTINUE);
  1527. if (ControlSet)
  1528. {
  1529. EventOut(">>> DbgKdContinue2\n");
  1530. m.ApiNumber = DbgKdContinueApi2;
  1531. m.u.Continue2.ContinueStatus = ContinueStatus;
  1532. m.u.Continue2.AnyControlSet = *ControlSet;
  1533. }
  1534. else
  1535. {
  1536. EventOut(">>> DbgKdContinue\n");
  1537. m.ApiNumber = DbgKdContinueApi;
  1538. m.u.Continue.ContinueStatus = ContinueStatus;
  1539. }
  1540. m.ReturnStatus = ContinueStatus;
  1541. m_Transport->WritePacket(&m, sizeof(m),
  1542. PACKET_TYPE_KD_STATE_MANIPULATE,
  1543. NULL, 0);
  1544. return STATUS_SUCCESS;
  1545. }
  1546. HRESULT
  1547. ConnLiveKernelTargetInfo::WaitInitialize(ULONG Flags,
  1548. ULONG Timeout,
  1549. WAIT_INIT_TYPE Type,
  1550. PULONG DesiredTimeout)
  1551. {
  1552. // Timeouts can't easily be supported at the moment and
  1553. // aren't really necessary.
  1554. if (Timeout != INFINITE)
  1555. {
  1556. return E_NOTIMPL;
  1557. }
  1558. *DesiredTimeout = Timeout;
  1559. m_EventPossible = m_CurrentPartition;
  1560. return S_OK;
  1561. }
  1562. HRESULT
  1563. ConnLiveKernelTargetInfo::ReleaseLastEvent(ULONG ContinueStatus)
  1564. {
  1565. HRESULT Status = S_OK;
  1566. NTSTATUS NtStatus;
  1567. if (!g_EventProcessSysId)
  1568. {
  1569. // No event to release.
  1570. return S_OK;
  1571. }
  1572. m_CurrentPartition = FALSE;
  1573. if (SPECIAL_EXECUTION(g_CmdState))
  1574. {
  1575. if (m_SwitchTarget)
  1576. {
  1577. DBGKD_MANIPULATE_STATE64 m;
  1578. EventOut(">>> Switch to system %d\n", m_SwitchTarget->m_UserId);
  1579. if (m_KdMaxManipulate <= DbgKdSwitchPartition)
  1580. {
  1581. ErrOut("System doesn't support partition switching\n");
  1582. return E_NOTIMPL;
  1583. }
  1584. m.ApiNumber = (USHORT)DbgKdSwitchPartition;
  1585. m.Processor = 0;
  1586. m.ProcessorLevel = 0;
  1587. m.u.SwitchPartition.Partition = m_SwitchTarget->m_SystemId;
  1588. m_Transport->WritePacket(&m, sizeof(m),
  1589. PACKET_TYPE_KD_STATE_MANIPULATE,
  1590. NULL, 0);
  1591. KdOut("DbgKdSwitchPartition returns 0x00000000\n");
  1592. m_SwitchTarget = NULL;
  1593. g_EngStatus |= ENG_STATUS_SPECIAL_EXECUTION;
  1594. }
  1595. else
  1596. {
  1597. // This can either be a real processor switch or
  1598. // a rewait for state change. Check the switch
  1599. // processor to be sure.
  1600. if (m_SwitchProcessor)
  1601. {
  1602. DBGKD_MANIPULATE_STATE64 m;
  1603. EventOut(">>> Switch to processor %d\n",
  1604. m_SwitchProcessor - 1);
  1605. m.ApiNumber = (USHORT)DbgKdSwitchProcessor;
  1606. m.Processor = (USHORT)(m_SwitchProcessor - 1);
  1607. // Quiet PREfix warnings.
  1608. m.ProcessorLevel = 0;
  1609. m_Transport->WritePacket(&m, sizeof(m),
  1610. PACKET_TYPE_KD_STATE_MANIPULATE,
  1611. NULL, 0);
  1612. KdOut("DbgKdSwitchActiveProcessor returns 0x00000000\n");
  1613. m_SwitchProcessor = 0;
  1614. g_EngStatus |= ENG_STATUS_SPECIAL_EXECUTION;
  1615. }
  1616. }
  1617. }
  1618. else
  1619. {
  1620. NtStatus = KdContinue(ContinueStatus,
  1621. (g_EngDefer & ENG_DEFER_UPDATE_CONTROL_SET) ?
  1622. &g_ControlSet : NULL);
  1623. if (!NT_SUCCESS(NtStatus))
  1624. {
  1625. ErrOut("KdContinue failed, 0x%08x\n", NtStatus);
  1626. Status = HRESULT_FROM_NT(NtStatus);
  1627. }
  1628. else
  1629. {
  1630. g_EngDefer &= ~ENG_DEFER_UPDATE_CONTROL_SET;
  1631. }
  1632. }
  1633. return Status;
  1634. }
  1635. HRESULT
  1636. ConnLiveKernelTargetInfo::WaitForEvent(ULONG Flags, ULONG Timeout,
  1637. ULONG ElapsedTime, PULONG EventStatus)
  1638. {
  1639. NTSTATUS NtStatus;
  1640. if (!IS_MACHINE_SET(this))
  1641. {
  1642. dprintf("Waiting to reconnect...\n");
  1643. if ((g_EngOptions & DEBUG_ENGOPT_INITIAL_BREAK) &&
  1644. IS_CONN_KERNEL_TARGET(this))
  1645. {
  1646. // Ask for a breakin to be sent once the
  1647. // code gets into resync.
  1648. m_Transport->m_SyncBreakIn = TRUE;
  1649. }
  1650. }
  1651. // When waiting for confirmation of a processor switch don't
  1652. // yield the engine lock in order to prevent other clients
  1653. // from trying to do things with the target while it's
  1654. // switching.
  1655. NtStatus = WaitStateChange(&g_StateChange, g_StateChangeBuffer,
  1656. sizeof(g_StateChangeBuffer) - 2,
  1657. (g_EngStatus &
  1658. ENG_STATUS_SPECIAL_EXECUTION) == 0);
  1659. if (NtStatus == STATUS_PENDING)
  1660. {
  1661. // A caller interrupted the current wait so exit
  1662. // without an error message.
  1663. return E_PENDING;
  1664. }
  1665. else if (!NT_SUCCESS(NtStatus))
  1666. {
  1667. ErrOut("DbgKdWaitStateChange failed: %08lx\n", NtStatus);
  1668. return HRESULT_FROM_NT(NtStatus);
  1669. }
  1670. g_EngStatus |= ENG_STATUS_STATE_CHANGED;
  1671. g_StateChangeData = g_StateChangeBuffer;
  1672. *EventStatus = ((ConnLiveKernelTargetInfo*)g_EventTarget)->
  1673. ProcessStateChange(&g_StateChange, g_StateChangeData);
  1674. return S_OK;
  1675. }
  1676. NTSTATUS
  1677. ConnLiveKernelTargetInfo::WaitStateChange
  1678. (OUT PDBGKD_ANY_WAIT_STATE_CHANGE StateChange,
  1679. OUT PVOID Buffer,
  1680. IN ULONG BufferLength,
  1681. IN BOOL SuspendEngine)
  1682. {
  1683. PVOID LocalStateChange;
  1684. NTSTATUS Status;
  1685. PUCHAR Data;
  1686. ULONG SizeofStateChange;
  1687. ULONG WaitStatus;
  1688. //
  1689. // Waiting for a state change message. Copy the message to the callers
  1690. // buffer.
  1691. //
  1692. DBG_ASSERT(m_Transport->m_WaitingThread == 0);
  1693. m_Transport->m_WaitingThread = GetCurrentThreadId();
  1694. if (SuspendEngine)
  1695. {
  1696. SUSPEND_ENGINE();
  1697. }
  1698. do
  1699. {
  1700. WaitStatus = m_Transport->
  1701. WaitForPacket(PACKET_TYPE_KD_STATE_CHANGE64, &LocalStateChange);
  1702. } while (WaitStatus != DBGKD_WAIT_PACKET &&
  1703. WaitStatus != DBGKD_WAIT_INTERRUPTED);
  1704. if (SuspendEngine)
  1705. {
  1706. RESUME_ENGINE();
  1707. }
  1708. m_Transport->m_WaitingThread = 0;
  1709. if (WaitStatus == DBGKD_WAIT_INTERRUPTED)
  1710. {
  1711. return STATUS_PENDING;
  1712. }
  1713. Status = STATUS_SUCCESS;
  1714. // If this is the very first wait we don't know what system
  1715. // we've connected to. Update the version information
  1716. // right away.
  1717. if (!IS_MACHINE_SET(this))
  1718. {
  1719. m_Transport->SaveReadPacket();
  1720. // Failures will be detected by checking the machine
  1721. // state later so don't worry about the return value.
  1722. InitFromKdVersion();
  1723. m_Transport->RestoreReadPacket();
  1724. if (!IS_MACHINE_SET(this))
  1725. {
  1726. //
  1727. // We were unable to determine what kind of machine
  1728. // has connected so we cannot properly communicate with it.
  1729. //
  1730. return STATUS_UNSUCCESSFUL;
  1731. }
  1732. //
  1733. // Trusted Windows systems have two OS's running, one
  1734. // regular NT and the other a trusted NT-like OS.
  1735. // If this is a Trusted Windows system set up systems
  1736. // for both the regular and trusted OSs.
  1737. //
  1738. if ((m_KdVersion.Flags & DBGKD_VERS_FLAG_PARTITIONS) &&
  1739. !FindTargetBySystemId(DBGKD_PARTITION_ALTERNATE))
  1740. {
  1741. ConnLiveKernelTargetInfo* AltTarg = new ConnLiveKernelTargetInfo;
  1742. if (!AltTarg)
  1743. {
  1744. return STATUS_NO_MEMORY;
  1745. }
  1746. // Avoid the ConnLiveKernelTargetInfo Initialize as
  1747. // we don't want a new transport created.
  1748. if (AltTarg->LiveKernelTargetInfo::Initialize() != S_OK)
  1749. {
  1750. delete AltTarg;
  1751. return STATUS_UNSUCCESSFUL;
  1752. }
  1753. m_Transport->Ref();
  1754. AltTarg->m_Transport = m_Transport;
  1755. m_Transport->SaveReadPacket();
  1756. AltTarg->InitFromKdVersion();
  1757. m_Transport->RestoreReadPacket();
  1758. if (!IS_MACHINE_SET(AltTarg))
  1759. {
  1760. delete AltTarg;
  1761. return STATUS_UNSUCCESSFUL;
  1762. }
  1763. if (DBGKD_MAJOR_TYPE(m_KdVersion.MajorVersion) == DBGKD_MAJOR_TNT)
  1764. {
  1765. // This is the trusted partition.
  1766. m_SystemId = DBGKD_PARTITION_ALTERNATE;
  1767. AltTarg->m_SystemId = DBGKD_PARTITION_DEFAULT;
  1768. }
  1769. else
  1770. {
  1771. // This is the regular partition.
  1772. m_SystemId = DBGKD_PARTITION_DEFAULT;
  1773. AltTarg->m_SystemId = DBGKD_PARTITION_ALTERNATE;
  1774. }
  1775. }
  1776. }
  1777. if (m_KdApi64)
  1778. {
  1779. if (m_KdVersion.ProtocolVersion < DBGKD_64BIT_PROTOCOL_VERSION2)
  1780. {
  1781. PDBGKD_WAIT_STATE_CHANGE64 Ws64 =
  1782. (PDBGKD_WAIT_STATE_CHANGE64)LocalStateChange;
  1783. ULONG Offset, Align, Pad;
  1784. //
  1785. // The 64-bit structures contain 64-bit quantities and
  1786. // therefore the compiler rounds the total size up to
  1787. // an even multiple of 64 bits (or even more, the IA64
  1788. // structures are 16-byte aligned). Internal structures
  1789. // are also aligned, so make sure that we account for any
  1790. // padding. Knowledge of which structures need which
  1791. // padding pretty much has to be hard-coded in.
  1792. //
  1793. C_ASSERT((sizeof(DBGKD_WAIT_STATE_CHANGE64) & 15) == 0);
  1794. SizeofStateChange =
  1795. sizeof(DBGKD_WAIT_STATE_CHANGE64) +
  1796. m_TypeInfo.SizeControlReport +
  1797. m_TypeInfo.SizeTargetContext;
  1798. // We shouldn't need to align the base of the control report
  1799. // so copy the base data and control report.
  1800. Offset = sizeof(DBGKD_WAIT_STATE_CHANGE64) +
  1801. m_TypeInfo.SizeControlReport;
  1802. memcpy(StateChange, Ws64, Offset);
  1803. //
  1804. // Add alignment padding before the context.
  1805. //
  1806. switch(m_MachineType)
  1807. {
  1808. case IMAGE_FILE_MACHINE_IA64:
  1809. Align = 15;
  1810. break;
  1811. default:
  1812. Align = 7;
  1813. break;
  1814. }
  1815. Pad = ((Offset + Align) & ~Align) - Offset;
  1816. Offset += Pad;
  1817. SizeofStateChange += Pad;
  1818. //
  1819. // Add alignment padding after the context.
  1820. //
  1821. Offset += m_TypeInfo.SizeTargetContext;
  1822. Pad = ((Offset + Align) & ~Align) - Offset;
  1823. SizeofStateChange += Pad;
  1824. }
  1825. else
  1826. {
  1827. PDBGKD_ANY_WAIT_STATE_CHANGE WsAny =
  1828. (PDBGKD_ANY_WAIT_STATE_CHANGE)LocalStateChange;
  1829. SizeofStateChange = sizeof(*WsAny);
  1830. *StateChange = *WsAny;
  1831. }
  1832. }
  1833. else
  1834. {
  1835. SizeofStateChange =
  1836. sizeof(DBGKD_WAIT_STATE_CHANGE32) +
  1837. m_TypeInfo.SizeControlReport +
  1838. m_TypeInfo.SizeTargetContext;
  1839. WaitStateChange32ToAny((PDBGKD_WAIT_STATE_CHANGE32)LocalStateChange,
  1840. m_TypeInfo.SizeControlReport,
  1841. StateChange);
  1842. }
  1843. if (StateChange->NewState & DbgKdAlternateStateChange)
  1844. {
  1845. // This state change came from the alternate partition.
  1846. g_EventTarget = FindTargetBySystemId(DBGKD_PARTITION_ALTERNATE);
  1847. StateChange->NewState &= ~DbgKdAlternateStateChange;
  1848. }
  1849. else
  1850. {
  1851. // Default partition state change.
  1852. g_EventTarget = FindTargetBySystemId(DBGKD_PARTITION_DEFAULT);
  1853. }
  1854. if (!g_EventTarget)
  1855. {
  1856. return STATUS_UNSUCCESSFUL;
  1857. }
  1858. ((ConnLiveKernelTargetInfo*)g_EventTarget)->m_CurrentPartition = TRUE;
  1859. switch(StateChange->NewState)
  1860. {
  1861. case DbgKdExceptionStateChange:
  1862. case DbgKdCommandStringStateChange:
  1863. if (BufferLength <
  1864. (m_Transport->s_PacketHeader.ByteCount - SizeofStateChange))
  1865. {
  1866. Status = STATUS_BUFFER_OVERFLOW;
  1867. }
  1868. else
  1869. {
  1870. Data = (UCHAR *)LocalStateChange + SizeofStateChange;
  1871. memcpy(Buffer, Data,
  1872. m_Transport->s_PacketHeader.ByteCount -
  1873. SizeofStateChange);
  1874. }
  1875. break;
  1876. case DbgKdLoadSymbolsStateChange:
  1877. if ( BufferLength < StateChange->u.LoadSymbols.PathNameLength )
  1878. {
  1879. Status = STATUS_BUFFER_OVERFLOW;
  1880. }
  1881. else
  1882. {
  1883. Data = ((UCHAR *) LocalStateChange) +
  1884. m_Transport->s_PacketHeader.ByteCount -
  1885. (int)StateChange->u.LoadSymbols.PathNameLength;
  1886. memcpy(Buffer, Data,
  1887. (int)StateChange->u.LoadSymbols.PathNameLength);
  1888. }
  1889. break;
  1890. default:
  1891. ErrOut("Unknown state change type %X\n", StateChange->NewState);
  1892. Status = STATUS_INVALID_PARAMETER;
  1893. break;
  1894. }
  1895. return Status;
  1896. }
  1897. #define EXCEPTION_CODE StateChange->u.Exception.ExceptionRecord.ExceptionCode
  1898. #define FIRST_CHANCE StateChange->u.Exception.FirstChance
  1899. ULONG
  1900. ConnLiveKernelTargetInfo::ProcessStateChange(PDBGKD_ANY_WAIT_STATE_CHANGE StateChange,
  1901. PCHAR StateChangeData)
  1902. {
  1903. ULONG EventStatus;
  1904. EventOut(">>> State change event %X, proc %d of %d\n",
  1905. StateChange->NewState, StateChange->Processor,
  1906. StateChange->NumberProcessors);
  1907. if (!m_NumProcessors)
  1908. {
  1909. dprintf("Kernel Debugger connection established.%s\n",
  1910. (g_EngOptions & DEBUG_ENGOPT_INITIAL_BREAK) ?
  1911. " (Initial Breakpoint requested)" : "");
  1912. // Initial connection after a fresh boot may only report
  1913. // a single processor as the others haven't started yet.
  1914. m_NumProcessors = StateChange->NumberProcessors;
  1915. CreateVirtualProcess(m_NumProcessors);
  1916. g_EventProcessSysId = m_ProcessHead->m_SystemId;
  1917. g_EventThreadSysId = VIRTUAL_THREAD_ID(StateChange->Processor);
  1918. FindEventProcessThread();
  1919. QueryKernelInfo(g_EventThread, TRUE);
  1920. // Now that we have the data block
  1921. // we can retrieve processor information.
  1922. InitializeForProcessor();
  1923. RemoveAllTargetBreakpoints();
  1924. OutputVersion();
  1925. NotifyDebuggeeActivation();
  1926. }
  1927. else
  1928. {
  1929. // Initial connection after a fresh boot may only report
  1930. // a single processor as the others haven't started yet.
  1931. // Pick up any additional processors.
  1932. if (StateChange->NumberProcessors > m_NumProcessors)
  1933. {
  1934. m_ProcessHead->
  1935. CreateVirtualThreads(m_NumProcessors,
  1936. StateChange->NumberProcessors -
  1937. m_NumProcessors);
  1938. m_NumProcessors = StateChange->NumberProcessors;
  1939. }
  1940. g_EventProcessSysId = m_ProcessHead->m_SystemId;
  1941. g_EventThreadSysId = VIRTUAL_THREAD_ID(StateChange->Processor);
  1942. FindEventProcessThread();
  1943. }
  1944. g_TargetEventPc = StateChange->ProgramCounter;
  1945. g_ControlReport = &StateChange->AnyControlReport;
  1946. if (g_EventThread)
  1947. {
  1948. g_EventThread->m_DataOffset = StateChange->Thread;
  1949. }
  1950. //
  1951. // If the reported instruction stream contained breakpoints
  1952. // the kernel automatically removed them. We need to
  1953. // ensure that breakpoints get reinserted properly if
  1954. // that's the case.
  1955. //
  1956. ULONG Count;
  1957. switch(m_MachineType)
  1958. {
  1959. case IMAGE_FILE_MACHINE_IA64:
  1960. Count = g_ControlReport->IA64ControlReport.InstructionCount;
  1961. break;
  1962. case IMAGE_FILE_MACHINE_I386:
  1963. Count = g_ControlReport->X86ControlReport.InstructionCount;
  1964. break;
  1965. case IMAGE_FILE_MACHINE_AMD64:
  1966. Count = g_ControlReport->Amd64ControlReport.InstructionCount;
  1967. break;
  1968. }
  1969. if (CheckBreakpointInsertedInRange(g_EventProcess,
  1970. g_TargetEventPc,
  1971. g_TargetEventPc + Count - 1))
  1972. {
  1973. SuspendExecution();
  1974. RemoveBreakpoints();
  1975. }
  1976. if (StateChange->NewState == DbgKdExceptionStateChange)
  1977. {
  1978. //
  1979. // Read the system range start address from the target system.
  1980. //
  1981. if (m_SystemRangeStart == 0)
  1982. {
  1983. QueryKernelInfo(g_EventThread, FALSE);
  1984. }
  1985. EventOut("Exception %X at %p\n", EXCEPTION_CODE, g_TargetEventPc);
  1986. if (EXCEPTION_CODE == STATUS_BREAKPOINT ||
  1987. EXCEPTION_CODE == STATUS_SINGLE_STEP ||
  1988. EXCEPTION_CODE == STATUS_WX86_BREAKPOINT ||
  1989. EXCEPTION_CODE == STATUS_WX86_SINGLE_STEP)
  1990. {
  1991. EventStatus = ProcessBreakpointOrStepException
  1992. (&StateChange->u.Exception.ExceptionRecord,
  1993. StateChange->u.Exception.FirstChance);
  1994. }
  1995. else if (EXCEPTION_CODE == STATUS_WAKE_SYSTEM_DEBUGGER)
  1996. {
  1997. // The target has requested that the debugger
  1998. // become active so just break in.
  1999. EventStatus = DEBUG_STATUS_BREAK;
  2000. }
  2001. else
  2002. {
  2003. //
  2004. // The interlocked SList code has a by-design faulting
  2005. // case, so ignore AVs at that particular symbol.
  2006. //
  2007. if (EXCEPTION_CODE == STATUS_ACCESS_VIOLATION &&
  2008. StateChange->u.Exception.FirstChance)
  2009. {
  2010. CHAR ExSym[MAX_SYMBOL_LEN];
  2011. ULONG64 ExDisp;
  2012. GetSymbol(StateChange->
  2013. u.Exception.ExceptionRecord.ExceptionAddress,
  2014. ExSym, sizeof(ExSym), &ExDisp);
  2015. if (ExDisp == 0 &&
  2016. !_stricmp(ExSym, "nt!ExpInterlockedPopEntrySListFault"))
  2017. {
  2018. return DEBUG_STATUS_GO_NOT_HANDLED;
  2019. }
  2020. }
  2021. EventStatus =
  2022. NotifyExceptionEvent(&StateChange->u.Exception.ExceptionRecord,
  2023. StateChange->u.Exception.FirstChance,
  2024. FALSE);
  2025. }
  2026. }
  2027. else if (StateChange->NewState == DbgKdLoadSymbolsStateChange)
  2028. {
  2029. if (StateChange->u.LoadSymbols.UnloadSymbols)
  2030. {
  2031. if (StateChange->u.LoadSymbols.PathNameLength == 0 &&
  2032. StateChange->u.LoadSymbols.ProcessId == 0)
  2033. {
  2034. if (StateChange->u.LoadSymbols.BaseOfDll == (ULONG64)KD_REBOOT ||
  2035. StateChange->u.LoadSymbols.BaseOfDll == (ULONG64)KD_HIBERNATE)
  2036. {
  2037. KdContinue(DBG_CONTINUE, NULL);
  2038. DebuggeeReset(StateChange->u.LoadSymbols.BaseOfDll ==
  2039. KD_REBOOT ?
  2040. DEBUG_SESSION_REBOOT :
  2041. DEBUG_SESSION_HIBERNATE,
  2042. TRUE);
  2043. EventStatus = DEBUG_STATUS_NO_DEBUGGEE;
  2044. }
  2045. else
  2046. {
  2047. ErrOut("Invalid module unload state change\n");
  2048. EventStatus = DEBUG_STATUS_IGNORE_EVENT;
  2049. }
  2050. }
  2051. else
  2052. {
  2053. EventStatus = NotifyUnloadModuleEvent
  2054. (StateChangeData, StateChange->u.LoadSymbols.BaseOfDll);
  2055. }
  2056. }
  2057. else
  2058. {
  2059. ImageInfo* Image;
  2060. CHAR FileName[_MAX_FNAME];
  2061. CHAR Ext[_MAX_EXT];
  2062. CHAR ImageName[_MAX_FNAME + _MAX_EXT];
  2063. CHAR ModNameBuf[_MAX_FNAME + _MAX_EXT + 1];
  2064. PSTR ModName = ModNameBuf;
  2065. ModName[0] = '\0';
  2066. _splitpath( StateChangeData, NULL, NULL, FileName, Ext );
  2067. sprintf( ImageName, "%s%s", FileName, Ext );
  2068. if (_stricmp(Ext, ".sys") == 0)
  2069. {
  2070. Image = g_EventProcess ? g_EventProcess->m_ImageHead : NULL;
  2071. while (Image)
  2072. {
  2073. if (_stricmp(ImageName, Image->m_ImagePath) == 0)
  2074. {
  2075. PSTR Dot;
  2076. ModName[0] = 'c';
  2077. strcpy( &ModName[1], ImageName );
  2078. Dot = strchr( ModName, '.' );
  2079. if (Dot)
  2080. {
  2081. *Dot = '\0';
  2082. }
  2083. ModName[8] = '\0';
  2084. break;
  2085. }
  2086. Image = Image->m_Next;
  2087. }
  2088. }
  2089. else if (StateChange->u.LoadSymbols.BaseOfDll ==
  2090. m_KdDebuggerData.KernBase)
  2091. {
  2092. //
  2093. // Recognize the kernel module.
  2094. //
  2095. ModName = KERNEL_MODULE_NAME;
  2096. }
  2097. EventStatus = NotifyLoadModuleEvent(
  2098. 0, StateChange->u.LoadSymbols.BaseOfDll,
  2099. StateChange->u.LoadSymbols.SizeOfImage,
  2100. ModName[0] ? ModName : NULL, ImageName,
  2101. StateChange->u.LoadSymbols.CheckSum, 0,
  2102. StateChange->u.LoadSymbols.BaseOfDll < m_SystemRangeStart);
  2103. //
  2104. // Attempt to preload the machine type of the image
  2105. // as we expect the headers to be available at this
  2106. // point, whereas they may be paged out later.
  2107. //
  2108. Image = g_EventProcess ? g_EventProcess->
  2109. FindImageByOffset(StateChange->u.LoadSymbols.BaseOfDll,
  2110. FALSE) : NULL;
  2111. if (Image)
  2112. {
  2113. Image->GetMachineType();
  2114. }
  2115. }
  2116. }
  2117. else if (StateChange->NewState == DbgKdCommandStringStateChange)
  2118. {
  2119. PSTR Command;
  2120. //
  2121. // The state change data has two strings one after
  2122. // the other. The first is a name string identifying
  2123. // the originator of the command. The second is
  2124. // the command itself.
  2125. //
  2126. Command = StateChangeData + strlen(StateChangeData) + 1;
  2127. _snprintf(g_LastEventDesc, sizeof(g_LastEventDesc) - 1,
  2128. "%.48s command: '%.192s'",
  2129. StateChangeData, Command);
  2130. EventStatus = ExecuteEventCommand(DEBUG_STATUS_NO_CHANGE, NULL,
  2131. Command);
  2132. // Break in if the command didn't explicitly continue.
  2133. if (EventStatus == DEBUG_STATUS_NO_CHANGE)
  2134. {
  2135. EventStatus = DEBUG_STATUS_BREAK;
  2136. }
  2137. }
  2138. else
  2139. {
  2140. //
  2141. // Invalid NewState in state change record.
  2142. //
  2143. ErrOut("\nUNEXPECTED STATE CHANGE %08lx\n\n",
  2144. StateChange->NewState);
  2145. EventStatus = DEBUG_STATUS_IGNORE_EVENT;
  2146. }
  2147. return EventStatus;
  2148. }
  2149. #undef EXCEPTION_CODE
  2150. #undef FIRST_CHANCE
  2151. //----------------------------------------------------------------------------
  2152. //
  2153. // LocalLiveKernelTargetInfo wait methods.
  2154. //
  2155. //----------------------------------------------------------------------------
  2156. HRESULT
  2157. LocalLiveKernelTargetInfo::WaitInitialize(ULONG Flags,
  2158. ULONG Timeout,
  2159. WAIT_INIT_TYPE Type,
  2160. PULONG DesiredTimeout)
  2161. {
  2162. *DesiredTimeout = Timeout;
  2163. m_EventPossible = m_FirstWait;
  2164. return S_OK;
  2165. }
  2166. HRESULT
  2167. LocalLiveKernelTargetInfo::WaitForEvent(ULONG Flags, ULONG Timeout,
  2168. ULONG ElapsedTime, PULONG EventStatus)
  2169. {
  2170. HRESULT Status;
  2171. SYSTEM_INFO SysInfo;
  2172. if (!m_FirstWait)
  2173. {
  2174. // A wait has already been done. Local kernels
  2175. // can only generate a single event so further
  2176. // waiting is not possible.
  2177. return S_FALSE;
  2178. }
  2179. g_EventTarget = this;
  2180. GetSystemInfo(&SysInfo);
  2181. m_NumProcessors = SysInfo.dwNumberOfProcessors;
  2182. // Set this right here since we know kernel debugging only works on
  2183. // recent systems using the 64 bit protocol.
  2184. m_KdApi64 = TRUE;
  2185. if ((Status = InitFromKdVersion()) != S_OK)
  2186. {
  2187. delete g_EventTarget;
  2188. g_EventTarget = NULL;
  2189. return Status;
  2190. }
  2191. // This is the first wait. Simulate any
  2192. // necessary events such as process and thread
  2193. // creations and image loads.
  2194. CreateVirtualProcess(m_NumProcessors);
  2195. g_EventProcessSysId = m_ProcessHead->m_SystemId;
  2196. // Current processor always starts at zero.
  2197. g_EventThreadSysId = VIRTUAL_THREAD_ID(0);
  2198. FindEventProcessThread();
  2199. QueryKernelInfo(g_EventThread, TRUE);
  2200. // Now that we have the data block
  2201. // we can retrieve processor information.
  2202. InitializeForProcessor();
  2203. // Clear the global state change just in case somebody's
  2204. // directly accessing it somewhere.
  2205. ZeroMemory(&g_StateChange, sizeof(g_StateChange));
  2206. g_StateChangeData = g_StateChangeBuffer;
  2207. g_StateChangeBuffer[0] = 0;
  2208. g_EngStatus |= ENG_STATUS_STATE_CHANGED;
  2209. // Do not provide a control report; this will force
  2210. // such information to come from context retrieval.
  2211. g_ControlReport = NULL;
  2212. // There isn't a current PC, let it be discovered.
  2213. g_TargetEventPc = 0;
  2214. // Warn if the kernel debugging code isn't available
  2215. // as that often causes problems.
  2216. if (g_NtDllCalls.NtQuerySystemInformation)
  2217. {
  2218. SYSTEM_KERNEL_DEBUGGER_INFORMATION KdInfo;
  2219. if (!NT_SUCCESS(g_NtDllCalls.NtQuerySystemInformation
  2220. (SystemKernelDebuggerInformation,
  2221. &KdInfo, sizeof(KdInfo), NULL)) ||
  2222. !KdInfo.KernelDebuggerEnabled)
  2223. {
  2224. WarnOut("*****************************************"
  2225. "**************************************\n");
  2226. WarnOut("WARNING: Local kernel debugging requires "
  2227. "booting with /debug to work optimally.\n");
  2228. WarnOut("*****************************************"
  2229. "**************************************\n");
  2230. }
  2231. }
  2232. OutputVersion();
  2233. NotifyDebuggeeActivation();
  2234. *EventStatus = DEBUG_STATUS_BREAK;
  2235. return S_OK;
  2236. }
  2237. //----------------------------------------------------------------------------
  2238. //
  2239. // ExdiLiveKernelTargetInfo wait methods.
  2240. //
  2241. //----------------------------------------------------------------------------
  2242. HRESULT
  2243. ExdiLiveKernelTargetInfo::WaitInitialize(ULONG Flags,
  2244. ULONG Timeout,
  2245. WAIT_INIT_TYPE Type,
  2246. PULONG DesiredTimeout)
  2247. {
  2248. *DesiredTimeout = Timeout;
  2249. m_EventPossible = TRUE;
  2250. return S_OK;
  2251. }
  2252. HRESULT
  2253. ExdiLiveKernelTargetInfo::ReleaseLastEvent(ULONG ContinueStatus)
  2254. {
  2255. HRESULT Status;
  2256. if (!g_EventProcessSysId)
  2257. {
  2258. // No event to release.
  2259. return S_OK;
  2260. }
  2261. //
  2262. // eXDI deals with hardware exceptions, not software
  2263. // exceptions, so there's no concept of handled/not-handled
  2264. // and first/second-chance.
  2265. //
  2266. if (g_EngDefer & ENG_DEFER_HARDWARE_TRACING)
  2267. {
  2268. // Processor trace flag was set. eXDI can change
  2269. // the trace flag itself, though, so use the
  2270. // official eXDI stepping methods rather than
  2271. // rely on the trace flag. This will result
  2272. // in a single instruction execution, after
  2273. // which the trace flag will be clear so
  2274. // go ahead and clear the defer flag.
  2275. Status = m_Server->DoSingleStep();
  2276. if (Status == S_OK)
  2277. {
  2278. g_EngDefer &= ~ENG_DEFER_HARDWARE_TRACING;
  2279. }
  2280. }
  2281. else
  2282. {
  2283. Status = m_Server->Run();
  2284. }
  2285. if (Status != S_OK)
  2286. {
  2287. ErrOut("IeXdiServer::Run failed, 0x%X\n", Status);
  2288. }
  2289. return Status;
  2290. }
  2291. HRESULT
  2292. ExdiLiveKernelTargetInfo::WaitForEvent(ULONG Flags, ULONG Timeout,
  2293. ULONG ElapsedTime, PULONG EventStatus)
  2294. {
  2295. HRESULT Status;
  2296. DWORD Cookie;
  2297. if ((Status = m_Server->
  2298. StartNotifyingRunChg(&m_RunChange, &Cookie)) != S_OK)
  2299. {
  2300. ErrOut("IeXdiServer::StartNotifyingRunChg failed, 0x%X\n", Status);
  2301. return Status;
  2302. }
  2303. RUN_STATUS_TYPE RunStatus;
  2304. if ((Status = m_Server->
  2305. GetRunStatus(&RunStatus, &m_RunChange.m_HaltReason,
  2306. &m_RunChange.m_ExecAddress,
  2307. &m_RunChange.m_ExceptionCode)) != S_OK)
  2308. {
  2309. m_Server->StopNotifyingRunChg(Cookie);
  2310. ErrOut("IeXdiServer::GetRunStatus failed, 0x%X\n", Status);
  2311. return Status;
  2312. }
  2313. DWORD WaitStatus;
  2314. if (RunStatus == rsRunning)
  2315. {
  2316. SUSPEND_ENGINE();
  2317. // We need to run a message pump so COM
  2318. // can deliver calls properly.
  2319. for (;;)
  2320. {
  2321. if (g_EngStatus & ENG_STATUS_EXIT_CURRENT_WAIT)
  2322. {
  2323. WaitStatus = WAIT_FAILED;
  2324. SetLastError(ERROR_IO_PENDING);
  2325. break;
  2326. }
  2327. WaitStatus = MsgWaitForMultipleObjects(1, &m_RunChange.m_Event,
  2328. FALSE, Timeout,
  2329. QS_ALLEVENTS);
  2330. if (WaitStatus == WAIT_OBJECT_0 + 1)
  2331. {
  2332. MSG Msg;
  2333. if (GetMessage(&Msg, NULL, 0, 0))
  2334. {
  2335. TranslateMessage(&Msg);
  2336. DispatchMessage(&Msg);
  2337. }
  2338. }
  2339. else
  2340. {
  2341. // We either successfully waited, timed-out or failed.
  2342. // Break out to handle it.
  2343. break;
  2344. }
  2345. }
  2346. RESUME_ENGINE();
  2347. }
  2348. else
  2349. {
  2350. WaitStatus = WAIT_OBJECT_0;
  2351. }
  2352. m_Server->StopNotifyingRunChg(Cookie);
  2353. // Make sure we're not leaving the event set.
  2354. ResetEvent(m_RunChange.m_Event);
  2355. if (WaitStatus == WAIT_TIMEOUT)
  2356. {
  2357. return S_FALSE;
  2358. }
  2359. else if (WaitStatus != WAIT_OBJECT_0)
  2360. {
  2361. Status = WIN32_LAST_STATUS();
  2362. ErrOut("WaitForSingleObject failed, 0x%X\n", Status);
  2363. return Status;
  2364. }
  2365. EventOut(">>> RunChange halt reason %d\n",
  2366. m_RunChange.m_HaltReason);
  2367. if (!IS_MACHINE_SET(this))
  2368. {
  2369. dprintf("Kernel Debugger connection established\n");
  2370. g_EventTarget = this;
  2371. //
  2372. // Try to figure out the processor configuration
  2373. // via the defined Ioctl.
  2374. //
  2375. // Default to one.
  2376. m_NumProcessors = 1;
  2377. if (DBGENG_EXDI_IOC_IDENTIFY_PROCESSORS > m_IoctlMin &&
  2378. DBGENG_EXDI_IOC_IDENTIFY_PROCESSORS < m_IoctlMax)
  2379. {
  2380. DBGENG_EXDI_IOCTL_BASE_IN IoctlIn;
  2381. DBGENG_EXDI_IOCTL_IDENTIFY_PROCESSORS_OUT IoctlOut;
  2382. ULONG OutUsed;
  2383. IoctlIn.Code = DBGENG_EXDI_IOC_IDENTIFY_PROCESSORS;
  2384. if (m_Server->
  2385. Ioctl(sizeof(IoctlIn), (PBYTE)&IoctlIn,
  2386. sizeof(IoctlOut), &OutUsed, (PBYTE)&IoctlOut) == S_OK)
  2387. {
  2388. m_NumProcessors = IoctlOut.NumberProcessors;
  2389. }
  2390. }
  2391. // eXDI kernels are always treated as Win2K so
  2392. // it's assumed it uses the 64-bit API.
  2393. if (m_KdSupport == EXDI_KD_NONE)
  2394. {
  2395. m_KdApi64 = TRUE;
  2396. m_SystemVersion = NT_SVER_W2K;
  2397. }
  2398. if ((Status = InitFromKdVersion()) != S_OK)
  2399. {
  2400. DeleteSystemInfo();
  2401. ResetSystemInfo();
  2402. g_EventTarget = NULL;
  2403. return Status;
  2404. }
  2405. CreateVirtualProcess(m_NumProcessors);
  2406. g_EventProcessSysId = m_ProcessHead->m_SystemId;
  2407. g_EventThreadSysId = VIRTUAL_THREAD_ID(GetCurrentProcessor());
  2408. FindEventProcessThread();
  2409. //
  2410. // Load kernel symbols.
  2411. //
  2412. if (m_ActualSystemVersion > NT_SVER_START &&
  2413. m_ActualSystemVersion < NT_SVER_END)
  2414. {
  2415. QueryKernelInfo(g_EventThread, TRUE);
  2416. }
  2417. else
  2418. {
  2419. // Initialize some debugger data fields from known
  2420. // information as there isn't a real data block.
  2421. m_KdDebuggerData.MmPageSize =
  2422. m_Machine->m_PageSize;
  2423. if (m_MachineType == IMAGE_FILE_MACHINE_AMD64)
  2424. {
  2425. // AMD64 always operates in PAE mode.
  2426. m_KdDebuggerData.PaeEnabled = TRUE;
  2427. }
  2428. }
  2429. // Now that we have the data block
  2430. // we can retrieve processor information.
  2431. InitializeForProcessor();
  2432. OutputVersion();
  2433. NotifyDebuggeeActivation();
  2434. }
  2435. else
  2436. {
  2437. g_EventTarget = this;
  2438. g_EventProcessSysId = m_ProcessHead->m_SystemId;
  2439. g_EventThreadSysId = VIRTUAL_THREAD_ID(GetCurrentProcessor());
  2440. FindEventProcessThread();
  2441. }
  2442. g_TargetEventPc = m_RunChange.m_ExecAddress;
  2443. g_ControlReport = NULL;
  2444. g_StateChangeData = NULL;
  2445. g_EngStatus |= ENG_STATUS_STATE_CHANGED;
  2446. *EventStatus = ProcessRunChange(m_RunChange.m_HaltReason,
  2447. m_RunChange.m_ExceptionCode);
  2448. return S_OK;
  2449. }
  2450. ULONG
  2451. ExdiLiveKernelTargetInfo::ProcessRunChange(ULONG HaltReason,
  2452. ULONG ExceptionCode)
  2453. {
  2454. ULONG EventStatus;
  2455. EXCEPTION_RECORD64 Record;
  2456. DBGENG_EXDI_IOCTL_BASE_IN IoctlBaseIn;
  2457. ULONG OutUsed;
  2458. // Assume no breakpoint information.
  2459. m_BpHit.Type = DBGENG_EXDI_IOCTL_BREAKPOINT_NONE;
  2460. switch(HaltReason)
  2461. {
  2462. case hrUser:
  2463. case hrUnknown:
  2464. // User requested break in.
  2465. // Unknown breakin also seems to be the status at power-up.
  2466. EventStatus = DEBUG_STATUS_BREAK;
  2467. break;
  2468. case hrException:
  2469. // Fake an exception record.
  2470. ZeroMemory(&Record, sizeof(Record));
  2471. // The exceptions reported are hardware exceptions so
  2472. // there's no easy mapping to NT exception codes.
  2473. // Just report them as access violations.
  2474. Record.ExceptionCode = STATUS_ACCESS_VIOLATION;
  2475. Record.ExceptionAddress = g_TargetEventPc;
  2476. // Hardware exceptions are always severe so always
  2477. // report them as second-chance.
  2478. EventStatus = NotifyExceptionEvent(&Record, FALSE, FALSE);
  2479. break;
  2480. case hrBp:
  2481. //
  2482. // Try and get which breakpoint it was.
  2483. //
  2484. if (DBGENG_EXDI_IOC_GET_BREAKPOINT_HIT > m_IoctlMin &&
  2485. DBGENG_EXDI_IOC_GET_BREAKPOINT_HIT < m_IoctlMax)
  2486. {
  2487. DBGENG_EXDI_IOCTL_GET_BREAKPOINT_HIT_OUT IoctlOut;
  2488. IoctlBaseIn.Code = DBGENG_EXDI_IOC_GET_BREAKPOINT_HIT;
  2489. if (m_Server->
  2490. Ioctl(sizeof(IoctlBaseIn), (PBYTE)&IoctlBaseIn,
  2491. sizeof(IoctlOut), &OutUsed, (PBYTE)&IoctlOut) != S_OK)
  2492. {
  2493. m_BpHit.Type = DBGENG_EXDI_IOCTL_BREAKPOINT_NONE;
  2494. }
  2495. }
  2496. // Fake a breakpoint exception record.
  2497. ZeroMemory(&Record, sizeof(Record));
  2498. Record.ExceptionCode = STATUS_BREAKPOINT;
  2499. Record.ExceptionAddress = g_TargetEventPc;
  2500. EventStatus = ProcessBreakpointOrStepException(&Record, TRUE);
  2501. break;
  2502. case hrStep:
  2503. // Fake a single-step exception record.
  2504. ZeroMemory(&Record, sizeof(Record));
  2505. Record.ExceptionCode = STATUS_SINGLE_STEP;
  2506. Record.ExceptionAddress = g_TargetEventPc;
  2507. EventStatus = ProcessBreakpointOrStepException(&Record, TRUE);
  2508. break;
  2509. default:
  2510. ErrOut("Unknown HALT_REASON %d\n", HaltReason);
  2511. EventStatus = DEBUG_STATUS_BREAK;
  2512. break;
  2513. }
  2514. return EventStatus;
  2515. }
  2516. //----------------------------------------------------------------------------
  2517. //
  2518. // UserTargetInfo wait methods.
  2519. //
  2520. //----------------------------------------------------------------------------
  2521. void
  2522. SynthesizeWakeEvent(LPDEBUG_EVENT64 Event,
  2523. ULONG ProcessId, ULONG ThreadId)
  2524. {
  2525. // Fake up an event.
  2526. ZeroMemory(Event, sizeof(*Event));
  2527. Event->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
  2528. Event->dwProcessId = ProcessId;
  2529. Event->dwThreadId = ThreadId;
  2530. Event->u.Exception.ExceptionRecord.ExceptionCode =
  2531. STATUS_WAKE_SYSTEM_DEBUGGER;
  2532. Event->u.Exception.dwFirstChance = TRUE;
  2533. }
  2534. #define THREADS_ALLOC 256
  2535. HRESULT
  2536. CreateNonInvasiveProcessAndThreads(PUSER_DEBUG_SERVICES Services,
  2537. ULONG ProcessId, ULONG Flags, ULONG Options,
  2538. PULONG InitialThreadId)
  2539. {
  2540. ULONG64 Process;
  2541. PUSER_THREAD_INFO Threads, ThreadBuffer;
  2542. ULONG ThreadsAlloc = 0;
  2543. ULONG ThreadCount;
  2544. HRESULT Status;
  2545. ULONG i;
  2546. ULONG ProcInfoFlags = (Flags & ENG_PROC_NO_SUSPEND_RESUME) ?
  2547. DBGSVC_PROC_INFO_NO_SUSPEND : 0;
  2548. //
  2549. // Retrieve process and thread information. This
  2550. // requires a thread buffer of unknown size and
  2551. // so involves a bit of trial and error.
  2552. //
  2553. for (;;)
  2554. {
  2555. ThreadsAlloc += THREADS_ALLOC;
  2556. ThreadBuffer = new USER_THREAD_INFO[ThreadsAlloc];
  2557. if (ThreadBuffer == NULL)
  2558. {
  2559. return E_OUTOFMEMORY;
  2560. }
  2561. if ((Status = Services->GetProcessInfo(ProcessId, ProcInfoFlags,
  2562. &Process, ThreadBuffer,
  2563. ThreadsAlloc,
  2564. &ThreadCount)) != S_OK &&
  2565. Status != S_FALSE)
  2566. {
  2567. delete [] ThreadBuffer;
  2568. return Status;
  2569. }
  2570. if (ThreadCount <= ThreadsAlloc)
  2571. {
  2572. break;
  2573. }
  2574. // The threads retrieved were suspended so resume them
  2575. // and close handles.
  2576. for (i = 0; i < ThreadsAlloc; i++)
  2577. {
  2578. if (!(Flags & ENG_PROC_NO_SUSPEND_RESUME))
  2579. {
  2580. Services->ResumeThreads(1, &ThreadBuffer[i].Handle, NULL);
  2581. }
  2582. Services->CloseHandle(ThreadBuffer[i].Handle);
  2583. }
  2584. delete [] ThreadBuffer;
  2585. // Set the allocation request size to what the
  2586. // reported count of threads was. The count may
  2587. // change between now and the next call so let
  2588. // the normal allocation extension get added in
  2589. // also to provide extra space for new threads.
  2590. ThreadsAlloc = ThreadCount;
  2591. }
  2592. //
  2593. // Create the process and thread structures from
  2594. // the retrieved data.
  2595. //
  2596. Threads = ThreadBuffer;
  2597. g_EngNotify++;
  2598. // Create the fake kernel process and initial thread.
  2599. g_EventProcessSysId = ProcessId;
  2600. g_EventThreadSysId = Threads->Id;
  2601. *InitialThreadId = Threads->Id;
  2602. NotifyCreateProcessEvent(0, GloballyUniqueProcessHandle(g_EventTarget,
  2603. Process),
  2604. Process, 0, 0, NULL, NULL, 0, 0,
  2605. Threads->Handle, 0, 0,
  2606. Flags | ENG_PROC_THREAD_CLOSE_HANDLE,
  2607. Options, ENG_PROC_THREAD_CLOSE_HANDLE,
  2608. FALSE, 0, FALSE);
  2609. // Create any remaining threads.
  2610. while (--ThreadCount > 0)
  2611. {
  2612. Threads++;
  2613. g_EventThreadSysId = Threads->Id;
  2614. NotifyCreateThreadEvent(Threads->Handle, 0, 0,
  2615. ENG_PROC_THREAD_CLOSE_HANDLE);
  2616. }
  2617. g_EngNotify--;
  2618. delete [] ThreadBuffer;
  2619. // Don't leave event variables set as these
  2620. // weren't true events.
  2621. g_EventProcessSysId = 0;
  2622. g_EventThreadSysId = 0;
  2623. g_EventProcess = NULL;
  2624. g_EventThread = NULL;
  2625. return S_OK;
  2626. }
  2627. HRESULT
  2628. ExamineActiveProcess(PUSER_DEBUG_SERVICES Services,
  2629. ULONG ProcessId, ULONG Flags, ULONG Options,
  2630. LPDEBUG_EVENT64 Event)
  2631. {
  2632. HRESULT Status;
  2633. ULONG InitialThreadId;
  2634. if ((Status = CreateNonInvasiveProcessAndThreads
  2635. (Services, ProcessId, Flags, Options, &InitialThreadId)) != S_OK)
  2636. {
  2637. ErrOut("Unable to examine process id %d, %s\n",
  2638. ProcessId, FormatStatusCode(Status));
  2639. return Status;
  2640. }
  2641. if (Flags & ENG_PROC_EXAMINED)
  2642. {
  2643. WarnOut("WARNING: Process %d is not attached as a debuggee\n",
  2644. ProcessId);
  2645. WarnOut(" The process can be examined but debug "
  2646. "events will not be received\n");
  2647. }
  2648. SynthesizeWakeEvent(Event, ProcessId, InitialThreadId);
  2649. return S_OK;
  2650. }
  2651. // When waiting for an attach we check process status relatively
  2652. // frequently. The overall timeout limit is also hard-coded
  2653. // as we expect some sort of debug event to always be delivered
  2654. // quickly.
  2655. #define ATTACH_PENDING_TIMEOUT 100
  2656. #define ATTACH_PENDING_TIMEOUT_LIMIT 60000
  2657. // When not waiting for an attach the wait only waits one second,
  2658. // then checks to see if things have changed in a way that
  2659. // affects the wait. All timeouts are given in multiples of
  2660. // this interval.
  2661. #define DEFAULT_WAIT_TIMEOUT 1000
  2662. // A message is printed after this timeout interval to
  2663. // let the user know a break-in is pending.
  2664. #define PENDING_BREAK_IN_MESSAGE_TIMEOUT_LIMIT 3000
  2665. HRESULT
  2666. LiveUserTargetInfo::WaitInitialize(ULONG Flags,
  2667. ULONG Timeout,
  2668. WAIT_INIT_TYPE Type,
  2669. PULONG DesiredTimeout)
  2670. {
  2671. ULONG AllPend = m_AllPendingFlags;
  2672. if (AllPend & ENG_PROC_ANY_ATTACH)
  2673. {
  2674. if (Type == WINIT_FIRST)
  2675. {
  2676. dprintf("*** wait with pending attach\n");
  2677. }
  2678. // While waiting for an attach we need to periodically
  2679. // check and see if the process has exited so we
  2680. // need to force a reasonably small timeout.
  2681. *DesiredTimeout = ATTACH_PENDING_TIMEOUT;
  2682. // Check and see if any of our pending processes
  2683. // has died unexpectedly.
  2684. VerifyPendingProcesses();
  2685. }
  2686. else
  2687. {
  2688. // We might be waiting on a break-in. Keep timeouts moderate
  2689. // to deal with apps hung with a lock that prevents
  2690. // the break from happening. The timeout is
  2691. // still long enough so that no substantial amount
  2692. // of CPU time is consumed.
  2693. *DesiredTimeout = DEFAULT_WAIT_TIMEOUT;
  2694. }
  2695. m_DataBpAddrValid = FALSE;
  2696. if (Type != WINIT_NOT_FIRST)
  2697. {
  2698. m_BreakInMessage = FALSE;
  2699. }
  2700. m_EventPossible = m_ProcessHead || m_ProcessPending;
  2701. return S_OK;
  2702. }
  2703. HRESULT
  2704. LiveUserTargetInfo::ReleaseLastEvent(ULONG ContinueStatus)
  2705. {
  2706. HRESULT Status;
  2707. if (!g_EventTarget || !m_DeferContinueEvent)
  2708. {
  2709. return S_OK;
  2710. }
  2711. for (;;)
  2712. {
  2713. if ((Status = m_Services->
  2714. ContinueEvent(ContinueStatus)) == S_OK)
  2715. {
  2716. break;
  2717. }
  2718. //
  2719. // If we got an out of memory error, wait again
  2720. //
  2721. if (Status != E_OUTOFMEMORY)
  2722. {
  2723. ErrOut("IUserDebugServices::ContinueEvent failed "
  2724. "with status 0x%X\n", Status);
  2725. return Status;
  2726. }
  2727. }
  2728. m_DeferContinueEvent = FALSE;
  2729. return S_OK;
  2730. }
  2731. HRESULT
  2732. LiveUserTargetInfo::WaitForEvent(ULONG Flags, ULONG Timeout,
  2733. ULONG ElapsedTime, PULONG EventStatus)
  2734. {
  2735. DEBUG_EVENT64 Event;
  2736. HRESULT Status;
  2737. ULONG EventUsed;
  2738. BOOL ContinueDefer;
  2739. BOOL BreakInTimeout;
  2740. PPENDING_PROCESS Pending;
  2741. ULONG PendingFlags = 0;
  2742. ULONG PendingOptions = DEBUG_PROCESS_ONLY_THIS_PROCESS;
  2743. ULONG ResumeProcId = 0;
  2744. ULONG AllPend;
  2745. BOOL InitSystem = FALSE;
  2746. //
  2747. // Check for partially initialized systems
  2748. // and query for all the system information that is needed.
  2749. // This needs to be done before the actual wait
  2750. // or examine so that the information is available
  2751. // for constructing processes and threads.
  2752. //
  2753. if (!m_MachinesInitialized)
  2754. {
  2755. if ((Status = InitFromServices()) != S_OK)
  2756. {
  2757. return Status;
  2758. }
  2759. InitSystem = TRUE;
  2760. }
  2761. AllPend = m_AllPendingFlags;
  2762. //
  2763. // There are two cases we want to handle timeouts for:
  2764. // 1. Timeout for a basic attach.
  2765. // 2. Timeout for a pending breakin.
  2766. // If neither of these things can happen we don't
  2767. // need to track delay time. Once one of those two
  2768. // things can happen we need to track delay time from
  2769. // the first time they became possible.
  2770. //
  2771. if ((AllPend & ENG_PROC_ANY_ATTACH) ||
  2772. (g_EngStatus & ENG_STATUS_PENDING_BREAK_IN))
  2773. {
  2774. if (m_WaitTimeBase == 0)
  2775. {
  2776. // Add one to avoid the case of ElapsedTime == 0
  2777. // causing a reinit the next time around.
  2778. m_WaitTimeBase = ElapsedTime + 1;
  2779. ElapsedTime = 0;
  2780. }
  2781. else
  2782. {
  2783. // Adjust for + 1 in time base above.
  2784. ElapsedTime++;
  2785. }
  2786. EventOut(">>> User elapsed time %d\n", ElapsedTime);
  2787. }
  2788. if ((AllPend & ENG_PROC_ANY_ATTACH) &&
  2789. ElapsedTime >= ATTACH_PENDING_TIMEOUT_LIMIT)
  2790. {
  2791. // Assume that the process has some kind
  2792. // of lock that's preventing the attach
  2793. // from succeeding and just do a soft attach.
  2794. AddExamineToPendingAttach();
  2795. }
  2796. // Refresh result of pending flags as they may have
  2797. // changed above due to AddAllExamineToPendingAttach.
  2798. if (m_AllPendingFlags & ENG_PROC_ANY_EXAMINE)
  2799. {
  2800. // If we're attaching noninvasively or reattaching
  2801. // and still haven't done the work go ahead and do it now.
  2802. Pending = FindPendingProcessByFlags(ENG_PROC_ANY_EXAMINE);
  2803. if (Pending == NULL)
  2804. {
  2805. DBG_ASSERT(FALSE);
  2806. return E_UNEXPECTED;
  2807. }
  2808. g_EventTarget = this;
  2809. if ((Status = ExamineActiveProcess
  2810. (m_Services, Pending->Id, Pending->Flags,
  2811. Pending->Options, &Event)) != S_OK)
  2812. {
  2813. g_EventTarget = NULL;
  2814. g_EventTarget = NULL;
  2815. return Status;
  2816. }
  2817. // If we just started examining a process we
  2818. // suspended all the threads during enumeration.
  2819. // We need to resume them after the normal
  2820. // SuspendExecution suspend to get the suspend
  2821. // count back to normal.
  2822. ResumeProcId = Pending->Id;
  2823. PendingFlags = Pending->Flags;
  2824. PendingOptions = Pending->Options;
  2825. RemovePendingProcess(Pending);
  2826. EventUsed = sizeof(Event);
  2827. // This event is not a real continuable event.
  2828. ContinueDefer = FALSE;
  2829. BreakInTimeout = FALSE;
  2830. goto WaitDone;
  2831. }
  2832. if (g_EngStatus & ENG_STATUS_PENDING_BREAK_IN)
  2833. {
  2834. if (!m_BreakInMessage &&
  2835. ElapsedTime >= PENDING_BREAK_IN_MESSAGE_TIMEOUT_LIMIT)
  2836. {
  2837. dprintf("Break-in sent, waiting %d seconds...\n",
  2838. g_PendingBreakInTimeoutLimit);
  2839. m_BreakInMessage = TRUE;
  2840. }
  2841. if (ElapsedTime >= g_PendingBreakInTimeoutLimit * 1000)
  2842. {
  2843. // Assume that the process has some kind
  2844. // of lock that's preventing the break-in
  2845. // exception from coming through and
  2846. // just suspend to let the user look at things.
  2847. if (!m_ProcessHead ||
  2848. !m_ProcessHead->m_ThreadHead)
  2849. {
  2850. WarnOut("WARNING: Break-in timed out without "
  2851. "an available thread. Rewaiting.\n");
  2852. m_WaitTimeBase = 0;
  2853. }
  2854. else
  2855. {
  2856. WarnOut("WARNING: Break-in timed out, suspending.\n");
  2857. WarnOut(" This is usually caused by "
  2858. "another thread holding the loader lock\n");
  2859. SynthesizeWakeEvent(&Event,
  2860. m_ProcessHead->m_SystemId,
  2861. m_ProcessHead->m_ThreadHead->
  2862. m_SystemId);
  2863. EventUsed = sizeof(Event);
  2864. ContinueDefer = FALSE;
  2865. BreakInTimeout = TRUE;
  2866. g_EngStatus &= ~ENG_STATUS_PENDING_BREAK_IN;
  2867. Status = S_OK;
  2868. g_EventTarget = this;
  2869. goto WaitDone;
  2870. }
  2871. }
  2872. }
  2873. if (g_EngStatus & ENG_STATUS_EXIT_CURRENT_WAIT)
  2874. {
  2875. return E_PENDING;
  2876. }
  2877. else
  2878. {
  2879. SUSPEND_ENGINE();
  2880. for (;;)
  2881. {
  2882. Status = m_Services->
  2883. WaitForEvent(Timeout, &Event, sizeof(Event), &EventUsed);
  2884. if (Status == E_OUTOFMEMORY)
  2885. {
  2886. // Allow memory pressure to ease and rewait.
  2887. Sleep(50);
  2888. }
  2889. else
  2890. {
  2891. break;
  2892. }
  2893. }
  2894. RESUME_ENGINE();
  2895. if (Status == S_FALSE)
  2896. {
  2897. return Status;
  2898. }
  2899. else if (Status != S_OK)
  2900. {
  2901. ErrOut("IUserDebugServices::WaitForEvent failed "
  2902. "with status 0x%X\n", Status);
  2903. return Status;
  2904. }
  2905. g_EventTarget = this;
  2906. }
  2907. ContinueDefer = TRUE;
  2908. BreakInTimeout = FALSE;
  2909. WaitDone:
  2910. if (EventUsed == sizeof(DEBUG_EVENT32))
  2911. {
  2912. DEBUG_EVENT32 Event32 = *(DEBUG_EVENT32*)&Event;
  2913. DebugEvent32To64(&Event32, &Event);
  2914. }
  2915. else if (EventUsed != sizeof(DEBUG_EVENT64))
  2916. {
  2917. ErrOut("Event data corrupt\n");
  2918. return E_FAIL;
  2919. }
  2920. g_Target = g_EventTarget;
  2921. m_DeferContinueEvent = ContinueDefer;
  2922. m_BreakInTimeout = BreakInTimeout;
  2923. EventOut(">>> Debug event %u for %X.%X\n",
  2924. Event.dwDebugEventCode, Event.dwProcessId,
  2925. Event.dwThreadId);
  2926. g_EventProcessSysId = Event.dwProcessId;
  2927. g_EventThreadSysId = Event.dwThreadId;
  2928. // Look up the process and thread infos in the cases
  2929. // where they already exist.
  2930. if (Event.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT &&
  2931. Event.dwDebugEventCode != CREATE_THREAD_DEBUG_EVENT)
  2932. {
  2933. FindEventProcessThread();
  2934. }
  2935. if (Event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
  2936. {
  2937. // If we're being notified of a new process take
  2938. // out the pending record for the process.
  2939. Pending = FindPendingProcessById(g_EventProcessSysId);
  2940. if (Pending == NULL &&
  2941. (m_AllPendingFlags & ENG_PROC_SYSTEM))
  2942. {
  2943. // Assume that this is the system process
  2944. // as we attached under a fake process ID so
  2945. // we can't check for a true match.
  2946. Pending = FindPendingProcessById(CSRSS_PROCESS_ID);
  2947. }
  2948. if (Pending != NULL)
  2949. {
  2950. PendingFlags = Pending->Flags;
  2951. PendingOptions = Pending->Options;
  2952. if (Pending->Flags & ENG_PROC_ATTACHED)
  2953. {
  2954. VerbOut("*** attach succeeded\n");
  2955. // If we're completing a full attach
  2956. // we are now a fully active debugger.
  2957. PendingFlags &= ~ENG_PROC_EXAMINED;
  2958. // Expect a break-in if a break thread
  2959. // was injected.
  2960. if (!(PendingFlags & ENG_PROC_NO_INITIAL_BREAK))
  2961. {
  2962. g_EngStatus |= ENG_STATUS_PENDING_BREAK_IN;
  2963. }
  2964. // If the process should be resumed
  2965. // mark that and it will happen just
  2966. // before leaving this routine.
  2967. if (PendingFlags & ENG_PROC_RESUME_AT_ATTACH)
  2968. {
  2969. ResumeProcId = Pending->Id;
  2970. }
  2971. }
  2972. RemovePendingProcess(Pending);
  2973. }
  2974. }
  2975. if (PendingFlags & ENG_PROC_ANY_EXAMINE)
  2976. {
  2977. PCSTR ArgsRet;
  2978. // We're examining the process rather than
  2979. // debugging it, so no module load events
  2980. // are going to come through. Reload from
  2981. // the system module list. This needs
  2982. // to work even if there isn't a path.
  2983. Reload(g_EventThread, "-s -P", &ArgsRet);
  2984. }
  2985. if (InitSystem)
  2986. {
  2987. NotifyDebuggeeActivation();
  2988. }
  2989. if ((Event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT ||
  2990. Event.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT) &&
  2991. (m_ServiceFlags & DBGSVC_CLOSE_PROC_THREAD_HANDLES))
  2992. {
  2993. PendingFlags |= ENG_PROC_THREAD_CLOSE_HANDLE;
  2994. }
  2995. g_EngStatus |= ENG_STATUS_STATE_CHANGED;
  2996. *EventStatus = ProcessDebugEvent(&Event, PendingFlags, PendingOptions);
  2997. // If we have an extra suspend count resume it out now
  2998. // that any normal suspends have been done and it's safe
  2999. // to remove the excess suspend.
  3000. if (ResumeProcId)
  3001. {
  3002. ProcessInfo* ExamProc =
  3003. FindProcessBySystemId(ResumeProcId);
  3004. // If we did a no-suspend examine we don't have the
  3005. // extra count, so suspend first and then resume to
  3006. // get accurate suspend counts for the threads.
  3007. // Be careful not to do this in the self-attach case
  3008. // as the suspend will hang things.
  3009. if (PendingFlags & ENG_PROC_NO_SUSPEND_RESUME)
  3010. {
  3011. if (ResumeProcId != GetCurrentProcessId())
  3012. {
  3013. SuspendResumeThreads(ExamProc, TRUE, NULL);
  3014. SuspendResumeThreads(ExamProc, FALSE, NULL);
  3015. }
  3016. }
  3017. else
  3018. {
  3019. SuspendResumeThreads(ExamProc, FALSE, NULL);
  3020. }
  3021. }
  3022. return S_OK;
  3023. }
  3024. ULONG
  3025. LiveUserTargetInfo::ProcessDebugEvent(DEBUG_EVENT64* Event,
  3026. ULONG PendingFlags,
  3027. ULONG PendingOptions)
  3028. {
  3029. ULONG EventStatus;
  3030. CHAR NameBuffer[MAX_IMAGE_PATH];
  3031. ULONG ModuleSize, CheckSum, TimeDateStamp;
  3032. char ModuleName[MAX_MODULE];
  3033. switch(Event->dwDebugEventCode)
  3034. {
  3035. case CREATE_PROCESS_DEBUG_EVENT:
  3036. LoadWow64ExtsIfNeeded(Event->u.CreateProcessInfo.hProcess);
  3037. EventStatus = NotifyCreateProcessEvent(
  3038. (ULONG64)Event->u.CreateProcessInfo.hFile,
  3039. GloballyUniqueProcessHandle(g_EventTarget,
  3040. (ULONG64)
  3041. Event->u.CreateProcessInfo.hProcess),
  3042. (ULONG64)Event->u.CreateProcessInfo.hProcess,
  3043. (ULONG64)Event->u.CreateProcessInfo.lpBaseOfImage,
  3044. 0, NULL, NULL, 0, 0,
  3045. (ULONG64)Event->u.CreateProcessInfo.hThread,
  3046. (ULONG64)Event->u.CreateProcessInfo.lpThreadLocalBase,
  3047. (ULONG64)Event->u.CreateProcessInfo.lpStartAddress,
  3048. PendingFlags, PendingOptions,
  3049. (PendingFlags & ENG_PROC_THREAD_CLOSE_HANDLE) ?
  3050. ENG_PROC_THREAD_CLOSE_HANDLE : 0,
  3051. TRUE,
  3052. Event->u.CreateProcessInfo.lpImageName,
  3053. Event->u.CreateProcessInfo.fUnicode);
  3054. break;
  3055. case EXIT_PROCESS_DEBUG_EVENT:
  3056. if (g_EventProcess == NULL)
  3057. {
  3058. // Assume that this unmatched exit process event is a leftover
  3059. // from a previous restart and just ignore it.
  3060. WarnOut("Ignoring unknown process exit for %X\n",
  3061. g_EventProcessSysId);
  3062. EventStatus = DEBUG_STATUS_IGNORE_EVENT;
  3063. }
  3064. else
  3065. {
  3066. EventStatus =
  3067. NotifyExitProcessEvent(Event->u.ExitProcess.dwExitCode);
  3068. }
  3069. break;
  3070. case CREATE_THREAD_DEBUG_EVENT:
  3071. EventStatus = NotifyCreateThreadEvent(
  3072. (ULONG64)Event->u.CreateThread.hThread,
  3073. (ULONG64)Event->u.CreateThread.lpThreadLocalBase,
  3074. (ULONG64)Event->u.CreateThread.lpStartAddress,
  3075. PendingFlags);
  3076. break;
  3077. case EXIT_THREAD_DEBUG_EVENT:
  3078. EventStatus = NotifyExitThreadEvent(Event->u.ExitThread.dwExitCode);
  3079. break;
  3080. case LOAD_DLL_DEBUG_EVENT:
  3081. strcpy(NameBuffer, "no_process");
  3082. GetEventName(Event->u.LoadDll.hFile,
  3083. Event->u.LoadDll.lpBaseOfDll,
  3084. Event->u.LoadDll.lpImageName,
  3085. Event->u.LoadDll.fUnicode,
  3086. NameBuffer, sizeof(NameBuffer));
  3087. GetHeaderInfo(g_EventProcess,
  3088. (ULONG64)Event->u.LoadDll.lpBaseOfDll,
  3089. &CheckSum, &TimeDateStamp, &ModuleSize);
  3090. CreateModuleNameFromPath(NameBuffer, ModuleName);
  3091. EventStatus = NotifyLoadModuleEvent(
  3092. (ULONG64)Event->u.LoadDll.hFile,
  3093. (ULONG64)Event->u.LoadDll.lpBaseOfDll,
  3094. ModuleSize, ModuleName, NameBuffer, CheckSum, TimeDateStamp,
  3095. TRUE);
  3096. break;
  3097. case UNLOAD_DLL_DEBUG_EVENT:
  3098. EventStatus = NotifyUnloadModuleEvent(
  3099. NULL, (ULONG64)Event->u.UnloadDll.lpBaseOfDll);
  3100. break;
  3101. case OUTPUT_DEBUG_STRING_EVENT:
  3102. EventStatus = OutputEventDebugString(&Event->u.DebugString);
  3103. break;
  3104. case RIP_EVENT:
  3105. EventStatus = NotifySystemErrorEvent(Event->u.RipInfo.dwError,
  3106. Event->u.RipInfo.dwType);
  3107. break;
  3108. case EXCEPTION_DEBUG_EVENT:
  3109. EventStatus = ProcessEventException(Event);
  3110. break;
  3111. default:
  3112. WarnOut("Unknown event number 0x%08lx\n",
  3113. Event->dwDebugEventCode);
  3114. EventStatus = DEBUG_STATUS_BREAK;
  3115. break;
  3116. }
  3117. return EventStatus;
  3118. }
  3119. #define ISTS() (!!(USER_SHARED_DATA->SuiteMask & (1 << TerminalServer)))
  3120. #define FIRST_CHANCE Event->u.Exception.dwFirstChance
  3121. ULONG
  3122. LiveUserTargetInfo::ProcessEventException(DEBUG_EVENT64* Event)
  3123. {
  3124. ULONG ExceptionCode;
  3125. ULONG EventStatus;
  3126. BOOL OutputDone = FALSE;
  3127. ImageInfo* Image;
  3128. ExceptionCode = Event->u.Exception.ExceptionRecord.ExceptionCode;
  3129. g_TargetEventPc = (ULONG64)
  3130. Event->u.Exception.ExceptionRecord.ExceptionAddress;
  3131. EventOut("Exception %X at %p\n", ExceptionCode, g_TargetEventPc);
  3132. //
  3133. // If we are debugging a crashed process, force the
  3134. // desktop we are on to the front so the user will know
  3135. // what happened.
  3136. //
  3137. if (g_EventToSignal != NULL &&
  3138. !ISTS() &&
  3139. !AnySystemProcesses(FALSE))
  3140. {
  3141. if (InitDynamicCalls(&g_User32CallsDesc) == S_OK &&
  3142. g_User32Calls.SwitchDesktop != NULL &&
  3143. g_User32Calls.GetThreadDesktop != NULL &&
  3144. g_User32Calls.CloseDesktop != NULL)
  3145. {
  3146. HDESK hDesk;
  3147. hDesk = g_User32Calls.GetThreadDesktop(::GetCurrentThreadId());
  3148. g_User32Calls.SwitchDesktop(hDesk);
  3149. g_User32Calls.CloseDesktop(hDesk);
  3150. }
  3151. }
  3152. if (g_EventThread && ExceptionCode == STATUS_VDM_EVENT)
  3153. {
  3154. ULONG ulRet = VDMEvent(Event);
  3155. switch(ulRet)
  3156. {
  3157. case VDMEVENT_NOT_HANDLED:
  3158. EventStatus = DEBUG_STATUS_GO_NOT_HANDLED;
  3159. break;
  3160. case VDMEVENT_HANDLED:
  3161. EventStatus = DEBUG_STATUS_GO_HANDLED;
  3162. break;
  3163. default:
  3164. // Give vdm code the option of mutating this into
  3165. // a standard exception (like STATUS_BREAKPOINT)
  3166. ExceptionCode = ulRet;
  3167. break;
  3168. }
  3169. }
  3170. switch(ExceptionCode)
  3171. {
  3172. case STATUS_BREAKPOINT:
  3173. case STATUS_SINGLE_STEP:
  3174. case STATUS_WX86_BREAKPOINT:
  3175. case STATUS_WX86_SINGLE_STEP:
  3176. if (!g_EventThread)
  3177. {
  3178. goto NotifyException;
  3179. }
  3180. EventStatus = ProcessBreakpointOrStepException
  3181. (&Event->u.Exception.ExceptionRecord, FIRST_CHANCE);
  3182. break;
  3183. case STATUS_VDM_EVENT:
  3184. if (!g_EventThread)
  3185. {
  3186. goto NotifyException;
  3187. }
  3188. // do nothing, it's already handled
  3189. EventStatus = DEBUG_STATUS_IGNORE_EVENT;
  3190. break;
  3191. case STATUS_ACCESS_VIOLATION:
  3192. if (FIRST_CHANCE &&
  3193. g_EventProcess &&
  3194. (Image = g_EventProcess->
  3195. FindImageByOffset(Event->u.Exception.
  3196. ExceptionRecord.ExceptionAddress, FALSE)) &&
  3197. !_stricmp(Image->m_ModuleName, "ntdll"))
  3198. {
  3199. CHAR ExSym[MAX_SYMBOL_LEN];
  3200. LPSTR Scan;
  3201. ULONG64 ExDisp;
  3202. //
  3203. // Ignore AVs that are expected in system code.
  3204. //
  3205. GetSymbol(Event->u.Exception.ExceptionRecord.ExceptionAddress,
  3206. ExSym, sizeof(ExSym), &ExDisp);
  3207. Scan = ExSym;
  3208. if (!_strnicmp(Scan, "ntdll!", 6))
  3209. {
  3210. Scan += 6;
  3211. if (*Scan == '_')
  3212. {
  3213. Scan += 1;
  3214. }
  3215. // This option allows new 3.51 binaries to run under
  3216. // this debugger on old 3.1, 3.5 systems and avoid stopping
  3217. // at access violations inside LDR that will be handled
  3218. // by the LDR anyway.
  3219. if ((g_EngOptions & DEBUG_ENGOPT_IGNORE_LOADER_EXCEPTIONS) &&
  3220. (!_stricmp(Scan, "LdrpSnapThunk") ||
  3221. !_stricmp(Scan, "LdrpWalkImportDescriptor")))
  3222. {
  3223. EventStatus = DEBUG_STATUS_GO_NOT_HANDLED;
  3224. break;
  3225. }
  3226. // The interlocked SList code has a by-design faulting
  3227. // case, so ignore AVs at that particular symbol.
  3228. if ((ExDisp == 0 &&
  3229. !_stricmp(Scan, "ExpInterlockedPopEntrySListFault")) ||
  3230. (m_ActualSystemVersion == NT_SVER_W2K &&
  3231. !_stricmp(Scan, "RtlpInterlockedPopEntrySList")))
  3232. {
  3233. EventStatus = DEBUG_STATUS_GO_NOT_HANDLED;
  3234. break;
  3235. }
  3236. }
  3237. }
  3238. goto NotifyException;
  3239. case STATUS_POSSIBLE_DEADLOCK:
  3240. if (m_PlatformId == VER_PLATFORM_WIN32_NT)
  3241. {
  3242. DBG_ASSERT(IS_USER_TARGET(g_EventTarget));
  3243. AnalyzeDeadlock(&Event->u.Exception.ExceptionRecord,
  3244. FIRST_CHANCE);
  3245. }
  3246. else
  3247. {
  3248. OutputDeadlock(&Event->u.Exception.ExceptionRecord,
  3249. FIRST_CHANCE);
  3250. }
  3251. OutputDone = TRUE;
  3252. goto NotifyException;
  3253. default:
  3254. {
  3255. NotifyException:
  3256. EventStatus =
  3257. NotifyExceptionEvent(&Event->u.Exception.ExceptionRecord,
  3258. Event->u.Exception.dwFirstChance,
  3259. OutputDone);
  3260. }
  3261. break;
  3262. }
  3263. //
  3264. // Do this for all exceptions, just in case some other
  3265. // thread caused an exception before we get around to
  3266. // handling the breakpoint event.
  3267. //
  3268. g_EngDefer |= ENG_DEFER_SET_EVENT;
  3269. return EventStatus;
  3270. }
  3271. #undef FIRST_CHANCE
  3272. #define INPUT_API_SIG 0xdefaced
  3273. typedef struct _hdi
  3274. {
  3275. DWORD dwSignature;
  3276. BYTE cLength;
  3277. BYTE cStatus;
  3278. } HDI;
  3279. ULONG
  3280. LiveUserTargetInfo::OutputEventDebugString(OUTPUT_DEBUG_STRING_INFO64* Info)
  3281. {
  3282. LPSTR Str, Str2;
  3283. ULONG dwNumberOfBytesRead;
  3284. HDI hdi;
  3285. ULONG EventStatus = DEBUG_STATUS_IGNORE_EVENT;
  3286. if (Info->nDebugStringLength == 0)
  3287. {
  3288. return EventStatus;
  3289. }
  3290. Str = (PSTR)calloc(1, Info->nDebugStringLength);
  3291. if (Str == NULL)
  3292. {
  3293. ErrOut("Unable to allocate debug output buffer\n");
  3294. return EventStatus;
  3295. }
  3296. if (ReadVirtual(g_EventProcess,
  3297. Info->lpDebugStringData, Str,
  3298. Info->nDebugStringLength,
  3299. &dwNumberOfBytesRead) == S_OK &&
  3300. (dwNumberOfBytesRead == (SIZE_T)Info->nDebugStringLength))
  3301. {
  3302. //
  3303. // Special processing for hacky debug input string
  3304. //
  3305. if (ReadVirtual(g_EventProcess,
  3306. Info->lpDebugStringData +
  3307. Info->nDebugStringLength,
  3308. &hdi, sizeof(hdi),
  3309. &dwNumberOfBytesRead) == S_OK &&
  3310. dwNumberOfBytesRead == sizeof(hdi) &&
  3311. hdi.dwSignature == INPUT_API_SIG)
  3312. {
  3313. StartOutLine(DEBUG_OUTPUT_DEBUGGEE_PROMPT, OUT_LINE_NO_PREFIX);
  3314. MaskOut(DEBUG_OUTPUT_DEBUGGEE_PROMPT, "%s", Str);
  3315. Str2 = (PSTR)calloc(1, hdi.cLength + 1);
  3316. if (Str2)
  3317. {
  3318. GetInput(NULL, Str2, hdi.cLength, GETIN_DEFAULT);
  3319. WriteVirtual(g_EventProcess,
  3320. Info->lpDebugStringData + 6,
  3321. Str2, (DWORD)hdi.cLength, NULL);
  3322. free(Str2);
  3323. }
  3324. else
  3325. {
  3326. ErrOut("Unable to allocate prompt buffer\n");
  3327. }
  3328. }
  3329. else if (g_OutputCommandRedirectPrefixLen &&
  3330. !_strnicmp(g_OutputCommandRedirectPrefix, Str,
  3331. g_OutputCommandRedirectPrefixLen))
  3332. {
  3333. PSTR Command = Str + g_OutputCommandRedirectPrefixLen;
  3334. _snprintf(g_LastEventDesc, sizeof(g_LastEventDesc) - 1,
  3335. "%.48s command: '%.192s'",
  3336. g_OutputCommandRedirectPrefix, Command);
  3337. EventStatus = ExecuteEventCommand(DEBUG_STATUS_NO_CHANGE, NULL,
  3338. Command);
  3339. // Break in if the command didn't explicitly continue.
  3340. if (EventStatus == DEBUG_STATUS_NO_CHANGE)
  3341. {
  3342. EventStatus = DEBUG_STATUS_BREAK;
  3343. }
  3344. }
  3345. else
  3346. {
  3347. StartOutLine(DEBUG_OUTPUT_DEBUGGEE, OUT_LINE_NO_PREFIX);
  3348. MaskOut(DEBUG_OUTPUT_DEBUGGEE, "%s", Str);
  3349. EVENT_FILTER* Filter =
  3350. &g_EventFilters[DEBUG_FILTER_DEBUGGEE_OUTPUT];
  3351. if (IS_EFEXECUTION_BREAK(Filter->Params.ExecutionOption) &&
  3352. BreakOnThisOutString(Str))
  3353. {
  3354. EventStatus = DEBUG_STATUS_BREAK;
  3355. }
  3356. }
  3357. }
  3358. else
  3359. {
  3360. ErrOut("Unable to read debug output string, %d\n",
  3361. GetLastError());
  3362. }
  3363. free(Str);
  3364. return EventStatus;
  3365. }
  3366. //----------------------------------------------------------------------------
  3367. //
  3368. // DumpTargetInfo wait methods.
  3369. //
  3370. //----------------------------------------------------------------------------
  3371. HRESULT
  3372. KernelDumpTargetInfo::FirstEvent(void)
  3373. {
  3374. HRESULT Status;
  3375. ULONG i;
  3376. CreateVirtualProcess(m_NumProcessors);
  3377. QueryKernelInfo(m_ProcessHead->m_ThreadHead, TRUE);
  3378. OutputVersion();
  3379. if (!IS_KERNEL_TRIAGE_DUMP(this))
  3380. {
  3381. if (m_KdDebuggerData.KiProcessorBlock)
  3382. {
  3383. ULONG PtrSize = m_Machine->m_Ptr64 ?
  3384. sizeof(ULONG64) : sizeof(ULONG);
  3385. for (i = 0; i < m_NumProcessors; i++)
  3386. {
  3387. Status =
  3388. ReadPointer(g_EventProcess, m_Machine,
  3389. m_KdDebuggerData.KiProcessorBlock +
  3390. i * PtrSize, &m_KiProcessors[i]);
  3391. if (Status != S_OK || !m_KiProcessors[i])
  3392. {
  3393. ErrOut("KiProcessorBlock[%d] could not be read\n", i);
  3394. return Status != S_OK ? Status : E_FAIL;
  3395. }
  3396. }
  3397. }
  3398. }
  3399. // Clear the global state change just in case somebody's
  3400. // directly accessing it somewhere.
  3401. ZeroMemory(&g_StateChange, sizeof(g_StateChange));
  3402. g_StateChangeData = g_StateChangeBuffer;
  3403. g_StateChangeBuffer[0] = 0;
  3404. return S_OK;
  3405. }
  3406. HRESULT
  3407. UserDumpTargetInfo::FirstEvent(void)
  3408. {
  3409. ULONG i;
  3410. ULONG Suspend;
  3411. ULONG64 Teb;
  3412. if (GetProductInfo(&m_ProductType, &m_SuiteMask) != S_OK)
  3413. {
  3414. m_ProductType = INVALID_PRODUCT_TYPE;
  3415. m_SuiteMask = 0;
  3416. }
  3417. OutputVersion();
  3418. // Create the process.
  3419. g_EventProcessSysId = m_EventProcessId;
  3420. if (GetThreadInfo(0, &g_EventThreadSysId,
  3421. &Suspend, &Teb) != S_OK)
  3422. {
  3423. // Dump doesn't contain thread information so
  3424. // fake it.
  3425. g_EventThreadSysId = VIRTUAL_THREAD_ID(0);
  3426. Suspend = 0;
  3427. Teb = 0;
  3428. }
  3429. EventOut("User dump process %x.%x with %u threads\n",
  3430. g_EventProcessSysId, g_EventThreadSysId,
  3431. m_ThreadCount);
  3432. NotifyCreateProcessEvent(0,
  3433. m_EventProcessSymHandle,
  3434. (ULONG64)
  3435. VIRTUAL_PROCESS_HANDLE(g_EventProcessSysId),
  3436. 0, 0, NULL, NULL, 0, 0,
  3437. (ULONG64)VIRTUAL_THREAD_HANDLE(0),
  3438. Teb, 0, 0, DEBUG_PROCESS_ONLY_THIS_PROCESS,
  3439. 0, FALSE, 0, FALSE);
  3440. // Update thread suspend count from dump info.
  3441. g_EventThread->m_SuspendCount = Suspend;
  3442. // Create any remaining threads.
  3443. for (i = 1; i < m_ThreadCount; i++)
  3444. {
  3445. GetThreadInfo(i, &g_EventThreadSysId, &Suspend, &Teb);
  3446. EventOut("User dump thread %d: %x\n", i, g_EventThreadSysId);
  3447. NotifyCreateThreadEvent((ULONG64)VIRTUAL_THREAD_HANDLE(i),
  3448. Teb, 0, 0);
  3449. // Update thread suspend count from dump info.
  3450. g_EventThread->m_SuspendCount = Suspend;
  3451. }
  3452. return S_OK;
  3453. }
  3454. HRESULT
  3455. DumpTargetInfo::WaitInitialize(ULONG Flags,
  3456. ULONG Timeout,
  3457. WAIT_INIT_TYPE Type,
  3458. PULONG DesiredTimeout)
  3459. {
  3460. *DesiredTimeout = Timeout;
  3461. m_EventPossible = m_FirstWait;
  3462. return S_OK;
  3463. }
  3464. HRESULT
  3465. DumpTargetInfo::WaitForEvent(ULONG Flags, ULONG Timeout,
  3466. ULONG ElapsedTime, PULONG EventStatus)
  3467. {
  3468. HRESULT Status;
  3469. BOOL HaveContext = FALSE;
  3470. if (m_NumEvents == 1 && !m_FirstWait)
  3471. {
  3472. // A wait has already been done. Most crash dumps
  3473. // can only generate a single event so further
  3474. // waiting is not possible.
  3475. return S_FALSE;
  3476. }
  3477. g_EventTarget = this;
  3478. if (m_FirstWait)
  3479. {
  3480. //
  3481. // This is the first wait. Simulate any
  3482. // necessary events such as process and thread
  3483. // creations and image loads.
  3484. //
  3485. // Don't give real callbacks for processes/threads as
  3486. // they're just faked in the dump case.
  3487. g_EngNotify++;
  3488. if ((Status = FirstEvent()) != S_OK)
  3489. {
  3490. g_EngNotify--;
  3491. return Status;
  3492. }
  3493. }
  3494. if (IS_KERNEL_TARGET(this))
  3495. {
  3496. ULONG CurProc = ((KernelDumpTargetInfo*)this)->GetCurrentProcessor();
  3497. if (CurProc == (ULONG)-1)
  3498. {
  3499. WarnOut("Could not determine the current processor, "
  3500. "using zero\n");
  3501. CurProc = 0;
  3502. }
  3503. // Always set up an event so that the debugger
  3504. // initializes to the point of having a process
  3505. // and thread so commands can be used.
  3506. g_EventProcessSysId =
  3507. g_EventTarget->m_ProcessHead->m_SystemId;
  3508. g_EventThreadSysId = VIRTUAL_THREAD_ID(CurProc);
  3509. HaveContext = IS_KERNEL_TRIAGE_DUMP(this) ||
  3510. g_EventTarget->m_KdDebuggerData.KiProcessorBlock;
  3511. if (HaveContext &&
  3512. (g_EventTarget->m_MachineType == IMAGE_FILE_MACHINE_I386 ||
  3513. g_EventTarget->m_MachineType == IMAGE_FILE_MACHINE_IA64) &&
  3514. !IS_KERNEL_TRIAGE_DUMP(g_EventTarget))
  3515. {
  3516. //
  3517. // Reset the page directory correctly since NT 4 stores
  3518. // the wrong CR3 value in the context.
  3519. //
  3520. // IA64 dumps start out with just the kernel page
  3521. // directory set so update everything.
  3522. //
  3523. FindEventProcessThread();
  3524. g_EventTarget->ChangeRegContext(g_EventThread);
  3525. if (g_EventTarget->m_Machine->
  3526. SetDefaultPageDirectories(g_EventThread, PAGE_DIR_ALL) != S_OK)
  3527. {
  3528. WarnOut("WARNING: Unable to reset page directories\n");
  3529. }
  3530. g_EventTarget->ChangeRegContext(NULL);
  3531. // Flush the cache just in case as vmem mappings changed.
  3532. g_EventProcess->m_VirtualCache.Empty();
  3533. }
  3534. }
  3535. else
  3536. {
  3537. UserDumpTargetInfo* UserDump = (UserDumpTargetInfo*)g_EventTarget;
  3538. g_EventProcessSysId = UserDump->m_EventProcessId;
  3539. g_EventThreadSysId = UserDump->m_EventThreadId;
  3540. HaveContext = TRUE;
  3541. EventOut("User dump event on %x.%x\n",
  3542. g_EventProcessSysId, g_EventThreadSysId);
  3543. }
  3544. // Do not provide a control report; this will force
  3545. // such information to come from context retrieval.
  3546. g_ControlReport = NULL;
  3547. g_TargetEventPc = (ULONG64)m_ExceptionRecord.ExceptionAddress;
  3548. g_EngStatus |= ENG_STATUS_STATE_CHANGED;
  3549. FindEventProcessThread();
  3550. if (HaveContext)
  3551. {
  3552. g_EventTarget->ChangeRegContext(g_EventThread);
  3553. }
  3554. //
  3555. // Go ahead and reload all the symbols.
  3556. // This is especially important for minidumps because without
  3557. // symbols and the executable image, we can't unassemble the
  3558. // current instruction.
  3559. //
  3560. // If we don't have any context information we need to try
  3561. // and load symbols with whatever we've got, so skip any
  3562. // path checks. Also, if we're on XP or newer there's enough
  3563. // information in the dump to get things running even without
  3564. // symbols, so don't fail on paths checks then either.
  3565. //
  3566. BOOL CheckPaths = TRUE;
  3567. if (!HaveContext ||
  3568. IS_USER_DUMP(this) ||
  3569. (g_EventTarget->m_ActualSystemVersion >= NT_SVER_XP &&
  3570. g_EventTarget->m_ActualSystemVersion < NT_SVER_END))
  3571. {
  3572. CheckPaths = FALSE;
  3573. }
  3574. PCSTR ArgsRet;
  3575. Status = g_EventTarget->Reload(g_EventThread, CheckPaths ? "" : "-P",
  3576. &ArgsRet);
  3577. g_EventTarget->ChangeRegContext(NULL);
  3578. // The engine is now initialized so a real event
  3579. // can be generated.
  3580. g_EngNotify--;
  3581. if (HaveContext && Status != S_OK)
  3582. {
  3583. return Status;
  3584. }
  3585. if (m_FirstWait)
  3586. {
  3587. if (IS_USER_TARGET(this))
  3588. {
  3589. SetKernel32BuildString(m_ProcessHead);
  3590. if (IS_USER_FULL_DUMP(this))
  3591. {
  3592. m_ProcessHead->VerifyKernel32Version();
  3593. }
  3594. }
  3595. NotifyDebuggeeActivation();
  3596. }
  3597. NotifyExceptionEvent(&m_ExceptionRecord, m_ExceptionFirstChance,
  3598. m_ExceptionRecord.ExceptionCode ==
  3599. STATUS_BREAKPOINT ||
  3600. m_ExceptionRecord.ExceptionCode ==
  3601. STATUS_WX86_BREAKPOINT);
  3602. *EventStatus = DEBUG_STATUS_BREAK;
  3603. return S_OK;
  3604. }
  3605. //----------------------------------------------------------------------------
  3606. //
  3607. // Event filters.
  3608. //
  3609. //----------------------------------------------------------------------------
  3610. void
  3611. ParseImageTail(PSTR Buffer, ULONG BufferSize)
  3612. {
  3613. int i;
  3614. char ch;
  3615. Buffer[0] = '\0';
  3616. i = 0;
  3617. while (ch = (char)tolower(*g_CurCmd))
  3618. {
  3619. if (ch == ' ' || ch == '\t' || ch == ';')
  3620. {
  3621. break;
  3622. }
  3623. // Only capture the path tail.
  3624. if (IS_SLASH(ch) || ch == ':')
  3625. {
  3626. i = 0;
  3627. }
  3628. else
  3629. {
  3630. Buffer[i++] = ch;
  3631. if (i == BufferSize - 1)
  3632. {
  3633. // don't overrun the buffer
  3634. break;
  3635. }
  3636. }
  3637. g_CurCmd++;
  3638. }
  3639. Buffer[i] = '\0';
  3640. }
  3641. void
  3642. ParseUnloadDllBreakAddr(void)
  3643. /*++
  3644. Routine Description:
  3645. Called after 'sxe ud' has been parsed. This routine detects an
  3646. optional DLL base address after the 'sxe ud', which tells the debugger
  3647. to run until that specific DLL is unloaded, not just the next DLL.
  3648. Arguments:
  3649. None.
  3650. Return Value:
  3651. None.
  3652. --*/
  3653. {
  3654. UCHAR ch;
  3655. g_UnloadDllBase = 0;
  3656. g_UnloadDllBaseName[0] = 0;
  3657. while (ch = (UCHAR)tolower(*g_CurCmd))
  3658. {
  3659. if (ch == ' ')
  3660. {
  3661. break;
  3662. }
  3663. // Skip leading ':'
  3664. if (ch != ':')
  3665. {
  3666. // Get the base address
  3667. g_UnloadDllBase = GetExpression();
  3668. sprintf(g_UnloadDllBaseName, "0x%s",
  3669. FormatAddr64(g_UnloadDllBase));
  3670. break;
  3671. }
  3672. g_CurCmd++;
  3673. }
  3674. }
  3675. void
  3676. ParseOutFilterPattern(void)
  3677. {
  3678. int i;
  3679. char ch;
  3680. i = 0;
  3681. while (ch = (char)tolower(*g_CurCmd))
  3682. {
  3683. if (ch == ' ')
  3684. {
  3685. break;
  3686. }
  3687. if (ch == ':')
  3688. {
  3689. i = 0;
  3690. }
  3691. else
  3692. {
  3693. g_OutEventFilterPattern[i++] = (char)toupper(ch);
  3694. if (i == sizeof(g_OutEventFilterPattern) - 1)
  3695. {
  3696. // Don't overrun the buffer.
  3697. break;
  3698. }
  3699. }
  3700. g_CurCmd++;
  3701. }
  3702. g_OutEventFilterPattern[i] = 0;
  3703. }
  3704. BOOL
  3705. BreakOnThisImageTail(PCSTR ImagePath, PCSTR FilterArg)
  3706. {
  3707. //
  3708. // No filter specified so break on all events.
  3709. //
  3710. if (!FilterArg || !FilterArg[0])
  3711. {
  3712. return TRUE;
  3713. }
  3714. //
  3715. // Some kind of error looking up the image path. Break anyhow.
  3716. //
  3717. if (!ImagePath || !ImagePath[0])
  3718. {
  3719. return TRUE;
  3720. }
  3721. PCSTR Tail = PathTail(ImagePath);
  3722. //
  3723. // Specified name may not have an extension. Break
  3724. // on the first event whose name matches regardless of its extension if
  3725. // the break name did not have one.
  3726. //
  3727. if (_strnicmp(Tail, FilterArg, strlen(FilterArg)) == 0)
  3728. {
  3729. return TRUE;
  3730. }
  3731. else if (MatchPattern((PSTR)Tail, (PSTR)FilterArg))
  3732. {
  3733. return TRUE;
  3734. }
  3735. return FALSE;
  3736. }
  3737. BOOL
  3738. BreakOnThisDllUnload(
  3739. ULONG64 DllBase
  3740. )
  3741. {
  3742. // 'sxe ud' with no base address specified. Break on all DLL unloads
  3743. if (g_UnloadDllBase == 0)
  3744. {
  3745. return TRUE;
  3746. }
  3747. // 'sxe ud' with base address specified. Break if this
  3748. // DLL's base address matches the one specified
  3749. return g_UnloadDllBase == DllBase;
  3750. }
  3751. BOOL
  3752. BreakOnThisOutString(PCSTR OutString)
  3753. {
  3754. if (!g_OutEventFilterPattern[0])
  3755. {
  3756. // No pattern means always break.
  3757. return TRUE;
  3758. }
  3759. return MatchPattern((PSTR)OutString, g_OutEventFilterPattern);
  3760. }
  3761. EVENT_FILTER*
  3762. GetSpecificExceptionFilter(ULONG Code)
  3763. {
  3764. ULONG i;
  3765. EVENT_FILTER* Filter;
  3766. Filter = g_EventFilters + FILTER_EXCEPTION_FIRST;
  3767. for (i = FILTER_EXCEPTION_FIRST; i <= FILTER_EXCEPTION_LAST; i++)
  3768. {
  3769. if (i != FILTER_DEFAULT_EXCEPTION &&
  3770. Filter->Params.ExceptionCode == Code)
  3771. {
  3772. return Filter;
  3773. }
  3774. Filter++;
  3775. }
  3776. return NULL;
  3777. }
  3778. ULONG
  3779. GetOtherExceptionParameters(ULONG Code, BOOL DefaultOnNotFound,
  3780. PDEBUG_EXCEPTION_FILTER_PARAMETERS* Params,
  3781. EVENT_COMMAND** Command)
  3782. {
  3783. ULONG Index;
  3784. for (Index = 0; Index < g_NumOtherExceptions; Index++)
  3785. {
  3786. if (Code == g_OtherExceptionList[Index].ExceptionCode)
  3787. {
  3788. *Params = g_OtherExceptionList + Index;
  3789. *Command = g_OtherExceptionCommands + Index;
  3790. return NO_ERROR;
  3791. }
  3792. }
  3793. if (DefaultOnNotFound)
  3794. {
  3795. *Params = &g_EventFilters[FILTER_DEFAULT_EXCEPTION].Params;
  3796. *Command = &g_EventFilters[FILTER_DEFAULT_EXCEPTION].Command;
  3797. return NO_ERROR;
  3798. }
  3799. else if (g_NumOtherExceptions == OTHER_EXCEPTION_LIST_MAX)
  3800. {
  3801. return LISTSIZE;
  3802. }
  3803. else
  3804. {
  3805. Index = g_NumOtherExceptions++;
  3806. g_OtherExceptionList[Index] =
  3807. g_EventFilters[FILTER_DEFAULT_EXCEPTION].Params;
  3808. g_OtherExceptionList[Index].ExceptionCode = Code;
  3809. ZeroMemory(&g_OtherExceptionCommands[Index],
  3810. sizeof(g_OtherExceptionCommands[Index]));
  3811. *Params = g_OtherExceptionList + Index;
  3812. *Command = g_OtherExceptionCommands + Index;
  3813. return NO_ERROR;
  3814. }
  3815. }
  3816. ULONG
  3817. SetOtherExceptionParameters(PDEBUG_EXCEPTION_FILTER_PARAMETERS Params,
  3818. EVENT_COMMAND* Command)
  3819. {
  3820. ULONG Index;
  3821. if (g_EventFilters[FILTER_DEFAULT_EXCEPTION].
  3822. Params.ExecutionOption == Params->ExecutionOption &&
  3823. g_EventFilters[FILTER_DEFAULT_EXCEPTION].
  3824. Params.ContinueOption == Params->ContinueOption &&
  3825. !memcmp(&g_EventFilters[FILTER_DEFAULT_EXCEPTION].Command,
  3826. Command, sizeof(*Command)))
  3827. {
  3828. // Exception state same as global state clears entry
  3829. // in list if there.
  3830. for (Index = 0; Index < g_NumOtherExceptions; Index++)
  3831. {
  3832. if (Params->ExceptionCode ==
  3833. g_OtherExceptionList[Index].ExceptionCode)
  3834. {
  3835. RemoveOtherException(Index);
  3836. NotifyChangeEngineState(DEBUG_CES_EVENT_FILTERS,
  3837. DEBUG_ANY_ID, TRUE);
  3838. break;
  3839. }
  3840. }
  3841. }
  3842. else
  3843. {
  3844. // Exception state different from global state is added
  3845. // to list if not already there.
  3846. for (Index = 0; Index < g_NumOtherExceptions; Index++)
  3847. {
  3848. if (Params->ExceptionCode ==
  3849. g_OtherExceptionList[Index].ExceptionCode)
  3850. {
  3851. break;
  3852. }
  3853. }
  3854. if (Index == g_NumOtherExceptions)
  3855. {
  3856. if (g_NumOtherExceptions == OTHER_EXCEPTION_LIST_MAX)
  3857. {
  3858. return LISTSIZE;
  3859. }
  3860. Index = g_NumOtherExceptions++;
  3861. }
  3862. g_OtherExceptionList[Index] = *Params;
  3863. g_OtherExceptionCommands[Index] = *Command;
  3864. NotifyChangeEngineState(DEBUG_CES_EVENT_FILTERS, Index, TRUE);
  3865. }
  3866. return 0;
  3867. }
  3868. void
  3869. RemoveOtherException(ULONG Index)
  3870. {
  3871. g_NumOtherExceptions--;
  3872. memmove(g_OtherExceptionList + Index,
  3873. g_OtherExceptionList + Index + 1,
  3874. (g_NumOtherExceptions - Index) *
  3875. sizeof(g_OtherExceptionList[0]));
  3876. delete [] g_OtherExceptionCommands[Index].Command[0];
  3877. delete [] g_OtherExceptionCommands[Index].Command[1];
  3878. memmove(g_OtherExceptionCommands + Index,
  3879. g_OtherExceptionCommands + Index + 1,
  3880. (g_NumOtherExceptions - Index) *
  3881. sizeof(g_OtherExceptionCommands[0]));
  3882. }
  3883. ULONG
  3884. SetEventFilterExecution(EVENT_FILTER* Filter, ULONG Execution)
  3885. {
  3886. ULONG Index = (ULONG)(Filter - g_EventFilters);
  3887. // Non-exception events don't have second chances so
  3888. // demote second-chance break to output. This matches
  3889. // the intuitive expectation that sxd will disable
  3890. // the break.
  3891. if (
  3892. #if DEBUG_FILTER_CREATE_THREAD > 0
  3893. Index >= DEBUG_FILTER_CREATE_THREAD &&
  3894. #endif
  3895. Index <= DEBUG_FILTER_SYSTEM_ERROR &&
  3896. Execution == DEBUG_FILTER_SECOND_CHANCE_BREAK)
  3897. {
  3898. Execution = DEBUG_FILTER_OUTPUT;
  3899. }
  3900. Filter->Params.ExecutionOption = Execution;
  3901. Filter->Flags |= FILTER_CHANGED_EXECUTION;
  3902. // Collect any additional arguments.
  3903. switch(Index)
  3904. {
  3905. case DEBUG_FILTER_CREATE_PROCESS:
  3906. case DEBUG_FILTER_EXIT_PROCESS:
  3907. case DEBUG_FILTER_LOAD_MODULE:
  3908. ParseImageTail(Filter->Argument, FILTER_MAX_ARGUMENT);
  3909. break;
  3910. case DEBUG_FILTER_UNLOAD_MODULE:
  3911. ParseUnloadDllBreakAddr();
  3912. break;
  3913. case DEBUG_FILTER_DEBUGGEE_OUTPUT:
  3914. ParseOutFilterPattern();
  3915. break;
  3916. }
  3917. return 0;
  3918. }
  3919. ULONG
  3920. SetEventFilterContinue(EVENT_FILTER* Filter, ULONG Continue)
  3921. {
  3922. Filter->Params.ContinueOption = Continue;
  3923. Filter->Flags |= FILTER_CHANGED_CONTINUE;
  3924. return 0;
  3925. }
  3926. ULONG
  3927. SetEventFilterCommand(DebugClient* Client, EVENT_FILTER* Filter,
  3928. EVENT_COMMAND* EventCommand, PSTR* Command)
  3929. {
  3930. if (Command[0] != NULL)
  3931. {
  3932. if (strlen(Command[0]) >= MAX_COMMAND)
  3933. {
  3934. return STRINGSIZE;
  3935. }
  3936. if (ChangeString(&EventCommand->Command[0],
  3937. &EventCommand->CommandSize[0],
  3938. Command[0][0] ? Command[0] : NULL) != S_OK)
  3939. {
  3940. return MEMORY;
  3941. }
  3942. }
  3943. if (Command[1] != NULL)
  3944. {
  3945. if (strlen(Command[1]) >= MAX_COMMAND)
  3946. {
  3947. return STRINGSIZE;
  3948. }
  3949. if (Filter != NULL &&
  3950. #if FILTER_SPECIFIC_FIRST > 0
  3951. (ULONG)(Filter - g_EventFilters) >= FILTER_SPECIFIC_FIRST &&
  3952. #endif
  3953. (ULONG)(Filter - g_EventFilters) <= FILTER_SPECIFIC_LAST)
  3954. {
  3955. WarnOut("Second-chance command for specific event ignored\n");
  3956. }
  3957. else if (ChangeString(&EventCommand->Command[1],
  3958. &EventCommand->CommandSize[1],
  3959. Command[1][0] ? Command[1] : NULL) != S_OK)
  3960. {
  3961. return MEMORY;
  3962. }
  3963. }
  3964. if (Command[0] != NULL || Command[1] != NULL)
  3965. {
  3966. if (Filter != NULL)
  3967. {
  3968. Filter->Flags |= FILTER_CHANGED_COMMAND;
  3969. }
  3970. EventCommand->Client = Client;
  3971. }
  3972. else
  3973. {
  3974. EventCommand->Client = NULL;
  3975. }
  3976. return 0;
  3977. }
  3978. #define EXEC_TO_CONT(Option) \
  3979. ((Option) == DEBUG_FILTER_BREAK ? \
  3980. DEBUG_FILTER_GO_HANDLED : DEBUG_FILTER_GO_NOT_HANDLED)
  3981. ULONG
  3982. SetEventFilterEither(DebugClient* Client, EVENT_FILTER* Filter,
  3983. ULONG Option, BOOL ContinueOption,
  3984. PSTR* Command)
  3985. {
  3986. ULONG Status;
  3987. if (Option != DEBUG_FILTER_REMOVE)
  3988. {
  3989. if (ContinueOption)
  3990. {
  3991. Status = SetEventFilterContinue(Filter, EXEC_TO_CONT(Option));
  3992. }
  3993. else
  3994. {
  3995. Status = SetEventFilterExecution(Filter, Option);
  3996. }
  3997. if (Status != 0)
  3998. {
  3999. return Status;
  4000. }
  4001. }
  4002. return SetEventFilterCommand(Client, Filter, &Filter->Command, Command);
  4003. }
  4004. ULONG
  4005. SetEventFilterByName(DebugClient* Client,
  4006. ULONG Option, BOOL ForceContinue, PSTR* Command)
  4007. {
  4008. PSTR Start = g_CurCmd;
  4009. char Name[8];
  4010. int i;
  4011. char Ch;
  4012. // Collect name.
  4013. i = 0;
  4014. while (i < sizeof(Name) - 1)
  4015. {
  4016. Ch = *g_CurCmd++;
  4017. if (!__iscsym(Ch))
  4018. {
  4019. g_CurCmd--;
  4020. break;
  4021. }
  4022. Name[i++] = (CHAR)tolower(Ch);
  4023. }
  4024. Name[i] = 0;
  4025. // Skip any whitespace after the name.
  4026. while (isspace(*g_CurCmd))
  4027. {
  4028. g_CurCmd++;
  4029. }
  4030. EVENT_FILTER* Filter;
  4031. BOOL Match = FALSE;
  4032. ULONG MatchIndex = DEBUG_ANY_ID;
  4033. ULONG Status = 0;
  4034. // Multiple filters can be altered if they share names.
  4035. Filter = g_EventFilters;
  4036. for (i = 0; i < FILTER_COUNT; i++)
  4037. {
  4038. if (Filter->ExecutionAbbrev != NULL &&
  4039. !strcmp(Name, Filter->ExecutionAbbrev))
  4040. {
  4041. Status = SetEventFilterEither(Client,
  4042. Filter, Option, ForceContinue,
  4043. Command);
  4044. if (Status != 0)
  4045. {
  4046. goto Exit;
  4047. }
  4048. if (!Match)
  4049. {
  4050. MatchIndex = i;
  4051. Match = TRUE;
  4052. }
  4053. else if (MatchIndex != (ULONG)i)
  4054. {
  4055. // Multiple matches.
  4056. MatchIndex = DEBUG_ANY_ID;
  4057. }
  4058. }
  4059. if (Filter->ContinueAbbrev != NULL &&
  4060. !strcmp(Name, Filter->ContinueAbbrev))
  4061. {
  4062. // Translate execution-style option to continue-style option.
  4063. Status = SetEventFilterEither(Client,
  4064. Filter, Option, TRUE, Command);
  4065. if (Status != 0)
  4066. {
  4067. goto Exit;
  4068. }
  4069. if (!Match)
  4070. {
  4071. MatchIndex = i;
  4072. Match = TRUE;
  4073. }
  4074. else if (MatchIndex != (ULONG)i)
  4075. {
  4076. // Multiple matches.
  4077. MatchIndex = DEBUG_ANY_ID;
  4078. }
  4079. }
  4080. Filter++;
  4081. }
  4082. if (!Match)
  4083. {
  4084. ULONG64 ExceptionCode;
  4085. // Name is unrecognized. Assume it's an exception code.
  4086. g_CurCmd = Start;
  4087. ExceptionCode = GetExpression();
  4088. if (NeedUpper(ExceptionCode))
  4089. {
  4090. return OVERFLOW;
  4091. }
  4092. DEBUG_EXCEPTION_FILTER_PARAMETERS Params, *CurParams;
  4093. EVENT_COMMAND EventCommand, *CurEventCommand;
  4094. if (Status = GetOtherExceptionParameters((ULONG)ExceptionCode, FALSE,
  4095. &CurParams, &CurEventCommand))
  4096. {
  4097. return Status;
  4098. }
  4099. Params = *CurParams;
  4100. if (Option != DEBUG_FILTER_REMOVE)
  4101. {
  4102. if (ForceContinue)
  4103. {
  4104. Params.ContinueOption = EXEC_TO_CONT(Option);
  4105. }
  4106. else
  4107. {
  4108. Params.ExecutionOption = Option;
  4109. }
  4110. }
  4111. Params.ExceptionCode = (ULONG)ExceptionCode;
  4112. EventCommand = *CurEventCommand;
  4113. Status = SetEventFilterCommand(Client, NULL, &EventCommand, Command);
  4114. if (Status != 0)
  4115. {
  4116. return Status;
  4117. }
  4118. return SetOtherExceptionParameters(&Params, &EventCommand);
  4119. }
  4120. Exit:
  4121. if (Match)
  4122. {
  4123. if (SyncOptionsWithFilters())
  4124. {
  4125. NotifyChangeEngineState(DEBUG_CES_EVENT_FILTERS |
  4126. DEBUG_CES_ENGINE_OPTIONS,
  4127. DEBUG_ANY_ID, TRUE);
  4128. }
  4129. else
  4130. {
  4131. NotifyChangeEngineState(DEBUG_CES_EVENT_FILTERS, MatchIndex, TRUE);
  4132. }
  4133. }
  4134. return Status;
  4135. }
  4136. char* g_EfExecutionNames[] =
  4137. {
  4138. "break", "second-chance break", "output", "ignore",
  4139. };
  4140. char* g_EfContinueNames[] =
  4141. {
  4142. "handled", "not handled",
  4143. };
  4144. void
  4145. ListEventFilters(void)
  4146. {
  4147. EVENT_FILTER* Filter;
  4148. ULONG i;
  4149. BOOL SetOption = TRUE;
  4150. Filter = g_EventFilters;
  4151. for (i = 0; i < FILTER_COUNT; i++)
  4152. {
  4153. if (Filter->ExecutionAbbrev != NULL)
  4154. {
  4155. dprintf("%4s - %s - %s",
  4156. Filter->ExecutionAbbrev, Filter->Name,
  4157. g_EfExecutionNames[Filter->Params.ExecutionOption]);
  4158. if (i >= FILTER_EXCEPTION_FIRST &&
  4159. Filter->ContinueAbbrev == NULL)
  4160. {
  4161. dprintf(" - %s\n",
  4162. g_EfContinueNames[Filter->Params.ContinueOption]);
  4163. }
  4164. else
  4165. {
  4166. dprintf("\n");
  4167. }
  4168. if (Filter->Command.Command[0] != NULL)
  4169. {
  4170. dprintf(" Command: \"%s\"\n",
  4171. Filter->Command.Command[0]);
  4172. }
  4173. if (Filter->Command.Command[1] != NULL)
  4174. {
  4175. dprintf(" Second command: \"%s\"\n",
  4176. Filter->Command.Command[1]);
  4177. }
  4178. }
  4179. if (Filter->ContinueAbbrev != NULL)
  4180. {
  4181. dprintf("%4s - %s continue - %s\n",
  4182. Filter->ContinueAbbrev, Filter->Name,
  4183. g_EfContinueNames[Filter->Params.ContinueOption]);
  4184. }
  4185. switch(i)
  4186. {
  4187. case DEBUG_FILTER_CREATE_PROCESS:
  4188. case DEBUG_FILTER_EXIT_PROCESS:
  4189. case DEBUG_FILTER_LOAD_MODULE:
  4190. case DEBUG_FILTER_UNLOAD_MODULE:
  4191. if (IS_EFEXECUTION_BREAK(Filter->Params.ExecutionOption) &&
  4192. Filter->Argument[0])
  4193. {
  4194. dprintf(" (only break for %s)\n", Filter->Argument);
  4195. }
  4196. break;
  4197. case DEBUG_FILTER_DEBUGGEE_OUTPUT:
  4198. if (IS_EFEXECUTION_BREAK(Filter->Params.ExecutionOption) &&
  4199. g_OutEventFilterPattern[0])
  4200. {
  4201. dprintf(" (only break for %s matches)\n",
  4202. g_OutEventFilterPattern);
  4203. }
  4204. break;
  4205. }
  4206. Filter++;
  4207. }
  4208. Filter = &g_EventFilters[FILTER_DEFAULT_EXCEPTION];
  4209. dprintf("\n * - Other exception - %s - %s\n",
  4210. g_EfExecutionNames[Filter->Params.ExecutionOption],
  4211. g_EfContinueNames[Filter->Params.ContinueOption]);
  4212. if (Filter->Command.Command[0] != NULL)
  4213. {
  4214. dprintf(" Command: \"%s\"\n",
  4215. Filter->Command.Command[0]);
  4216. }
  4217. if (Filter->Command.Command[1] != NULL)
  4218. {
  4219. dprintf(" Second command: \"%s\"\n",
  4220. Filter->Command.Command[1]);
  4221. }
  4222. if (g_NumOtherExceptions > 0)
  4223. {
  4224. dprintf(" Exception option for:\n");
  4225. for (i = 0; i < g_NumOtherExceptions; i++)
  4226. {
  4227. dprintf(" %08lx - %s - %s\n",
  4228. g_OtherExceptionList[i].ExceptionCode,
  4229. g_EfExecutionNames[g_OtherExceptionList[i].
  4230. ExecutionOption],
  4231. g_EfContinueNames[g_OtherExceptionList[i].
  4232. ContinueOption]);
  4233. if (g_OtherExceptionCommands[i].Command[0] != NULL)
  4234. {
  4235. dprintf(" Command: \"%s\"\n",
  4236. g_OtherExceptionCommands[i].Command[0]);
  4237. }
  4238. if (g_OtherExceptionCommands[i].Command[1] != NULL)
  4239. {
  4240. dprintf(" Second command: \"%s\"\n",
  4241. g_OtherExceptionCommands[i].Command[1]);
  4242. }
  4243. }
  4244. }
  4245. }
  4246. void
  4247. ParseSetEventFilter(DebugClient* Client)
  4248. {
  4249. UCHAR Ch;
  4250. // Verify that exception constants are properly updated.
  4251. DBG_ASSERT(!strcmp(g_EventFilters[FILTER_EXCEPTION_FIRST - 1].Name,
  4252. "Debuggee output"));
  4253. C_ASSERT(DIMA(g_EventFilters) == FILTER_COUNT);
  4254. Ch = PeekChar();
  4255. if (Ch == '\0')
  4256. {
  4257. ListEventFilters();
  4258. }
  4259. else
  4260. {
  4261. ULONG Option;
  4262. Ch = (UCHAR)tolower(Ch);
  4263. g_CurCmd++;
  4264. switch(Ch)
  4265. {
  4266. case 'd':
  4267. Option = DEBUG_FILTER_SECOND_CHANCE_BREAK;
  4268. break;
  4269. case 'e':
  4270. Option = DEBUG_FILTER_BREAK;
  4271. break;
  4272. case 'i':
  4273. Option = DEBUG_FILTER_IGNORE;
  4274. break;
  4275. case 'n':
  4276. Option = DEBUG_FILTER_OUTPUT;
  4277. break;
  4278. case '-':
  4279. // Special value to indicate "don't change the option".
  4280. // Used for just changing commands.
  4281. Option = DEBUG_FILTER_REMOVE;
  4282. break;
  4283. default:
  4284. error(SYNTAX);
  4285. break;
  4286. }
  4287. BOOL ForceContinue;
  4288. PSTR Command[2];
  4289. ULONG Which;
  4290. ForceContinue = FALSE;
  4291. Command[0] = NULL;
  4292. Command[1] = NULL;
  4293. for (;;)
  4294. {
  4295. while (isspace(PeekChar()))
  4296. {
  4297. g_CurCmd++;
  4298. }
  4299. if (*g_CurCmd == '-' || *g_CurCmd == '/')
  4300. {
  4301. switch(tolower(*(++g_CurCmd)))
  4302. {
  4303. case 'c':
  4304. if (*(++g_CurCmd) == '2')
  4305. {
  4306. Which = 1;
  4307. g_CurCmd++;
  4308. }
  4309. else
  4310. {
  4311. Which = 0;
  4312. }
  4313. if (PeekChar() != '"')
  4314. {
  4315. error(SYNTAX);
  4316. }
  4317. if (Command[Which] != NULL)
  4318. {
  4319. error(SYNTAX);
  4320. }
  4321. Command[Which] = ++g_CurCmd;
  4322. while (*g_CurCmd && *g_CurCmd != '"')
  4323. {
  4324. g_CurCmd++;
  4325. }
  4326. if (*g_CurCmd != '"')
  4327. {
  4328. error(SYNTAX);
  4329. }
  4330. *g_CurCmd = 0;
  4331. break;
  4332. case 'h':
  4333. ForceContinue = TRUE;
  4334. break;
  4335. default:
  4336. error(SYNTAX);
  4337. }
  4338. g_CurCmd++;
  4339. }
  4340. else
  4341. {
  4342. break;
  4343. }
  4344. }
  4345. ULONG Status;
  4346. if (*g_CurCmd == '*')
  4347. {
  4348. g_CurCmd++;
  4349. Status = SetEventFilterEither
  4350. (Client, &g_EventFilters[FILTER_DEFAULT_EXCEPTION],
  4351. Option, ForceContinue, Command);
  4352. if (Status == 0)
  4353. {
  4354. while (g_NumOtherExceptions)
  4355. {
  4356. RemoveOtherException(0);
  4357. }
  4358. }
  4359. }
  4360. else
  4361. {
  4362. Status = SetEventFilterByName(Client,
  4363. Option, ForceContinue, Command);
  4364. }
  4365. if (Status != 0)
  4366. {
  4367. error(Status);
  4368. }
  4369. }
  4370. }
  4371. char
  4372. ExecutionChar(ULONG Execution)
  4373. {
  4374. switch(Execution)
  4375. {
  4376. case DEBUG_FILTER_BREAK:
  4377. return 'e';
  4378. case DEBUG_FILTER_SECOND_CHANCE_BREAK:
  4379. return 'd';
  4380. case DEBUG_FILTER_OUTPUT:
  4381. return 'n';
  4382. case DEBUG_FILTER_IGNORE:
  4383. return 'i';
  4384. }
  4385. return 0;
  4386. }
  4387. char
  4388. ContinueChar(ULONG Continue)
  4389. {
  4390. switch(Continue)
  4391. {
  4392. case DEBUG_FILTER_GO_HANDLED:
  4393. return 'e';
  4394. case DEBUG_FILTER_GO_NOT_HANDLED:
  4395. return 'd';
  4396. }
  4397. return 0;
  4398. }
  4399. void
  4400. ListFiltersAsCommands(DebugClient* Client, ULONG Flags)
  4401. {
  4402. ULONG i;
  4403. EVENT_FILTER* Filter = g_EventFilters;
  4404. for (i = 0; i < FILTER_COUNT; i++)
  4405. {
  4406. if (Filter->Flags & FILTER_CHANGED_EXECUTION)
  4407. {
  4408. PCSTR Abbrev = Filter->ExecutionAbbrev != NULL ?
  4409. Filter->ExecutionAbbrev : "*";
  4410. dprintf("sx%c %s",
  4411. ExecutionChar(Filter->Params.ExecutionOption), Abbrev);
  4412. switch(i)
  4413. {
  4414. case DEBUG_FILTER_CREATE_PROCESS:
  4415. case DEBUG_FILTER_EXIT_PROCESS:
  4416. case DEBUG_FILTER_LOAD_MODULE:
  4417. case DEBUG_FILTER_UNLOAD_MODULE:
  4418. case DEBUG_FILTER_DEBUGGEE_OUTPUT:
  4419. if (IS_EFEXECUTION_BREAK(Filter->Params.ExecutionOption) &&
  4420. Filter->Argument[0])
  4421. {
  4422. dprintf(":%s", Filter->Argument);
  4423. }
  4424. break;
  4425. }
  4426. dprintf(" ;%c", (Flags & SXCMDS_ONE_LINE) ? ' ' : '\n');
  4427. }
  4428. if (Filter->Flags & FILTER_CHANGED_CONTINUE)
  4429. {
  4430. PCSTR Abbrev = Filter->ContinueAbbrev;
  4431. if (Abbrev == NULL)
  4432. {
  4433. Abbrev = Filter->ExecutionAbbrev != NULL ?
  4434. Filter->ExecutionAbbrev : "*";
  4435. }
  4436. dprintf("sx%c -h %s ;%c",
  4437. ContinueChar(Filter->Params.ContinueOption), Abbrev,
  4438. (Flags & SXCMDS_ONE_LINE) ? ' ' : '\n');
  4439. }
  4440. if (Filter->Flags & FILTER_CHANGED_COMMAND)
  4441. {
  4442. PCSTR Abbrev = Filter->ExecutionAbbrev != NULL ?
  4443. Filter->ExecutionAbbrev : "*";
  4444. dprintf("sx-");
  4445. if (Filter->Command.Command[0] != NULL)
  4446. {
  4447. dprintf(" -c \"%s\"", Filter->Command.Command[0]);
  4448. }
  4449. if (Filter->Command.Command[1] != NULL)
  4450. {
  4451. dprintf(" -c2 \"%s\"", Filter->Command.Command[1]);
  4452. }
  4453. dprintf(" %s ;%c", Abbrev,
  4454. (Flags & SXCMDS_ONE_LINE) ? ' ' : '\n');
  4455. }
  4456. Filter++;
  4457. }
  4458. PDEBUG_EXCEPTION_FILTER_PARAMETERS Other = g_OtherExceptionList;
  4459. EVENT_COMMAND* EventCommand = g_OtherExceptionCommands;
  4460. for (i = 0; i < g_NumOtherExceptions; i++)
  4461. {
  4462. dprintf("sx%c 0x%x ;%c",
  4463. ExecutionChar(Other->ExecutionOption), Other->ExceptionCode,
  4464. (Flags & SXCMDS_ONE_LINE) ? ' ' : '\n');
  4465. dprintf("sx%c -h 0x%x ;%c",
  4466. ContinueChar(Other->ContinueOption), Other->ExceptionCode,
  4467. (Flags & SXCMDS_ONE_LINE) ? ' ' : '\n');
  4468. if (EventCommand->Command[0] != NULL ||
  4469. EventCommand->Command[1] != NULL)
  4470. {
  4471. dprintf("sx-");
  4472. if (EventCommand->Command[0] != NULL)
  4473. {
  4474. dprintf(" -c \"%s\"", EventCommand->Command[0]);
  4475. }
  4476. if (EventCommand->Command[1] != NULL)
  4477. {
  4478. dprintf(" -c2 \"%s\"", EventCommand->Command[1]);
  4479. }
  4480. dprintf(" 0x%x ;%c", Other->ExceptionCode,
  4481. (Flags & SXCMDS_ONE_LINE) ? ' ' : '\n');
  4482. }
  4483. Other++;
  4484. EventCommand++;
  4485. }
  4486. if (Flags & SXCMDS_ONE_LINE)
  4487. {
  4488. dprintf("\n");
  4489. }
  4490. }
  4491. struct SHARED_FILTER_AND_OPTION
  4492. {
  4493. ULONG FilterIndex;
  4494. ULONG OptionBit;
  4495. };
  4496. SHARED_FILTER_AND_OPTION g_SharedFilterOptions[] =
  4497. {
  4498. DEBUG_FILTER_INITIAL_BREAKPOINT, DEBUG_ENGOPT_INITIAL_BREAK,
  4499. DEBUG_FILTER_INITIAL_MODULE_LOAD, DEBUG_ENGOPT_INITIAL_MODULE_BREAK,
  4500. DEBUG_FILTER_EXIT_PROCESS, DEBUG_ENGOPT_FINAL_BREAK,
  4501. };
  4502. BOOL
  4503. SyncFiltersWithOptions(void)
  4504. {
  4505. ULONG ExOption;
  4506. BOOL Changed = FALSE;
  4507. ULONG i;
  4508. for (i = 0; i < DIMA(g_SharedFilterOptions); i++)
  4509. {
  4510. ExOption = (g_EngOptions & g_SharedFilterOptions[i].OptionBit) ?
  4511. DEBUG_FILTER_BREAK : DEBUG_FILTER_IGNORE;
  4512. if (g_EventFilters[g_SharedFilterOptions[i].FilterIndex].
  4513. Params.ExecutionOption != ExOption)
  4514. {
  4515. g_EventFilters[g_SharedFilterOptions[i].FilterIndex].
  4516. Params.ExecutionOption = ExOption;
  4517. Changed = TRUE;
  4518. }
  4519. }
  4520. return Changed;
  4521. }
  4522. BOOL
  4523. SyncOptionsWithFilters(void)
  4524. {
  4525. ULONG Bit;
  4526. BOOL Changed = FALSE;
  4527. ULONG i;
  4528. for (i = 0; i < DIMA(g_SharedFilterOptions); i++)
  4529. {
  4530. Bit = IS_EFEXECUTION_BREAK
  4531. (g_EventFilters[g_SharedFilterOptions[i].FilterIndex].
  4532. Params.ExecutionOption) ?
  4533. g_SharedFilterOptions[i].OptionBit : 0;
  4534. if ((g_EngOptions & g_SharedFilterOptions[i].OptionBit) ^ Bit)
  4535. {
  4536. g_EngOptions =
  4537. (g_EngOptions & ~g_SharedFilterOptions[i].OptionBit) | Bit;
  4538. Changed = TRUE;
  4539. }
  4540. }
  4541. return Changed;
  4542. }