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.

3470 lines
99 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Generic failure analysis framework.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. #include <time.h>
  11. BOOL g_SymbolsReloaded;
  12. HRESULT
  13. ModuleParams::Update(void)
  14. {
  15. HRESULT Status;
  16. ULONG i;
  17. DEBUG_MODULE_PARAMETERS Params;
  18. if (m_Valid)
  19. {
  20. return S_OK;
  21. }
  22. if ((Status = g_ExtSymbols->GetModuleByModuleName(m_Name, 0,
  23. &i, &m_Base)) == S_OK &&
  24. (Status = g_ExtSymbols->GetModuleParameters(1, &m_Base, i,
  25. &Params)) == S_OK)
  26. {
  27. m_Size = Params.Size;
  28. m_Valid = TRUE;
  29. }
  30. return Status;
  31. }
  32. // Read a null terminated string from the address specified.
  33. BOOL ReadAcsiiString(ULONG64 Address, PCHAR DestBuffer, ULONG BufferLen)
  34. {
  35. ULONG OneByteRead;
  36. ULONG BytesRead = 0;
  37. if (Address && DestBuffer)
  38. {
  39. while (BufferLen && ReadMemory(Address, DestBuffer, 1, &OneByteRead))
  40. {
  41. BytesRead++;
  42. if ((*DestBuffer) == 0)
  43. {
  44. return BytesRead;
  45. }
  46. BufferLen--;
  47. DestBuffer++;
  48. Address++;
  49. }
  50. }
  51. return 0;
  52. }
  53. LONG
  54. FaExceptionFilter(
  55. struct _EXCEPTION_POINTERS *ExceptionInfo
  56. )
  57. {
  58. ULONG Code = ExceptionInfo->ExceptionRecord->ExceptionCode;
  59. if (Code == E_OUTOFMEMORY || Code == E_INVALIDARG)
  60. {
  61. // Expected exceptions that the analysis code
  62. // can throw to terminate the analysis. Drop
  63. // into the handler.
  64. return EXCEPTION_EXECUTE_HANDLER;
  65. }
  66. // Otherwise this isn't an exception we expected.
  67. // Let it continue on so that it isn't hidden and
  68. // can be debugged.
  69. return EXCEPTION_CONTINUE_SEARCH;
  70. }
  71. BOOL
  72. FaGetSymbol(
  73. ULONG64 Address,
  74. PCHAR Name,
  75. PULONG64 Disp,
  76. ULONG NameSize
  77. )
  78. {
  79. CHAR Buffer[MAX_PATH] = {0};
  80. *Name = 0;
  81. GetSymbol(Address, Name, Disp);
  82. if (*Name == 0)
  83. {
  84. //
  85. // Get the actual Image name from debugger module list
  86. //
  87. ULONG Index;
  88. CHAR ModBuffer[100];
  89. ULONG64 Base;
  90. if (S_OK == g_ExtSymbols->
  91. GetModuleByOffset(Address, 0, &Index, &Base))
  92. {
  93. if (g_ExtSymbols->
  94. GetModuleNames(Index, Base,
  95. ModBuffer, sizeof(ModBuffer), NULL,
  96. NULL, 0, NULL,
  97. NULL, 0, NULL) == S_OK)
  98. {
  99. PCHAR Break = strrchr(ModBuffer, '\\');
  100. if (Break)
  101. {
  102. CopyString(ModBuffer, Break + 1, sizeof(ModBuffer));
  103. }
  104. CopyString(Name, ModBuffer, NameSize);
  105. if (Break = strchr(Name, '.'))
  106. {
  107. *Break = 0;
  108. }
  109. *Disp = Address - Base;
  110. }
  111. }
  112. }
  113. return (*Name != 0);
  114. }
  115. BOOL
  116. FaIsFunctionAddr(
  117. ULONG64 IP,
  118. PSTR FuncName
  119. )
  120. // Check if IP is in the function FuncName
  121. {
  122. static ULONG64 s_LastIP = 0;
  123. static CHAR s_Buffer[MAX_PATH];
  124. CHAR *Scan, *FnIP;
  125. ULONG64 Disp;
  126. if (s_LastIP != IP)
  127. {
  128. // This would make it faster for multiple IsFunctionAddr for same IP
  129. GetSymbol(IP, s_Buffer, &Disp);
  130. s_LastIP = IP;
  131. }
  132. if (Scan = strchr(s_Buffer, '!'))
  133. {
  134. FnIP = Scan + 1;
  135. while (*FnIP == '_')
  136. {
  137. ++FnIP;
  138. }
  139. }
  140. else
  141. {
  142. FnIP = &s_Buffer[0];
  143. }
  144. return !strncmp(FnIP, FuncName, strlen(FuncName));
  145. }
  146. BOOL
  147. FaGetFollowupInfo(
  148. IN OPTIONAL ULONG64 Addr,
  149. PCHAR SymbolName,
  150. PCHAR Owner,
  151. ULONG OwnerSize
  152. )
  153. {
  154. EXT_TRIAGE_FOLLOWUP FollowUp = &_EFN_GetTriageFollowupFromSymbol;
  155. DEBUG_TRIAGE_FOLLOWUP_INFO Info;
  156. CHAR Buffer[MAX_PATH];
  157. if (!*SymbolName)
  158. {
  159. ULONG64 Disp;
  160. FaGetSymbol(Addr, Buffer, &Disp, sizeof(Buffer));
  161. SymbolName = Buffer;
  162. }
  163. if (*SymbolName)
  164. {
  165. Info.SizeOfStruct = sizeof(Info);
  166. Info.OwnerName = Owner;
  167. Info.OwnerNameSize = (USHORT)OwnerSize;
  168. if ((*FollowUp)(g_ExtClient, SymbolName, &Info) > TRIAGE_FOLLOWUP_IGNORE)
  169. {
  170. // This is an interesting routine to followup on
  171. return TRUE;
  172. }
  173. }
  174. if (Owner)
  175. {
  176. *Owner=0;
  177. }
  178. return FALSE;
  179. }
  180. HRESULT
  181. FaGetPoolTagFollowup(
  182. PCHAR szPoolTag,
  183. PSTR Followup,
  184. ULONG FollowupSize
  185. )
  186. {
  187. ULONG PoolTag;
  188. DEBUG_POOLTAG_DESCRIPTION TagDesc = {0};
  189. PGET_POOL_TAG_DESCRIPTION pGetTagDesc = NULL;
  190. TagDesc.SizeOfStruct = sizeof(TagDesc);
  191. if (g_ExtControl->
  192. GetExtensionFunction(0, "GetPoolTagDescription",
  193. (FARPROC*)&pGetTagDesc) == S_OK &&
  194. pGetTagDesc)
  195. {
  196. PoolTag = *((PULONG) szPoolTag);
  197. if ((*pGetTagDesc)(PoolTag, &TagDesc) == S_OK)
  198. {
  199. PCHAR Dot;
  200. if (Dot = strchr(TagDesc.Binary, '.'))
  201. {
  202. *Dot = 0;
  203. }
  204. if (TagDesc.Binary[0])
  205. {
  206. if (FaGetFollowupInfo(0, TagDesc.Binary, Followup, FollowupSize))
  207. {
  208. return S_OK;
  209. }
  210. }
  211. if (TagDesc.Owner[0])
  212. {
  213. CopyString(Followup, TagDesc.Owner, FollowupSize);
  214. return S_OK;
  215. }
  216. }
  217. }
  218. return E_FAIL;
  219. }
  220. ULONG64
  221. FaGetImplicitStackOffset(
  222. void
  223. )
  224. {
  225. // IDebugRegisters::GetStackOffset not used since it
  226. // ignores implicit context
  227. ULONG64 Stk = 0;
  228. switch (g_TargetMachine)
  229. {
  230. case IMAGE_FILE_MACHINE_I386:
  231. Stk = GetExpression("@esp");
  232. break;
  233. case IMAGE_FILE_MACHINE_IA64:
  234. Stk = GetExpression("@sp");
  235. break;
  236. case IMAGE_FILE_MACHINE_AMD64:
  237. Stk = GetExpression("@rsp");
  238. break;
  239. }
  240. return Stk;
  241. }
  242. DECLARE_API( analyze )
  243. {
  244. ULONG EventType, ProcId, ThreadId;
  245. BOOL Force = FALSE;
  246. BOOL ForceUser = FALSE;
  247. INIT_API();
  248. if (g_ExtControl->GetLastEventInformation(&EventType, &ProcId, &ThreadId,
  249. NULL, 0, NULL,
  250. NULL, 0, NULL) != S_OK)
  251. {
  252. ExtErr("Unable to get last event information\n");
  253. goto Exit;
  254. }
  255. //
  256. // Check for -f in both cases
  257. //
  258. PCSTR tmpArgs = args;
  259. while (*args)
  260. {
  261. if (*args == '-')
  262. {
  263. ++args;
  264. if (*args == 'f')
  265. {
  266. Force = TRUE;
  267. break;
  268. } else if (!strncmp(args, "show",4))
  269. {
  270. Force = TRUE;
  271. } else if (*args == 'u')
  272. {
  273. // could be use for user stack anlysis in k-mode
  274. // ForceUser = TRUE;
  275. }
  276. }
  277. ++args;
  278. }
  279. args = tmpArgs;
  280. //
  281. // Call the correct routine to process the event.
  282. //
  283. if ((EventType == DEBUG_EVENT_EXCEPTION) || (Force == TRUE))
  284. {
  285. ULONG DebugType, DebugQual;
  286. if (g_ExtControl->GetDebuggeeType(&DebugType, &DebugQual) != S_OK)
  287. {
  288. ExtErr("Unable to determine debuggee type\n");
  289. Status = E_FAIL;
  290. }
  291. else
  292. {
  293. if (ForceUser)
  294. {
  295. DebugType = DEBUG_CLASS_USER_WINDOWS;
  296. }
  297. switch(DebugType)
  298. {
  299. case DEBUG_CLASS_KERNEL:
  300. //
  301. // For live debug sessions force the symbols to get reloaded
  302. // the first time as we find many sessions where the
  303. // debugger got reconnected and no module list exists.
  304. // This also happens for user mode breaks in kd where the
  305. // module list is wrong.
  306. //
  307. if ((g_TargetQualifier == DEBUG_KERNEL_CONNECTION) &&
  308. (!g_SymbolsReloaded++))
  309. {
  310. g_ExtSymbols->Reload("");
  311. }
  312. Status = AnalyzeBugCheck(args);
  313. break;
  314. case DEBUG_CLASS_USER_WINDOWS:
  315. Status = AnalyzeUserException(args);
  316. break;
  317. case DEBUG_CLASS_UNINITIALIZED:
  318. ExtErr("No debuggee\n");
  319. Status = E_FAIL;
  320. default:
  321. ExtErr("Unknown debuggee type\n");
  322. Status = E_INVALIDARG;
  323. }
  324. }
  325. }
  326. else if (EventType == 0)
  327. {
  328. dprintf("The debuggee is ready to run\n");
  329. Status = S_OK;
  330. }
  331. else
  332. {
  333. Status = E_NOINTERFACE;
  334. }
  335. if (Status == E_NOINTERFACE)
  336. {
  337. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, ".lastevent",
  338. DEBUG_EXECUTE_DEFAULT);
  339. }
  340. Exit:
  341. EXIT_API();
  342. return Status;
  343. }
  344. HRESULT
  345. _EFN_GetFailureAnalysis(
  346. IN PDEBUG_CLIENT Client,
  347. IN ULONG Flags,
  348. OUT PDEBUG_FAILURE_ANALYSIS* Analysis
  349. )
  350. {
  351. BOOL Enter = (g_ExtClient != Client);
  352. HRESULT Hr;
  353. if (Enter)
  354. {
  355. INIT_API();
  356. }
  357. ULONG DebugType, DebugQual;
  358. if ((Hr = g_ExtControl->GetDebuggeeType(&DebugType,
  359. &DebugQual)) != S_OK)
  360. {
  361. ExtErr("Unable to determine debuggee type\n");
  362. }
  363. else if (DebugType == DEBUG_CLASS_KERNEL)
  364. {
  365. BUGCHECK_ANALYSIS Bc;
  366. *Analysis = (IDebugFailureAnalysis*)BcAnalyze(&Bc, Flags);
  367. Hr = *Analysis ? S_OK : E_OUTOFMEMORY;
  368. }
  369. else if (DebugType == DEBUG_CLASS_USER_WINDOWS)
  370. {
  371. EX_STATE ExState;
  372. *Analysis = (IDebugFailureAnalysis*)UeAnalyze(&ExState, Flags);
  373. Hr = *Analysis ? S_OK : E_OUTOFMEMORY;
  374. }
  375. else
  376. {
  377. Hr = E_INVALIDARG;
  378. }
  379. if (Enter)
  380. {
  381. EXIT_API();
  382. }
  383. return Hr;
  384. }
  385. DECLARE_API( dumpfa )
  386. {
  387. INIT_API();
  388. ULONG64 Address = GetExpression(args);
  389. if (Address)
  390. {
  391. ULONG64 Data;
  392. ULONG64 DataUsed;
  393. ULONG EntrySize;
  394. EntrySize = GetTypeSize("ext!_FA_ENTRY");
  395. InitTypeRead(Address, ext!DebugFailureAnalysis);
  396. Data = ReadField(m_Data);
  397. DataUsed = ReadField(m_DataUsed);
  398. g_ExtControl->Output(1, "DataUsed %x\n", (ULONG)DataUsed);
  399. while (DataUsed > EntrySize)
  400. {
  401. ULONG FullSize;
  402. InitTypeRead(Data, ext!_FA_ENTRY);
  403. g_ExtControl->Output(1,
  404. "Type = %08lx - Size = %x\n",
  405. (ULONG)ReadField(Tag),
  406. ReadField(DataSize));
  407. FullSize = (ULONG)ReadField(FullSize);
  408. Data += FullSize;
  409. DataUsed -= FullSize;
  410. }
  411. }
  412. EXIT_API();
  413. return S_OK;
  414. }
  415. //----------------------------------------------------------------------------
  416. //
  417. // DebugFailureAnalysisImpl.
  418. //
  419. //----------------------------------------------------------------------------
  420. #define FA_ALIGN(Size) (((Size) + 7) & ~7)
  421. #define FA_GROW_BY 4096
  422. #if DBG
  423. #define SCORCH_ENTRY(Entry) \
  424. memset((Entry) + 1, 0xdb, (Entry)->FullSize - sizeof(*(Entry)))
  425. #else
  426. #define SCORCH_ENTRY(Entry)
  427. #endif
  428. #define RAISE_ERROR(Code) RaiseException(Code, 0, 0, NULL)
  429. DebugFailureAnalysis::DebugFailureAnalysis(void)
  430. {
  431. m_Refs = 1;
  432. m_FailureClass = DEBUG_CLASS_UNINITIALIZED;
  433. m_FailureType = DEBUG_FLR_UNKNOWN;
  434. m_FailureCode = 0;
  435. m_Data = NULL;
  436. m_DataLen = 0;
  437. m_DataUsed = 0;
  438. ZeroMemory(PossibleFollowups, sizeof(PossibleFollowups));
  439. BestClassFollowUp = (FlpClasses)0;
  440. }
  441. DebugFailureAnalysis::~DebugFailureAnalysis(void)
  442. {
  443. free(m_Data);
  444. }
  445. STDMETHODIMP
  446. DebugFailureAnalysis::QueryInterface(
  447. THIS_
  448. IN REFIID InterfaceId,
  449. OUT PVOID* Interface
  450. )
  451. {
  452. HRESULT Status;
  453. *Interface = NULL;
  454. Status = S_OK;
  455. if (IsEqualIID(InterfaceId, IID_IUnknown) ||
  456. IsEqualIID(InterfaceId, __uuidof(IDebugFailureAnalysis)))
  457. {
  458. *Interface = (IDebugFailureAnalysis *)this;
  459. AddRef();
  460. }
  461. else
  462. {
  463. Status = E_NOINTERFACE;
  464. }
  465. return Status;
  466. }
  467. STDMETHODIMP_(ULONG)
  468. DebugFailureAnalysis::AddRef(
  469. THIS
  470. )
  471. {
  472. return InterlockedIncrement((PLONG)&m_Refs);
  473. }
  474. STDMETHODIMP_(ULONG)
  475. DebugFailureAnalysis::Release(
  476. THIS
  477. )
  478. {
  479. LONG Refs = InterlockedDecrement((PLONG)&m_Refs);
  480. if (Refs == 0)
  481. {
  482. delete this;
  483. }
  484. return Refs;
  485. }
  486. STDMETHODIMP_(ULONG)
  487. DebugFailureAnalysis::GetFailureClass(void)
  488. {
  489. return m_FailureClass;
  490. }
  491. STDMETHODIMP_(DEBUG_FAILURE_TYPE)
  492. DebugFailureAnalysis::GetFailureType(void)
  493. {
  494. return m_FailureType;
  495. }
  496. STDMETHODIMP_(ULONG)
  497. DebugFailureAnalysis::GetFailureCode(void)
  498. {
  499. return m_FailureCode;
  500. }
  501. STDMETHODIMP_(FA_ENTRY*)
  502. DebugFailureAnalysis::Get(FA_TAG Tag)
  503. {
  504. FA_ENTRY* Entry = NULL;
  505. while ((Entry = NextEntry(Entry)) != NULL)
  506. {
  507. if (Entry->Tag == Tag)
  508. {
  509. return Entry;
  510. }
  511. }
  512. return NULL;
  513. }
  514. STDMETHODIMP_(FA_ENTRY*)
  515. DebugFailureAnalysis::GetNext(FA_ENTRY* Entry, FA_TAG Tag, FA_TAG TagMask)
  516. {
  517. while ((Entry = NextEntry(Entry)) != NULL)
  518. {
  519. if ((Entry->Tag & TagMask) == Tag)
  520. {
  521. return Entry;
  522. }
  523. }
  524. return NULL;
  525. }
  526. STDMETHODIMP_(FA_ENTRY*)
  527. DebugFailureAnalysis::GetString(FA_TAG Tag, PSTR Str, ULONG MaxSize)
  528. {
  529. FA_ENTRY* Entry = Get(Tag);
  530. if (Entry != NULL)
  531. {
  532. if (Entry->DataSize > MaxSize)
  533. {
  534. return NULL;
  535. }
  536. CopyString(Str, FA_ENTRY_DATA(PSTR, Entry),MaxSize);
  537. }
  538. return Entry;
  539. }
  540. STDMETHODIMP_(FA_ENTRY*)
  541. DebugFailureAnalysis::GetBuffer(FA_TAG Tag, PVOID Buf, ULONG Size)
  542. {
  543. FA_ENTRY* Entry = Get(Tag);
  544. if (Entry != NULL)
  545. {
  546. if (Entry->DataSize != Size)
  547. {
  548. return NULL;
  549. }
  550. memcpy(Buf, FA_ENTRY_DATA(PUCHAR, Entry), Size);
  551. }
  552. return Entry;
  553. }
  554. STDMETHODIMP_(FA_ENTRY*)
  555. DebugFailureAnalysis::GetUlong(FA_TAG Tag, PULONG Value)
  556. {
  557. return GetBuffer(Tag, Value, sizeof(*Value));
  558. }
  559. STDMETHODIMP_(FA_ENTRY*)
  560. DebugFailureAnalysis::GetUlong64(FA_TAG Tag, PULONG64 Value)
  561. {
  562. return GetBuffer(Tag, Value, sizeof(*Value));
  563. }
  564. STDMETHODIMP_(FA_ENTRY*)
  565. DebugFailureAnalysis::NextEntry(FA_ENTRY* Entry)
  566. {
  567. if (Entry == NULL)
  568. {
  569. Entry = (FA_ENTRY*)m_Data;
  570. }
  571. else
  572. {
  573. Entry = (FA_ENTRY*)((PUCHAR)Entry + Entry->FullSize);
  574. }
  575. if (ValidEntry(Entry))
  576. {
  577. return Entry;
  578. }
  579. else
  580. {
  581. return NULL;
  582. }
  583. }
  584. FA_ENTRY*
  585. DebugFailureAnalysis::Set(FA_TAG Tag, ULONG Size)
  586. {
  587. FA_ENTRY* Entry;
  588. ULONG FullSize;
  589. // Compute full rounded size.
  590. FullSize = sizeof(FA_ENTRY) + FA_ALIGN(Size);
  591. // Check and see if there's already an entry.
  592. Entry = Get(Tag);
  593. if (Entry != NULL)
  594. {
  595. // If it's already large enough use it and
  596. // pack in remaining data.
  597. if (Entry->FullSize >= FullSize)
  598. {
  599. ULONG Pack = Entry->FullSize - FullSize;
  600. if (Pack > 0)
  601. {
  602. PackData((PUCHAR)Entry + FullSize, Pack);
  603. Entry->FullSize = (USHORT)FullSize;
  604. }
  605. Entry->DataSize = (USHORT)Size;
  606. SCORCH_ENTRY(Entry);
  607. return Entry;
  608. }
  609. // Entry is too small so remove it.
  610. PackData((PUCHAR)Entry, Entry->FullSize);
  611. }
  612. return Add(Tag, Size);
  613. }
  614. FA_ENTRY*
  615. DebugFailureAnalysis::SetString(FA_TAG Tag, PSTR Str)
  616. {
  617. ULONG Size = strlen(Str) + 1;
  618. FA_ENTRY* Entry = Set(Tag, Size);
  619. if (Entry != NULL)
  620. {
  621. memcpy(FA_ENTRY_DATA(PSTR, Entry), Str, Size);
  622. }
  623. return Entry;
  624. }
  625. FA_ENTRY*
  626. DebugFailureAnalysis::SetStrings(FA_TAG Tag, ULONG Count, PSTR* Strs)
  627. {
  628. ULONG i;
  629. ULONG Size = 0;
  630. for (i = 0; i < Count; i++)
  631. {
  632. Size += strlen(Strs[i]) + 1;
  633. }
  634. // Put a double terminator at the very end.
  635. Size++;
  636. FA_ENTRY* Entry = Set(Tag, Size);
  637. if (Entry != NULL)
  638. {
  639. PSTR Data = FA_ENTRY_DATA(PSTR, Entry);
  640. for (i = 0; i < Count; i++)
  641. {
  642. Size = strlen(Strs[i]) + 1;
  643. memcpy(Data, Strs[i], Size);
  644. Data += Size;
  645. }
  646. *Data = 0;
  647. }
  648. return Entry;
  649. }
  650. FA_ENTRY*
  651. DebugFailureAnalysis::SetBuffer(FA_TAG Tag, PVOID Buf, ULONG Size)
  652. {
  653. FA_ENTRY* Entry = Set(Tag, Size);
  654. if (Entry != NULL)
  655. {
  656. memcpy(FA_ENTRY_DATA(PUCHAR, Entry), Buf, Size);
  657. }
  658. return Entry;
  659. }
  660. FA_ENTRY*
  661. DebugFailureAnalysis::Add(FA_TAG Tag, ULONG Size)
  662. {
  663. // Compute full rounded size.
  664. ULONG FullSize = sizeof(FA_ENTRY) + FA_ALIGN(Size);
  665. FA_ENTRY* Entry = AllocateEntry(FullSize);
  666. if (Entry != NULL)
  667. {
  668. Entry->Tag = Tag;
  669. Entry->FullSize = (USHORT)FullSize;
  670. Entry->DataSize = (USHORT)Size;
  671. SCORCH_ENTRY(Entry);
  672. }
  673. return Entry;
  674. }
  675. ULONG
  676. DebugFailureAnalysis::Delete(FA_TAG Tag, FA_TAG TagMask)
  677. {
  678. ULONG Deleted = 0;
  679. FA_ENTRY* Entry = NextEntry(NULL);
  680. while (Entry != NULL)
  681. {
  682. if ((Entry->Tag & TagMask) == Tag)
  683. {
  684. PackData((PUCHAR)Entry, Entry->FullSize);
  685. Deleted++;
  686. // Check and see if we packed away the last entry.
  687. if (!ValidEntry(Entry))
  688. {
  689. break;
  690. }
  691. }
  692. else
  693. {
  694. Entry = NextEntry(Entry);
  695. }
  696. }
  697. return Deleted;
  698. }
  699. void
  700. DebugFailureAnalysis::Empty(void)
  701. {
  702. // Reset used to just the header.
  703. m_DataUsed = 0;
  704. }
  705. FA_ENTRY*
  706. DebugFailureAnalysis::AllocateEntry(ULONG FullSize)
  707. {
  708. // Sizes must fit in USHORTs. This shouldn't be
  709. // a big problem since analyses shouldn't have
  710. // huge data items in them.
  711. if (FullSize > 0xffff)
  712. {
  713. RAISE_ERROR(E_INVALIDARG);
  714. return NULL;
  715. }
  716. if (m_DataUsed + FullSize > m_DataLen)
  717. {
  718. ULONG NewLen = m_DataLen;
  719. do
  720. {
  721. NewLen += FA_GROW_BY;
  722. }
  723. while (m_DataUsed + FullSize > NewLen);
  724. PUCHAR NewData = (PUCHAR)realloc(m_Data, NewLen);
  725. if (NewData == NULL)
  726. {
  727. RAISE_ERROR(E_OUTOFMEMORY);
  728. return NULL;
  729. }
  730. m_Data = NewData;
  731. m_DataLen = NewLen;
  732. }
  733. FA_ENTRY* Entry = (FA_ENTRY*)(m_Data + m_DataUsed);
  734. m_DataUsed += FullSize;
  735. return Entry;
  736. }
  737. void
  738. DebugFailureAnalysis::DbFindBucketInfo(
  739. void
  740. )
  741. {
  742. SolutionDatabaseHandler *Db;
  743. CHAR Solution[SOLUTION_TEXT_SIZE];
  744. CHAR SolOSVer[OS_VER_SIZE];
  745. ULONG RaidBug;
  746. FA_ENTRY* BucketEntry;
  747. FA_ENTRY* GBucketEntry;
  748. FA_ENTRY* DriverNameEntry = NULL;
  749. FA_ENTRY* TimeStampEntry = NULL;
  750. static CHAR SolvedBucket[MAX_PATH] = {0}, SolvedgBucket[MAX_PATH] = {0};
  751. static CHAR SolutionString[MAX_PATH] = {0};
  752. static ULONG SolutionId = 0, SolutionType, SolutionIdgBucket = 0;
  753. if (GetProcessingFlags() & FAILURE_ANALYSIS_NO_DB_LOOKUP)
  754. {
  755. return;
  756. }
  757. if (!(BucketEntry = Get(DEBUG_FLR_BUCKET_ID)))
  758. {
  759. return;
  760. }
  761. if (!strcmp(SolvedBucket, FA_ENTRY_DATA(PCHAR, BucketEntry)))
  762. {
  763. if (SolutionType != CiSolUnsolved)
  764. {
  765. SetString(DEBUG_FLR_INTERNAL_SOLUTION_TEXT, SolutionString);
  766. }
  767. SetUlong(DEBUG_FLR_SOLUTION_ID, SolutionId);
  768. SetUlong(DEBUG_FLR_SOLUTION_TYPE, SolutionType);
  769. // Generic bucket
  770. if (BucketEntry = Get(DEBUG_FLR_DEFAULT_BUCKET_ID))
  771. {
  772. if (!strcmp(SolvedgBucket, FA_ENTRY_DATA(PCHAR, BucketEntry)))
  773. {
  774. SetUlong(DEBUG_FLR_DEFAULT_SOLUTION_ID, SolutionIdgBucket);
  775. }
  776. }
  777. return;
  778. }
  779. // if (!(DriverNameEntry = Get(DEBUG_FLR_IMAGE_NAME)) ||
  780. // !(TimeStampEntry = Get(DEBUG_FLR_IMAGE_TIMESTAMP)))
  781. // {
  782. // return;
  783. // }
  784. HRESULT Hr;
  785. BOOL SolDbInitialized = g_SolDb != NULL;
  786. if (!SolDbInitialized)
  787. {
  788. if (FAILED(Hr = InitializeDatabaseHandlers(g_ExtControl, 4)))
  789. {
  790. // dprintf("Database initialize failed %lx\n", Hr);
  791. return;
  792. }
  793. SolDbInitialized = TRUE;
  794. }
  795. if (g_SolDb->ConnectToDataBase())
  796. {
  797. if (GBucketEntry = Get(DEBUG_FLR_DEFAULT_BUCKET_ID))
  798. {
  799. CopyString(SolvedgBucket, FA_ENTRY_DATA(PCHAR, GBucketEntry), sizeof(SolvedgBucket));
  800. }
  801. //
  802. // List crashes for the same bucket
  803. //
  804. CopyString(SolvedBucket, FA_ENTRY_DATA(PCHAR, BucketEntry), sizeof(SolvedBucket));
  805. if (SUCCEEDED(Hr = g_SolDb->GetSolutionFromDB(FA_ENTRY_DATA(PCHAR, BucketEntry),
  806. SolvedgBucket, NULL, 0,
  807. // FA_ENTRY_DATA(PCHAR, DriverNameEntry),
  808. // (ULONG)(*FA_ENTRY_DATA(PULONG64, TimeStampEntry)),
  809. 0, Solution, SOLUTION_TEXT_SIZE,
  810. &SolutionId, &SolutionType,
  811. &SolutionIdgBucket)))
  812. {
  813. if (SolutionId != 0)
  814. {
  815. SetString(DEBUG_FLR_INTERNAL_SOLUTION_TEXT, Solution);
  816. CopyString(SolutionString, Solution, sizeof(SolutionString));
  817. } else
  818. {
  819. SolutionId = -1; // unsolved
  820. SolutionType = 0;
  821. }
  822. if (SolutionIdgBucket == 0)
  823. {
  824. SolutionIdgBucket = -1; // unsolved
  825. }
  826. SetUlong(DEBUG_FLR_SOLUTION_ID, SolutionId);
  827. SetUlong(DEBUG_FLR_SOLUTION_TYPE, SolutionType);
  828. SetUlong(DEBUG_FLR_DEFAULT_SOLUTION_ID, SolutionIdgBucket);
  829. } else
  830. {
  831. // We did not succesfully look up in DB
  832. SolvedgBucket[0] = '\0';
  833. SolvedBucket[0] = '\0';
  834. }
  835. #if 0
  836. if (SolOSVer[0] != '\0')
  837. {
  838. SetString(DEBUG_FLR_FIXED_IN_OSVERSION, SolOSVer);
  839. }
  840. }
  841. if (Db->FindRaidBug(FA_ENTRY_DATA(PCHAR, Entry),
  842. &RaidBug) == S_OK)
  843. {
  844. SetUlong64(DEBUG_FLR_INTERNAL_RAID_BUG, RaidBug);
  845. }
  846. #endif
  847. }
  848. ;
  849. if (SolDbInitialized)
  850. {
  851. UnInitializeDatabaseHandlers(FALSE);
  852. }
  853. return;
  854. }
  855. FLR_LOOKUP_TABLE FlrLookupTable[] = {
  856. DEBUG_FLR_RESERVED , "RESERVED"
  857. ,DEBUG_FLR_DRIVER_OBJECT , "DRIVER_OBJECT"
  858. ,DEBUG_FLR_DEVICE_OBJECT , "DEVICE_OBJECT"
  859. ,DEBUG_FLR_INVALID_PFN , "INVALID_PFN"
  860. ,DEBUG_FLR_WORKER_ROUTINE , "WORKER_ROUTINE"
  861. ,DEBUG_FLR_WORK_ITEM , "WORK_ITEM"
  862. ,DEBUG_FLR_INVALID_DPC_FOUND , "INVALID_DPC_FOUND"
  863. ,DEBUG_FLR_PROCESS_OBJECT , "PROCESS_OBJECT"
  864. ,DEBUG_FLR_FAILED_INSTRUCTION_ADDRESS , "FAILED_INSTRUCTION_ADDRESS"
  865. ,DEBUG_FLR_LAST_CONTROL_TRANSFER , "LAST_CONTROL_TRANSFER"
  866. ,DEBUG_FLR_ACPI_EXTENSION , "ACPI_EXTENSION"
  867. ,DEBUG_FLR_ACPI_OBJECT , "ACPI_OBJECT"
  868. ,DEBUG_FLR_PROCESS_NAME , "PROCESS_NAME"
  869. ,DEBUG_FLR_READ_ADDRESS , "READ_ADDRESS"
  870. ,DEBUG_FLR_WRITE_ADDRESS , "WRITE_ADDRESS"
  871. ,DEBUG_FLR_CRITICAL_SECTION , "CRITICAL_SECTION"
  872. ,DEBUG_FLR_BAD_HANDLE , "BAD_HANDLE"
  873. ,DEBUG_FLR_INVALID_HEAP_ADDRESS , "INVALID_HEAP_ADDRESS"
  874. ,DEBUG_FLR_IRP_ADDRESS , "IRP_ADDRESS"
  875. ,DEBUG_FLR_IRP_MAJOR_FN , "IRP_MAJOR_FN"
  876. ,DEBUG_FLR_IRP_MINOR_FN , "IRP_MINOR_FN"
  877. ,DEBUG_FLR_IRP_CANCEL_ROUTINE , "IRP_CANCEL_ROUTINE"
  878. ,DEBUG_FLR_IOSB_ADDRESS , "IOSB_ADDRESS"
  879. ,DEBUG_FLR_INVALID_USEREVENT , "INVALID_USEREVENT"
  880. ,DEBUG_FLR_PREVIOUS_MODE , "PREVIOUS_MODE"
  881. ,DEBUG_FLR_CURRENT_IRQL , "CURRENT_IRQL"
  882. ,DEBUG_FLR_PREVIOUS_IRQL , "PREVIOUS_IRQL"
  883. ,DEBUG_FLR_REQUESTED_IRQL , "REQUESTED_IRQL"
  884. ,DEBUG_FLR_ASSERT_DATA , "ASSERT_DATA"
  885. ,DEBUG_FLR_ASSERT_FILE , "ASSERT_FILE_LOCATION"
  886. ,DEBUG_FLR_EXCEPTION_PARAMETER1 , "EXCEPTION_PARAMETER1"
  887. ,DEBUG_FLR_EXCEPTION_PARAMETER2 , "EXCEPTION_PARAMETER2"
  888. ,DEBUG_FLR_EXCEPTION_PARAMETER3 , "EXCEPTION_PARAMETER3"
  889. ,DEBUG_FLR_EXCEPTION_PARAMETER4 , "EXCEPTION_PARAMETER4"
  890. ,DEBUG_FLR_EXCEPTION_RECORD , "EXCEPTION_RECORD"
  891. ,DEBUG_FLR_POOL_ADDRESS , "POOL_ADDRESS"
  892. ,DEBUG_FLR_CORRUPTING_POOL_ADDRESS , "CORRUPTING_POOL_ADDRESS"
  893. ,DEBUG_FLR_CORRUPTING_POOL_TAG , "CORRUPTING_POOL_TAG"
  894. ,DEBUG_FLR_FREED_POOL_TAG , "FREED_POOL_TAG"
  895. ,DEBUG_FLR_SPECIAL_POOL_CORRUPTION_TYPE , "SPECIAL_POOL_CORRUPTION_TYPE"
  896. ,DEBUG_FLR_FILE_ID , "FILE_ID"
  897. ,DEBUG_FLR_FILE_LINE , "FILE_LINE"
  898. ,DEBUG_FLR_BUGCHECK_STR , "BUGCHECK_STR"
  899. ,DEBUG_FLR_BUGCHECK_SPECIFIER , "BUGCHECK_SPECIFIER"
  900. ,DEBUG_FLR_DRIVER_VERIFIER_IO_VIOLATION_TYPE, "DRIVER_VERIFIER_IO_VIOLATION_TYPE"
  901. ,DEBUG_FLR_EXCEPTION_CODE , "EXCEPTION_CODE"
  902. ,DEBUG_FLR_STATUS_CODE , "STATUS_CODE"
  903. ,DEBUG_FLR_IOCONTROL_CODE , "IOCONTROL_CODE"
  904. ,DEBUG_FLR_MM_INTERNAL_CODE , "MM_INTERNAL_CODE"
  905. ,DEBUG_FLR_DRVPOWERSTATE_SUBCODE , "DRVPOWERSTATE_SUBCODE"
  906. ,DEBUG_FLR_CORRUPT_MODULE_LIST , "CORRUPT_MODULE_LIST"
  907. ,DEBUG_FLR_BAD_STACK , "BAD_STACK"
  908. ,DEBUG_FLR_ZEROED_STACK , "ZEROED_STACK"
  909. ,DEBUG_FLR_WRONG_SYMBOLS , "WRONG_SYMBOLS"
  910. ,DEBUG_FLR_FOLLOWUP_DRIVER_ONLY , "FOLLOWUP_DRIVER_ONLY"
  911. ,DEBUG_FLR_CPU_OVERCLOCKED , "CPU_OVERCLOCKED"
  912. ,DEBUG_FLR_MANUAL_BREAKIN , "MANUAL_BREAKIN"
  913. ,DEBUG_FLR_POSSIBLE_INVALID_CONTROL_TRANSFER, "POSSIBLE_INVALID_CONTROL_TRANSFER"
  914. ,DEBUG_FLR_POISONED_TB , "POISONED_TB"
  915. ,DEBUG_FLR_UNKNOWN_MODULE , "UNKNOWN_MODULE"
  916. ,DEBUG_FLR_ANALYZAABLE_POOL_CORRUPTION , "ANALYZAABLE_POOL_CORRUPTION"
  917. ,DEBUG_FLR_SINGLE_BIT_ERROR , "SINGLE_BIT_ERROR"
  918. ,DEBUG_FLR_TWO_BIT_ERROR , "TWO_BIT_ERROR"
  919. ,DEBUG_FLR_INVALID_KERNEL_CONTEXT , "INVALID_KERNEL_CONTEXT"
  920. ,DEBUG_FLR_DISK_HARDWARE_ERROR , "DISK_HARDWARE_ERROR"
  921. ,DEBUG_FLR_POOL_CORRUPTOR , "POOL_CORRUPTOR"
  922. ,DEBUG_FLR_MEMORY_CORRUPTOR , "MEMORY_CORRUPTOR"
  923. ,DEBUG_FLR_UNALIGNED_STACK_POINTER , "UNALIGNED_STACK_POINTER"
  924. ,DEBUG_FLR_OLD_OS_VERSION , "OLD_OS_VERSION"
  925. ,DEBUG_FLR_BUGCHECKING_DRIVER , "BUGCHECKING_DRIVER"
  926. ,DEBUG_FLR_BUCKET_ID , "BUCKET_ID"
  927. ,DEBUG_FLR_IMAGE_NAME , "IMAGE_NAME"
  928. ,DEBUG_FLR_SYMBOL_NAME , "SYMBOL_NAME"
  929. ,DEBUG_FLR_FOLLOWUP_NAME , "FOLLOWUP_NAME"
  930. ,DEBUG_FLR_STACK_COMMAND , "STACK_COMMAND"
  931. ,DEBUG_FLR_STACK_TEXT , "STACK_TEXT"
  932. ,DEBUG_FLR_INTERNAL_SOLUTION_TEXT , "INTERNAL_SOLUTION_TEXT"
  933. ,DEBUG_FLR_MODULE_NAME , "MODULE_NAME"
  934. ,DEBUG_FLR_INTERNAL_RAID_BUG , "INTERNAL_RAID_BUG"
  935. ,DEBUG_FLR_FIXED_IN_OSVERSION , "FIXED_IN_OSVERSION"
  936. ,DEBUG_FLR_DEFAULT_BUCKET_ID , "DEFAULT_BUCKET_ID"
  937. ,DEBUG_FLR_FAULTING_IP , "FAULTING_IP"
  938. ,DEBUG_FLR_FAULTING_MODULE , "FAULTING_MODULE"
  939. ,DEBUG_FLR_IMAGE_TIMESTAMP , "DEBUG_FLR_IMAGE_TIMESTAMP"
  940. ,DEBUG_FLR_FOLLOWUP_IP , "FOLLOWUP_IP"
  941. ,DEBUG_FLR_FAULTING_THREAD , "FAULTING_THREAD"
  942. ,DEBUG_FLR_CONTEXT , "CONTEXT"
  943. ,DEBUG_FLR_TRAP_FRAME , "TRAP_FRAME"
  944. ,DEBUG_FLR_TSS , "TSS"
  945. ,DEBUG_FLR_SHOW_ERRORLOG , "ERROR_LOG"
  946. ,DEBUG_FLR_MASK_ALL , "MASK_ALL"
  947. // Zero entry Must be last;
  948. ,DEBUG_FLR_INVALID , "INVALID"
  949. };
  950. void
  951. DebugFailureAnalysis::OutputEntryParam(DEBUG_FLR_PARAM_TYPE Type)
  952. {
  953. FA_ENTRY *Entry = Get(Type);
  954. if (Entry)
  955. {
  956. OutputEntry(Entry);
  957. }
  958. }
  959. void
  960. DebugFailureAnalysis::OutputEntry(FA_ENTRY* Entry)
  961. {
  962. CHAR Buffer[MAX_PATH];
  963. CHAR Module[MAX_PATH];
  964. ULONG64 Base;
  965. ULONG64 Address;
  966. ULONG OutCtl;
  967. ULONG i = 0;
  968. OutCtl = DEBUG_OUTCTL_AMBIENT;
  969. switch(Entry->Tag)
  970. {
  971. // These are just tags - don't print out
  972. case DEBUG_FLR_CORRUPT_MODULE_LIST:
  973. case DEBUG_FLR_BAD_STACK:
  974. case DEBUG_FLR_ZEROED_STACK:
  975. case DEBUG_FLR_WRONG_SYMBOLS:
  976. case DEBUG_FLR_FOLLOWUP_DRIVER_ONLY:
  977. case DEBUG_FLR_UNKNOWN_MODULE:
  978. case DEBUG_FLR_ANALYZAABLE_POOL_CORRUPTION:
  979. case DEBUG_FLR_INVALID_KERNEL_CONTEXT:
  980. case DEBUG_FLR_SOLUTION_TYPE:
  981. case DEBUG_FLR_MANUAL_BREAKIN:
  982. // soluion ids from DB
  983. case DEBUG_FLR_SOLUTION_ID:
  984. case DEBUG_FLR_DEFAULT_SOLUTION_ID:
  985. // Field folded into others
  986. case DEBUG_FLR_BUGCHECK_SPECIFIER:
  987. return;
  988. // Marged with other output
  989. return;
  990. }
  991. //
  992. // Find the entry in the description table
  993. //
  994. while(FlrLookupTable[i].Data &&
  995. Entry->Tag != FlrLookupTable[i].Data)
  996. {
  997. i++;
  998. }
  999. dprintf("\n%s: ", FlrLookupTable[i].String);
  1000. switch(Entry->Tag)
  1001. {
  1002. // Notification to user
  1003. case DEBUG_FLR_DISK_HARDWARE_ERROR:
  1004. // FlrLookupTable value has already been printed
  1005. dprintf("There was error with disk hardware\n");
  1006. break;
  1007. // Strings:
  1008. case DEBUG_FLR_ASSERT_DATA:
  1009. case DEBUG_FLR_ASSERT_FILE:
  1010. case DEBUG_FLR_BUCKET_ID:
  1011. case DEBUG_FLR_DEFAULT_BUCKET_ID:
  1012. case DEBUG_FLR_STACK_TEXT:
  1013. case DEBUG_FLR_STACK_COMMAND:
  1014. case DEBUG_FLR_INTERNAL_SOLUTION_TEXT:
  1015. case DEBUG_FLR_FIXED_IN_OSVERSION:
  1016. case DEBUG_FLR_BUGCHECK_STR:
  1017. case DEBUG_FLR_IMAGE_NAME:
  1018. case DEBUG_FLR_MODULE_NAME:
  1019. case DEBUG_FLR_PROCESS_NAME:
  1020. case DEBUG_FLR_FOLLOWUP_NAME:
  1021. case DEBUG_FLR_POOL_CORRUPTOR:
  1022. case DEBUG_FLR_MEMORY_CORRUPTOR:
  1023. case DEBUG_FLR_BUGCHECKING_DRIVER:
  1024. case DEBUG_FLR_SYMBOL_NAME:
  1025. case DEBUG_FLR_CORRUPTING_POOL_TAG:
  1026. case DEBUG_FLR_FREED_POOL_TAG:
  1027. dprintf(" %s\n", FA_ENTRY_DATA(PCHAR, Entry));
  1028. break;
  1029. // DWORDs:
  1030. case DEBUG_FLR_PREVIOUS_IRQL:
  1031. case DEBUG_FLR_CURRENT_IRQL:
  1032. case DEBUG_FLR_MM_INTERNAL_CODE:
  1033. case DEBUG_FLR_SPECIAL_POOL_CORRUPTION_TYPE:
  1034. case DEBUG_FLR_PREVIOUS_MODE:
  1035. case DEBUG_FLR_IMAGE_TIMESTAMP:
  1036. case DEBUG_FLR_SINGLE_BIT_ERROR:
  1037. case DEBUG_FLR_TWO_BIT_ERROR:
  1038. dprintf(" %lx\n", *FA_ENTRY_DATA(PULONG64, Entry));
  1039. break;
  1040. // DWORDs:
  1041. case DEBUG_FLR_INTERNAL_RAID_BUG:
  1042. case DEBUG_FLR_OLD_OS_VERSION:
  1043. dprintf(" %d\n", *FA_ENTRY_DATA(PULONG64, Entry));
  1044. break;
  1045. // Pointers
  1046. case DEBUG_FLR_PROCESS_OBJECT:
  1047. case DEBUG_FLR_DEVICE_OBJECT:
  1048. case DEBUG_FLR_DRIVER_OBJECT:
  1049. case DEBUG_FLR_ACPI_OBJECT:
  1050. case DEBUG_FLR_IRP_ADDRESS:
  1051. case DEBUG_FLR_EXCEPTION_PARAMETER1:
  1052. case DEBUG_FLR_EXCEPTION_PARAMETER2:
  1053. case DEBUG_FLR_FAULTING_THREAD:
  1054. case DEBUG_FLR_WORK_ITEM:
  1055. dprintf(" %p\n", *FA_ENTRY_DATA(PULONG64, Entry));
  1056. break;
  1057. // Pointers to code
  1058. case DEBUG_FLR_WORKER_ROUTINE:
  1059. case DEBUG_FLR_IRP_CANCEL_ROUTINE:
  1060. case DEBUG_FLR_FAILED_INSTRUCTION_ADDRESS:
  1061. case DEBUG_FLR_FAULTING_IP:
  1062. case DEBUG_FLR_FOLLOWUP_IP:
  1063. case DEBUG_FLR_FAULTING_MODULE:
  1064. FaGetSymbol(*FA_ENTRY_DATA(PULONG64, Entry), Buffer, &Address, sizeof(Buffer));
  1065. dprintf("\n%s+%I64lx\n", Buffer, Address);
  1066. g_ExtControl->OutputDisassemblyLines(OutCtl, 0, 1,
  1067. *FA_ENTRY_DATA(PULONG64, Entry),
  1068. 0, NULL, NULL, NULL, NULL);
  1069. break;
  1070. // Address description
  1071. case DEBUG_FLR_READ_ADDRESS:
  1072. case DEBUG_FLR_WRITE_ADDRESS:
  1073. case DEBUG_FLR_POOL_ADDRESS:
  1074. case DEBUG_FLR_CORRUPTING_POOL_ADDRESS:
  1075. {
  1076. PCSTR Desc = DescribeAddress(*FA_ENTRY_DATA(PULONG64, Entry));
  1077. if (!Desc)
  1078. {
  1079. Desc = "";
  1080. }
  1081. dprintf(" %p %s\n", *FA_ENTRY_DATA(PULONG64, Entry), Desc);
  1082. break;
  1083. }
  1084. case DEBUG_FLR_EXCEPTION_CODE:
  1085. case DEBUG_FLR_STATUS_CODE:
  1086. {
  1087. DEBUG_DECODE_ERROR Err;
  1088. Err.Code = (ULONG) *FA_ENTRY_DATA(PULONG, Entry);
  1089. Err.TreatAsStatus = (Entry->Tag == DEBUG_FLR_STATUS_CODE);
  1090. // dprintf(" %lx", *FA_ENTRY_DATA(PULONG, Entry));
  1091. DecodeErrorForMessage( &Err );
  1092. if (!Err.TreatAsStatus)
  1093. {
  1094. dprintf("(%s) %#x (%u) - %s\n",
  1095. Err.Source, Err.Code, Err.Code, Err.Message);
  1096. }
  1097. else
  1098. {
  1099. dprintf("(%s) %#x - %s\n",
  1100. Err.Source, Err.Code, Err.Message);
  1101. }
  1102. break;
  1103. }
  1104. case DEBUG_FLR_CPU_OVERCLOCKED:
  1105. dprintf(" *** Machine was determined to be overclocked !\n");
  1106. break;
  1107. case DEBUG_FLR_ACPI_EXTENSION:
  1108. dprintf(" %p -- (!acpikd.acpiext %p)\n", *FA_ENTRY_DATA(PULONG64, Entry),
  1109. *FA_ENTRY_DATA(PULONG64, Entry));
  1110. sprintf(Buffer, "!acpikd.acpiext %I64lx", *FA_ENTRY_DATA(PULONG64, Entry));
  1111. g_ExtControl->Execute(OutCtl, Buffer, DEBUG_EXECUTE_DEFAULT);
  1112. break;
  1113. case DEBUG_FLR_TRAP_FRAME:
  1114. dprintf(" %p -- (.trap %I64lx)\n", *FA_ENTRY_DATA(PULONG64, Entry),
  1115. *FA_ENTRY_DATA(PULONG64, Entry));
  1116. sprintf(Buffer, ".trap %I64lx", *FA_ENTRY_DATA(PULONG64, Entry));
  1117. g_ExtControl->Execute(OutCtl, Buffer, DEBUG_EXECUTE_DEFAULT);
  1118. g_ExtControl->Execute(OutCtl, ".trap", DEBUG_EXECUTE_DEFAULT);
  1119. break;
  1120. case DEBUG_FLR_CONTEXT:
  1121. dprintf(" %p -- (.cxr %I64lx)\n", *FA_ENTRY_DATA(PULONG64, Entry),
  1122. *FA_ENTRY_DATA(PULONG64, Entry));
  1123. sprintf(Buffer, ".cxr %I64lx", *FA_ENTRY_DATA(PULONG64, Entry));
  1124. g_ExtControl->Execute(OutCtl, Buffer, DEBUG_EXECUTE_DEFAULT);
  1125. g_ExtControl->Execute(OutCtl, ".cxr", DEBUG_EXECUTE_DEFAULT);
  1126. break;
  1127. case DEBUG_FLR_EXCEPTION_RECORD:
  1128. dprintf(" %p -- (.exr %I64lx)\n", *FA_ENTRY_DATA(PULONG64, Entry),
  1129. *FA_ENTRY_DATA(PULONG64, Entry));
  1130. sprintf(Buffer, ".exr %I64lx", *FA_ENTRY_DATA(PULONG64, Entry));
  1131. g_ExtControl->Execute(OutCtl, Buffer, DEBUG_EXECUTE_DEFAULT);
  1132. break;
  1133. case DEBUG_FLR_TSS:
  1134. dprintf(" %p -- (.tss %I64lx)\n", *FA_ENTRY_DATA(PULONG64, Entry),
  1135. *FA_ENTRY_DATA(PULONG64, Entry));
  1136. sprintf(Buffer, ".tss %I64lx", *FA_ENTRY_DATA(PULONG64, Entry));
  1137. g_ExtControl->Execute(OutCtl, Buffer, DEBUG_EXECUTE_DEFAULT);
  1138. g_ExtControl->Execute(OutCtl, ".trap", DEBUG_EXECUTE_DEFAULT);
  1139. break;
  1140. case DEBUG_FLR_LAST_CONTROL_TRANSFER:
  1141. case DEBUG_FLR_POSSIBLE_INVALID_CONTROL_TRANSFER:
  1142. dprintf(" from %p to %p\n",
  1143. FA_ENTRY_DATA(PULONG64, Entry)[0],
  1144. FA_ENTRY_DATA(PULONG64, Entry)[1]);
  1145. break;
  1146. case DEBUG_FLR_CRITICAL_SECTION:
  1147. dprintf("%p (!cs -s %p)\n",
  1148. *FA_ENTRY_DATA(PULONG64, Entry),
  1149. *FA_ENTRY_DATA(PULONG64, Entry));
  1150. break;
  1151. case DEBUG_FLR_BAD_HANDLE:
  1152. dprintf("%p (!htrace %p)\n",
  1153. *FA_ENTRY_DATA(PULONG64, Entry),
  1154. *FA_ENTRY_DATA(PULONG64, Entry));
  1155. break;
  1156. case DEBUG_FLR_INVALID_HEAP_ADDRESS:
  1157. dprintf("%p (!heap -p -a %p)\n",
  1158. *FA_ENTRY_DATA(PULONG64, Entry),
  1159. *FA_ENTRY_DATA(PULONG64, Entry));
  1160. break;
  1161. case DEBUG_FLR_SHOW_ERRORLOG:
  1162. g_ExtControl->Execute(OutCtl, "!errlog", DEBUG_EXECUTE_DEFAULT);
  1163. break;
  1164. default:
  1165. dprintf(" *** Unknown TAG in analysis list %lx\n\n",
  1166. Entry->Tag);
  1167. return;
  1168. }
  1169. return;
  1170. }
  1171. void
  1172. DebugFailureAnalysis::Output()
  1173. {
  1174. ULONG RetVal;
  1175. FA_ENTRY* Entry;
  1176. BOOL Verbose = (GetProcessingFlags() & FAILURE_ANALYSIS_VERBOSE);
  1177. //
  1178. // In verbose mode, show everything that we figured out during analysis
  1179. //
  1180. if (Verbose)
  1181. {
  1182. Entry = NULL;
  1183. while (Entry = NextEntry(Entry))
  1184. {
  1185. OutputEntry(Entry);
  1186. }
  1187. }
  1188. if (Get(DEBUG_FLR_POISONED_TB))
  1189. {
  1190. dprintf("*** WARNING: nt!MmPoisonedTb is non-zero:\n"
  1191. "*** The machine has been manipulated using the kernel debugger.\n"
  1192. "*** MachineOwner should be contacted first\n\n\n");
  1193. }
  1194. PCHAR SolInOS = NULL;
  1195. if (Entry = Get(DEBUG_FLR_FIXED_IN_OSVERSION))
  1196. {
  1197. SolInOS = FA_ENTRY_DATA(PCHAR, Entry);
  1198. }
  1199. PCHAR Solution = NULL;
  1200. if (Entry = Get(DEBUG_FLR_INTERNAL_SOLUTION_TEXT))
  1201. {
  1202. Solution = FA_ENTRY_DATA(PCHAR, Entry);
  1203. }
  1204. //
  1205. // Print the bad driver if we are not in verbose mode - otherwise
  1206. // is is printed out using the params
  1207. //
  1208. if (!Verbose && !Solution)
  1209. {
  1210. if (Entry = Get(DEBUG_FLR_CORRUPTING_POOL_TAG))
  1211. {
  1212. dprintf("Probably pool corruption caused by Tag: %s\n",
  1213. FA_ENTRY_DATA(PCHAR, Entry));
  1214. }
  1215. else
  1216. {
  1217. PCHAR DriverName = NULL;
  1218. PCHAR SymName = NULL;
  1219. if (Entry = Get(DEBUG_FLR_IMAGE_NAME))
  1220. {
  1221. DriverName = FA_ENTRY_DATA(PCHAR, Entry);
  1222. }
  1223. if (Entry = Get(DEBUG_FLR_SYMBOL_NAME))
  1224. {
  1225. SymName = FA_ENTRY_DATA(PCHAR, Entry);
  1226. }
  1227. if (DriverName || SymName)
  1228. {
  1229. dprintf("Probably caused by : ");
  1230. if (SymName && DriverName)
  1231. {
  1232. dprintf("%s ( %s )\n", DriverName, SymName);
  1233. }
  1234. else if (SymName)
  1235. {
  1236. dprintf("%s\n", SymName);
  1237. }
  1238. else
  1239. {
  1240. dprintf("%s\n", DriverName);
  1241. }
  1242. }
  1243. }
  1244. }
  1245. if (Verbose || !Solution)
  1246. {
  1247. PCHAR FollowupAlias = NULL;
  1248. //
  1249. // Print what the user should do:
  1250. // - Followup person
  1251. // - Solution text if there is one.
  1252. //
  1253. if (Entry = Get(DEBUG_FLR_FOLLOWUP_NAME))
  1254. {
  1255. dprintf("\nFollowup: %s\n", FA_ENTRY_DATA(PCHAR, Entry));
  1256. }
  1257. else
  1258. {
  1259. dprintf(" *** Followup info cannot be found !!! Please contact \"Debugger Team\"\n");
  1260. }
  1261. dprintf("---------\n");
  1262. if (Entry = Get(DEBUG_FLR_POSSIBLE_INVALID_CONTROL_TRANSFER))
  1263. {
  1264. CHAR Buffer[MAX_PATH];
  1265. ULONG64 Address;
  1266. FaGetSymbol(FA_ENTRY_DATA(PULONG64, Entry)[0], Buffer, &Address, sizeof(Buffer));
  1267. dprintf(" *** Possible invalid call from %p ( %s+0x%1p )\n",
  1268. FA_ENTRY_DATA(PULONG64, Entry)[0],
  1269. Buffer,
  1270. Address);
  1271. FaGetSymbol(FA_ENTRY_DATA(PULONG64, Entry)[1], Buffer, &Address, sizeof(Buffer));
  1272. dprintf(" *** Expected target %p ( %s+0x%1p )\n",
  1273. FA_ENTRY_DATA(PULONG64, Entry)[1],
  1274. Buffer,
  1275. Address);
  1276. }
  1277. dprintf("\n");
  1278. }
  1279. if (Entry = Get(DEBUG_FLR_INTERNAL_RAID_BUG))
  1280. {
  1281. dprintf("Raid bug for this failure: %d\n\n",
  1282. *FA_ENTRY_DATA(PULONG64, Entry));
  1283. }
  1284. if (Solution)
  1285. {
  1286. dprintf(" This problem has a known fix.\n"
  1287. " Please connect to the following URL for details:\n"
  1288. " ------------------------------------------------\n"
  1289. " %s\n\n",
  1290. Solution);
  1291. }
  1292. if (SolInOS)
  1293. {
  1294. dprintf(" This has been fixed in : %s\n", SolInOS);
  1295. }
  1296. }
  1297. LPSTR
  1298. TimeToStr(
  1299. ULONG TimeDateStamp,
  1300. BOOL DateOnly
  1301. )
  1302. {
  1303. LPSTR TimeDateStr; // pointer to static cruntime buffer.
  1304. static char datebuffer[100];
  1305. tm * pTime;
  1306. time_t TDStamp = (time_t) (LONG) TimeDateStamp;
  1307. // Handle invalid \ page out timestamps, since ctime blows up on
  1308. // this number
  1309. if ((TimeDateStamp == 0) || (TimeDateStamp == -1))
  1310. {
  1311. return "unknown_date";
  1312. }
  1313. else if (DateOnly)
  1314. {
  1315. pTime = localtime(&TDStamp);
  1316. sprintf(datebuffer, "%d_%d_%d",
  1317. pTime->tm_mon + 1, pTime->tm_mday, pTime->tm_year + 1900);
  1318. return datebuffer;
  1319. }
  1320. else
  1321. {
  1322. // TimeDateStamp is always a 32 bit quantity on the target,
  1323. // and we need to sign extend for 64 bit host since time_t
  1324. // has been extended to 64 bits.
  1325. TDStamp = (time_t) (LONG) TimeDateStamp;
  1326. TimeDateStr = ctime((time_t *)&TDStamp);
  1327. if (TimeDateStr)
  1328. {
  1329. TimeDateStr[strlen(TimeDateStr) - 1] = 0;
  1330. }
  1331. else
  1332. {
  1333. TimeDateStr = "***** Invalid";
  1334. }
  1335. return TimeDateStr;
  1336. }
  1337. }
  1338. void
  1339. DebugFailureAnalysis::GenerateBucketId(void)
  1340. {
  1341. ULONG LengthUsed = 0;
  1342. CHAR BucketId[MAX_PATH] = {0};
  1343. PSTR BucketPtr = BucketId;
  1344. PSTR Str;
  1345. FA_ENTRY* Entry;
  1346. FA_ENTRY* NameEntry;
  1347. FA_ENTRY* ModuleEntry;
  1348. ULONG ModuleTimestamp = 0;
  1349. CHAR Command[MAX_PATH] = {0};
  1350. CHAR followup[MAX_PATH];
  1351. //
  1352. // Set the final command string
  1353. //
  1354. if (Entry = Get(DEBUG_FLR_STACK_COMMAND))
  1355. {
  1356. CopyString(Command, FA_ENTRY_DATA(PSTR, Entry), sizeof(Command) - 5);
  1357. strcat(Command, " ; ");
  1358. }
  1359. strcat(Command, "kb");
  1360. SetString(DEBUG_FLR_STACK_COMMAND, Command);
  1361. if (Get(DEBUG_FLR_OLD_OS_VERSION))
  1362. {
  1363. SetString(DEBUG_FLR_DEFAULT_BUCKET_ID, "OLD_OS");
  1364. }
  1365. //
  1366. // Don't change the bucket ID for these two things as the debugger code
  1367. // to detect them is not 100% reliable.
  1368. //
  1369. //if (Get(DEBUG_FLR_CPU_OVERCLOCKED))
  1370. //{
  1371. // SetString(DEBUG_FLR_BUCKET_ID, "CPU_OVERCLOCKED");
  1372. // return;
  1373. //}
  1374. //
  1375. //
  1376. // If the faulting module exists:
  1377. // Get the module timestamp of the faulting module.
  1378. // Check if it is an old driver.
  1379. //
  1380. ModuleEntry = Get(DEBUG_FLR_MODULE_NAME);
  1381. if (ModuleEntry)
  1382. {
  1383. ULONG Index;
  1384. ULONG64 Base;
  1385. DEBUG_MODULE_PARAMETERS Params;
  1386. g_ExtSymbols->GetModuleByModuleName(FA_ENTRY_DATA(PCHAR, ModuleEntry),
  1387. 0, &Index, &Base);
  1388. if (Base &&
  1389. g_ExtSymbols->GetModuleParameters(1, &Base, Index, &Params) == S_OK)
  1390. {
  1391. ModuleTimestamp = Params.TimeDateStamp;
  1392. }
  1393. }
  1394. NameEntry = Get(DEBUG_FLR_IMAGE_NAME);
  1395. if (NameEntry)
  1396. {
  1397. if (!strcmp(FA_ENTRY_DATA(PCHAR, NameEntry), "Unknown_Image"))
  1398. {
  1399. NameEntry = NULL;
  1400. }
  1401. }
  1402. if (ModuleTimestamp && NameEntry)
  1403. {
  1404. PCHAR String;
  1405. ULONG LookupTimestamp;
  1406. String = g_pTriager->GetFollowupStr("OldImages",
  1407. FA_ENTRY_DATA(PCHAR, NameEntry));
  1408. if (String)
  1409. {
  1410. LookupTimestamp = strtol(String, NULL, 16);
  1411. //
  1412. // If the driver is known to be bad, just use driver name
  1413. //
  1414. if (LookupTimestamp > ModuleTimestamp)
  1415. {
  1416. if (FaGetFollowupInfo(NULL,
  1417. FA_ENTRY_DATA(PCHAR, ModuleEntry),
  1418. followup,
  1419. sizeof(followup)))
  1420. {
  1421. SetString(DEBUG_FLR_FOLLOWUP_NAME, followup);
  1422. }
  1423. //sprintf(BucketPtr, "OLD_IMAGE_%s_TS_%lX",
  1424. // FA_ENTRY_DATA(PCHAR, NameEntry),
  1425. // ModuleTimestamp);
  1426. PrintString(BucketPtr, sizeof(BucketId) - LengthUsed, "OLD_IMAGE_%s",
  1427. FA_ENTRY_DATA(PCHAR, NameEntry));
  1428. SetString(DEBUG_FLR_BUCKET_ID, BucketId);
  1429. return;
  1430. }
  1431. }
  1432. }
  1433. if (Entry = Get(DEBUG_FLR_POSSIBLE_INVALID_CONTROL_TRANSFER))
  1434. {
  1435. if (Get(DEBUG_FLR_SINGLE_BIT_ERROR))
  1436. {
  1437. SetString(DEBUG_FLR_BUCKET_ID, "SINGLE_BIT_CPU_CALL_ERROR");
  1438. }
  1439. else if (Get(DEBUG_FLR_TWO_BIT_ERROR))
  1440. {
  1441. SetString(DEBUG_FLR_BUCKET_ID, "TWO_BIT_CPU_CALL_ERROR");
  1442. }
  1443. else
  1444. {
  1445. SetString(DEBUG_FLR_BUCKET_ID, "CPU_CALL_ERROR");
  1446. }
  1447. return;
  1448. }
  1449. if (Entry = Get(DEBUG_FLR_MANUAL_BREAKIN))
  1450. {
  1451. SetString(DEBUG_FLR_BUCKET_ID, "MANUAL_BREAKIN");
  1452. SetString(DEBUG_FLR_FOLLOWUP_NAME, "MachineOwner");
  1453. return;
  1454. }
  1455. if (!PossibleFollowups[FlpSpecific].Owner[0])
  1456. {
  1457. BOOL bPoolTag = FALSE;
  1458. if (Entry = Get(DEBUG_FLR_BUGCHECKING_DRIVER))
  1459. {
  1460. PrintString(BucketPtr, sizeof(BucketId) - LengthUsed,
  1461. "%s_BUGCHECKING_DRIVER_%s",
  1462. FA_ENTRY_DATA(PCHAR, Get(DEBUG_FLR_BUGCHECK_STR)),
  1463. FA_ENTRY_DATA(PCHAR, Entry));
  1464. }
  1465. else if (Entry = Get(DEBUG_FLR_MEMORY_CORRUPTOR))
  1466. {
  1467. PrintString(BucketPtr, sizeof(BucketId) - LengthUsed,
  1468. "MEMORY_CORRUPTION_%s",
  1469. FA_ENTRY_DATA(PCHAR, Entry));
  1470. }
  1471. else if (Entry = Get(DEBUG_FLR_POOL_CORRUPTOR))
  1472. {
  1473. PrintString(BucketPtr, sizeof(BucketId) - LengthUsed,
  1474. "POOL_CORRUPTION_%s",
  1475. FA_ENTRY_DATA(PCHAR, Entry));
  1476. }
  1477. else if (Entry = Get(DEBUG_FLR_CORRUPTING_POOL_TAG))
  1478. {
  1479. PrintString(BucketPtr, sizeof(BucketId) - LengthUsed,
  1480. "CORRUPTING_POOLTAG_%s",
  1481. FA_ENTRY_DATA(PCHAR, Entry));
  1482. bPoolTag = TRUE;
  1483. }
  1484. if (Entry)
  1485. {
  1486. if (bPoolTag &&
  1487. (FaGetPoolTagFollowup(FA_ENTRY_DATA(PCHAR, Entry),
  1488. followup,
  1489. sizeof(followup)) == S_OK))
  1490. {
  1491. SetString(DEBUG_FLR_FOLLOWUP_NAME, followup);
  1492. } else if (FaGetFollowupInfo(NULL,
  1493. FA_ENTRY_DATA(PCHAR, Entry),
  1494. followup,
  1495. sizeof(followup)))
  1496. {
  1497. SetString(DEBUG_FLR_FOLLOWUP_NAME, followup);
  1498. }
  1499. SetString(DEBUG_FLR_BUCKET_ID, BucketId);
  1500. return;
  1501. }
  1502. }
  1503. //
  1504. // Only check this after as we could still have found a bad driver
  1505. // with a bad stack (like drivers that cause stack corruption ...)
  1506. //
  1507. Str = NULL;
  1508. Entry = NULL;
  1509. while (Entry = NextEntry(Entry))
  1510. {
  1511. switch(Entry->Tag)
  1512. {
  1513. case DEBUG_FLR_WRONG_SYMBOLS:
  1514. Str = "WRONG_SYMBOLS";
  1515. break;
  1516. case DEBUG_FLR_BAD_STACK:
  1517. Str = "BAD_STACK";
  1518. break;
  1519. case DEBUG_FLR_ZEROED_STACK:
  1520. Str = "ZEROED_STACK";
  1521. break;
  1522. case DEBUG_FLR_INVALID_KERNEL_CONTEXT:
  1523. Str = "INVALID_KERNEL_CONTEXT";
  1524. break;
  1525. case DEBUG_FLR_CORRUPT_MODULE_LIST:
  1526. Str = "CORRUPT_MODULELIST";
  1527. break;
  1528. break;
  1529. }
  1530. if (Str)
  1531. {
  1532. if (FaGetFollowupInfo(NULL,
  1533. "ProcessingError",
  1534. followup,
  1535. sizeof(followup)))
  1536. {
  1537. SetString(DEBUG_FLR_FOLLOWUP_NAME, followup);
  1538. }
  1539. SetString(DEBUG_FLR_BUCKET_ID, Str);
  1540. return;
  1541. }
  1542. }
  1543. //
  1544. // Add failure code.
  1545. //
  1546. if (Entry = Get(DEBUG_FLR_BUGCHECK_STR))
  1547. {
  1548. PrintString(BucketPtr, sizeof(BucketId) - LengthUsed, "%s", FA_ENTRY_DATA(PCHAR, Entry));
  1549. LengthUsed += strlen(BucketPtr);
  1550. BucketPtr = BucketId + LengthUsed;
  1551. }
  1552. if (Entry = Get(DEBUG_FLR_BUGCHECK_SPECIFIER))
  1553. {
  1554. PrintString(BucketPtr, sizeof(BucketId) - LengthUsed, "%s", FA_ENTRY_DATA(PCHAR, Entry));
  1555. LengthUsed += strlen(BucketPtr);
  1556. BucketPtr = BucketId + LengthUsed;
  1557. }
  1558. //
  1559. // If it's driver only, but the failure is not in a driver, then show the
  1560. // full name of the failure. If we could not get the name, or we really
  1561. // have a driver only, show the name of the image.
  1562. //
  1563. if ( (Entry = Get(DEBUG_FLR_SYMBOL_NAME)) &&
  1564. ( !Get(DEBUG_FLR_FOLLOWUP_DRIVER_ONLY) ||
  1565. (BestClassFollowUp < FlpUnknownDrv)))
  1566. {
  1567. //
  1568. // If the faulting IP and the read address are the same, this is
  1569. // an interesting scenario we want to catch.
  1570. //
  1571. if (Get(DEBUG_FLR_FAILED_INSTRUCTION_ADDRESS))
  1572. {
  1573. PrintString(BucketPtr,
  1574. sizeof(BucketId) - LengthUsed,
  1575. "_BAD_IP");
  1576. LengthUsed += strlen(BucketPtr);
  1577. BucketPtr = BucketId + LengthUsed;
  1578. }
  1579. PrintString(BucketPtr,
  1580. sizeof(BucketId) - LengthUsed,
  1581. "_%s",
  1582. FA_ENTRY_DATA(PCHAR, Entry));
  1583. LengthUsed += strlen(BucketPtr);
  1584. BucketPtr = BucketId + LengthUsed;
  1585. }
  1586. else if (NameEntry)
  1587. {
  1588. PrintString(BucketPtr,
  1589. sizeof(BucketId) - LengthUsed,
  1590. "_IMAGE_%s",
  1591. FA_ENTRY_DATA(PCHAR, NameEntry));
  1592. LengthUsed += strlen(BucketPtr);
  1593. BucketPtr = BucketId + LengthUsed;
  1594. // Also add timestamp in this case.
  1595. if (ModuleTimestamp)
  1596. {
  1597. PrintString(BucketPtr,
  1598. sizeof(BucketId) - LengthUsed,
  1599. "_DATE_%s",
  1600. TimeToStr(ModuleTimestamp, TRUE));
  1601. LengthUsed += strlen(BucketPtr);
  1602. BucketPtr = BucketId + LengthUsed;
  1603. }
  1604. }
  1605. //
  1606. // Store the bucket ID in the analysis structure
  1607. //
  1608. //BucketDone:
  1609. for (PCHAR Scan = &BucketId[0]; *Scan; ++Scan)
  1610. {
  1611. // remove special chars that cause problems for IIS or SQL
  1612. if (*Scan == '<' || *Scan == '>' || *Scan == '|' ||
  1613. *Scan == '`' || *Scan == '\''|| (!isprint(*Scan)) )
  1614. {
  1615. *Scan = '_';
  1616. }
  1617. }
  1618. SetString(DEBUG_FLR_BUCKET_ID, BucketId);
  1619. }
  1620. void
  1621. DebugFailureAnalysis::AnalyzeStack(void)
  1622. {
  1623. PDEBUG_OUTPUT_CALLBACKS PrevCB;
  1624. ULONG i;
  1625. BOOL BoostToSpecific = FALSE;
  1626. ULONG64 TrapFrame = 0;
  1627. ULONG64 Thread = 0;
  1628. ULONG64 ImageNameAddr = 0;
  1629. DEBUG_STACK_FRAME Stk[MAX_STACK_FRAMES];
  1630. ULONG Frames = 0;
  1631. ULONG Trap0EFrameLimit = 2;
  1632. ULONG64 OriginalFaultingAddress = 0;
  1633. CHAR Command[50] = {0};
  1634. FA_ENTRY* Entry;
  1635. BOOL BadContext = FALSE;
  1636. ULONG PtrSize = IsPtr64() ? 8 : 4;
  1637. BOOL IsVrfBugcheck = FALSE;
  1638. //
  1639. // If someone provided a best followup already, just return
  1640. //
  1641. if (PossibleFollowups[MaxFlpClass-1].Owner[0])
  1642. {
  1643. return;
  1644. }
  1645. if (g_TargetClass == DEBUG_CLASS_KERNEL)
  1646. {
  1647. // Check if CPU is overclocked
  1648. //if (BcIsCpuOverClocked())
  1649. //{
  1650. // SetUlong64(DEBUG_FLR_CPU_OVERCLOCKED, -1);
  1651. //
  1652. // BestClassFollowUp = FlpOSInternalRoutine;
  1653. // strcpy(PossibleFollowups[FlpOSInternalRoutine].Owner, "MachineOwner");
  1654. // return;
  1655. //}
  1656. //
  1657. // Check if this bugcheck has any specific followup that independant
  1658. // of the failure stack
  1659. //
  1660. if (Entry = Get(DEBUG_FLR_BUGCHECK_STR))
  1661. {
  1662. PCHAR String;
  1663. String = g_pTriager->GetFollowupStr("bugcheck",
  1664. FA_ENTRY_DATA(PCHAR, Entry));
  1665. if (String)
  1666. {
  1667. if (!strncmp(String, "maybe_", 6))
  1668. {
  1669. BestClassFollowUp = FlpOSRoutine;
  1670. CopyString(PossibleFollowups[FlpOSRoutine].Owner,
  1671. String + 6,
  1672. sizeof(PossibleFollowups[FlpOSRoutine].Owner));
  1673. }
  1674. else if (!strncmp(String, "specific_", 9))
  1675. {
  1676. BoostToSpecific = TRUE;
  1677. }
  1678. else
  1679. {
  1680. BestClassFollowUp = FlpSpecific;
  1681. CopyString(PossibleFollowups[FlpSpecific].Owner,
  1682. String,
  1683. sizeof(PossibleFollowups[FlpSpecific].Owner));
  1684. return;
  1685. }
  1686. }
  1687. }
  1688. }
  1689. //
  1690. // Add trap frame, context info from the current stack
  1691. //
  1692. // Note(kksharma):We only need one of these to get to
  1693. // faulting stack (and only one of them should
  1694. // be available otherwise somethings wrong)
  1695. //
  1696. Entry = NULL;
  1697. while (Entry = NextEntry(Entry))
  1698. {
  1699. switch(Entry->Tag)
  1700. {
  1701. case DEBUG_FLR_CONTEXT:
  1702. sprintf(Command, ".cxr %I64lx",
  1703. *FA_ENTRY_DATA(PULONG64, Entry));
  1704. break;
  1705. case DEBUG_FLR_TRAP_FRAME:
  1706. sprintf(Command, ".trap %I64lx",
  1707. *FA_ENTRY_DATA(PULONG64, Entry));
  1708. break;
  1709. case DEBUG_FLR_TSS:
  1710. sprintf(Command, ".tss %I64lx",
  1711. *FA_ENTRY_DATA(PULONG64, Entry));
  1712. break;
  1713. case DEBUG_FLR_FAULTING_THREAD:
  1714. sprintf(Command, ".thread %I64lx",
  1715. *FA_ENTRY_DATA(PULONG64, Entry));
  1716. break;
  1717. case DEBUG_FLR_EXCEPTION_RECORD:
  1718. if (*FA_ENTRY_DATA(PULONG64, Entry) == -1)
  1719. {
  1720. sprintf(Command, ".ecxr");
  1721. }
  1722. break;
  1723. case DEBUG_FLR_FAULTING_IP:
  1724. case DEBUG_FLR_FAULTING_MODULE:
  1725. //
  1726. // We already have some info from the bugcheck
  1727. // Use that address to start off with.
  1728. // But if we could not use it to set any followup, then continue
  1729. // lookinh for the others.
  1730. //
  1731. if (OriginalFaultingAddress = *FA_ENTRY_DATA(PULONG64, Entry))
  1732. {
  1733. if (!GetTriageInfoFromStack(0, 1, OriginalFaultingAddress,
  1734. PossibleFollowups,
  1735. &BestClassFollowUp))
  1736. {
  1737. OriginalFaultingAddress = 0;
  1738. }
  1739. }
  1740. break;
  1741. default:
  1742. break;
  1743. }
  1744. if (Command[0] && OriginalFaultingAddress)
  1745. {
  1746. break;
  1747. }
  1748. }
  1749. RepeatGetCommand:
  1750. if (!Command[0])
  1751. {
  1752. //
  1753. // Get the current stack.
  1754. //
  1755. if (S_OK != g_ExtControl->GetStackTrace(0, 0, 0, Stk, MAX_STACK_FRAMES,
  1756. &Frames))
  1757. {
  1758. Frames = 0;
  1759. }
  1760. //
  1761. // Make sure this is a valid stack to analyze. Such as for kernel mode
  1762. // try to recognize stack after user breakin and send to machineowner
  1763. //
  1764. if (m_FailureType == DEBUG_FLR_KERNEL &&
  1765. m_FailureCode == 0 && Frames >= 3)
  1766. {
  1767. if (IsManualBreakin(Stk, Frames))
  1768. {
  1769. // set machine owner as followup
  1770. SetUlong(DEBUG_FLR_MANUAL_BREAKIN, TRUE);
  1771. strcpy(PossibleFollowups[MaxFlpClass-1].Owner, "MachineOwner");
  1772. PossibleFollowups[MaxFlpClass-1].InstructionOffset = Stk[0].InstructionOffset;
  1773. return;
  1774. }
  1775. }
  1776. //
  1777. // Get the current stack and check if we can get trap
  1778. // frame/context from it
  1779. //
  1780. ULONG64 ExceptionPointers = 0;
  1781. for (i = 0; i < Frames; ++i)
  1782. {
  1783. #if 0
  1784. // Stack walker taskes care of these when walking stack
  1785. if (GetTrapFromStackFrameFPO(&stk[i], &TrapFrame))
  1786. {
  1787. break;
  1788. }
  1789. #endif
  1790. //
  1791. // First argument of this function is the assert
  1792. // Second argument of this function is the file name
  1793. // Third argument of this function is the line number
  1794. //
  1795. if (FaIsFunctionAddr(Stk[i].InstructionOffset, "RtlAssert"))
  1796. {
  1797. ULONG Len;
  1798. CHAR AssertData[MAX_PATH + 1] = {0};
  1799. if (Len = ReadAcsiiString(Stk[i].Params[0],
  1800. AssertData,
  1801. sizeof(AssertData)))
  1802. {
  1803. SetString(DEBUG_FLR_ASSERT_DATA, AssertData);
  1804. }
  1805. if (Len = ReadAcsiiString(Stk[i].Params[1],
  1806. AssertData,
  1807. sizeof(AssertData)))
  1808. {
  1809. strncat(AssertData, " at Line ", sizeof(AssertData) - Len);
  1810. Len = strlen(AssertData);
  1811. PrintString(AssertData + Len,
  1812. sizeof(AssertData) - Len - 1,
  1813. "%I64lx",
  1814. Stk[i].Params[2]);
  1815. SetString(DEBUG_FLR_ASSERT_FILE, AssertData);
  1816. }
  1817. }
  1818. // If Trap 0E is the second or 3rd frame on the stack, we can just
  1819. // switch to that trap frame.
  1820. // Otherwise, we want to leave it as is because the failure is
  1821. // most likely due to the frames between bugcheck and trap0E
  1822. //
  1823. // ebp of KiTrap0E is the trap frame
  1824. //
  1825. if ((i <= Trap0EFrameLimit) &&
  1826. FaIsFunctionAddr(Stk[i].InstructionOffset, "KiTrap0E"))
  1827. {
  1828. TrapFrame = Stk[i].Reserved[2];
  1829. break;
  1830. }
  1831. //
  1832. // take first param - spin lock - and it contains the thread that
  1833. // owns the spin lock.
  1834. // Make sure to zero the bottom bit as it is always set ...
  1835. //
  1836. if ((i == 0) &&
  1837. FaIsFunctionAddr(Stk[i].InstructionOffset,
  1838. "SpinLockSpinningForTooLong"))
  1839. {
  1840. if (ReadPointer(Stk[0].Params[0], &Thread) &&
  1841. Thread)
  1842. {
  1843. Thread &= ~0x1;
  1844. }
  1845. break;
  1846. }
  1847. //
  1848. // First arg of KiMemoryFault is the trap frame
  1849. //
  1850. if (FaIsFunctionAddr(Stk[i].InstructionOffset, "KiMemoryFault") ||
  1851. FaIsFunctionAddr(Stk[i].InstructionOffset,
  1852. "Ki386CheckDivideByZeroTrap"))
  1853. {
  1854. TrapFrame = Stk[i].Params[0];
  1855. break;
  1856. }
  1857. //
  1858. // Third arg of KiMemoryFault is the trap frame
  1859. //
  1860. if (FaIsFunctionAddr(Stk[i].InstructionOffset,
  1861. "KiDispatchException"))
  1862. {
  1863. TrapFrame = Stk[i].Params[2];
  1864. break;
  1865. }
  1866. //
  1867. // First argument of this function is EXCEPTION_POINTERS
  1868. //
  1869. if (FaIsFunctionAddr(Stk[i].InstructionOffset,
  1870. "PspUnhandledExceptionInSystemThread"))
  1871. {
  1872. ExceptionPointers = Stk[i].Params[0];
  1873. break;
  1874. }
  1875. //
  1876. // First argument of this function is a BUGCHECK_DATA structure
  1877. // The thread is the second parameter in that data structure
  1878. //
  1879. if (FaIsFunctionAddr(Stk[i].InstructionOffset,
  1880. "WdBugCheckStuckDriver") ||
  1881. FaIsFunctionAddr(Stk[i].InstructionOffset,
  1882. "WdpBugCheckStuckDriver"))
  1883. {
  1884. ReadPointer(Stk[i].Params[0] + PtrSize, &Thread);
  1885. break;
  1886. }
  1887. //
  1888. // First argument of these functions are EXCEPTION_POINTERS
  1889. //
  1890. if (FaIsFunctionAddr(Stk[i].InstructionOffset,
  1891. "PopExceptionFilter") ||
  1892. FaIsFunctionAddr(Stk[i].InstructionOffset,
  1893. "RtlUnhandledExceptionFilter2"))
  1894. {
  1895. ExceptionPointers = Stk[i].Params[0];
  1896. break;
  1897. }
  1898. //
  1899. // THIRD argument has the name of Exe
  1900. // nt!PspCatchCriticalBreak(char* Msg, void* Object,unsigned char* ImageFileName)
  1901. //
  1902. if (FaIsFunctionAddr(Stk[i].InstructionOffset,
  1903. "PspCatchCriticalBreak"))
  1904. {
  1905. ImageNameAddr = Stk[i].Params[2];
  1906. break;
  1907. }
  1908. //
  1909. // VERIFIER : Look for possible verifier failures
  1910. // verifier!VerifierStopMessage means verifier caused the break
  1911. //
  1912. if (FaIsFunctionAddr(Stk[i].InstructionOffset,
  1913. "VerifierStopMessage"))
  1914. {
  1915. IsVrfBugcheck = TRUE;
  1916. break;
  1917. }
  1918. }
  1919. if (ExceptionPointers)
  1920. {
  1921. ULONG64 Exr = 0, Cxr = 0;
  1922. if (!ReadPointer(ExceptionPointers, &Exr) ||
  1923. !ReadPointer(ExceptionPointers + PtrSize, &Cxr))
  1924. {
  1925. // dprintf("Unable to read exception pointers at %p\n",
  1926. // ExcepPtr);
  1927. }
  1928. if (Exr)
  1929. {
  1930. SetUlong64(DEBUG_FLR_EXCEPTION_RECORD, Exr);
  1931. }
  1932. if (Cxr)
  1933. {
  1934. sprintf(Command, ".cxr %I64lx", Cxr);
  1935. SetUlong64(DEBUG_FLR_CONTEXT, Cxr);
  1936. }
  1937. }
  1938. if (TrapFrame)
  1939. {
  1940. sprintf(Command, ".trap %I64lx", TrapFrame);
  1941. SetUlong64(DEBUG_FLR_TRAP_FRAME, TrapFrame);
  1942. }
  1943. if (Thread)
  1944. {
  1945. sprintf(Command, ".thread %I64lx", Thread);
  1946. SetUlong64(DEBUG_FLR_FAULTING_THREAD, Thread);
  1947. }
  1948. if (ImageNameAddr)
  1949. {
  1950. CHAR Buffer[50]={0}, *pImgExt;
  1951. ULONG cb;
  1952. if (ReadMemory(ImageNameAddr, Buffer, sizeof(Buffer) - 1, &cb) &&
  1953. Buffer[0])
  1954. {
  1955. if (pImgExt = strchr(Buffer, '.'))
  1956. {
  1957. // we do not want imageextension here
  1958. *pImgExt = 0;
  1959. }
  1960. SetString(DEBUG_FLR_MODULE_NAME, Buffer);
  1961. }
  1962. }
  1963. if (IsVrfBugcheck)
  1964. {
  1965. ULONG64 AvrfCxr = 0;
  1966. // We hit this when app verifier breaks into kd and usermode
  1967. // analysis isn't called
  1968. if (DoVerifierAnalysis(NULL, this) == S_OK)
  1969. {
  1970. if (GetUlong64(DEBUG_FLR_CONTEXT, &AvrfCxr) != NULL)
  1971. {
  1972. sprintf(Command, ".cxr %I64lx", AvrfCxr);
  1973. }
  1974. }
  1975. }
  1976. }
  1977. //
  1978. // execute the command and get an updated stack
  1979. //
  1980. if (Command[0])
  1981. {
  1982. g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE, Command,
  1983. DEBUG_EXECUTE_NOT_LOGGED);
  1984. if (g_ExtControl->GetStackTrace(0, 0, 0, Stk, MAX_STACK_FRAMES,
  1985. &Frames) != S_OK)
  1986. {
  1987. Frames = 0;
  1988. }
  1989. }
  1990. //
  1991. // Get relevant stack
  1992. //
  1993. // We can get stack with 1 frame because a .trap can bring us to the
  1994. // faulting instruction, and if it's a 3rd party driver with no symbols
  1995. // and image, the stack can be 1 frame - although a very valid one.
  1996. //
  1997. if (Frames)
  1998. {
  1999. ULONG64 Values[3];
  2000. Values[0] = Stk[0].ReturnOffset;
  2001. Values[1] = Stk[0].InstructionOffset;
  2002. Values[2] = Stk[0].StackOffset;
  2003. SetUlong64s(DEBUG_FLR_LAST_CONTROL_TRANSFER, 3, Values);
  2004. // If everything on the stack is user mode in the case of a kernel
  2005. // mode failure, we got some bad context information.
  2006. if (IsFollowupContext(Values[0],Values[1],Values[2]) != FollowYes)
  2007. {
  2008. SetUlong64(DEBUG_FLR_INVALID_KERNEL_CONTEXT, 0);
  2009. BadContext = TRUE;
  2010. }
  2011. else
  2012. {
  2013. GetTriageInfoFromStack(&Stk[0], Frames, 0, PossibleFollowups,
  2014. &BestClassFollowUp);
  2015. }
  2016. }
  2017. ULONG64 StackBase = FaGetImplicitStackOffset();
  2018. //
  2019. // If the stack pointer is not aligned, take a note of that.
  2020. //
  2021. if (StackBase & 0x3)
  2022. {
  2023. Set(DEBUG_FLR_UNALIGNED_STACK_POINTER, 0);
  2024. }
  2025. //
  2026. // If we have an image name (possibly directly from the bugcheck
  2027. // information) try to get the followup from that.
  2028. //
  2029. if ((BestClassFollowUp < FlpUnknownDrv) &&
  2030. (Entry = Get(DEBUG_FLR_MODULE_NAME)))
  2031. {
  2032. FaGetFollowupInfo(NULL,
  2033. FA_ENTRY_DATA(PCHAR, Entry),
  2034. PossibleFollowups[FlpUnknownDrv].Owner,
  2035. sizeof(PossibleFollowups[FlpUnknownDrv].Owner));
  2036. if (PossibleFollowups[FlpUnknownDrv].Owner[0])
  2037. {
  2038. BestClassFollowUp = FlpUnknownDrv;
  2039. }
  2040. }
  2041. //
  2042. // If we could not find anything at this point, look further up the stack
  2043. // for a trap frame to catch failures of this kind:
  2044. // nt!RtlpBreakWithStatusInstruction
  2045. // nt!KiBugCheckDebugBreak+0x19
  2046. // nt!KeBugCheck2+0x499
  2047. // nt!KeBugCheckEx+0x19
  2048. // nt!_KiTrap0E+0x224
  2049. //
  2050. if (!Command[0] &&
  2051. (BestClassFollowUp < FlpOSFilterDrv) &&
  2052. (Trap0EFrameLimit != 0xff))
  2053. {
  2054. Trap0EFrameLimit = 0xff;
  2055. goto RepeatGetCommand;
  2056. }
  2057. //
  2058. // Last resort, manually read the stack and look for some symbol
  2059. // to followup on.
  2060. //
  2061. if ((BadContext == FALSE) &&
  2062. ((BestClassFollowUp == FlpIgnore) ||
  2063. ((BestClassFollowUp < FlpOSRoutine) && (Frames <= 2))))
  2064. {
  2065. FindFollowupOnRawStack(StackBase,
  2066. PossibleFollowups,
  2067. &BestClassFollowUp);
  2068. }
  2069. //
  2070. // Get something !
  2071. //
  2072. if (BestClassFollowUp < FlpOSRoutine)
  2073. {
  2074. if (!BestClassFollowUp)
  2075. {
  2076. PossibleFollowups[FlpOSInternalRoutine].InstructionOffset =
  2077. GetExpression("@$ip");
  2078. }
  2079. if (!PossibleFollowups[FlpOSInternalRoutine].Owner[0] ||
  2080. !_stricmp(PossibleFollowups[FlpOSInternalRoutine].Owner, "ignore"))
  2081. {
  2082. FaGetFollowupInfo(NULL,
  2083. "default",
  2084. PossibleFollowups[FlpOSInternalRoutine].Owner,
  2085. sizeof(PossibleFollowups[FlpOSInternalRoutine].Owner));
  2086. BestClassFollowUp = FlpOSRoutine;
  2087. }
  2088. }
  2089. //
  2090. // Special handling so a bugcheck EA can always take predence over a pool
  2091. // corruption.
  2092. //
  2093. if (BoostToSpecific)
  2094. {
  2095. for (i = MaxFlpClass-1; i ; i--)
  2096. {
  2097. if (PossibleFollowups[i].Owner[0])
  2098. {
  2099. PossibleFollowups[FlpSpecific] = PossibleFollowups[i];
  2100. break;
  2101. }
  2102. }
  2103. }
  2104. //
  2105. // Get the faulting stack
  2106. //
  2107. g_OutCapCb.Reset();
  2108. g_OutCapCb.Output(0, "\n");
  2109. g_ExtClient->GetOutputCallbacks(&PrevCB);
  2110. g_ExtClient->SetOutputCallbacks(&g_OutCapCb);
  2111. g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT |
  2112. DEBUG_OUTCTL_NOT_LOGGED, Stk, Frames,
  2113. DEBUG_STACK_ARGUMENTS |
  2114. DEBUG_STACK_FRAME_ADDRESSES |
  2115. DEBUG_STACK_SOURCE_LINE);
  2116. g_ExtClient->SetOutputCallbacks(PrevCB);
  2117. if (*g_OutCapCb.GetCapturedText())
  2118. {
  2119. SetString(DEBUG_FLR_STACK_TEXT, g_OutCapCb.GetCapturedText());
  2120. }
  2121. //
  2122. // Reset the current state to normal so !analyze does not have any
  2123. // side-effects
  2124. //
  2125. if (Command[0])
  2126. {
  2127. SetString(DEBUG_FLR_STACK_COMMAND, Command);
  2128. //
  2129. // Clear the set context
  2130. //
  2131. g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE, ".cxr 0; .thread",
  2132. DEBUG_EXECUTE_NOT_LOGGED);
  2133. }
  2134. }
  2135. VOID
  2136. DebugFailureAnalysis::FindFollowupOnRawStack(
  2137. ULONG64 StackBase,
  2138. PFOLLOWUP_DESCS PossibleFollowups,
  2139. FlpClasses *BestClassFollowUp
  2140. )
  2141. {
  2142. #define NUM_ADDRS 200
  2143. ULONG i;
  2144. ULONG PtrSize = IsPtr64() ? 8 : 4;
  2145. BOOL AddressFound = FALSE;
  2146. BOOL ZeroedStack = TRUE;
  2147. ULONG64 AddrToLookup;
  2148. FlpClasses RawStkBestFollowup;
  2149. if (*BestClassFollowUp >= FlpUnknownDrv)
  2150. {
  2151. // Any better fron raw stack won't be as accurate as what we have
  2152. return;
  2153. } else if (*BestClassFollowUp == FlpIgnore)
  2154. {
  2155. // We don't want to followup on os internal routine here
  2156. RawStkBestFollowup = FlpOSInternalRoutine;
  2157. } else
  2158. {
  2159. RawStkBestFollowup = *BestClassFollowUp;
  2160. }
  2161. // Align stack to natural pointer size.
  2162. StackBase &= ~((ULONG64)PtrSize - 1);
  2163. for (i = 0; i < NUM_ADDRS; i++)
  2164. {
  2165. if (!ReadPointer(StackBase, &AddrToLookup))
  2166. {
  2167. break;
  2168. }
  2169. StackBase+= PtrSize;
  2170. if (AddrToLookup)
  2171. {
  2172. FOLLOW_ADDRESS Follow;
  2173. ZeroedStack = FALSE;
  2174. Follow = IsPotentialFollowupAddress(AddrToLookup);
  2175. if (Follow == FollowStop)
  2176. {
  2177. break;
  2178. }
  2179. else if (Follow == FollowSkip)
  2180. {
  2181. continue;
  2182. }
  2183. AddressFound = TRUE;
  2184. GetTriageInfoFromStack(0, 1, AddrToLookup,
  2185. PossibleFollowups,
  2186. &RawStkBestFollowup);
  2187. if (RawStkBestFollowup == FlpUnknownDrv)
  2188. {
  2189. break;
  2190. }
  2191. }
  2192. }
  2193. if (!AddressFound)
  2194. {
  2195. if (ZeroedStack)
  2196. {
  2197. SetUlong64(DEBUG_FLR_ZEROED_STACK, 0);
  2198. }
  2199. else
  2200. {
  2201. SetUlong64(DEBUG_FLR_BAD_STACK, 0);
  2202. }
  2203. }
  2204. if (RawStkBestFollowup > FlpOSInternalRoutine)
  2205. {
  2206. *BestClassFollowUp = RawStkBestFollowup;
  2207. }
  2208. }
  2209. BOOL
  2210. DebugFailureAnalysis::GetTriageInfoFromStack(
  2211. PDEBUG_STACK_FRAME Stack,
  2212. ULONG Frames,
  2213. ULONG64 SingleInstruction,
  2214. PFOLLOWUP_DESCS PossibleFollowups,
  2215. FlpClasses *BestClassFollowUp)
  2216. {
  2217. ULONG i;
  2218. EXT_TRIAGE_FOLLOWUP FollowUp = &_EFN_GetTriageFollowupFromSymbol;
  2219. BOOL bStat = FALSE;
  2220. BOOL IgnorePoolCorruptionFlp = FALSE;
  2221. FOLLOW_ADDRESS Follow;
  2222. if (Get(DEBUG_FLR_ANALYZAABLE_POOL_CORRUPTION))
  2223. {
  2224. IgnorePoolCorruptionFlp = TRUE;
  2225. }
  2226. for (i = 0; i < Frames; ++i)
  2227. {
  2228. ULONG64 Disp;
  2229. ULONG64 Instruction;
  2230. CHAR Module[20] = {0};
  2231. CHAR Buffer[MAX_PATH];
  2232. CHAR Owner[100];
  2233. DWORD dwOwner;
  2234. DEBUG_TRIAGE_FOLLOWUP_INFO Info;
  2235. FlpClasses ClassFollowUp = FlpIgnore;
  2236. FlpClasses StoreClassFollowUp = FlpIgnore;
  2237. Instruction = SingleInstruction;
  2238. if (!SingleInstruction)
  2239. {
  2240. Instruction = Stack[i].InstructionOffset;
  2241. }
  2242. //
  2243. // Determine how to process this address.
  2244. //
  2245. Follow = IsPotentialFollowupAddress(Instruction);
  2246. if (Follow == FollowStop)
  2247. {
  2248. break;
  2249. }
  2250. else if (Follow == FollowSkip)
  2251. {
  2252. continue;
  2253. }
  2254. Buffer[0] = 0;
  2255. FaGetSymbol(Instruction, Buffer, &Disp, sizeof(Buffer));
  2256. if (Buffer[0] == 0)
  2257. {
  2258. //
  2259. // Either its a bad stack or someone jumped called to bad IP
  2260. //
  2261. continue;
  2262. }
  2263. //
  2264. // Check if this routine has any special significance for getting
  2265. // faulting module
  2266. //
  2267. PCHAR Routine = strchr(Buffer, '!');
  2268. if (Routine)
  2269. {
  2270. *Routine = 0;
  2271. }
  2272. CopyString(Module, Buffer, sizeof(Module));
  2273. if (Routine)
  2274. {
  2275. *Routine = '!';
  2276. Routine++;
  2277. if (Stack && !strcmp(Routine, "IopCompleteRequest"))
  2278. {
  2279. // First argument is Irp Tail, get the driver from Irp
  2280. ULONG TailOffset = 0;
  2281. ULONG64 Irp;
  2282. GetFieldOffset("nt!_IRP", "Tail", &TailOffset);
  2283. if (TailOffset)
  2284. {
  2285. FA_ENTRY* Entry = NULL;
  2286. PCHAR ModuleName = NULL;
  2287. Irp = Stack[i].Params[0] - TailOffset;
  2288. SetUlong64(DEBUG_FLR_IRP_ADDRESS, Irp);
  2289. if (BcGetDriverNameFromIrp(this, Irp, NULL, NULL))
  2290. {
  2291. if (Entry = Get(DEBUG_FLR_IMAGE_NAME))
  2292. {
  2293. CopyString(Buffer, FA_ENTRY_DATA(PCHAR, Entry), sizeof(Buffer));
  2294. PCHAR Dot;
  2295. if (Dot = strchr(Buffer, '.'))
  2296. {
  2297. *Dot = 0;
  2298. CopyString(Module, Buffer, sizeof(Module));
  2299. }
  2300. }
  2301. }
  2302. }
  2303. }
  2304. else if ((i == 0) && Stack &&
  2305. !strcmp(Routine, "ObpCloseHandleTableEntry"))
  2306. {
  2307. //
  2308. // Check for possible memory corruption
  2309. // 2nd parameter is HANDLE_TABLE_ENTRY
  2310. //
  2311. if (CheckForCorruptionInHTE(Stack[i].Params[1], Owner, sizeof(Owner)))
  2312. {
  2313. // We have pool corrupting PoolTag in analysis
  2314. // continue with default analysis for now
  2315. }
  2316. }
  2317. }
  2318. ClassFollowUp = GetFollowupClass(Instruction, Module, Routine);
  2319. if (ClassFollowUp == FlpIgnore)
  2320. {
  2321. continue;
  2322. }
  2323. Info.SizeOfStruct = sizeof(Info);
  2324. Info.OwnerName = &Owner[0];
  2325. Info.OwnerNameSize = sizeof(Owner);
  2326. if (dwOwner = (*FollowUp)(g_ExtClient, Buffer, &Info))
  2327. {
  2328. PCHAR pOwner = Owner;
  2329. if (dwOwner == TRIAGE_FOLLOWUP_IGNORE)
  2330. {
  2331. ClassFollowUp = FlpIgnore;
  2332. }
  2333. else if (!strncmp(Owner, "maybe_", 6))
  2334. {
  2335. pOwner = Owner + 6;
  2336. ClassFollowUp = (FlpClasses) ((ULONG) ClassFollowUp - 1);
  2337. }
  2338. else if (!strncmp(Owner, "last_", 5))
  2339. {
  2340. pOwner = Owner + 5;
  2341. ClassFollowUp = FlpOSInternalRoutine;
  2342. }
  2343. else if (!strncmp(Owner, "specific_", 9))
  2344. {
  2345. pOwner = Owner + 9;
  2346. ClassFollowUp = FlpSpecific;
  2347. }
  2348. else if (!_stricmp(Owner, "pool_corruption"))
  2349. {
  2350. if (IgnorePoolCorruptionFlp)
  2351. {
  2352. continue;
  2353. }
  2354. //
  2355. // If we have non-kernel followups already on the stack
  2356. // it could be them no correctly handling this stack.
  2357. // If we only have kernel calls, then it must be pool
  2358. // corruption.
  2359. //
  2360. // We later rely on a pool corruption always being marked
  2361. // as a FlpUnknownDrv
  2362. //
  2363. StoreClassFollowUp = FlpUnknownDrv;
  2364. ClassFollowUp = FlpOSFilterDrv;
  2365. }
  2366. if (StoreClassFollowUp == FlpIgnore)
  2367. {
  2368. StoreClassFollowUp = ClassFollowUp;
  2369. }
  2370. //
  2371. // Save this entry if it's better than anything else we have.
  2372. //
  2373. if (ClassFollowUp > *BestClassFollowUp)
  2374. {
  2375. bStat = TRUE;
  2376. *BestClassFollowUp = StoreClassFollowUp;
  2377. CopyString(PossibleFollowups[StoreClassFollowUp].Owner,
  2378. pOwner,
  2379. sizeof(PossibleFollowups[StoreClassFollowUp].Owner));
  2380. PossibleFollowups[StoreClassFollowUp].InstructionOffset =
  2381. Instruction;
  2382. if (StoreClassFollowUp == FlpUnknownDrv)
  2383. {
  2384. // Best match possible
  2385. return bStat;
  2386. }
  2387. }
  2388. }
  2389. }
  2390. return bStat;
  2391. }
  2392. BOOL
  2393. DebugFailureAnalysis::AddCorruptModules(void)
  2394. {
  2395. //
  2396. // Check if we have an old build. Anything smaller than OSBuild
  2397. // and not identified specifically by build number in the list is old.
  2398. //
  2399. PCHAR String;
  2400. CHAR BuildString[7];
  2401. ULONG BuildNum = 0;
  2402. BOOL FoundCorruptor = FALSE;
  2403. BOOL PoolCorruption = FALSE;
  2404. ULONG Loaded;
  2405. ULONG Unloaded;
  2406. CHAR Name[MAX_PATH];
  2407. CHAR ImageName[MAX_PATH];
  2408. CHAR CorruptModule[MAX_PATH];
  2409. FA_ENTRY *Entry;
  2410. FA_ENTRY *BugCheckEntry;
  2411. sprintf(BuildString, "%d", g_TargetBuild);
  2412. if (!g_pTriager->GetFollowupStr("OSBuild", BuildString))
  2413. {
  2414. if (String = g_pTriager->GetFollowupStr("OSBuild", "old"))
  2415. {
  2416. BuildNum = strtol(String, NULL, 10);
  2417. if (BuildNum > g_TargetBuild)
  2418. {
  2419. SetUlong64(DEBUG_FLR_OLD_OS_VERSION, g_TargetBuild);
  2420. }
  2421. }
  2422. }
  2423. //
  2424. // If we have a specific solution, return
  2425. // if we can't get a module list, return
  2426. //
  2427. if (PossibleFollowups[FlpSpecific].Owner[0] ||
  2428. (g_ExtSymbols->GetNumberModules(&Loaded, &Unloaded) != S_OK))
  2429. {
  2430. return FALSE;
  2431. }
  2432. //
  2433. // Determine if the failure was likely caused by a pool corruption
  2434. //
  2435. if ((BestClassFollowUp < FlpUnknownDrv) ||
  2436. !_stricmp(PossibleFollowups[FlpUnknownDrv].Owner, "pool_corruption"))
  2437. {
  2438. PoolCorruption = TRUE;
  2439. }
  2440. BugCheckEntry = Get(DEBUG_FLR_BUGCHECK_STR);
  2441. //
  2442. // Loop three types to find the types of corruptors in order.
  2443. // the order must match the order in which we generate the bucket name
  2444. // for these types so the image name ends up correct.
  2445. //
  2446. for (ULONG TypeLoop = 0; TypeLoop < 3; TypeLoop++)
  2447. {
  2448. if ((TypeLoop == 0) && !BugCheckEntry)
  2449. {
  2450. continue;
  2451. }
  2452. if ((TypeLoop == 2) && !PoolCorruption)
  2453. {
  2454. continue;
  2455. }
  2456. for (ULONG Index = 0; Index < Loaded + Unloaded; Index++)
  2457. {
  2458. ULONG64 Base;
  2459. DEBUG_FLR_PARAM_TYPE Type = (DEBUG_FLR_PARAM_TYPE)0;
  2460. PCHAR Scan;
  2461. PCHAR DriverName;
  2462. DEBUG_MODULE_PARAMETERS Params;
  2463. ULONG Start, End = 0;
  2464. if (g_ExtSymbols->GetModuleByIndex(Index, &Base) != S_OK)
  2465. {
  2466. continue;
  2467. }
  2468. if (g_ExtSymbols->GetModuleNames(Index, Base,
  2469. ImageName, MAX_PATH, NULL,
  2470. Name, MAX_PATH, NULL,
  2471. NULL, 0, NULL) != S_OK)
  2472. {
  2473. continue;
  2474. }
  2475. if (g_ExtSymbols->GetModuleParameters(1, &Base, Index,
  2476. &Params) != S_OK)
  2477. {
  2478. continue;
  2479. }
  2480. //
  2481. // Strip the path
  2482. //
  2483. DriverName = ImageName;
  2484. if (Scan = strrchr(DriverName, '\\'))
  2485. {
  2486. DriverName = Scan+1;
  2487. }
  2488. //
  2489. // Look for the module in both the various bad drivers list.
  2490. // poolcorruptor and memorycorruptor lists in triage.ini
  2491. //
  2492. switch (TypeLoop)
  2493. {
  2494. case 0:
  2495. Type = DEBUG_FLR_BUGCHECKING_DRIVER;
  2496. PrintString(CorruptModule, sizeof(CorruptModule), "%s_%s",
  2497. FA_ENTRY_DATA(PCHAR, BugCheckEntry), DriverName);
  2498. g_pTriager->GetFollowupDate("bugcheckingDriver", CorruptModule,
  2499. &Start, &End);
  2500. break;
  2501. case 1:
  2502. Type = DEBUG_FLR_MEMORY_CORRUPTOR;
  2503. g_pTriager->GetFollowupDate("memorycorruptors", DriverName,
  2504. &Start, &End);
  2505. break;
  2506. case 2:
  2507. //
  2508. // Only look at kernel mode pool corruptors if the failure
  2509. // is a kernel mode crash (and same for user mode), because
  2510. // a kernel pool corruptor will almost never affect an app
  2511. // (apps don't see data in pool blocks)
  2512. //
  2513. if ((BOOL)(GetFailureType() != DEBUG_FLR_KERNEL) ==
  2514. (BOOL)((Params.Flags & DEBUG_MODULE_USER_MODE) != 0))
  2515. {
  2516. Type = DEBUG_FLR_POOL_CORRUPTOR;
  2517. g_pTriager->GetFollowupDate("poolcorruptors", DriverName,
  2518. &Start, &End);
  2519. }
  2520. break;
  2521. }
  2522. //
  2523. // Add it to the list if it's really known to be a bad driver.
  2524. //
  2525. if (End)
  2526. {
  2527. //
  2528. // Check to see if the timestamp is older than a fixed
  2529. // driver. If the module is unloaded and no fix is know,
  2530. // then also mark it as bad
  2531. //
  2532. if ( (Params.TimeDateStamp &&
  2533. (Params.TimeDateStamp < End) &&
  2534. (Params.TimeDateStamp >= Start)) ||
  2535. ((Params.Flags & DEBUG_MODULE_UNLOADED) &&
  2536. (End == 0xffffffff)) )
  2537. {
  2538. // Don't store the timestamp on memory corrupting
  2539. // modules to simplify bucketing annd allow for
  2540. // name lookup.
  2541. //
  2542. //sprintf(CorruptModule, "%s_%08lx",
  2543. // DriverName, Params.TimeDateStamp);
  2544. //
  2545. // Store the first driver we find as the cause,
  2546. // bug accumulate the list of known memory corruptors.
  2547. //
  2548. if (!FoundCorruptor)
  2549. {
  2550. SetString(DEBUG_FLR_MODULE_NAME, Name);
  2551. SetString(DEBUG_FLR_IMAGE_NAME, DriverName);
  2552. SetUlong64(DEBUG_FLR_IMAGE_TIMESTAMP,
  2553. Params.TimeDateStamp);
  2554. FoundCorruptor = TRUE;
  2555. }
  2556. //
  2557. // Remove the dot since we check the followup
  2558. // based on that string.
  2559. //
  2560. if (Scan = strrchr(DriverName, '.'))
  2561. {
  2562. *Scan = 0;
  2563. }
  2564. if (strlen(DriverName) < sizeof(CorruptModule))
  2565. {
  2566. CopyString(CorruptModule, DriverName,
  2567. sizeof(CorruptModule));
  2568. }
  2569. Entry = Add(Type, strlen(CorruptModule) + 1);
  2570. if (Entry)
  2571. {
  2572. CopyString(FA_ENTRY_DATA(PCHAR, Entry),
  2573. CorruptModule, Entry->FullSize);
  2574. }
  2575. }
  2576. }
  2577. }
  2578. }
  2579. return FoundCorruptor;
  2580. }
  2581. void
  2582. DebugFailureAnalysis::SetSymbolNameAndModule()
  2583. {
  2584. ULONG64 Address = 0;
  2585. CHAR Buffer[MAX_PATH];
  2586. ULONG64 Disp, Base = 0;
  2587. ULONG Index;
  2588. ULONG i;
  2589. //
  2590. // Store the best followup name in the analysis results
  2591. //
  2592. for (i = MaxFlpClass-1; i ; i--)
  2593. {
  2594. if (PossibleFollowups[i].Owner[0])
  2595. {
  2596. if (PossibleFollowups[i].InstructionOffset)
  2597. {
  2598. Address = PossibleFollowups[i].InstructionOffset;
  2599. SetUlong64(DEBUG_FLR_FOLLOWUP_IP,
  2600. PossibleFollowups[i].InstructionOffset);
  2601. }
  2602. SetString(DEBUG_FLR_FOLLOWUP_NAME, PossibleFollowups[i].Owner);
  2603. break;
  2604. }
  2605. }
  2606. //
  2607. // Now that we have the followip, get the module names.
  2608. //
  2609. // The address may not be set in the case where we just
  2610. // had a driver name with no real address for it
  2611. //
  2612. if (Address)
  2613. {
  2614. //
  2615. // Try to get the full symbol name.
  2616. // leave space for Displacement
  2617. //
  2618. Buffer[0] = 0;
  2619. if (FaGetSymbol(Address, Buffer, &Disp, sizeof(Buffer) - 20))
  2620. {
  2621. sprintf(Buffer + strlen(Buffer), "+%I64lx", Disp);
  2622. SetString(DEBUG_FLR_SYMBOL_NAME, Buffer);
  2623. }
  2624. //
  2625. // Now get the Mod name
  2626. //
  2627. g_ExtSymbols->GetModuleByOffset(Address, 0, &Index, &Base);
  2628. if (Base)
  2629. {
  2630. CHAR ModBuf[100];
  2631. CHAR ImageBuf[100];
  2632. PCHAR Scan;
  2633. PCHAR ImageName;
  2634. if (g_ExtSymbols->GetModuleNames(Index, Base,
  2635. ImageBuf, sizeof(ImageBuf), NULL,
  2636. ModBuf, sizeof(ModBuf), NULL,
  2637. NULL, 0, NULL) == S_OK)
  2638. {
  2639. //
  2640. // Check for unknown module.
  2641. // If it's not, then we should have something valid.
  2642. //
  2643. if (!strstr(ModBuf, "Unknown"))
  2644. {
  2645. //
  2646. // Strip the path - keep the extension
  2647. //
  2648. ImageName = ImageBuf;
  2649. if (Scan = strrchr(ImageName, '\\'))
  2650. {
  2651. ImageName = Scan+1;
  2652. }
  2653. SetString(DEBUG_FLR_MODULE_NAME, ModBuf);
  2654. SetString(DEBUG_FLR_IMAGE_NAME, ImageName);
  2655. DEBUG_MODULE_PARAMETERS Params;
  2656. ULONG TimeStamp = 0;
  2657. if (g_ExtSymbols->GetModuleParameters(1, &Base, Index,
  2658. &Params) == S_OK)
  2659. {
  2660. TimeStamp = Params.TimeDateStamp;
  2661. }
  2662. SetUlong64(DEBUG_FLR_IMAGE_TIMESTAMP, TimeStamp);
  2663. return;
  2664. }
  2665. }
  2666. }
  2667. }
  2668. //
  2669. // If we make it here there was an error getting module name,
  2670. // so set things to "unknown".
  2671. //
  2672. if (!Get(DEBUG_FLR_MODULE_NAME))
  2673. {
  2674. SetUlong64(DEBUG_FLR_UNKNOWN_MODULE, 1);
  2675. SetString(DEBUG_FLR_MODULE_NAME, "Unknown_Module");
  2676. SetString(DEBUG_FLR_IMAGE_NAME, "Unknown_Image");
  2677. SetUlong64(DEBUG_FLR_IMAGE_TIMESTAMP, 0);
  2678. }
  2679. }
  2680. HRESULT
  2681. DebugFailureAnalysis::CheckModuleSymbols(PSTR ModName, PSTR ShowName)
  2682. {
  2683. ULONG ModIndex;
  2684. ULONG64 ModBase;
  2685. DEBUG_MODULE_PARAMETERS ModParams;
  2686. if (S_OK != g_ExtSymbols->GetModuleByModuleName(ModName, 0, &ModIndex,
  2687. &ModBase))
  2688. {
  2689. ExtErr("***** Debugger could not find %s in module list, "
  2690. "dump might be corrupt.\n"
  2691. "***** Followup with Debugger team\n\n",
  2692. ModName);
  2693. SetString(DEBUG_FLR_CORRUPT_MODULE_LIST, ModName);
  2694. return E_FAILURE_CORRUPT_MODULE_LIST;
  2695. }
  2696. else if ((S_OK != g_ExtSymbols->GetModuleParameters(1, &ModBase, 0,
  2697. &ModParams)) ||
  2698. (ModParams.SymbolType == DEBUG_SYMTYPE_NONE) ||
  2699. (ModParams.SymbolType == DEBUG_SYMTYPE_EXPORT))
  2700. // (ModParams.Flags & DEBUG_MODULE_SYM_BAD_CHECKSUM))
  2701. {
  2702. ExtErr("***** %s symbols are WRONG. Please fix symbols to "
  2703. "do analysis.\n\n", ShowName);
  2704. SetUlong64(DEBUG_FLR_WRONG_SYMBOLS, ModBase);
  2705. return E_FAILURE_WRONG_SYMBOLS;
  2706. }
  2707. return S_OK;
  2708. }
  2709. void
  2710. DebugFailureAnalysis::ProcessInformation(void)
  2711. {
  2712. //
  2713. // Analysis of abstracted information.
  2714. //
  2715. // Now that raw information has been gathered,
  2716. // perform abstract analysis of the gathered
  2717. // information to produce even higher-level
  2718. // information. The process iterates until no
  2719. // new information is produced.
  2720. //
  2721. AnalyzeStack();
  2722. while (ProcessInformationPass())
  2723. {
  2724. // Iterate.
  2725. }
  2726. //
  2727. // Only add corrupt modules if we did not find a specific solution.
  2728. //
  2729. // If we do find a memory corruptor, the followup and name will be set
  2730. // from the module name as part of bucketing.
  2731. if (!AddCorruptModules())
  2732. {
  2733. SetSymbolNameAndModule();
  2734. }
  2735. GenerateBucketId();
  2736. DbFindBucketInfo();
  2737. }
  2738. ULONG64
  2739. GetControlTransferTargetX86(ULONG64 StackOffset, PULONG64 ReturnOffset)
  2740. {
  2741. ULONG Done;
  2742. UCHAR InstrBuf[8];
  2743. ULONG StackReturn;
  2744. ULONG64 Target;
  2745. ULONG JumpCount;
  2746. //
  2747. // Check that we just performed a call, which implies
  2748. // the first value on the stack is equal to the return address
  2749. // computed during stack walk.
  2750. //
  2751. if (!ReadMemory(StackOffset, &StackReturn, 4, &Done) ||
  2752. (Done != 4) ||
  2753. StackReturn != (ULONG)*ReturnOffset)
  2754. {
  2755. return 0;
  2756. }
  2757. //
  2758. // Check for call rel32 instruction.
  2759. //
  2760. if (!ReadMemory(*ReturnOffset - 5, InstrBuf, 5, &Done) ||
  2761. (Done != 5) ||
  2762. (InstrBuf[0] != 0xe8))
  2763. {
  2764. return 0;
  2765. }
  2766. Target = (LONG64)(LONG)
  2767. ((ULONG)*ReturnOffset + *(ULONG UNALIGNED *)&InstrBuf[1]);
  2768. // Adjust the return offset to point to the start of the instruction.
  2769. (*ReturnOffset) -= 5;
  2770. //
  2771. // We may have called an import thunk or something else which
  2772. // immediately jumps somewhere else, so follow jumps.
  2773. //
  2774. JumpCount = 8;
  2775. for (;;)
  2776. {
  2777. if (!ReadMemory(Target, InstrBuf, 6, &Done) ||
  2778. Done < 5)
  2779. {
  2780. // We expect to be able to read the target memory
  2781. // as that's where we think IP is. If this fails
  2782. // we need to flag it as a problem.
  2783. return Target;
  2784. }
  2785. if (InstrBuf[0] == 0xe9)
  2786. {
  2787. Target = (LONG64)(LONG)
  2788. ((ULONG)Target + 5 + *(ULONG UNALIGNED *)&InstrBuf[1]);
  2789. }
  2790. else if (InstrBuf[0] == 0xff && InstrBuf[1] == 0x25)
  2791. {
  2792. ULONG64 Ind;
  2793. if (Done < 6)
  2794. {
  2795. // We see a jump but we don't have all the
  2796. // memory. To avoid spurious errors we just
  2797. // give up.
  2798. return 0;
  2799. }
  2800. Ind = (LONG64)(LONG)*(ULONG UNALIGNED *)&InstrBuf[2];
  2801. if (!ReadMemory(Ind, &Target, 4, &Done) ||
  2802. Done != 4)
  2803. {
  2804. return 0;
  2805. }
  2806. Target = (LONG64)(LONG)Target;
  2807. }
  2808. else
  2809. {
  2810. break;
  2811. }
  2812. if (JumpCount-- == 0)
  2813. {
  2814. // We've been tracing jumps too long, just give up.
  2815. return 0;
  2816. }
  2817. }
  2818. return Target;
  2819. }
  2820. BOOL
  2821. DebugFailureAnalysis::ProcessInformationPass(void)
  2822. {
  2823. ULONG Done;
  2824. ULONG64 ExceptionCode;
  2825. ULONG64 Arg1, Arg2;
  2826. ULONG64 Values[2];
  2827. ULONG PtrSize = IsPtr64() ? 8 : 4;
  2828. FA_ENTRY* Entry;
  2829. //
  2830. // Determine if the current fault is due to inability
  2831. // to execute an instruction. The checks are:
  2832. // 1. A read access violation at the current IP indicates
  2833. // the current instruction memory is invalid.
  2834. // 2. An illegal instruction fault indicates the current
  2835. // instruction is invalid.
  2836. //
  2837. if (!Get(DEBUG_FLR_FAILED_INSTRUCTION_ADDRESS))
  2838. {
  2839. if (GetUlong64(DEBUG_FLR_EXCEPTION_CODE, &ExceptionCode) &&
  2840. (ExceptionCode == STATUS_ILLEGAL_INSTRUCTION) &&
  2841. GetUlong64(DEBUG_FLR_FAULTING_IP, &Arg1))
  2842. {
  2843. // Invalid instruction.
  2844. SetUlong64(DEBUG_FLR_FAILED_INSTRUCTION_ADDRESS, Arg1);
  2845. return TRUE;
  2846. }
  2847. if ( // ExceptionCode == STATUS_ACCESS_VIOLATION &&
  2848. GetUlong64(DEBUG_FLR_READ_ADDRESS, &Arg1) &&
  2849. GetUlong64(DEBUG_FLR_FAULTING_IP, &Arg2) &&
  2850. Arg1 == Arg2)
  2851. {
  2852. // Invalid instruction.
  2853. SetUlong64(DEBUG_FLR_FAILED_INSTRUCTION_ADDRESS, Arg1);
  2854. return TRUE;
  2855. }
  2856. }
  2857. //
  2858. // If we've determined that the current failure is
  2859. // due to inability to execute an instruction, check
  2860. // and see whether there's a call to the instruction.
  2861. // If the instruction prior at the return address can be analyzed,
  2862. // check for known instruction sequences to see if perhaps
  2863. // the processor incorrectly handled a control transfer.
  2864. //
  2865. if (!Get(DEBUG_FLR_POSSIBLE_INVALID_CONTROL_TRANSFER) &&
  2866. (Entry = Get(DEBUG_FLR_LAST_CONTROL_TRANSFER)))
  2867. {
  2868. ULONG64 ReturnOffset = FA_ENTRY_DATA(PULONG64, Entry)[0];
  2869. Arg2 = FA_ENTRY_DATA(PULONG64, Entry)[1];
  2870. ULONG64 StackOffset = FA_ENTRY_DATA(PULONG64, Entry)[2];
  2871. ULONG64 Target = 0;
  2872. switch(g_TargetMachine)
  2873. {
  2874. case IMAGE_FILE_MACHINE_I386:
  2875. Target = GetControlTransferTargetX86(StackOffset, &ReturnOffset);
  2876. break;
  2877. }
  2878. if (Target && Target != Arg2)
  2879. {
  2880. char Sym1[MAX_PATH], Sym2[MAX_PATH];
  2881. ULONG64 Disp;
  2882. //
  2883. // If both addresses are within the same function
  2884. // we assume that there has been some execution
  2885. // in the function and therefore this doesn't
  2886. // actually indicate a problem.
  2887. // NOTE - DbgBreakPointWithStatus has an internal label
  2888. // which messes up symbols, so account for that too by
  2889. // checking we are 10 bytes within the function.
  2890. //
  2891. FaGetSymbol(Target, Sym1, &Disp, sizeof(Sym1));
  2892. FaGetSymbol(Arg2, Sym2, &Disp, sizeof(Sym2));
  2893. if ((Arg2 - Target > 10) &&
  2894. (strcmp(Sym1, Sym2) != 0))
  2895. {
  2896. PCHAR String;
  2897. ULONG64 BitDiff;
  2898. ULONG64 BitDiff2;
  2899. Values[0] = ReturnOffset;
  2900. Values[1] = Target;
  2901. SetUlong64s(DEBUG_FLR_POSSIBLE_INVALID_CONTROL_TRANSFER,
  2902. 2, Values);
  2903. //
  2904. // If the difference between the two address is a power of 2,
  2905. // then it's a single bit error.
  2906. // Also, to avoid sign extension issues due to a 1 bit error
  2907. // in the top bit, check if the difference betweent the two is
  2908. // only the sign extensions, and zero out the top 32 bits if
  2909. // it's the case.
  2910. //
  2911. BitDiff = Arg2 ^ Target;
  2912. if ((BitDiff >> 32) == 0xFFFFFFFF)
  2913. {
  2914. BitDiff &= 0xFFFFFFFF;
  2915. }
  2916. if (!(BitDiff2 = (BitDiff & (BitDiff - 1))))
  2917. {
  2918. Set(DEBUG_FLR_SINGLE_BIT_ERROR, 1);
  2919. }
  2920. if (!(BitDiff2 & (BitDiff2 - 1)))
  2921. {
  2922. Set(DEBUG_FLR_TWO_BIT_ERROR, 1);
  2923. }
  2924. if (String = g_pTriager->GetFollowupStr("badcpu", ""))
  2925. {
  2926. BestClassFollowUp = FlpSpecific;
  2927. CopyString(PossibleFollowups[FlpSpecific].Owner,
  2928. String,
  2929. sizeof(PossibleFollowups[FlpSpecific].Owner));
  2930. SetString(DEBUG_FLR_MODULE_NAME, "No_Module");
  2931. SetString(DEBUG_FLR_IMAGE_NAME, "No_Image");
  2932. SetUlong64(DEBUG_FLR_IMAGE_TIMESTAMP, 0);
  2933. }
  2934. return TRUE;
  2935. }
  2936. }
  2937. }
  2938. //
  2939. // If the process is determine to be of importance to this failure,
  2940. // also expose the process name.
  2941. // This will overwrite the PROCESS_NAME of the default process.
  2942. //
  2943. if (GetUlong64(DEBUG_FLR_PROCESS_OBJECT, &Arg1) &&
  2944. !Get(DEBUG_FLR_PROCESS_NAME))
  2945. {
  2946. ULONG NameOffset;
  2947. CHAR Name[17];
  2948. if (!GetFieldOffset("nt!_EPROCESS", "ImageFileName", &NameOffset) &&
  2949. NameOffset)
  2950. {
  2951. if (ReadMemory(Arg1 + NameOffset, Name, sizeof(Name), &Done) &&
  2952. (Done == sizeof(Name)))
  2953. {
  2954. Name[16] = 0;
  2955. SetString(DEBUG_FLR_PROCESS_NAME, Name);
  2956. return TRUE;
  2957. }
  2958. }
  2959. }
  2960. return FALSE;
  2961. }