Source code of Windows XP (NT5)
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.

2191 lines
63 KiB

  1. /*++
  2. Copyright (c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. bugcheck.cpp
  5. Abstract:
  6. WinDbg Extension Api
  7. Environment:
  8. User Mode.
  9. Revision History:
  10. Andre Vachon (andreva)
  11. bugcheck analyzer.
  12. --*/
  13. #include "precomp.h"
  14. #include <kdextsfn.h>
  15. #pragma hdrstop
  16. extern BUGDESC_APIREFS g_BugDescApiRefs[];
  17. extern ULONG g_NumBugDescApiRefs;
  18. PSTR g_PoolRegion[DbgPoolRegionMax] = {
  19. "Unknown", // DbgPoolRegionUnknown,
  20. "Special pool", // DbgPoolRegionSpecial,
  21. "Paged pool", // DbgPoolRegionPaged,
  22. "Nonpaged pool", // DbgPoolRegionNonPaged,
  23. "Pool code", // DbgPoolRegionCode,
  24. "Nonpaged pool expansion", // DbgPoolRegionNonPagedExpansion,
  25. };
  26. BOOL
  27. AnalyzeCrashInfo(
  28. PBUGCHECK_ANALYSIS Bc,
  29. BOOL Verbose
  30. );
  31. void
  32. GetCrashInfoFromBugCheck(
  33. PBUGCHECK_ANALYSIS Bc,
  34. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  35. );
  36. HRESULT
  37. BugCheckCE(
  38. PDEBUG_CLIENT Client,
  39. PBUGCHECK_ANALYSIS Bc
  40. )
  41. {
  42. HRESULT Status;
  43. ULONG Index;
  44. ULONG64 BaseAddress;
  45. CHAR ImageNameBuffer[512];
  46. //
  47. // The address at fault is in parameter 1
  48. //
  49. dprintf("Faulting code address : %p\n", Bc->Args[0]);
  50. Status = E_FAIL;
  51. if (Bc->Args[0])
  52. {
  53. Status = g_ExtSymbols->GetModuleByOffset(Bc->Args[0], 0,
  54. &Index, &BaseAddress);
  55. if (Status == S_OK)
  56. {
  57. Status = g_ExtSymbols->GetModuleNames(DEBUG_ANY_ID, BaseAddress,
  58. ImageNameBuffer,
  59. sizeof(ImageNameBuffer),
  60. NULL, NULL, 0, NULL,
  61. NULL, 0, NULL);
  62. }
  63. }
  64. if (Status == S_OK)
  65. {
  66. dprintf("Possible faulting driver name : %s\n", ImageNameBuffer);
  67. dprintf(" BaseAddress = %p\n", BaseAddress);
  68. dprintf(" Offset = %p\n", Bc->Args[0]-BaseAddress);
  69. }
  70. else
  71. {
  72. dprintf("Faulting driver name : UNKNOWN\n");
  73. }
  74. return Status;
  75. }
  76. /*
  77. Get the description record for a bugcheck code.
  78. */
  79. BOOL
  80. GetBugCheckDescription(
  81. PBUGCHECK_ANALYSIS Bc
  82. )
  83. {
  84. ULONG i;
  85. for (i=0; i<g_NumBugDescApiRefs; i++) {
  86. if (g_BugDescApiRefs[i].Code == Bc->Code) {
  87. (g_BugDescApiRefs[i].pExamineRoutine)(Bc);
  88. return TRUE;
  89. }
  90. }
  91. return FALSE;
  92. }
  93. void
  94. PrintBugDescription(
  95. PBUGCHECK_ANALYSIS pBugCheck
  96. )
  97. {
  98. LPTSTR Name = pBugCheck->szName;
  99. LPTSTR Description = pBugCheck->szDescription;
  100. if (!Name)
  101. {
  102. Name = "Unknown bugcheck code";
  103. }
  104. if (!Description)
  105. {
  106. Description = "Unknown bugcheck description\n";
  107. }
  108. dprintf("%s (%lx)\n%s", Name, pBugCheck->Code, Description);
  109. dprintf("Arguments:\n");
  110. for (ULONG i=0; i<4; i++) {
  111. dprintf("Arg%lx: %p",i+1,pBugCheck->Args[i]);
  112. if (pBugCheck->szParamsDesc[i]) {
  113. dprintf(", %s", pBugCheck->szParamsDesc[i]);
  114. }
  115. dprintf("\n");
  116. }
  117. }
  118. DECLARE_API( analyzebugcheck )
  119. /*++
  120. Routine Description:
  121. analyze a bugcheck.
  122. Arguments:
  123. None.
  124. Return Value:
  125. None.
  126. --*/
  127. {
  128. BUGCHECK_ANALYSIS Bc = {0};
  129. BOOL Verbose=FALSE;
  130. INIT_API();
  131. while (*args == ' ' || *args == '\t') args++;
  132. while (*args == '-') {
  133. ++args;
  134. switch (*args) {
  135. case 'v':
  136. Verbose = TRUE;
  137. ++args;
  138. break;
  139. case 's':
  140. if (!strncmp(args, "show",4))
  141. {
  142. ULONG64 Code;
  143. args+=4;
  144. GetExpressionEx(args, &Code, &args);
  145. Bc.Code = (ULONG)Code;
  146. GetBugCheckDescription(&Bc);
  147. PrintBugDescription(&Bc);
  148. EXIT_API();
  149. return Status;
  150. }
  151. default:
  152. dprintf("Unknown option %c\n", *args);
  153. break;
  154. }
  155. while (*args == ' ' || *args == '\t') args++;
  156. }
  157. Status = g_ExtControl->ReadBugCheckData(&Bc.Code, &Bc.Args[0], &Bc.Args[1],
  158. &Bc.Args[2], &Bc.Args[3]);
  159. if (Status != S_OK)
  160. {
  161. EXIT_API();
  162. return Status;
  163. }
  164. #if 0
  165. // disable this
  166. if (Bc.Code == 0) {
  167. //
  168. // It might be watchdog bugcheck
  169. //
  170. ULONG64 WdBcAddr;
  171. ULONG res;
  172. WdBcAddr = GetExpression("watchdog!g_WdBugCheckData");
  173. if (WdBcAddr &&
  174. ReadMemory(WdBcAddr, &Bc.Code, sizeof(Bc.Code), &res) &&
  175. ReadPointer(WdBcAddr+sizeof(Bc.Code), &Bc.Args[0]) &&
  176. ReadPointer(WdBcAddr+sizeof(Bc.Code), &Bc.Args[1]) &&
  177. ReadPointer(WdBcAddr+sizeof(Bc.Code), &Bc.Args[2]) &&
  178. ReadPointer(WdBcAddr+sizeof(Bc.Code), &Bc.Args[3])) {
  179. dprintf("\n*** Watchdog bugcheck.\n");
  180. }
  181. }
  182. #endif
  183. Status = AnalyzeCrashInfo(&Bc, Verbose) ? S_OK : E_FAIL;
  184. if (!Verbose) {
  185. EXIT_API();
  186. return Status;
  187. }
  188. switch (Bc.Code)
  189. {
  190. case 0xCE:
  191. Status = BugCheckCE(Client, &Bc);
  192. break;
  193. default:
  194. break;
  195. }
  196. //
  197. // Create a new minidump file of this crash
  198. //
  199. #if 0
  200. ULONG FailTime = 0;
  201. ULONG UpTime = 0;
  202. CHAR CurrentTime[20];
  203. CHAR CurrentDate[20];
  204. CHAR Buffer[MAX_PATH];
  205. g_ExtControl->GetCurrentTimeDate(&FailTime);
  206. g_ExtControl->GetCurrentSystemUpTime(&UpTime);
  207. _strtime(CurrentTime);
  208. _strdate(CurrentDate);
  209. if (CurrentTime && UpTime)
  210. {
  211. sprintf(Buffer, "Dump%s-%s-%08lx-%08lx-%s.dmp",
  212. FailTime, Uptime, Currentdate, CurrentTime);
  213. Status = g_ExtClient->WriteDumpFile(Buffer ,DEBUG_DUMP_SMALL);
  214. }
  215. #endif
  216. CHAR Buffer[MAX_PATH];
  217. if (GetTempFileName(".", "DMP", 0, Buffer))
  218. {
  219. Status = g_ExtClient->WriteDumpFile(Buffer ,DEBUG_DUMP_SMALL);
  220. if (Status == S_OK)
  221. {
  222. //
  223. // We create a file - now lets send it to the database
  224. //
  225. //CopyFile(Buffer, "c:\\xxxx", 0);
  226. DeleteFile(Buffer);
  227. }
  228. }
  229. dprintf("\n\n");
  230. EXIT_API();
  231. return S_OK;
  232. }
  233. EXTENSION_API( GetKerFailureAnalysis )(
  234. IN PDEBUG_CLIENT Client,
  235. OUT PDEBUG_FAILURE_ANALYSIS* pAnalysis
  236. )
  237. {
  238. BUGCHECK_ANALYSIS Bc = {0};
  239. BOOL Verbose;
  240. INIT_API();
  241. Status = g_ExtControl->ReadBugCheckData(&Bc.Code, &Bc.Args[0], &Bc.Args[1],
  242. &Bc.Args[2], &Bc.Args[3]);
  243. if (Status != S_OK)
  244. {
  245. EXIT_API();
  246. return Status;
  247. }
  248. GetCrashInfoFromBugCheck(&Bc, pAnalysis);
  249. Status = *pAnalysis ? S_OK : E_FAIL;
  250. EXIT_API();
  251. return Status;
  252. }
  253. #define MAX_STACK_FRAMES 50
  254. #define DWORD_ALIGN(n) (((n+sizeof(DWORD)-1)/n)*n)
  255. #define DECL_GETINFO(bcname) \
  256. void \
  257. GetInfoFor##bcname ( \
  258. PBUGCHECK_ANALYSIS Bc, \
  259. PDEBUG_FAILURE_ANALYSIS *pCrashInfo \
  260. )
  261. DECL_GETINFO( DRIVER_CAUGHT_MODIFYING_FREED_POOL );
  262. DECL_GETINFO( DRIVER_VERIFIER_IOMANAGER_VIOLATION );
  263. DECL_GETINFO( IRQL_NOT_LESS_OR_EQUAL );
  264. DECL_GETINFO( KMODE_EXCEPTION_NOT_HANDLED );
  265. DECL_GETINFO( SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION );
  266. DECL_GETINFO( TIMER_OR_DPC_INVALID );
  267. DECL_GETINFO( UNEXPECTED_KERNEL_MODE_TRAP );
  268. DECL_GETINFO( DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL );
  269. BOOL
  270. AddContextInfoFromStack(
  271. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  272. );
  273. BOOL
  274. GetTrapFromStackFrameFPO(
  275. PDEBUG_STACK_FRAME StackFrame,
  276. PULONG64 TrapFrame
  277. );
  278. ULONG64
  279. GetImplicitContextInstrOffset( void )
  280. {
  281. ULONG64 IP=0;
  282. switch (TargetMachine) {
  283. case IMAGE_FILE_MACHINE_I386:
  284. IP = GetExpression("@eip");
  285. break;
  286. case IMAGE_FILE_MACHINE_IA64:
  287. IP = GetExpression("@iip");
  288. break;
  289. case IMAGE_FILE_MACHINE_AMD64:
  290. IP = GetExpression("@rip");
  291. break;
  292. }
  293. return IP;
  294. }
  295. BOOL
  296. AnalyzeValue(
  297. PDEBUG_FLR_PARAM_VALUES pCrashParam,
  298. BOOL Verbose,
  299. BOOL ShowFollowup
  300. )
  301. {
  302. CHAR Buffer[MAX_PATH];
  303. CHAR Module[MAX_PATH];
  304. ULONG64 Base;
  305. ULONG64 Address;
  306. BOOL ShowFollowForBufferName = FALSE;
  307. ULONG OutCtl;
  308. if (!Verbose) {
  309. // show only info directly related to faulting driver
  310. if (((pCrashParam->ParamType & 0xf0000000) != DEBUG_FLR_IP) &&
  311. ((pCrashParam->ParamType & 0xf0000000) != DEBUG_FLR_THREAD)) {
  312. return FALSE;
  313. }
  314. OutCtl = DEBUG_OUTCTL_IGNORE;
  315. } else {
  316. OutCtl = DEBUG_OUTCTL_AMBIENT;
  317. }
  318. switch (pCrashParam->ParamType) {
  319. default:
  320. dprintf("Unknown type %lx, value %p\n", pCrashParam->ParamType, pCrashParam->Value);
  321. return FALSE;
  322. case DEBUG_FLR_CONTEXT:
  323. if (Verbose) {
  324. dprintf("Context %p\n", pCrashParam->Value);
  325. }
  326. sprintf(Buffer, ".cxr %I64lx", pCrashParam->Value);
  327. g_ExtControl->Execute(OutCtl,Buffer,DEBUG_EXECUTE_DEFAULT);
  328. if (Verbose) {
  329. g_ExtControl->Execute(OutCtl,"k",DEBUG_EXECUTE_DEFAULT);
  330. } else if (ShowFollowup) {
  331. ULONG64 Disp;
  332. // Get symbol for IP in the context
  333. Address = GetImplicitContextInstrOffset();
  334. Buffer[0] = 0;
  335. GetSymbol(Address, Buffer, &Disp);
  336. Module[0] = 0;
  337. g_ExtSymbols->GetModuleByOffset(Address,0, NULL, &Base);
  338. g_ExtSymbols->GetModuleNameString(DEBUG_MODNAME_IMAGE,DEBUG_ANY_ID, Base, &Module[0], sizeof(Module), NULL);
  339. dprintf("Faulting driver %s ( %s+%I64lx )\n",
  340. Module,
  341. Buffer,
  342. Disp);
  343. ShowFollowForBufferName = TRUE;
  344. }
  345. g_ExtControl->Execute(OutCtl,".cxr",DEBUG_EXECUTE_DEFAULT);
  346. break;
  347. case DEBUG_FLR_CURRENT_IRQL:
  348. dprintf("Current IRQL %lx\n", pCrashParam->Value);
  349. break;
  350. case DEBUG_FLR_DEVICE_OBJECT:
  351. dprintf("Device Object %p\n", pCrashParam->Value);
  352. sprintf(Buffer, "!devobj %I64lx", pCrashParam->Value);
  353. g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
  354. case DEBUG_FLR_DRIVER_OBJECT:
  355. dprintf("Driver Object %p\n", pCrashParam->Value);
  356. if (g_ExtControl) {
  357. sprintf(Buffer, "!drvobj %I64lx", pCrashParam->Value);
  358. g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
  359. }
  360. case DEBUG_FLR_EXCEPTION_CODE:
  361. dprintf("Unhandled exception %lx\n", pCrashParam->Value);
  362. break;
  363. case DEBUG_FLR_EXCEPTION_PARAMETER1:
  364. dprintf("Exception parameter 1 : %p\n", pCrashParam->Value);
  365. break;
  366. case DEBUG_FLR_EXCEPTION_PARAMETER2:
  367. dprintf("Exception parameter 2 : %p\n", pCrashParam->Value);
  368. break;
  369. case DEBUG_FLR_EXCEPTION_RECORD:
  370. dprintf("Exception Record %p\n", pCrashParam->Value);
  371. if (g_ExtControl) {
  372. sprintf(Buffer, ".exr %I64lx", pCrashParam->Value);
  373. g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
  374. }
  375. break;
  376. case DEBUG_FLR_POSSIBLE_FAULTING_MODULE:
  377. case DEBUG_FLR_FAULTING_MODULE:
  378. case DEBUG_FLR_IP: {
  379. if (pCrashParam->ParamType == DEBUG_FLR_POSSIBLE_FAULTING_MODULE) {
  380. dprintf("Probably caused by ");
  381. } else {
  382. dprintf("Fault occurred in ");
  383. }
  384. GetSymbol(pCrashParam->Value, Buffer, &Address);
  385. Module[0] = 0;
  386. g_ExtSymbols->GetModuleByOffset(pCrashParam->Value,0, NULL, &Base);
  387. g_ExtSymbols->GetModuleNameString(DEBUG_MODNAME_IMAGE,DEBUG_ANY_ID, Base, &Module[0], sizeof(Module), NULL);
  388. dprintf("driver %s ( %s+%I64lx )\n",
  389. Module,
  390. Buffer,
  391. Address);
  392. ShowFollowForBufferName = TRUE;
  393. break;
  394. }
  395. case DEBUG_FLR_FOLLOWUP_IP: {
  396. GetSymbol(pCrashParam->Value, Buffer, &Address);
  397. ShowFollowForBufferName = TRUE;
  398. break;
  399. }
  400. case DEBUG_FLR_IRP_ADDRESS:
  401. dprintf("Irp %p\n", pCrashParam->Value);
  402. if (g_ExtControl) {
  403. sprintf(Buffer, "!irp %I64lx", pCrashParam->Value);
  404. g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
  405. }
  406. case DEBUG_FLR_IRP_CANCEL_ROUTINE:
  407. GetSymbol(pCrashParam->Value, Buffer, &Address);
  408. dprintf("Irp cancel routine %p ( %s+%I64lx )\n",
  409. pCrashParam->Value,
  410. Buffer,
  411. Address);
  412. break;
  413. case DEBUG_FLR_MM_INTERNAL_CODE:
  414. dprintf("Mm internal code %lx\n", pCrashParam->Value);
  415. break;
  416. case DEBUG_FLR_POOL_ADDRESS: {
  417. dprintf("Relevant Pool %p\n", pCrashParam->Value);
  418. if (g_ExtControl) {
  419. sprintf(Buffer, "!pool %I64lx", pCrashParam->Value);
  420. g_ExtControl->Execute(DEBUG_OUTCTL_AMBIENT,Buffer,DEBUG_EXECUTE_DEFAULT);
  421. }
  422. break;
  423. }
  424. case DEBUG_FLR_PREVIOUS_IRQL:
  425. dprintf("Previous IRQL %lx\n", pCrashParam->Value);
  426. break;
  427. case DEBUG_FLR_PREVIOUS_MODE:
  428. dprintf("Crash occured in %s mode\n", pCrashParam->Value ? "User" : "Kernel");
  429. break;
  430. case DEBUG_FLR_READ_ADDRESS: {
  431. PSTR PoolRegion = NULL;
  432. PGET_POOL_REGION GetPoolRegion = NULL;
  433. dprintf("Read address %p", pCrashParam->Value);
  434. if (g_ExtControl->GetExtensionFunction(0, "GetPoolRegion", (FARPROC*)&GetPoolRegion) == S_OK) {
  435. if (GetPoolRegion) {
  436. DEBUG_POOL_REGION RegionId;
  437. (*GetPoolRegion)(g_ExtClient, pCrashParam->Value,&RegionId);
  438. PoolRegion = g_PoolRegion[RegionId];
  439. }
  440. }
  441. if (PoolRegion) {
  442. dprintf(", %s\n",PoolRegion);
  443. } else {
  444. dprintf("\n");
  445. }
  446. break;
  447. }
  448. case DEBUG_FLR_TRAP:
  449. if (Verbose) {
  450. dprintf("TrapFrame %p\n", pCrashParam->Value);
  451. }
  452. sprintf(Buffer, ".trap %I64lx", pCrashParam->Value);
  453. g_ExtControl->Execute(OutCtl,Buffer,DEBUG_EXECUTE_DEFAULT);
  454. if (Verbose) {
  455. g_ExtControl->Execute(OutCtl,"k",DEBUG_EXECUTE_DEFAULT);
  456. } else {
  457. ULONG64 Disp;
  458. // Get symbol for IP in the context
  459. Address = GetImplicitContextInstrOffset();
  460. Buffer[0] = 0;
  461. GetSymbol(Address, Buffer, &Disp);
  462. Module[0] = 0;
  463. g_ExtSymbols->GetModuleByOffset(Address,0, NULL, &Base);
  464. g_ExtSymbols->GetModuleNameString(DEBUG_MODNAME_IMAGE,DEBUG_ANY_ID, Base, &Module[0], sizeof(Module), NULL);
  465. dprintf("Faulting driver %s ( %s+%I64lx )\n",
  466. Module,
  467. Buffer,
  468. Disp);
  469. ShowFollowForBufferName = TRUE;
  470. }
  471. g_ExtControl->Execute(OutCtl,".trap",DEBUG_EXECUTE_DEFAULT);
  472. break;
  473. case DEBUG_FLR_TRAP_EXCEPTION:
  474. dprintf("Unhandled exception %lx\n", pCrashParam->Value);
  475. break;
  476. case DEBUG_FLR_TSS:
  477. if (Verbose) {
  478. dprintf("TSS %p\n", pCrashParam->Value);
  479. }
  480. sprintf(Buffer, ".tss %I64lx", pCrashParam->Value);
  481. g_ExtControl->Execute(OutCtl,Buffer,DEBUG_EXECUTE_DEFAULT);
  482. g_ExtControl->Execute(OutCtl,"k",DEBUG_EXECUTE_DEFAULT);
  483. g_ExtControl->Execute(OutCtl,".trap",DEBUG_EXECUTE_DEFAULT);
  484. break;
  485. case DEBUG_FLR_WORK_ITEM:
  486. dprintf("Work Item %p\n", pCrashParam->Value);
  487. break;
  488. case DEBUG_FLR_WORKER_ROUTINE:
  489. GetSymbol(pCrashParam->Value, Buffer, &Address);
  490. dprintf("Wroket routine %p ( %s+%I64lx )\n",
  491. pCrashParam->Value,
  492. Buffer,
  493. Address);
  494. break;
  495. case DEBUG_FLR_WRITE_ADDRESS: {
  496. PSTR PoolRegion = NULL;
  497. PGET_POOL_REGION GetPoolRegion = NULL;
  498. dprintf("Write address %p", pCrashParam->Value);
  499. if (g_ExtControl->GetExtensionFunction(0, "GetPoolRegion", (FARPROC*)&GetPoolRegion) == S_OK) {
  500. if (GetPoolRegion) {
  501. DEBUG_POOL_REGION RegionId;
  502. (*GetPoolRegion)(g_ExtClient, pCrashParam->Value,&RegionId);
  503. PoolRegion = g_PoolRegion[RegionId];
  504. }
  505. }
  506. if (PoolRegion) {
  507. dprintf(", %s\n",PoolRegion);
  508. } else {
  509. dprintf("\n");
  510. }
  511. break;
  512. }
  513. }
  514. if (!ShowFollowForBufferName || !ShowFollowup) {
  515. return 1;
  516. }
  517. EXT_TRIAGE_FOLLOWP FollowUp = NULL;
  518. if (g_ExtControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol", (FARPROC *)&FollowUp) == S_OK) {
  519. DEBUG_TRIAGE_FOLLOWUP_INFO fInfo;
  520. if (FollowUp) {
  521. fInfo.SizeOfStruct = sizeof(fInfo);
  522. fInfo.OwnerName.Buffer = &Module[0];
  523. fInfo.OwnerName.MaximumLength = sizeof(Module);
  524. if ((*FollowUp)(Buffer, &fInfo)) {
  525. dprintf("Followup : %s\n", fInfo.OwnerName.Buffer);
  526. return 3;
  527. }
  528. }
  529. }
  530. return 1;
  531. }
  532. PDEBUG_FAILURE_ANALYSIS
  533. FAInitMemBlock(
  534. ULONG Size
  535. )
  536. /*
  537. Allocate and initialize memory for FAILUSER_ANALYZER
  538. */
  539. {
  540. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  541. CrashInfo = (PDEBUG_FAILURE_ANALYSIS) malloc(Size);
  542. if (!CrashInfo) {
  543. return NULL;
  544. }
  545. ZeroMemory(CrashInfo, Size);
  546. CrashInfo->SizeOfHeader = sizeof(DEBUG_FLR_PARAM_VALUES);
  547. CrashInfo->Size = Size;
  548. return CrashInfo;
  549. }
  550. PDEBUG_FAILURE_ANALYSIS
  551. FAReInitMemBlock(
  552. PDEBUG_FAILURE_ANALYSIS pOldBlock,
  553. ULONG Size
  554. )
  555. /*
  556. Allocate and initialize memory for FAILUSER_ANALYZER from pOldBlock
  557. */
  558. {
  559. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  560. if (pOldBlock && (Size < pOldBlock->Size)) {
  561. return NULL;
  562. }
  563. CrashInfo = (PDEBUG_FAILURE_ANALYSIS) malloc(Size);
  564. if (!CrashInfo) {
  565. return NULL;
  566. }
  567. ZeroMemory(CrashInfo, Size);
  568. if (pOldBlock) {
  569. memcpy(CrashInfo, pOldBlock, pOldBlock->Size);
  570. }
  571. CrashInfo->SizeOfHeader = sizeof(DEBUG_FLR_PARAM_VALUES);
  572. CrashInfo->Size = Size;
  573. return CrashInfo;
  574. }
  575. void
  576. GetCrashInfoFromBugCheck(
  577. PBUGCHECK_ANALYSIS Bc,
  578. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  579. )
  580. {
  581. *pCrashInfo = NULL;
  582. switch (Bc->Code) {
  583. #define GETINFOCASE(bcname) \
  584. case bcname : \
  585. GetInfoFor##bcname (Bc, pCrashInfo); \
  586. break;
  587. #define DUPINFOCASE(bcname) \
  588. case bcname:
  589. GETINFOCASE( DRIVER_CAUGHT_MODIFYING_FREED_POOL );
  590. DUPINFOCASE( PAGE_FAULT_IN_FREED_SPECIAL_POOL );
  591. DUPINFOCASE( PAGE_FAULT_BEYOND_END_OF_ALLOCATION );
  592. DUPINFOCASE( TERMINAL_SERVER_DRIVER_MADE_INCORRECT_MEMORY_REFERENCE );
  593. DUPINFOCASE( PAGE_FAULT_IN_NONPAGED_AREA );
  594. DUPINFOCASE( DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION );
  595. GETINFOCASE( DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL );
  596. DUPINFOCASE( DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS )
  597. GETINFOCASE( DRIVER_VERIFIER_IOMANAGER_VIOLATION );
  598. DUPINFOCASE( DRIVER_IRQL_NOT_LESS_OR_EQUAL );
  599. GETINFOCASE( IRQL_NOT_LESS_OR_EQUAL );
  600. GETINFOCASE( KMODE_EXCEPTION_NOT_HANDLED );
  601. GETINFOCASE( SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION );
  602. GETINFOCASE( TIMER_OR_DPC_INVALID );
  603. GETINFOCASE( UNEXPECTED_KERNEL_MODE_TRAP );
  604. #undef DUPINFOCASE
  605. #undef GETINFOCASE
  606. default:
  607. break;
  608. }
  609. AddContextInfoFromStack(pCrashInfo);
  610. if (*pCrashInfo) {
  611. (*pCrashInfo)->FailureType = DEBUG_FLR_BUGCHECK;
  612. } else {
  613. }
  614. return;
  615. }
  616. BOOL
  617. AnalyzeCrashInfo(
  618. PBUGCHECK_ANALYSIS Bc,
  619. BOOL Verbose
  620. )
  621. {
  622. PDEBUG_FAILURE_ANALYSIS pCrashInfo;
  623. ULONG ValCount;
  624. BOOL StackShown=FALSE;
  625. if (!Bc) {
  626. dprintf("No analysis without BugCheckInfo\n");
  627. return FALSE;
  628. }
  629. pCrashInfo = NULL;
  630. GetCrashInfoFromBugCheck(Bc, &pCrashInfo);
  631. dprintf("*******************************************************************************\n");
  632. dprintf("* *\n");
  633. dprintf("* Bugcheck Analysis *\n");
  634. dprintf("* *\n");
  635. dprintf("*******************************************************************************\n");
  636. dprintf("\n");
  637. if (Verbose)
  638. {
  639. GetBugCheckDescription(Bc);
  640. PrintBugDescription(Bc);
  641. dprintf("\n\nDetails:\n");
  642. } else {
  643. dprintf("Use !analyzebugcheck -v to get more information.\n\n");
  644. }
  645. if (Bc->Code && !Verbose) {
  646. dprintf("BugCheck %lX, {%1p, %1p, %1p, %1p}\n",
  647. Bc->Code,
  648. Bc->Args[0],Bc->Args[1],Bc->Args[2],Bc->Args[3]);
  649. }
  650. if (!pCrashInfo) {
  651. return FALSE;
  652. }
  653. BOOL FollowUpShown = FALSE;
  654. BOOL DriverShown = FALSE;
  655. if (!Verbose) {
  656. // First show what we thought caused failure
  657. for (ValCount=0; ValCount<pCrashInfo->ParamCount; ValCount++) {
  658. ULONG retval;
  659. if (pCrashInfo->Params[ValCount].ParamType == DEBUG_FLR_POSSIBLE_FAULTING_MODULE) {
  660. if (retval = AnalyzeValue(&pCrashInfo->Params[ValCount], Verbose, !FollowUpShown)) {
  661. DriverShown = TRUE;
  662. FollowUpShown = FollowUpShown || (retval & 2);
  663. if (!Verbose && FollowUpShown) {
  664. // We got the faulting driver
  665. break;
  666. }
  667. }
  668. }
  669. }
  670. // Now check for any other things showing faulting IP
  671. for (ValCount=0; ValCount<pCrashInfo->ParamCount; ValCount++) {
  672. ULONG retval;
  673. if ((((pCrashInfo->Params[ValCount].ParamType & 0xf0000000) == DEBUG_FLR_THREAD) ||
  674. (pCrashInfo->Params[ValCount].ParamType == DEBUG_FLR_IP) ||
  675. (pCrashInfo->Params[ValCount].ParamType == DEBUG_FLR_FAULTING_MODULE) ||
  676. (pCrashInfo->Params[ValCount].ParamType == DEBUG_FLR_POSSIBLE_FAULTING_MODULE)) &&
  677. DriverShown) {
  678. continue;
  679. }
  680. if ((pCrashInfo->Params[ValCount].ParamType & 0xf0000000) == DEBUG_FLR_IP) {
  681. if (retval = AnalyzeValue(&pCrashInfo->Params[ValCount], Verbose, !FollowUpShown)) {
  682. DriverShown = TRUE;
  683. FollowUpShown = FollowUpShown || (retval & 2);
  684. if (!Verbose && FollowUpShown) {
  685. // We got the followup info
  686. break;
  687. }
  688. }
  689. }
  690. }
  691. } else {
  692. for (ValCount=0; ValCount<pCrashInfo->ParamCount; ValCount++) {
  693. ULONG retval;
  694. if (retval = AnalyzeValue(&pCrashInfo->Params[ValCount], Verbose, !FollowUpShown)) {
  695. DriverShown = TRUE;
  696. FollowUpShown = FollowUpShown || (retval & 2);
  697. }
  698. if ((pCrashInfo->Params[ValCount].ParamType & 0xf0000000) == DEBUG_FLR_THREAD) {
  699. StackShown = TRUE;
  700. }
  701. }
  702. }
  703. if (!FollowUpShown) {
  704. EXT_TRIAGE_FOLLOWP FollowUp = NULL;
  705. if (g_ExtControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol", (FARPROC *)&FollowUp) == S_OK) {
  706. DEBUG_TRIAGE_FOLLOWUP_INFO fInfo;
  707. if (FollowUp) {
  708. CHAR Buffer[100];
  709. fInfo.SizeOfStruct = sizeof(fInfo);
  710. fInfo.OwnerName.Buffer = &Buffer[0];
  711. fInfo.OwnerName.MaximumLength = sizeof(Buffer);
  712. if ((*FollowUp)("default", &fInfo)) {
  713. dprintf("Followup : %s\n", fInfo.OwnerName.Buffer);
  714. }
  715. }
  716. }
  717. }
  718. if (pCrashInfo->DriverNameOffset && Verbose) {
  719. PWCHAR DriverName;
  720. DriverName = (PWCHAR) ((PCHAR) pCrashInfo + pCrashInfo->DriverNameOffset);
  721. dprintf("Driver at fault : %ws\n", DriverName);
  722. }
  723. free (pCrashInfo);
  724. if (!Verbose) {
  725. dprintf("\n");
  726. } else if (!StackShown) {
  727. g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS, NULL, 20,
  728. DEBUG_STACK_FRAME_ADDRESSES |
  729. DEBUG_STACK_COLUMN_NAMES);
  730. }
  731. return TRUE;
  732. }
  733. BOOL
  734. ReadUnicodeString(
  735. ULONG64 Address,
  736. PWCHAR Buffer,
  737. ULONG BufferSize,
  738. PULONG StringSize)
  739. {
  740. UNICODE_STRING64 uStr;
  741. UNICODE_STRING32 uStr32;
  742. ULONG res;
  743. if (!Buffer) {
  744. return FALSE;
  745. }
  746. if (!IsPtr64()) {
  747. if (!ReadMemory(Address, &uStr32, sizeof(uStr32), &res)) {
  748. return FALSE;
  749. }
  750. uStr.Length = uStr32.Length;
  751. uStr.MaximumLength = uStr32.MaximumLength;
  752. uStr.Buffer = (ULONG64) (LONG64) (LONG) uStr32.Buffer;
  753. } else {
  754. if (!ReadMemory(Address, &uStr, sizeof(uStr), &res)) {
  755. return FALSE;
  756. }
  757. }
  758. if (StringSize) {
  759. *StringSize = uStr.Length;
  760. }
  761. uStr.Length = (USHORT) min(BufferSize, uStr.Length);
  762. if (!ReadMemory(uStr.Buffer, Buffer, uStr.Length, &res)) {
  763. return FALSE;
  764. }
  765. return TRUE;
  766. }
  767. BOOL
  768. AddKiBugcheckDriver(
  769. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  770. )
  771. /*
  772. Add driver name to CrashInfo if a KiBugCheckReferences a valid name
  773. */
  774. {
  775. ULONG64 KiBugCheckDriver;
  776. WCHAR DriverName[MAX_PATH];
  777. KiBugCheckDriver = GetExpression("NT!KiBugCheckDriver");
  778. if (KiBugCheckDriver) {
  779. ULONG length;
  780. PDEBUG_FAILURE_ANALYSIS NewInfo;
  781. ZeroMemory(DriverName, sizeof(DriverName));
  782. if (!ReadUnicodeString(KiBugCheckDriver, DriverName, sizeof(DriverName), &length)) {
  783. return FALSE;
  784. }
  785. DriverName[sizeof(DriverName) - 1] = 0;
  786. length = wcslen(DriverName);
  787. if (length) {
  788. NewInfo = FAInitMemBlock((*pCrashInfo)->Size + length + sizeof(WCHAR));
  789. if (!NewInfo) {
  790. return FALSE;
  791. }
  792. memcpy(NewInfo, *pCrashInfo, (*pCrashInfo)->Size);
  793. NewInfo->Size = (*pCrashInfo)->Size + length + sizeof(WCHAR);
  794. NewInfo->DriverNameOffset = (*pCrashInfo)->Size;
  795. memcpy((PCHAR) NewInfo + NewInfo->DriverNameOffset, DriverName, length + sizeof(WCHAR));
  796. *pCrashInfo = NewInfo;
  797. return TRUE;
  798. }
  799. }
  800. return FALSE;
  801. }
  802. BOOL
  803. IsFunctionAddr(
  804. ULONG64 IP,
  805. PSTR FuncName
  806. )
  807. // Check if IP is in the function FuncName
  808. {
  809. CHAR Buffer[MAX_PATH], *scan, *FnIP;
  810. ULONG64 Disp;
  811. GetSymbol(IP, Buffer, &Disp);
  812. if (scan = strchr(Buffer, '!')) {
  813. FnIP = scan+1;
  814. while (*FnIP == '_') ++FnIP;
  815. } else {
  816. FnIP = &Buffer[0];
  817. }
  818. return !strncmp(FnIP, FuncName, strlen(FuncName));
  819. }
  820. BOOL
  821. GetFirstNonNtModOnStack(
  822. PDEBUG_STACK_FRAME Stack,
  823. ULONG nFrames,
  824. PDEBUG_STACK_FRAME *pFrame
  825. );
  826. BOOL
  827. IsNtModuleAddress(
  828. ULONG64 Address
  829. );
  830. BOOL
  831. GetFirstTriageableRoutineOnStack(
  832. PDEBUG_STACK_FRAME Stack,
  833. ULONG nFrames,
  834. PDEBUG_STACK_FRAME *pFollowupFrame,
  835. PDEBUG_STACK_FRAME *pNonNtFrame
  836. );
  837. BOOL
  838. GetFollowupInfo(
  839. IN OPTIONAL ULONG64 Addr,
  840. IN OPTIONAL PSTR SymbolName,
  841. OUT OPTIONAL PCHAR *pOwner,
  842. ULONG OwnerSize
  843. );
  844. BOOL
  845. AddContextInfoFromStack(
  846. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  847. )
  848. //
  849. // Add trap frame, context info from the current stack
  850. //
  851. // Note(kksharma):We only need one of these to get to faulting stack (and only
  852. // one of them should should be available otherwise somethings wrong)
  853. //
  854. {
  855. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  856. ULONG i;
  857. ULONG ContextInfoIndex = -1;
  858. ULONG FaultingAddressIndex = -1;
  859. ULONG64 TrapFrame = 0;
  860. ULONG64 Exr=0, Cxr=0;
  861. DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES];
  862. ULONG frames;
  863. ULONG64 FollowupAddress = 0;
  864. ULONG64 PossibleFaultingAddress = 0;
  865. ULONG64 OriginalFaultingAddress = 0;
  866. ULONG nNewEntries = 0;
  867. CrashInfo = *pCrashInfo;
  868. if (CrashInfo) {
  869. // Check if we have anything to get context from
  870. for (i=0; i<CrashInfo->ParamCount; ++i) {
  871. if ((CrashInfo->Params[i].ParamType == DEBUG_FLR_TRAP) ||
  872. (CrashInfo->Params[i].ParamType == DEBUG_FLR_CONTEXT) ||
  873. (CrashInfo->Params[i].ParamType == DEBUG_FLR_THREAD)) {
  874. // We already have context info
  875. ContextInfoIndex = i;
  876. }
  877. if ((CrashInfo->Params[i].ParamType & 0xf0000000) == DEBUG_FLR_IP) {
  878. // We already have context info
  879. FaultingAddressIndex = i;
  880. OriginalFaultingAddress = CrashInfo->Params[i].Value;
  881. }
  882. if ((ContextInfoIndex != -1) &&
  883. (FaultingAddressIndex != -1)) {
  884. break;
  885. }
  886. }
  887. }
  888. if (ContextInfoIndex == -1) {
  889. //
  890. // Get the current stack and check if we can get tarp frame/context from it
  891. //
  892. ULONG64 ExceptionPointers = 0;
  893. if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) == S_OK) {
  894. for (i=0; i<frames; ++i) {
  895. #if 0
  896. // Stack walker taskes care of these when walking stack
  897. if (GetTrapFromStackFrameFPO(&stk[i], &TrapFrame)) {
  898. break;
  899. }
  900. // ebp of KiTrap0E is the trap frame
  901. if (IsFunctionAddr(stk[i].InstructionOffset, "KiTrap0E")) {
  902. TrapFrame = stk[i].FrameOffset;
  903. break;
  904. }
  905. #endif
  906. // First arg of KiMemoryFault is the trap frame
  907. if (IsFunctionAddr(stk[i].InstructionOffset, "KiMemoryFault")) {
  908. TrapFrame = stk[i].Params[0];
  909. break;
  910. }
  911. // Third arg of KiMemoryFault is the trap frame
  912. if (IsFunctionAddr(stk[i].InstructionOffset, "KiDispatchException")) {
  913. TrapFrame = stk[i].Params[2];
  914. break;
  915. }
  916. // First argument of this function is EXCEPTION_POINTERS
  917. if (IsFunctionAddr(stk[i].InstructionOffset, "PspUnhandledExceptionInSystemThread")) {
  918. ExceptionPointers = stk[i].Params[0];
  919. break;
  920. }
  921. }
  922. }
  923. if (ExceptionPointers) {
  924. ULONG PtrSize= IsPtr64() ? 8 : 4;
  925. if (!ReadPointer(ExceptionPointers, &Exr) ||
  926. !ReadPointer(ExceptionPointers + PtrSize, &Cxr)) {
  927. // dprintf("Unable to read exception poointers at %p\n", ExcepPtr);
  928. }
  929. }
  930. if (TrapFrame) nNewEntries++;
  931. if (Exr) nNewEntries++;
  932. if (Cxr) nNewEntries++;
  933. }
  934. //
  935. // We are done with context info, now track down faulting module / IP
  936. //
  937. if (FaultingAddressIndex != -1) {
  938. // We are done if this has some followup info available
  939. if (GetFollowupInfo((*pCrashInfo)->Params[FaultingAddressIndex].Value, NULL, NULL, 0)) {
  940. if (nNewEntries) {
  941. goto AddNewEntries;
  942. }
  943. return TRUE;
  944. }
  945. }
  946. //
  947. // Set the context
  948. //
  949. CHAR Command[50] = {0};
  950. if (ContextInfoIndex != -1) {
  951. switch ((*pCrashInfo)->Params[i].ParamType) {
  952. case DEBUG_FLR_CONTEXT:
  953. sprintf(Command, ".cxr %I64lx", (*pCrashInfo)->Params[i].Value);
  954. break;
  955. case DEBUG_FLR_TRAP:
  956. sprintf(Command, ".trap %I64lx", (*pCrashInfo)->Params[i].Value);
  957. break;
  958. case DEBUG_FLR_TSS:
  959. sprintf(Command, ".tss %I64lx", (*pCrashInfo)->Params[i].Value);
  960. break;
  961. case DEBUG_FLR_THREAD:
  962. sprintf(Command, ".thread %I64lx", (*pCrashInfo)->Params[i].Value);
  963. break;
  964. }
  965. if (Command[0]) {
  966. g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE, Command, DEBUG_EXECUTE_NOT_LOGGED);
  967. }
  968. } else {
  969. if (TrapFrame) {
  970. sprintf(Command, ".trap %I64lx", TrapFrame);
  971. } else if (Cxr) {
  972. sprintf(Command, ".cxr %I64lx", Cxr);
  973. }
  974. if (Command[0]) {
  975. g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE, Command, DEBUG_EXECUTE_NOT_LOGGED);
  976. }
  977. }
  978. //
  979. // Get relevant stack
  980. //
  981. if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) != S_OK) {
  982. frames = 0;
  983. }
  984. //
  985. // Last resort, Go through stack to guess likely culprit
  986. //
  987. CrashInfo = *pCrashInfo;
  988. PDEBUG_STACK_FRAME FollowupFrame = NULL, FirstNonNtFrame = NULL;
  989. GetFirstTriageableRoutineOnStack(&stk[0], frames, &FollowupFrame, &FirstNonNtFrame);
  990. if (Command[0]) {
  991. //
  992. // Clear the set context
  993. //
  994. g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE, ".cxr", DEBUG_EXECUTE_NOT_LOGGED);
  995. }
  996. if (FollowupFrame && FollowupFrame->InstructionOffset) {
  997. FollowupAddress = FollowupFrame->InstructionOffset;
  998. nNewEntries++;
  999. }
  1000. //
  1001. // If the faulting address we had doesn't seem right, check FollowupFrame
  1002. //
  1003. if ((FaultingAddressIndex == -1) || !OriginalFaultingAddress ||
  1004. IsNtModuleAddress(OriginalFaultingAddress)) {
  1005. //
  1006. // If we got the FollowupFrame, use it as the possible cause of fault
  1007. //
  1008. if (FollowupFrame && FollowupFrame->InstructionOffset &&
  1009. (FollowupFrame->InstructionOffset != OriginalFaultingAddress)) {
  1010. PossibleFaultingAddress = FollowupFrame->InstructionOffset;
  1011. nNewEntries++;
  1012. }
  1013. }
  1014. AddNewEntries:
  1015. if (nNewEntries) {
  1016. PDEBUG_FAILURE_ANALYSIS NewInfo;
  1017. if (CrashInfo) {
  1018. NewInfo = FAReInitMemBlock(CrashInfo, CrashInfo->Size+ (nNewEntries*sizeof(DEBUG_FLR_PARAM_VALUES)));
  1019. free(CrashInfo);
  1020. } else {
  1021. NewInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + (nNewEntries * sizeof(DEBUG_FLR_PARAM_VALUES)));
  1022. }
  1023. if (!NewInfo) {
  1024. return FALSE;
  1025. }
  1026. if (PossibleFaultingAddress) {
  1027. NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE;
  1028. NewInfo->Params[NewInfo->ParamCount].Value = PossibleFaultingAddress;
  1029. NewInfo->ParamCount++;
  1030. }
  1031. if (FollowupAddress) {
  1032. NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_FOLLOWUP_IP;
  1033. NewInfo->Params[NewInfo->ParamCount].Value = FollowupAddress;
  1034. NewInfo->ParamCount++;
  1035. }
  1036. if (TrapFrame) {
  1037. NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_TRAP;
  1038. NewInfo->Params[NewInfo->ParamCount].Value = TrapFrame;
  1039. ContextInfoIndex = NewInfo->ParamCount;
  1040. NewInfo->ParamCount++;
  1041. }
  1042. if (Exr) {
  1043. NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_EXCEPTION_RECORD;
  1044. NewInfo->Params[NewInfo->ParamCount].Value = Exr;
  1045. NewInfo->ParamCount++;
  1046. }
  1047. if (Cxr) {
  1048. NewInfo->Params[NewInfo->ParamCount].ParamType = DEBUG_FLR_CONTEXT;
  1049. NewInfo->Params[NewInfo->ParamCount].Value = Cxr;
  1050. ContextInfoIndex = NewInfo->ParamCount;
  1051. NewInfo->ParamCount++;
  1052. }
  1053. *pCrashInfo = NewInfo;
  1054. }
  1055. return TRUE;
  1056. }
  1057. void
  1058. GetModuleBaseAndOffset(
  1059. ULONG64 Address,
  1060. PULONG64 Base,
  1061. PULONG64 Offset
  1062. )
  1063. //
  1064. // Split the address into module base and offset in module
  1065. //
  1066. {
  1067. CHAR Buffer[MAX_PATH], *scan;
  1068. Buffer[0] = 0;
  1069. GetSymbol(Address, Buffer, Offset);
  1070. *Base = 0;
  1071. if (scan = strchr(Buffer, '!')) {
  1072. *scan = 0;
  1073. *Base = GetExpression(Buffer);
  1074. *Offset = Address - *Base;
  1075. }
  1076. }
  1077. BOOL
  1078. GetFollowupInfo(
  1079. IN OPTIONAL ULONG64 Addr,
  1080. IN OPTIONAL PSTR SymbolName,
  1081. OUT OPTIONAL PCHAR *pOwner,
  1082. ULONG OwnerSize
  1083. )
  1084. {
  1085. static CHAR Buffer[MAX_PATH], Owner[100];
  1086. EXT_TRIAGE_FOLLOWP FollowUp = NULL;
  1087. if (g_ExtControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol", (FARPROC *)&FollowUp) == S_OK) {
  1088. DEBUG_TRIAGE_FOLLOWUP_INFO fInfo;
  1089. if (!SymbolName) {
  1090. ULONG64 Disp;
  1091. GetSymbol(Addr, Buffer, &Disp);
  1092. SymbolName = &Buffer[0];
  1093. }
  1094. if (FollowUp && *SymbolName) {
  1095. fInfo.SizeOfStruct = sizeof(fInfo);
  1096. if (pOwner) {
  1097. fInfo.OwnerName.Buffer = *pOwner;
  1098. fInfo.OwnerName.MaximumLength = (USHORT)OwnerSize;
  1099. } else {
  1100. fInfo.OwnerName.Buffer = &Owner[0];
  1101. fInfo.OwnerName.MaximumLength = sizeof(Owner);
  1102. }
  1103. if ((*FollowUp)(SymbolName, &fInfo)) {
  1104. // This is an interesting routine to followup on
  1105. return TRUE;
  1106. }
  1107. }
  1108. }
  1109. return FALSE;
  1110. }
  1111. BOOL
  1112. IsNtModuleAddress(
  1113. ULONG64 Address
  1114. )
  1115. {
  1116. ULONG64 Disp, KernBase=0;
  1117. ULONG KernSize=0,i;
  1118. if (g_ExtSymbols->GetModuleByModuleName("nt", 0, &i, &KernBase) == S_OK) {
  1119. DEBUG_MODULE_PARAMETERS Params;
  1120. if (g_ExtSymbols->GetModuleParameters(1, &KernBase, i, &Params) == S_OK) {
  1121. KernSize = Params.Size;
  1122. if (((ULONG) (Address - KernBase) < KernSize) &&
  1123. (Address >= KernBase)) {
  1124. return TRUE;
  1125. }
  1126. }
  1127. }
  1128. return FALSE;
  1129. }
  1130. BOOL
  1131. GetFirstTriageableRoutineOnStack(
  1132. PDEBUG_STACK_FRAME Stack,
  1133. ULONG nFrames,
  1134. PDEBUG_STACK_FRAME *pFollowupFrame,
  1135. PDEBUG_STACK_FRAME *pNonNtFrame
  1136. )
  1137. //
  1138. // Find and return first routine on stack which can be succesfully traiged
  1139. // If no such routine is found, this will default to first non-nt routine
  1140. //
  1141. {
  1142. ULONG i;
  1143. CHAR Buffer[MAX_PATH], *scan, Owner[100];
  1144. ULONG64 Disp, KernBase=0;
  1145. ULONG KernSize=0;
  1146. *pFollowupFrame = NULL;
  1147. *pNonNtFrame = NULL;
  1148. if (g_ExtSymbols->GetModuleByModuleName("nt", 0, &i, &KernBase) == S_OK) {
  1149. DEBUG_MODULE_PARAMETERS Params;
  1150. if (g_ExtSymbols->GetModuleParameters(1, &KernBase, i, &Params) == S_OK) {
  1151. KernSize = Params.Size;
  1152. }
  1153. }
  1154. EXT_TRIAGE_FOLLOWP FollowUp = NULL;
  1155. if (g_ExtControl->GetExtensionFunction(0, "GetTriageFollowupFromSymbol", (FARPROC *)&FollowUp) != S_OK) {
  1156. FollowUp = NULL;
  1157. }
  1158. for (i=0; i<nFrames; ++i) {
  1159. DEBUG_TRIAGE_FOLLOWUP_INFO fInfo;
  1160. Buffer[0] = 0;
  1161. GetSymbol(Stack[i].InstructionOffset, Buffer, &Disp);
  1162. if (FollowUp && (*pFollowupFrame == NULL)) {
  1163. fInfo.SizeOfStruct = sizeof(fInfo);
  1164. fInfo.OwnerName.Buffer = &Owner[0];
  1165. fInfo.OwnerName.MaximumLength = sizeof(Owner);
  1166. if ((*FollowUp)(Buffer, &fInfo)) {
  1167. // This is an interesting routine to followup on
  1168. *pFollowupFrame = &Stack[i];
  1169. }
  1170. }
  1171. if (*pNonNtFrame == NULL) {
  1172. if (KernSize && KernBase) {
  1173. if ((KernBase > Stack[i].InstructionOffset) ||
  1174. (KernBase + KernSize) <= Stack[i].InstructionOffset) {
  1175. *pNonNtFrame = &Stack[i];
  1176. }
  1177. } else {
  1178. if (strncmp(Buffer, "nt", 2)) {
  1179. *pNonNtFrame = &Stack[i];
  1180. }
  1181. }
  1182. }
  1183. if (*pFollowupFrame && *pNonNtFrame) {
  1184. return TRUE;
  1185. }
  1186. }
  1187. if (*pFollowupFrame || *pNonNtFrame) {
  1188. return TRUE;
  1189. }
  1190. return FALSE;
  1191. }
  1192. BOOL
  1193. GetFirstNonNtModOnStack(
  1194. PDEBUG_STACK_FRAME Stack,
  1195. ULONG nFrames,
  1196. PDEBUG_STACK_FRAME *pFrame
  1197. )
  1198. //
  1199. // Find and return first routine on stack which is not from nt module
  1200. //
  1201. {
  1202. ULONG i;
  1203. CHAR Buffer[MAX_PATH], *scan;
  1204. ULONG64 Disp, KernBase=0;
  1205. ULONG KernSize=0;
  1206. if (g_ExtSymbols->GetModuleByModuleName("nt", 0, &i, &KernBase) == S_OK) {
  1207. DEBUG_MODULE_PARAMETERS Params;
  1208. if (g_ExtSymbols->GetModuleParameters(1, &KernBase, i, &Params) == S_OK) {
  1209. KernSize = Params.Size;
  1210. }
  1211. }
  1212. for (i=0; i<nFrames; ++i) {
  1213. if (KernSize && KernBase) {
  1214. if (KernBase <= Stack[i].InstructionOffset &&
  1215. (KernBase + KernSize) >= Stack[i].InstructionOffset) {
  1216. *pFrame = &Stack[i];
  1217. return TRUE;
  1218. }
  1219. } else {
  1220. Buffer[0] = 0;
  1221. GetSymbol(Stack[i].InstructionOffset, Buffer, &Disp);
  1222. if (strncmp(Buffer, "nt", 2)) {
  1223. *pFrame = &Stack[i];
  1224. return TRUE;
  1225. }
  1226. }
  1227. }
  1228. return FALSE;
  1229. }
  1230. BOOL
  1231. GetFirstNonNtModAddr(
  1232. ULONG64 *pAddr
  1233. )
  1234. //
  1235. // Find and return first routine on stack which is not from nt module
  1236. //
  1237. {
  1238. DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES], *Frame;
  1239. ULONG nFrames;
  1240. if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &nFrames ) == S_OK) {
  1241. if (GetFirstNonNtModOnStack(&stk[0], nFrames, &Frame)) {
  1242. *pAddr = Frame->InstructionOffset;
  1243. return TRUE;
  1244. }
  1245. }
  1246. return FALSE;
  1247. }
  1248. BOOL
  1249. GetTssFromStackFrameFPO(
  1250. PDEBUG_STACK_FRAME StackFrame,
  1251. PULONG Tss
  1252. )
  1253. {
  1254. if (TargetMachine != IMAGE_FILE_MACHINE_I386) {
  1255. return FALSE;
  1256. }
  1257. if (StackFrame->FuncTableEntry) {
  1258. PFPO_DATA FpoData = (PFPO_DATA)StackFrame->FuncTableEntry;
  1259. if (FpoData->cbFrame == FRAME_TSS) {
  1260. *Tss = (ULONG)StackFrame->Reserved[1];
  1261. return TRUE;
  1262. }
  1263. }
  1264. return FALSE;
  1265. }
  1266. BOOL
  1267. GetIPFromTss(
  1268. ULONG Tss,
  1269. PULONG64 IP
  1270. )
  1271. {
  1272. CHAR Buffer[MAX_PATH];
  1273. HRESULT Hr = E_FAIL;
  1274. if (g_ExtControl) {
  1275. sprintf(Buffer, ".tss %lx", Tss);
  1276. g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE,Buffer,DEBUG_EXECUTE_DEFAULT);
  1277. Hr = g_ExtRegisters->GetInstructionOffset(IP);
  1278. g_ExtControl->Execute(DEBUG_OUTCTL_IGNORE,".thread",DEBUG_EXECUTE_DEFAULT);
  1279. }
  1280. return Hr == S_OK;
  1281. }
  1282. BOOL
  1283. GetTrapFromStackFrameFPO(
  1284. PDEBUG_STACK_FRAME StackFrame,
  1285. PULONG64 TrapFrame
  1286. )
  1287. //
  1288. // Check stack frame if it has trap info in it.
  1289. // Return TRUE if trap frame address is initialised in TrapFrame
  1290. //
  1291. {
  1292. if (TargetMachine != IMAGE_FILE_MACHINE_I386) {
  1293. return FALSE;
  1294. }
  1295. if (StackFrame->FuncTableEntry) {
  1296. PFPO_DATA FpoData = (PFPO_DATA)StackFrame->FuncTableEntry;
  1297. if (FpoData->cbFrame == FRAME_TRAP) {
  1298. *TrapFrame = StackFrame->Reserved[2];
  1299. return TRUE;
  1300. }
  1301. }
  1302. return FALSE;
  1303. }
  1304. void
  1305. GetInfoForKMODE_EXCEPTION_NOT_HANDLED( // (1e)
  1306. PBUGCHECK_ANALYSIS Bc,
  1307. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  1308. )
  1309. /*
  1310. */
  1311. {
  1312. DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES];
  1313. ULONG frames, i;
  1314. ULONG64 TrapFrame=0;
  1315. ULONG ParamCount = 4;
  1316. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  1317. #if 0
  1318. // This is now grabbed in another generic routine
  1319. if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) == S_OK) {
  1320. for (i=0; i<frames; ++i) {
  1321. if (IsFunctionAddr(stk[i].InstructionOffset, "KiDispatchException")) {
  1322. TrapFrame = stk[i].Params[2];
  1323. break;
  1324. }
  1325. }
  1326. }
  1327. if (TrapFrame) {
  1328. ParamCount++;
  1329. }
  1330. #endif
  1331. CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
  1332. if (!CrashInfo) {
  1333. *pCrashInfo = NULL;
  1334. return;
  1335. }
  1336. CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
  1337. CrashInfo->BugCode = Bc->Code;
  1338. // Initialize known parameters
  1339. CrashInfo->ParamCount = ParamCount;
  1340. CrashInfo->Params[0].ParamType = DEBUG_FLR_EXCEPTION_CODE;
  1341. CrashInfo->Params[0].Value = Bc->Args[0];
  1342. CrashInfo->Params[1].ParamType = DEBUG_FLR_IP;
  1343. CrashInfo->Params[1].Value = Bc->Args[1];
  1344. CrashInfo->Params[2].ParamType = DEBUG_FLR_EXCEPTION_PARAMETER1;
  1345. CrashInfo->Params[2].Value = Bc->Args[2];
  1346. CrashInfo->Params[3].ParamType = DEBUG_FLR_EXCEPTION_PARAMETER2;
  1347. CrashInfo->Params[3].Value = Bc->Args[3];
  1348. if (TrapFrame) {
  1349. CrashInfo->Params[4].ParamType = DEBUG_FLR_TRAP;
  1350. CrashInfo->Params[4].Value = TrapFrame;
  1351. }
  1352. *pCrashInfo = CrashInfo;
  1353. return;
  1354. }
  1355. void
  1356. GetInfoForUNEXPECTED_KERNEL_MODE_TRAP( // (7f)
  1357. PBUGCHECK_ANALYSIS Bc,
  1358. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  1359. )
  1360. // It would be good to have TSS or TRAP address as exception parameter
  1361. {
  1362. DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES];
  1363. ULONG frames, i;
  1364. ULONG Tss=0;
  1365. ULONG64 TrapFrame=0;
  1366. ULONG ParamCount = 1;
  1367. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  1368. #if 0
  1369. // unnecessary
  1370. if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) == S_OK) {
  1371. for (i=0; i<frames; ++i) {
  1372. if (GetTssFromStackFrameFPO(&stk[i], &Tss)) {
  1373. break;
  1374. }
  1375. if (GetTrapFromStackFrameFPO(&stk[i], &TrapFrame)) {
  1376. break;
  1377. }
  1378. if (IsFunctionAddr(stk[i].InstructionOffset, "KiTrap")) {
  1379. TrapFrame = stk[i].FrameOffset;
  1380. break;
  1381. }
  1382. }
  1383. }
  1384. #endif
  1385. if (Tss || TrapFrame) {
  1386. ParamCount++;
  1387. }
  1388. CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
  1389. if (!CrashInfo) {
  1390. *pCrashInfo = NULL;
  1391. return;
  1392. }
  1393. CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
  1394. CrashInfo->BugCode = Bc->Code;
  1395. // Initialize known parameters
  1396. CrashInfo->ParamCount = ParamCount;
  1397. CrashInfo->Params[0].ParamType = DEBUG_FLR_TRAP_EXCEPTION;
  1398. CrashInfo->Params[0].Value = Bc->Args[0];
  1399. if (Tss) {
  1400. CrashInfo->Params[1].ParamType = DEBUG_FLR_TSS;
  1401. CrashInfo->Params[1].Value = Tss;
  1402. } else if (TrapFrame) {
  1403. CrashInfo->Params[1].ParamType = DEBUG_FLR_TRAP;
  1404. CrashInfo->Params[1].Value = TrapFrame;
  1405. }
  1406. *pCrashInfo = CrashInfo;
  1407. }
  1408. void GetInfoForIRQL_NOT_LESS_OR_EQUAL( // (a)
  1409. PBUGCHECK_ANALYSIS Bc,
  1410. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  1411. )
  1412. /*
  1413. * Parameters
  1414. *
  1415. * Parameter 1 Memory referenced
  1416. * Parameter 2 IRQL Value
  1417. * Parameter 3 0 - Read 1 - Write
  1418. * Parameter 4 Address that referenced the memory
  1419. *
  1420. *
  1421. * Special Case
  1422. *
  1423. * If Parameter 3 is nonzero and equal to Parameter 1, this means that
  1424. * a worker routine returned at a raised IRQL.
  1425. * In this case:
  1426. *
  1427. * Parameter 1 Address of work routine
  1428. * Parameter 2 IRQL at time of reference
  1429. * Parameter 3 Address of work routine
  1430. * Parameter 4 Work item
  1431. *
  1432. */
  1433. {
  1434. ULONG ParamCount = 3;
  1435. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  1436. CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
  1437. if (!CrashInfo) {
  1438. *pCrashInfo = NULL;
  1439. return;
  1440. }
  1441. *pCrashInfo = CrashInfo;
  1442. CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
  1443. CrashInfo->BugCode = Bc->Code;
  1444. // Initialize known parameters
  1445. CrashInfo->ParamCount = ParamCount;
  1446. if ((Bc->Args[0] == Bc->Args[2]) && Bc->Args[2]) {
  1447. // special case
  1448. CrashInfo->Params[0].ParamType = DEBUG_FLR_WORKER_ROUTINE;
  1449. CrashInfo->Params[0].Value = Bc->Args[2];
  1450. CrashInfo->Params[1].ParamType = DEBUG_FLR_WORK_ITEM;
  1451. CrashInfo->Params[1].Value = Bc->Args[3];
  1452. CrashInfo->Params[2].ParamType = DEBUG_FLR_CURRENT_IRQL;
  1453. CrashInfo->Params[2].Value = Bc->Args[1];
  1454. return;
  1455. }
  1456. CrashInfo->Params[0].ParamType = Bc->Args[2] ? DEBUG_FLR_WRITE_ADDRESS : DEBUG_FLR_READ_ADDRESS;
  1457. CrashInfo->Params[0].Value = Bc->Args[0];
  1458. CrashInfo->Params[1].ParamType = DEBUG_FLR_CURRENT_IRQL;
  1459. CrashInfo->Params[1].Value = Bc->Args[1];
  1460. CrashInfo->Params[2].ParamType = DEBUG_FLR_IP;
  1461. CrashInfo->Params[2].Value = Bc->Args[3];
  1462. return;
  1463. }
  1464. void GetInfoForSPECIAL_POOL_DETECTED_MEMORY_CORRUPTION( // (c1)
  1465. PBUGCHECK_ANALYSIS Bc,
  1466. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  1467. )
  1468. /*
  1469. */
  1470. {
  1471. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  1472. DEBUG_STACK_FRAME stk[MAX_STACK_FRAMES], *Frame;
  1473. ULONG ParamCount = 1;
  1474. ULONG frames;
  1475. ULONG64 ModBase, Offset;
  1476. if (g_ExtControl->GetStackTrace(0, 0, 0, stk, MAX_STACK_FRAMES, &frames ) == S_OK) {
  1477. if (GetFirstNonNtModOnStack(&stk[0], frames, &Frame)) {
  1478. GetModuleBaseAndOffset(Frame->InstructionOffset, &ModBase, &Offset);
  1479. ParamCount = 3;
  1480. }
  1481. }
  1482. CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
  1483. if (!CrashInfo) {
  1484. *pCrashInfo = NULL;
  1485. return;
  1486. }
  1487. CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
  1488. CrashInfo->BugCode = Bc->Code;
  1489. // Initialize known parameters
  1490. CrashInfo->ParamCount = ParamCount;
  1491. CrashInfo->Params[0].ParamType = DEBUG_FLR_SPECIAL_POOL_CORRUPTION_TYPE;
  1492. CrashInfo->Params[0].Value = Bc->Args[3];
  1493. if (ParamCount == 3) {
  1494. CrashInfo->Params[1].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE;
  1495. CrashInfo->Params[1].Value = ModBase;
  1496. CrashInfo->Params[2].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE_OFFSET;
  1497. CrashInfo->Params[2].Value = Offset;
  1498. }
  1499. *pCrashInfo = CrashInfo;
  1500. return;
  1501. }
  1502. void GetInfoForDRIVER_CAUGHT_MODIFYING_FREED_POOL( // (c6)
  1503. PBUGCHECK_ANALYSIS Bc,
  1504. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  1505. )
  1506. /*
  1507. An attempt was made to access freed pool memory. The faulty component is
  1508. displayed in the current kernel stack.
  1509. Arguments:
  1510. Arg1: memory referenced
  1511. Arg2: value 0 = read operation, 1 = write operation
  1512. Arg3: previous mode.
  1513. Arg4: 4.
  1514. */
  1515. {
  1516. DEBUG_POOL_DATA PoolData;
  1517. ULONG ParamCount = 3;
  1518. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  1519. CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
  1520. if (!CrashInfo) {
  1521. *pCrashInfo = NULL;
  1522. return;
  1523. }
  1524. CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
  1525. CrashInfo->BugCode = Bc->Code;
  1526. // Initialize known parameters
  1527. CrashInfo->ParamCount = ParamCount;
  1528. CrashInfo->Params[0].ParamType = Bc->Args[1] ? DEBUG_FLR_WRITE_ADDRESS : DEBUG_FLR_READ_ADDRESS;
  1529. CrashInfo->Params[0].Value = Bc->Args[0];
  1530. CrashInfo->Params[1].ParamType = DEBUG_FLR_PREVIOUS_MODE;
  1531. CrashInfo->Params[1].Value = Bc->Args[2];
  1532. CrashInfo->Params[2].ParamType = DEBUG_FLR_POOL_ADDRESS;
  1533. CrashInfo->Params[2].Value = Bc->Args[0]; // This is address in the pool,
  1534. // _EFN_GetPoolData will give more info
  1535. *pCrashInfo = CrashInfo;
  1536. return;
  1537. }
  1538. void GetInfoForTIMER_OR_DPC_INVALID( // (c7)
  1539. PBUGCHECK_ANALYSIS Bc,
  1540. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  1541. )
  1542. /*
  1543. *
  1544. * This is issued if a kernel timer or DPC is found somewhere in
  1545. * memory where it is not permitted.
  1546. *
  1547. * Bugcheck Parameters
  1548. *
  1549. * Parameter 1 0: Timer object 1: DPC object 2: DPC routine
  1550. * Parameter 2 Address of object
  1551. * Parameter 3 Beginning of memory range checked
  1552. * Parameter 4 End of memory range checked
  1553. *
  1554. * This condition is usually caused by a driver failing to cancel a
  1555. * timer or DPC before freeing the memory where it resides.
  1556. *
  1557. * This returns the address of DPC routine
  1558. */
  1559. {
  1560. ULONG ParamCount = 0;
  1561. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  1562. ULONG PtrSize = IsPtr64() ? 8 : 4;
  1563. ULONG64 ObjAddress;
  1564. ULONG64 ModBase, ModOffset;
  1565. CHAR Buffer[MAX_PATH];
  1566. ObjAddress = Bc->Args[1];
  1567. switch (Bc->Args[0]) {
  1568. case 0: //Timer object
  1569. ULONG DpcOffsetInTimer;
  1570. /*
  1571. KTIMER struct:
  1572. +0x000 Header :
  1573. +0x000 Type : UChar
  1574. +0x001 Absolute : UChar
  1575. +0x002 Size : UChar
  1576. +0x003 Inserted : UChar
  1577. +0x004 SignalState : Int4B
  1578. +0x008 WaitListHead :
  1579. +0x000 Flink : Ptr
  1580. +0x004 Blink : Ptr
  1581. +0x010 DueTime :
  1582. +0x000 LowPart : Uint4B
  1583. +0x004 HighPart : Uint4B
  1584. +0x000 u :
  1585. +0x000 LowPart : Uint4B
  1586. +0x004 HighPart : Uint4B
  1587. +0x000 QuadPart : Uint8B
  1588. +0x018 TimerListEntry :
  1589. +0x000 Flink : Ptr
  1590. +0x004 Blink : Ptr
  1591. +0x020 Dpc : Ptr
  1592. */
  1593. if (GetFieldOffset("nt!_KTIMER", "Dpc", &DpcOffsetInTimer)) {
  1594. // we don't have types
  1595. DpcOffsetInTimer = 0x10 + PtrSize*4;
  1596. }
  1597. if (!ReadPointer(ObjAddress + DpcOffsetInTimer, &ObjAddress)) {
  1598. // fail
  1599. break;
  1600. }
  1601. // Fall thru
  1602. case 1:
  1603. ULONG DeferredRoutinOffsetInKDPC;
  1604. /*
  1605. KDPC struct
  1606. +0x000 Type : Int2B
  1607. +0x002 Number : UChar
  1608. +0x003 Importance : UChar
  1609. +0x004 DpcListEntry : _LIST_ENTRY
  1610. +0x00c DeferredRoutine : Ptr32
  1611. */
  1612. if (GetFieldOffset("nt!_KDPC", "DeferredRoutine", &DeferredRoutinOffsetInKDPC)) {
  1613. DeferredRoutinOffsetInKDPC = 4 + PtrSize*2;
  1614. }
  1615. if (!ReadPointer(ObjAddress + DeferredRoutinOffsetInKDPC, &ObjAddress)) {
  1616. // fail
  1617. break;
  1618. }
  1619. // Fall thru
  1620. case 2:
  1621. GetModuleBaseAndOffset(ObjAddress, &ModBase, &ModOffset);
  1622. if (ModBase) {
  1623. ParamCount = 3;
  1624. }
  1625. }
  1626. ULONG64 Disp;
  1627. ULONG NameLen;
  1628. ULONG ParamSize;
  1629. ParamSize = ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES);
  1630. GetSymbol(ObjAddress, Buffer, &Disp);
  1631. NameLen = strlen(Buffer) + 1;
  1632. NameLen = DWORD_ALIGN(NameLen);
  1633. CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamSize + NameLen);
  1634. if (!CrashInfo) {
  1635. *pCrashInfo = NULL;
  1636. return;
  1637. }
  1638. CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
  1639. CrashInfo->BugCode = Bc->Code;
  1640. // Initialize known parameters
  1641. CrashInfo->ParamCount = ParamCount;
  1642. if (ParamCount) {
  1643. CrashInfo->Params[0].ParamType = DEBUG_FLR_INVALID_DPC_FOUND;
  1644. CrashInfo->Params[0].Value = ObjAddress;
  1645. CrashInfo->Params[1].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE;
  1646. CrashInfo->Params[1].Value = ModBase;
  1647. CrashInfo->Params[2].ParamType = DEBUG_FLR_POSSIBLE_FAULTING_MODULE_OFFSET;
  1648. CrashInfo->Params[2].Value = ModOffset;
  1649. CrashInfo->SymNameOffset = sizeof(DEBUG_FAILURE_ANALYSIS) + ParamSize;
  1650. strncpy(((char *) CrashInfo) + CrashInfo->SymNameOffset, Buffer, NameLen);
  1651. }
  1652. *pCrashInfo = CrashInfo;
  1653. return;
  1654. }
  1655. void GetInfoForDRIVER_VERIFIER_IOMANAGER_VIOLATION( // (c9)
  1656. PBUGCHECK_ANALYSIS Bc,
  1657. PDEBUG_FAILURE_ANALYSIS *pCrashInfo
  1658. )
  1659. /*
  1660. The IO manager has caught a misbehaving driver
  1661. */
  1662. {
  1663. ULONG ParamCount = 0;
  1664. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  1665. DEBUG_FLR_PARAM_VALUES Values[6];
  1666. ULONG64 Irp, DevObj, DrvObj;
  1667. Values[0].ParamType = DEBUG_FLR_DRIVER_VERIFIER_IOMANAGER_VIOLATION_TYPE;
  1668. Values[0].Value = Bc->Args[0];
  1669. ParamCount = 1;
  1670. Irp = DevObj = DrvObj = 0;
  1671. if (Bc->Args[ 0 ] == 0x1) {
  1672. // "Invalid IRP passed to IoFreeIrp";
  1673. Irp = Bc->Args[1];
  1674. Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
  1675. Values[1].Value = Irp;
  1676. ParamCount++;
  1677. } else if (Bc->Args[ 0 ] == 0x2) {
  1678. // "IRP still associated with a thread at IoFreeIrp";
  1679. Irp = Bc->Args[1];
  1680. Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
  1681. Values[1].Value = Irp;
  1682. ParamCount++;
  1683. } else if (Bc->Args[ 0 ] == 0x3) {
  1684. // "Invalid IRP passed to IoCallDriver";
  1685. Irp = Bc->Args[1];
  1686. Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
  1687. Values[1].Value = Irp;
  1688. ParamCount++;
  1689. } else if (Bc->Args[ 0 ] == 0x4) {
  1690. // "Invalid Device object passed to IoCallDriver";
  1691. DevObj = Bc->Args[1];
  1692. Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
  1693. Values[1].Value = DevObj;
  1694. ParamCount++;
  1695. } else if (Bc->Args[ 0 ] == 0x5) {
  1696. // "Irql not equal across call to the driver dispatch routine"
  1697. DevObj = Bc->Args[1];
  1698. Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
  1699. Values[1].Value = DevObj;
  1700. Values[2].ParamType = DEBUG_FLR_PREVIOUS_IRQL;
  1701. Values[2].Value = Bc->Args[2];
  1702. Values[3].ParamType = DEBUG_FLR_CURRENT_IRQL;
  1703. Values[3].Value = Bc->Args[3];
  1704. ParamCount+=3;
  1705. } else if (Bc->Args[ 0 ] == 0x6) {
  1706. // "IRP passed to IoCompleteRequest contains invalid status"
  1707. // Param 1 = "the status";
  1708. Irp = Bc->Args[2];
  1709. Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
  1710. Values[1].Value = Irp;
  1711. ParamCount++;
  1712. } else if (Bc->Args[ 0 ] == 0x7) {
  1713. // "IRP passed to IoCompleteRequest still has cancel routine"
  1714. Irp = Bc->Args[2];
  1715. Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
  1716. Values[1].Value = Irp;
  1717. Values[2].ParamType = DEBUG_FLR_IRP_CANCEL_ROUTINE;
  1718. Values[2].Value = Bc->Args[1];
  1719. ParamCount+=2;
  1720. } else if (Bc->Args[ 0 ] == 0x8) {
  1721. // "Call to IoBuildAsynchronousFsdRequest threw an exce
  1722. DevObj = Bc->Args[1];
  1723. Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
  1724. Values[1].Value = DevObj;
  1725. Values[2].ParamType = DEBUG_FLR_IRP_MAJOR_FN;
  1726. Values[2].Value = Bc->Args[2];
  1727. Values[3].ParamType = DEBUG_FLR_EXCEPTION_CODE;
  1728. Values[3].Value = Bc->Args[3];
  1729. ParamCount+=3;
  1730. } else if (Bc->Args[ 0 ] == 0x9) {
  1731. // "Call to IoBuildDeviceIoControlRequest threw an exce
  1732. DevObj = Bc->Args[1];
  1733. Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
  1734. Values[1].Value = DevObj;
  1735. Values[2].ParamType = DEBUG_FLR_IOCONTROL_CODE;
  1736. Values[2].Value = Bc->Args[2];
  1737. Values[3].ParamType = DEBUG_FLR_EXCEPTION_CODE;
  1738. Values[3].Value = Bc->Args[3];
  1739. ParamCount+=3;
  1740. } else if (Bc->Args[ 0 ] == 0x10) {
  1741. // "Reinitialization of Device object timer";
  1742. DevObj = Bc->Args[1];
  1743. Values[1].ParamType = DEBUG_FLR_DEVICE_OBJECT;
  1744. Values[1].Value = DevObj;
  1745. ParamCount++;
  1746. } else if (Bc->Args[ 0 ] == 0x12) {
  1747. // "Invalid IOSB in IRP at APC IopCompleteRequest (appe
  1748. Values[1].ParamType = DEBUG_FLR_IOSB_ADDRESS;
  1749. Values[1].Value = DevObj;
  1750. ParamCount++;
  1751. } else if (Bc->Args[ 0 ] == 0x13) {
  1752. // "Invalid UserEvent in IRP at APC IopCompleteRequest
  1753. Values[1].ParamType = DEBUG_FLR_INVALID_USEREVENT;
  1754. Values[1].Value = Bc->Args[1];
  1755. ParamCount++;
  1756. } else if (Bc->Args[ 0 ] == 0x14) {
  1757. // "Irql > DPC at IoCompleteRequest";
  1758. Irp = Bc->Args[2];
  1759. Values[1].ParamType = DEBUG_FLR_IRP_ADDRESS;
  1760. Values[1].Value = Irp;
  1761. Values[2].ParamType = DEBUG_FLR_CURRENT_IRQL;
  1762. Values[2].Value = Bc->Args[1];
  1763. ParamCount+=2;
  1764. }
  1765. ULONG ParamSize;
  1766. ParamSize = ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES);
  1767. if (Irp != 0) {
  1768. DEBUG_IRP_INFO IrpInfo;
  1769. PGET_IRP_INFO GetIrpInfo;
  1770. if (g_ExtControl->GetExtensionFunction(0, "GetIrpInfo", (FARPROC*)&GetIrpInfo) == S_OK) {
  1771. IrpInfo.SizeOfStruct = sizeof(IrpInfo);
  1772. if (GetIrpInfo &&
  1773. ((*GetIrpInfo)(g_ExtClient,Irp, &IrpInfo) == S_OK)) {
  1774. DevObj = IrpInfo.CurrentStack.DeviceObject;
  1775. }
  1776. }
  1777. }
  1778. if (DevObj != 0) {
  1779. DEBUG_DEVICE_OBJECT_INFO DevObjInfo;
  1780. PGET_DEVICE_OBJECT_INFO GetDevObjInfo;
  1781. if (g_ExtControl->GetExtensionFunction(0, "GetDevObjInfo", (FARPROC*)&GetDevObjInfo) == S_OK) {
  1782. DevObjInfo.SizeOfStruct = sizeof(DEBUG_DEVICE_OBJECT_INFO);
  1783. if (GetDevObjInfo &&
  1784. ((*GetDevObjInfo)(g_ExtClient,DevObj, &DevObjInfo) == S_OK)) {
  1785. DrvObj = DevObjInfo.DriverObject;
  1786. }
  1787. }
  1788. }
  1789. ULONG64 DriverName = 0;
  1790. ULONG DriverNameLen = 0;
  1791. if (DrvObj != 0) {
  1792. DEBUG_DRIVER_OBJECT_INFO DrvObjInfo;
  1793. PGET_DRIVER_OBJECT_INFO GetDrvObjInfo;
  1794. if (g_ExtControl->GetExtensionFunction(0, "GetDrvObjInfo", (FARPROC*)&GetDrvObjInfo) == S_OK) {
  1795. DrvObjInfo.SizeOfStruct = sizeof(DEBUG_DRIVER_OBJECT_INFO);
  1796. if (GetDrvObjInfo &&
  1797. ((*GetDrvObjInfo)(g_ExtClient,DrvObj, &DrvObjInfo) == S_OK)) {
  1798. DriverNameLen = DrvObjInfo.DriverName.Length;
  1799. DriverName = DrvObjInfo.DriverName.Buffer;
  1800. }
  1801. }
  1802. }
  1803. if (DriverName) {
  1804. if (DriverNameLen > 1024) { // sanity check
  1805. DriverNameLen = 1024;
  1806. }
  1807. DriverNameLen = DWORD_ALIGN(DriverNameLen + sizeof(WCHAR));
  1808. }
  1809. CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamSize + DriverNameLen);
  1810. if (!CrashInfo) {
  1811. *pCrashInfo = NULL;
  1812. return;
  1813. }
  1814. *pCrashInfo = CrashInfo;
  1815. CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
  1816. CrashInfo->BugCode = Bc->Code;
  1817. // Initialize known parameters
  1818. CrashInfo->ParamCount = ParamCount;
  1819. memcpy(&CrashInfo->Params, Values, ParamSize);
  1820. if (DriverName) {
  1821. ULONG result, b;
  1822. CrashInfo->DriverNameOffset = sizeof(DEBUG_FAILURE_ANALYSIS) + ParamSize;
  1823. b = ReadMemory(DriverName,
  1824. ((PCHAR) CrashInfo) + CrashInfo->DriverNameOffset,
  1825. DriverNameLen,
  1826. &result);
  1827. if (!b || (result != DriverNameLen)) {
  1828. wcscpy((PWCHAR) (((PCHAR) CrashInfo) + CrashInfo->DriverNameOffset),L"Name paged out");
  1829. }
  1830. *((PWCHAR) (((PCHAR) CrashInfo) + DriverNameLen)) = 0;
  1831. }
  1832. }
  1833. DECL_GETINFO( DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL ) // 0xD5
  1834. /*
  1835. * Parameters
  1836. *
  1837. * Parameter 1 Memory referenced
  1838. * Parameter 2 0: Read 1: Write
  1839. * Parameter 3 Address that referenced memory (if known)
  1840. * Parameter 4 Reserved
  1841. *
  1842. */
  1843. {
  1844. ULONG ParamCount;
  1845. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  1846. ParamCount = Bc->Args[2] ? 3 : 2;
  1847. CrashInfo = FAInitMemBlock(sizeof(DEBUG_FAILURE_ANALYSIS) + ParamCount*sizeof(DEBUG_FLR_PARAM_VALUES));
  1848. if (!CrashInfo) {
  1849. *pCrashInfo = NULL;
  1850. return;
  1851. }
  1852. CrashInfo->FailureType = DEBUG_FLR_BUGCHECK;
  1853. CrashInfo->BugCode = Bc->Code;
  1854. // Initialize known parameters
  1855. CrashInfo->ParamCount = ParamCount;
  1856. CrashInfo->Params[0].ParamType = Bc->Args[1] ? DEBUG_FLR_WRITE_ADDRESS : DEBUG_FLR_READ_ADDRESS;
  1857. CrashInfo->Params[0].Value = Bc->Args[0];
  1858. if (Bc->Args[2]) {
  1859. CrashInfo->Params[1].ParamType = DEBUG_FLR_IP;
  1860. CrashInfo->Params[1].Value = Bc->Args[2];
  1861. }
  1862. CrashInfo->Params[ParamCount - 1].ParamType = DEBUG_FLR_MM_INTERNAL_CODE;
  1863. CrashInfo->Params[ParamCount - 1].Value = Bc->Args[3];
  1864. *pCrashInfo = CrashInfo;
  1865. AddKiBugcheckDriver(pCrashInfo);
  1866. }
  1867. DECL_GETINFO( DRIVER_VERIFIER_DETECTED_VIOLATION ) // 0xC4
  1868. /*
  1869. * Parameters
  1870. *
  1871. * Parameter 1 subclass of violation
  1872. * Parameter 2, 3, 4 vary depending on parameter 1
  1873. *
  1874. */
  1875. {
  1876. ULONG64 DriverNameAddr;
  1877. WCHAR DriverName[MAX_PATH];
  1878. CHAR RoutineName[MAX_PATH];
  1879. ULONG res;
  1880. ULONG ParamCount = 0;
  1881. PDEBUG_FAILURE_ANALYSIS CrashInfo;
  1882. DriverName[0] = 0;
  1883. if (DriverNameAddr = GetExpression("ViBadDriver")) {
  1884. if (ReadMemory(DriverNameAddr, DriverName, sizeof(DriverName), &res)) {
  1885. // We have driver name
  1886. }
  1887. }
  1888. RoutineName[0] = 0;
  1889. ULONG64 Addr, Disp;
  1890. if (GetFirstNonNtModAddr(&Addr)) {
  1891. GetSymbol(Addr, &RoutineName[0], &Disp);
  1892. }
  1893. }
  1894. #undef DECL_GETINFO