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.

784 lines
20 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Thread abstraction.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. // Thread specified in thread commands. Used for specific
  10. // thread stepping and execution.
  11. ThreadInfo* g_SelectedThread;
  12. SELECT_EXECUTION_THREAD g_SelectExecutionThread = SELTHREAD_ANY;
  13. ThreadInfo* g_RegContextSaved;
  14. ULONG64 g_SaveImplicitThread;
  15. ULONG64 g_SaveImplicitProcess;
  16. ContextSave* g_SavedMachineContext;
  17. //----------------------------------------------------------------------------
  18. //
  19. // ThreadInfo.
  20. //
  21. //----------------------------------------------------------------------------
  22. ThreadInfo::ThreadInfo(ProcessInfo* Process,
  23. ULONG SystemId,
  24. ULONG64 DataOffset,
  25. ULONG64 Handle,
  26. ULONG Flags,
  27. ULONG64 StartOffset)
  28. {
  29. m_Process = Process;
  30. if (m_Process)
  31. {
  32. m_UserId = FindNextUserId(LAYER_THREAD);
  33. }
  34. else
  35. {
  36. m_UserId = 0xffffffff;
  37. }
  38. m_Next = NULL;
  39. m_SystemId = SystemId;
  40. m_Exited = FALSE;
  41. m_DataOffset = DataOffset;
  42. m_Handle = Handle;
  43. m_Flags = Flags;
  44. m_Name[0] = 0;
  45. ZeroMemory(&m_DataBreakBps, sizeof(m_DataBreakBps));
  46. m_NumDataBreaks = 0;
  47. m_EventStrings = NULL;
  48. m_StartOffset = StartOffset;
  49. m_Frozen = FALSE;
  50. m_SuspendCount = 0;
  51. m_FreezeCount = 0;
  52. m_InternalFreezeCount = 0;
  53. if (m_Process)
  54. {
  55. m_Process->InsertThread(this);
  56. }
  57. }
  58. ThreadInfo::~ThreadInfo(void)
  59. {
  60. if (!m_Process)
  61. {
  62. return;
  63. }
  64. RemoveThreadBreakpoints(this);
  65. ClearEventStrings();
  66. if (m_Flags & ENG_PROC_THREAD_CLOSE_HANDLE)
  67. {
  68. DBG_ASSERT(IS_LIVE_USER_TARGET(m_Process->m_Target) &&
  69. ((LiveUserTargetInfo*)m_Process->m_Target)->
  70. m_Services);
  71. ((LiveUserTargetInfo*)m_Process->m_Target)->
  72. m_Services->CloseHandle(m_Handle);
  73. }
  74. if (this == m_Process->m_Target->m_RegContextThread)
  75. {
  76. m_Process->m_Target->m_RegContextThread = NULL;
  77. m_Process->m_Target->m_RegContextProcessor = -1;
  78. }
  79. if (m_Process->m_ImplicitThreadDataThread == this)
  80. {
  81. m_Process->ResetImplicitData();
  82. }
  83. if (m_Process->m_Target->m_ImplicitProcessDataThread == this)
  84. {
  85. m_Process->m_Target->ResetImplicitData();
  86. }
  87. m_Process->RemoveThread(this);
  88. g_UserIdFragmented[LAYER_THREAD]++;
  89. if (this == g_Thread)
  90. {
  91. g_Thread = NULL;
  92. }
  93. if (this == g_EventThread)
  94. {
  95. g_EventThread = NULL;
  96. DiscardLastEvent();
  97. }
  98. if (g_StepTraceBp && g_StepTraceBp->m_MatchThread == this)
  99. {
  100. g_StepTraceBp->m_MatchThread = NULL;
  101. if (g_WatchFunctions.IsStarted())
  102. {
  103. g_WatchFunctions.End(NULL);
  104. }
  105. ResetStepTrace();
  106. g_StepTraceBp->m_Flags &= ~DEBUG_BREAKPOINT_ENABLED;
  107. }
  108. if (g_DeferBp && g_DeferBp->m_MatchThread == this)
  109. {
  110. g_DeferBp->m_MatchThread = NULL;
  111. }
  112. if (g_SelectedThread == this)
  113. {
  114. SelectExecutionThread(NULL, SELTHREAD_ANY);
  115. }
  116. }
  117. EventString*
  118. ThreadInfo::AllocEventString(ULONG Len)
  119. {
  120. EventString* Str = (EventString*)malloc(sizeof(*Str) + Len);
  121. if (Str)
  122. {
  123. Str->String[0] = 0;
  124. Str->Next = NULL;
  125. }
  126. return Str;
  127. }
  128. void
  129. ThreadInfo::AppendEventString(EventString* EventStr)
  130. {
  131. //
  132. // Add at the end of the list to preserve order.
  133. //
  134. EventStr->Next = NULL;
  135. if (!m_EventStrings)
  136. {
  137. m_EventStrings = EventStr;
  138. }
  139. else
  140. {
  141. EventString* End = m_EventStrings;
  142. while (End->Next)
  143. {
  144. End = End->Next;
  145. }
  146. End->Next = EventStr;
  147. }
  148. }
  149. HRESULT
  150. ThreadInfo::AddEventString(PSTR String)
  151. {
  152. EventString* EventStr;
  153. ULONG Len = strlen(String);
  154. if (!(EventStr = AllocEventString(Len)))
  155. {
  156. return E_OUTOFMEMORY;
  157. }
  158. strcpy(EventStr->String, String);
  159. return S_OK;
  160. }
  161. void
  162. ThreadInfo::ClearEventStrings(void)
  163. {
  164. EventString* Str;
  165. while (m_EventStrings)
  166. {
  167. Str = m_EventStrings;
  168. m_EventStrings = Str->Next;
  169. free(Str);
  170. }
  171. }
  172. void
  173. ThreadInfo::OutputEventStrings(void)
  174. {
  175. EventString* Str;
  176. for (Str = g_EventThread->m_EventStrings; Str; Str = Str->Next)
  177. {
  178. dprintf("%s\n", Str->String);
  179. }
  180. }
  181. void
  182. ThreadInfo::OutputTimes(void)
  183. {
  184. ULONG64 Create, Exit, Kernel, User;
  185. if (m_Process->m_Target->
  186. GetThreadTimes(this, &Create, &Exit, &Kernel, &User) == S_OK)
  187. {
  188. dprintf("Created: %s\n", TimeToStr(FileTimeToTimeDateStamp(Create)));
  189. if (m_Exited)
  190. {
  191. dprintf("Exited: %s\n", TimeToStr(FileTimeToTimeDateStamp(Exit)));
  192. }
  193. dprintf("Kernel: %s\n", DurationToStr(Kernel));
  194. dprintf("User: %s\n", DurationToStr(User));
  195. }
  196. else
  197. {
  198. ErrOut("Thread times not available\n");
  199. }
  200. }
  201. void
  202. ThreadInfo::PrepareForExecution(void)
  203. {
  204. ClearEventStrings();
  205. }
  206. #define TLS_BASE_SLOTS_32 0xe10
  207. #define TLS_EXP_SLOTS_32 0xf94
  208. #define TLS_BASE_SLOTS_64 0x1480
  209. #define TLS_EXP_SLOTS_64 0x1780
  210. HRESULT
  211. ThreadInfo::GetTlsSlotAddress(ULONG Index, PULONG64 Addr)
  212. {
  213. HRESULT Status;
  214. ULONG64 TebBase;
  215. ULONG BaseSlots, ExpSlots, PtrSize;
  216. if (m_Process->m_Target->m_PlatformId != VER_PLATFORM_WIN32_NT)
  217. {
  218. return E_NOTIMPL;
  219. }
  220. if ((Status = m_Process->m_Target->
  221. GetThreadInfoTeb(this, 0, 0, &TebBase)) != S_OK)
  222. {
  223. return Status;
  224. }
  225. if (m_Process->m_Target->m_Machine->m_Ptr64)
  226. {
  227. BaseSlots = TLS_BASE_SLOTS_64;
  228. ExpSlots = TLS_EXP_SLOTS_64;
  229. PtrSize = 8;
  230. }
  231. else
  232. {
  233. BaseSlots = TLS_BASE_SLOTS_32;
  234. ExpSlots = TLS_EXP_SLOTS_32;
  235. PtrSize = 4;
  236. }
  237. if (Index < TLS_MINIMUM_AVAILABLE)
  238. {
  239. *Addr = TebBase + BaseSlots + Index * PtrSize;
  240. return S_OK;
  241. }
  242. else
  243. {
  244. ULONG64 ExpBase;
  245. if (m_Process->m_Target->m_SystemVersion < NT_SVER_W2K)
  246. {
  247. return E_INVALIDARG;
  248. }
  249. if ((Status = m_Process->m_Target->
  250. ReadPointer(m_Process, m_Process->m_Target->m_Machine,
  251. TebBase + ExpSlots, &ExpBase)) != S_OK)
  252. {
  253. return Status;
  254. }
  255. *Addr = ExpBase + Index * PtrSize;
  256. return S_OK;
  257. }
  258. }
  259. //----------------------------------------------------------------------------
  260. //
  261. // Functions.
  262. //
  263. //----------------------------------------------------------------------------
  264. ThreadInfo*
  265. FindAnyThreadByUserId(ULONG Id)
  266. {
  267. TargetInfo* Target;
  268. ProcessInfo* Process;
  269. ThreadInfo* Thread;
  270. ForAllLayers()
  271. {
  272. if (Thread->m_UserId == Id)
  273. {
  274. return Thread;
  275. }
  276. }
  277. return NULL;
  278. }
  279. ThreadInfo*
  280. FindAnyThreadBySystemId(ULONG Id)
  281. {
  282. TargetInfo* Target;
  283. ProcessInfo* Process;
  284. ThreadInfo* Thread;
  285. ForAllLayers()
  286. {
  287. if (Thread->m_SystemId == Id)
  288. {
  289. return Thread;
  290. }
  291. }
  292. return NULL;
  293. }
  294. void
  295. SetCurrentThread(ThreadInfo* Thread, BOOL Hidden)
  296. {
  297. BOOL Changed = g_Thread != Thread;
  298. if (Thread != NULL)
  299. {
  300. Thread->m_Process->m_CurrentThread = Thread;
  301. Thread->m_Process->m_Target->m_CurrentProcess = Thread->m_Process;
  302. SetLayersFromThread(Thread);
  303. if (g_Target)
  304. {
  305. g_Target->ChangeRegContext(Thread);
  306. }
  307. }
  308. else
  309. {
  310. if (g_Target)
  311. {
  312. g_Target->ChangeRegContext(NULL);
  313. }
  314. SetLayersFromTarget(NULL);
  315. }
  316. // We're switching processors so invalidate
  317. // the implicit data pointers so they get refreshed.
  318. ResetImplicitData();
  319. // In kernel targets update the page directory for the current
  320. // processor's page directory base value so that virtual
  321. // memory mappings are done according to the current processor
  322. // state. This only applies to full dumps because triage
  323. // dumps only have a single processor, so there's nothing to
  324. // switch, and summary dumps only guarantee that the crashing
  325. // processor's page directory page is saved. A user can
  326. // still manually change the directory through .context if
  327. // they wish.
  328. if (IS_KERNEL_TARGET(g_Target) && IS_KERNEL_FULL_DUMP(g_Target))
  329. {
  330. if (g_Target->m_Machine->
  331. SetDefaultPageDirectories(Thread, PAGE_DIR_ALL) != S_OK)
  332. {
  333. WarnOut("WARNING: Unable to reset page directories\n");
  334. }
  335. }
  336. if (!Hidden && Changed)
  337. {
  338. if (Thread != NULL)
  339. {
  340. g_Machine->GetPC(&g_AssemDefault);
  341. g_UnasmDefault = g_AssemDefault;
  342. }
  343. NotifyChangeEngineState(DEBUG_CES_CURRENT_THREAD,
  344. Thread != NULL ?
  345. Thread->m_UserId : DEBUG_ANY_ID,
  346. TRUE);
  347. }
  348. }
  349. void
  350. SetCurrentProcessorThread(TargetInfo* Target,
  351. ULONG Processor, BOOL Hidden)
  352. {
  353. //
  354. // Switch to the thread representing a particular processor.
  355. // This only works with the kernel virtual threads.
  356. //
  357. DBG_ASSERT(IS_KERNEL_TARGET(Target));
  358. ThreadInfo* Thread = Target->m_ProcessHead->
  359. FindThreadBySystemId(VIRTUAL_THREAD_ID(Processor));
  360. DBG_ASSERT(Thread != NULL);
  361. if (Thread == NULL)
  362. {
  363. return;
  364. }
  365. SetCurrentThread(Thread, Hidden);
  366. }
  367. void
  368. SaveSetCurrentProcessorThread(TargetInfo* Target, ULONG Processor)
  369. {
  370. // This is only used for kd sessions to conserve
  371. // bandwidth when temporarily switching processors.
  372. DBG_ASSERT(IS_KERNEL_TARGET(Target));
  373. g_RegContextSaved = Target->m_RegContextThread;
  374. g_SavedMachineContext = Target->m_EffMachine->PushContext(NULL);
  375. Target->m_RegContextThread = NULL;
  376. Target->m_RegContextProcessor = -1;
  377. g_SaveImplicitThread = Target->m_ProcessHead->m_ImplicitThreadData;
  378. g_SaveImplicitProcess = Target->m_ImplicitProcessData;
  379. // Don't notify on this change as it is only temporary.
  380. g_EngNotify++;
  381. SetCurrentProcessorThread(Target, Processor, TRUE);
  382. g_EngNotify--;
  383. }
  384. void
  385. RestoreCurrentProcessorThread(TargetInfo* Target)
  386. {
  387. // This is only used for kd sessions to conserve
  388. // bandwidth when temporarily switching processors.
  389. DBG_ASSERT(IS_KERNEL_TARGET(Target));
  390. if (g_RegContextSaved != NULL)
  391. {
  392. Target->m_RegContextProcessor =
  393. VIRTUAL_THREAD_INDEX(g_RegContextSaved->m_Handle);
  394. }
  395. else
  396. {
  397. Target->m_RegContextProcessor = -1;
  398. }
  399. g_LastSelector = -1;
  400. Target->m_RegContextThread = g_RegContextSaved;
  401. Target->m_ProcessHead->m_ImplicitThreadData = g_SaveImplicitThread;
  402. Target->m_ImplicitProcessData = g_SaveImplicitProcess;
  403. Target->m_EffMachine->PopContext(g_SavedMachineContext);
  404. g_SavedMachineContext = NULL;
  405. // Don't notify on this change as it was only temporary.
  406. g_EngNotify++;
  407. SetCurrentThread(Target->m_RegContextThread, TRUE);
  408. g_EngNotify--;
  409. }
  410. void
  411. SetPromptThread(ThreadInfo* Thread, ULONG OciFlags)
  412. {
  413. SetCurrentThread(Thread, FALSE);
  414. ResetCurrentScope();
  415. OutCurInfo(OciFlags, g_Machine->m_AllMask,
  416. DEBUG_OUTPUT_PROMPT_REGISTERS);
  417. // Assem/unasm defaults already reset so just update
  418. // the dump default from them.
  419. g_DumpDefault = g_AssemDefault;
  420. }
  421. void
  422. ParseThreadCmds(DebugClient* Client)
  423. {
  424. CHAR Ch;
  425. ThreadInfo* Thread, *Thrd, *OrigThread;
  426. ULONG Id;
  427. ULONG TraceFlags;
  428. BOOL FreezeThread = FALSE;
  429. PCHAR Tmp;
  430. ULONG64 Frame, Stack, Instr;
  431. ULONG NumFrames, PtrDef;
  432. if (!g_Process)
  433. {
  434. error(BADTHREAD);
  435. }
  436. Ch = PeekChar();
  437. if (Ch == '\0' || Ch == ';')
  438. {
  439. g_Process->OutputThreadInfo(NULL, FALSE);
  440. }
  441. else
  442. {
  443. g_CurCmd++;
  444. Thread = g_Thread;
  445. FreezeThread = TRUE;
  446. if (Ch == '.')
  447. {
  448. // Current thread is the default.
  449. }
  450. else if (Ch == '#')
  451. {
  452. Thread = g_EventThread;
  453. }
  454. else if (Ch == '*')
  455. {
  456. Thread = NULL;
  457. FreezeThread = FALSE;
  458. }
  459. else if (Ch == '[')
  460. {
  461. g_CurCmd--;
  462. Id = (ULONG)GetTermExpression("Thread ID missing from");
  463. Thread = FindAnyThreadByUserId(Id);
  464. if (Thread == NULL)
  465. {
  466. error(BADTHREAD);
  467. }
  468. }
  469. else if (Ch == '~')
  470. {
  471. if (*g_CurCmd != '[')
  472. {
  473. error(SYNTAX);
  474. }
  475. Id = (ULONG)GetTermExpression("Thread ID missing from");
  476. Thread = FindAnyThreadBySystemId(Id);
  477. if (Thread == NULL)
  478. {
  479. error(BADTHREAD);
  480. }
  481. }
  482. else if (Ch >= '0' && Ch <= '9')
  483. {
  484. Id = 0;
  485. do
  486. {
  487. Id = Id * 10 + Ch - '0';
  488. Ch = *g_CurCmd++;
  489. }
  490. while (Ch >= '0' && Ch <= '9');
  491. g_CurCmd--;
  492. Thread = FindAnyThreadByUserId(Id);
  493. if (Thread == NULL)
  494. {
  495. error(BADTHREAD);
  496. }
  497. }
  498. else
  499. {
  500. g_CurCmd--;
  501. }
  502. Ch = PeekChar();
  503. if (Ch == '\0' || Ch == ';')
  504. {
  505. g_Process->OutputThreadInfo(Thread, TRUE);
  506. }
  507. else
  508. {
  509. g_CurCmd++;
  510. switch (Ch = (CHAR)tolower(Ch))
  511. {
  512. case 'b':
  513. Ch = (CHAR)tolower(*g_CurCmd);
  514. g_CurCmd++;
  515. if (Ch != 'p' && Ch != 'a' && Ch != 'u' && Ch != 'm')
  516. {
  517. if (Ch == '\0' || Ch == ';')
  518. {
  519. g_CurCmd--;
  520. }
  521. error(SYNTAX);
  522. }
  523. ParseBpCmd(Client, Ch, Thread);
  524. break;
  525. case 'e':
  526. Tmp = g_CurCmd;
  527. OrigThread = g_Thread;
  528. for (Thrd = g_Process->m_ThreadHead;
  529. Thrd;
  530. Thrd = Thrd->m_Next)
  531. {
  532. if (Thread == NULL || Thrd == Thread)
  533. {
  534. g_CurCmd = Tmp;
  535. SetCurrentThread(Thrd, TRUE);
  536. ProcessCommands(Client, TRUE);
  537. if (g_EngStatus & ENG_STATUS_USER_INTERRUPT)
  538. {
  539. g_EngStatus &= ~ENG_STATUS_USER_INTERRUPT;
  540. break;
  541. }
  542. }
  543. }
  544. SetCurrentThread(OrigThread, TRUE);
  545. break;
  546. case 'f':
  547. case 'u':
  548. if (Thread == NULL)
  549. {
  550. Thread = g_Process->m_ThreadHead;
  551. while (Thread)
  552. {
  553. Thread->m_Frozen = (BOOL)(Ch == 'f');
  554. Thread = Thread->m_Next;
  555. }
  556. }
  557. else
  558. {
  559. Thread->m_Frozen = (BOOL)(Ch == 'f');
  560. }
  561. break;
  562. case 'g':
  563. if (Thread)
  564. {
  565. g_Target->ChangeRegContext(Thread);
  566. }
  567. ParseGoCmd(Thread, FreezeThread);
  568. g_Target->ChangeRegContext(g_Thread);
  569. break;
  570. case 'k':
  571. if (Thread == NULL)
  572. {
  573. Tmp = g_CurCmd;
  574. for (Thread = g_Process->m_ThreadHead;
  575. Thread;
  576. Thread = Thread->m_Next)
  577. {
  578. g_CurCmd = Tmp;
  579. dprintf("\n");
  580. g_Process->OutputThreadInfo(Thread, FALSE);
  581. g_Target->ChangeRegContext(Thread);
  582. ParseStackTrace(&TraceFlags, &Frame,
  583. &Stack, &Instr, &NumFrames,
  584. &PtrDef);
  585. DoStackTrace(Client, Frame, Stack, Instr, PtrDef,
  586. NumFrames, TraceFlags);
  587. if (g_EngStatus & ENG_STATUS_USER_INTERRUPT)
  588. {
  589. break;
  590. }
  591. }
  592. }
  593. else
  594. {
  595. g_Target->ChangeRegContext(Thread);
  596. ParseStackTrace(&TraceFlags, &Frame,
  597. &Stack, &Instr, &NumFrames,
  598. &PtrDef);
  599. DoStackTrace(Client, Frame, Stack, Instr, PtrDef,
  600. NumFrames, TraceFlags);
  601. }
  602. g_Target->ChangeRegContext(g_Thread);
  603. break;
  604. case 'm':
  605. case 'n':
  606. if (!IS_LIVE_USER_TARGET(g_Target))
  607. {
  608. error(SESSIONNOTSUP);
  609. }
  610. ((LiveUserTargetInfo*)g_Target)->
  611. SuspendResumeThreads(g_Process, Ch == 'n', Thread);
  612. break;
  613. case 'p':
  614. case 't':
  615. if (Thread)
  616. {
  617. g_Target->ChangeRegContext(Thread);
  618. }
  619. ParseStepTrace(Thread, FreezeThread, Ch);
  620. g_Target->ChangeRegContext(g_Thread);
  621. break;
  622. case 'r':
  623. if (Thread == NULL)
  624. {
  625. Tmp = g_CurCmd;
  626. for (Thread = g_Process->m_ThreadHead;
  627. Thread;
  628. Thread = Thread->m_Next)
  629. {
  630. g_CurCmd = Tmp;
  631. g_Target->ChangeRegContext(Thread);
  632. ParseRegCmd();
  633. }
  634. }
  635. else
  636. {
  637. g_Target->ChangeRegContext(Thread);
  638. ParseRegCmd();
  639. }
  640. g_Target->ChangeRegContext(g_Thread);
  641. break;
  642. case 's':
  643. if (Thread == NULL)
  644. {
  645. error(BADTHREAD);
  646. }
  647. SetPromptThread(Thread, SPT_DEFAULT_OCI_FLAGS);
  648. break;
  649. default:
  650. error(SYNTAX);
  651. }
  652. }
  653. }
  654. }
  655. BOOL
  656. IsSelectedExecutionThread(ThreadInfo* Thread,
  657. SELECT_EXECUTION_THREAD Type)
  658. {
  659. switch(Type)
  660. {
  661. case SELTHREAD_INTERNAL_THREAD:
  662. // If we're checking whether this is an internally
  663. // selected thread we need an exact match.
  664. return Thread &&
  665. g_SelectExecutionThread == Type && Thread == g_SelectedThread;
  666. case SELTHREAD_THREAD:
  667. // For user-driven execution control there is either
  668. // a specific thread or a match-any state with no thread.
  669. return Thread && (!g_SelectedThread || Thread == g_SelectedThread);
  670. case SELTHREAD_ANY:
  671. // Check to see if any selection has been made.
  672. return !g_SelectedThread;
  673. default:
  674. DBG_ASSERT(FALSE);
  675. return FALSE;
  676. }
  677. }
  678. void
  679. SelectExecutionThread(ThreadInfo* Thread,
  680. SELECT_EXECUTION_THREAD Type)
  681. {
  682. if (!Thread || Type == SELTHREAD_ANY)
  683. {
  684. g_SelectExecutionThread = SELTHREAD_ANY;
  685. g_SelectedThread = NULL;
  686. }
  687. else
  688. {
  689. g_SelectExecutionThread = Type;
  690. g_SelectedThread = Thread;
  691. }
  692. }
  693. BOOL
  694. ThreadWillResume(ThreadInfo* Thread)
  695. {
  696. // If the thread isn't selected for execution or
  697. // it's manually frozen it won't be resumed.
  698. return !Thread->m_Frozen &&
  699. IsSelectedExecutionThread(Thread, SELTHREAD_THREAD);
  700. }