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.

647 lines
17 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // User-mode exception analysis.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. #include "nturtl.h"
  11. typedef void (*EX_STATE_ANALYZER)(PEX_STATE ExState,
  12. UserDebugFailureAnalysis* Analysis);
  13. //----------------------------------------------------------------------------
  14. //
  15. // Exception-specific analyzers.
  16. //
  17. //----------------------------------------------------------------------------
  18. #define IMPL_EXS_ANALYZER(Name) \
  19. void \
  20. Exa_##Name(PEX_STATE ExState, \
  21. UserDebugFailureAnalysis* Analysis)
  22. IMPL_EXS_ANALYZER(STATUS_ACCESS_VIOLATION)
  23. {
  24. Analysis->SetUlong64(ExState->Exr.ExceptionInformation[0] ?
  25. DEBUG_FLR_WRITE_ADDRESS : DEBUG_FLR_READ_ADDRESS,
  26. ExState->Exr.ExceptionInformation[1]);
  27. Analysis->SetString(DEBUG_FLR_BUGCHECK_STR, "ACCESS_VIOLATION");
  28. }
  29. //----------------------------------------------------------------------------
  30. //
  31. // App verifier-specific analyzers.
  32. //
  33. //----------------------------------------------------------------------------
  34. #define IMPL_AVRF_ANALYZER(Name) \
  35. void \
  36. Avrf_##Name(PAVRF_STOP AvrfStop, \
  37. DebugFailureAnalysis* Analysis)
  38. IMPL_AVRF_ANALYZER(APPLICATION_VERIFIER_INVALID_HANDLE)
  39. {
  40. EXT_GET_HANDLE_TRACE pGetHandleTrace;
  41. if (AvrfStop->Params[1])
  42. {
  43. Analysis->SetUlong64(DEBUG_FLR_EXCEPTION_RECORD, AvrfStop->Params[1]);
  44. }
  45. if (AvrfStop->Params[2])
  46. {
  47. Analysis->SetUlong64(DEBUG_FLR_CONTEXT, AvrfStop->Params[2]);
  48. }
  49. if ((g_TargetQualifier == DEBUG_DUMP_SMALL) ||
  50. (g_TargetQualifier == DEBUG_DUMP_DEFAULT) ||
  51. (g_TargetQualifier == DEBUG_DUMP_FULL))
  52. {
  53. return;
  54. }
  55. // Look for most recent handle trace which resulted in
  56. // bad reference
  57. if (g_ExtControl->
  58. GetExtensionFunction(0, "GetHandleTrace",
  59. (FARPROC*)&pGetHandleTrace) == S_OK &&
  60. pGetHandleTrace)
  61. {
  62. ULONG64 Handle = 0;
  63. ULONG64 Stack[10];
  64. #ifndef HANDLE_TRACE_DB_BADREF
  65. #define HANDLE_TRACE_DB_BADREF 3
  66. #endif
  67. if ((*pGetHandleTrace)(g_ExtClient, HANDLE_TRACE_DB_BADREF,
  68. 0, &Handle,
  69. Stack, sizeof(Stack)/sizeof(Stack[0])) == S_OK)
  70. {
  71. // Found the bad handle !!
  72. Analysis->SetUlong64(DEBUG_FLR_BAD_HANDLE, Handle);
  73. }
  74. }
  75. return;
  76. }
  77. IMPL_AVRF_ANALYZER(APPLICATION_VERIFIER_LOCK_IN_UNLOADED_DLL)
  78. {
  79. CHAR DllName[MAX_PATH];
  80. if (AvrfStop->Params[0])
  81. {
  82. Analysis->SetUlong64(DEBUG_FLR_CRITICAL_SECTION, AvrfStop->Params[0]);
  83. }
  84. if (AvrfStop->Params[2])
  85. {
  86. if (ReadMemory(AvrfStop->Params[2],
  87. DllName,
  88. sizeof(DllName),
  89. NULL))
  90. {
  91. DllName[MAX_PATH-1] = DllName[MAX_PATH-2] = 0;
  92. if (DllName[0])
  93. {
  94. wchr2ansi((PWCHAR) DllName, DllName);
  95. Analysis->SetString(DEBUG_FLR_IMAGE_NAME, DllName);
  96. Analysis->SetUlong(DEBUG_FLR_FOLLOWUP_DRIVER_ONLY, 1);
  97. }
  98. }
  99. }
  100. if (AvrfStop->Params[3])
  101. {
  102. Analysis->SetUlong64(DEBUG_FLR_FAULTING_MODULE, AvrfStop->Params[3]);
  103. }
  104. }
  105. IMPL_AVRF_ANALYZER(APPLICATION_VERIFIER_ACCESS_VIOLATION)
  106. {
  107. if (AvrfStop->Params[0])
  108. {
  109. Analysis->SetUlong64(DEBUG_FLR_INVALID_HEAP_ADDRESS, AvrfStop->Params[0]);
  110. }
  111. if (AvrfStop->Params[1])
  112. {
  113. Analysis->SetUlong64(DEBUG_FLR_FAULTING_IP, AvrfStop->Params[1]);
  114. }
  115. if (AvrfStop->Params[2])
  116. {
  117. Analysis->SetUlong64(DEBUG_FLR_EXCEPTION_RECORD, AvrfStop->Params[2]);
  118. }
  119. if (AvrfStop->Params[3])
  120. {
  121. Analysis->SetUlong64(DEBUG_FLR_CONTEXT, AvrfStop->Params[3]);
  122. }
  123. }
  124. IMPL_AVRF_ANALYZER(APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK)
  125. {
  126. if (AvrfStop->Params[1])
  127. {
  128. Analysis->SetUlong64(DEBUG_FLR_INVALID_HEAP_ADDRESS, AvrfStop->Params[1]);
  129. }
  130. }
  131. IMPL_AVRF_ANALYZER(APPLICATION_VERIFIER_LOCK_IN_FREED_HEAP)
  132. {
  133. CHAR DllName[MAX_PATH];
  134. if (AvrfStop->Params[0])
  135. {
  136. Analysis->SetUlong64(DEBUG_FLR_CRITICAL_SECTION, AvrfStop->Params[0]);
  137. }
  138. }
  139. BOOL
  140. CheckAppVerifierEnabled(
  141. void
  142. )
  143. {
  144. ULONG64 PebAddress;
  145. ULONG Flags;
  146. ULONG BytesRead;
  147. ULONG I;
  148. ULONG64 GlobalFlags;
  149. //
  150. // No app verifier on NT 4
  151. //
  152. if (g_TargetBuild < 2195)
  153. {
  154. return FALSE;
  155. }
  156. GetPebAddress(0, &PebAddress);
  157. if (PebAddress)
  158. {
  159. if (!InitTypeRead (PebAddress, ntdll!_PEB))
  160. {
  161. GlobalFlags = ReadField (NtGlobalFlag);
  162. if ((GlobalFlags & FLG_APPLICATION_VERIFIER))
  163. {
  164. return TRUE;
  165. }
  166. }
  167. }
  168. return FALSE;
  169. }
  170. BOOL
  171. GetVerifierDataFromException(
  172. PEX_STATE ExState,
  173. PULONG Code,
  174. PULONG64 Param1,
  175. PULONG64 Param2,
  176. PULONG64 Param3,
  177. PULONG64 Param4
  178. )
  179. {
  180. CHAR Buffer[MAX_PATH];
  181. ULONG64 Disp;
  182. *Code = 0;
  183. if (ExState == NULL)
  184. {
  185. return FALSE;
  186. }
  187. if (ExState->FirstChance &&
  188. ExState->Exr.ExceptionCode == STATUS_INVALID_HANDLE)
  189. {
  190. if (FaIsFunctionAddr(ExState->Exr.ExceptionAddress,
  191. "KiRaiseUserExceptionDispatcher"))
  192. {
  193. // Most likely this is a use of invalid handle, but verifier
  194. // couldn't catch it because app is under debugger
  195. *Code = APPLICATION_VERIFIER_INVALID_HANDLE ; // INVALID_HANDLE;
  196. *Param1 = STATUS_INVALID_HANDLE;
  197. return TRUE;
  198. }
  199. }
  200. return FALSE;
  201. }
  202. BOOL
  203. GetVerifierStopData(
  204. PULONG Code,
  205. PULONG64 Param1,
  206. PULONG64 Param2,
  207. PULONG64 Param3,
  208. PULONG64 Param4
  209. )
  210. {
  211. ULONG64 CurrentStopAddress;
  212. ULONG PointerSize = IsPtr64() ? 8 : 4;
  213. *Code = 0;
  214. CurrentStopAddress = GetExpression("ntdll!AVrfpStopData");
  215. if (CurrentStopAddress == 0)
  216. {
  217. CurrentStopAddress = GetExpression("verifier!AVrfpStopData");
  218. }
  219. if (CurrentStopAddress == 0)
  220. {
  221. dprintf( "Unable to resolve AVrfpStopData symbol.\n");
  222. return FALSE;
  223. }
  224. if (!ReadMemory(CurrentStopAddress, Code, sizeof(*Code), NULL) ||
  225. !ReadPointer(CurrentStopAddress + PointerSize, Param1) ||
  226. !ReadPointer(CurrentStopAddress + 2*PointerSize, Param2) ||
  227. !ReadPointer(CurrentStopAddress + 3*PointerSize, Param3) ||
  228. !ReadPointer(CurrentStopAddress + 4*PointerSize, Param4))
  229. {
  230. dprintf("Cannot read AVrfpStopData values.\n");
  231. return FALSE;
  232. }
  233. if (*Code)
  234. {
  235. return TRUE;
  236. }
  237. return FALSE;
  238. }
  239. HRESULT
  240. DoVerifierAnalysis(
  241. PEX_STATE ExState,
  242. DebugFailureAnalysis* Analysis
  243. )
  244. {
  245. AVRF_STOP AvrfStop = {0};
  246. if (!GetVerifierStopData(&AvrfStop.Code, &AvrfStop.Params[0], &AvrfStop.Params[1],
  247. &AvrfStop.Params[2], &AvrfStop.Params[3]) &&
  248. !GetVerifierDataFromException(ExState, &AvrfStop.Code, &AvrfStop.Params[0],
  249. &AvrfStop.Params[1], &AvrfStop.Params[2],
  250. &AvrfStop.Params[3]))
  251. {
  252. // Doesn't look like a verifier bug
  253. return S_FALSE;
  254. }
  255. CHAR BugCheckStr[40];
  256. sprintf(BugCheckStr, "AVRF_%lx", AvrfStop.Code);
  257. Analysis->SetString(DEBUG_FLR_BUGCHECK_STR, BugCheckStr);
  258. #define CALL_AVRF_ANALYZER(Name) \
  259. case Name: \
  260. Avrf_##Name(&AvrfStop, \
  261. Analysis); \
  262. break;
  263. switch (AvrfStop.Code)
  264. {
  265. CALL_AVRF_ANALYZER(APPLICATION_VERIFIER_INVALID_HANDLE);
  266. CALL_AVRF_ANALYZER(APPLICATION_VERIFIER_LOCK_IN_UNLOADED_DLL);
  267. CALL_AVRF_ANALYZER(APPLICATION_VERIFIER_CORRUPTED_HEAP_BLOCK);
  268. CALL_AVRF_ANALYZER(APPLICATION_VERIFIER_ACCESS_VIOLATION);
  269. case APPLICATION_VERIFIER_LOCK_DOUBLE_INITIALIZE:
  270. case APPLICATION_VERIFIER_LOCK_OVER_RELEASED:
  271. case APPLICATION_VERIFIER_LOCK_NOT_INITIALIZED:
  272. case APPLICATION_VERIFIER_LOCK_ALREADY_INITIALIZED:
  273. case APPLICATION_VERIFIER_LOCK_INVALID_LOCK_COUNT:
  274. CALL_AVRF_ANALYZER(APPLICATION_VERIFIER_LOCK_IN_FREED_HEAP);
  275. default:
  276. break;
  277. }
  278. return S_OK;
  279. }
  280. //----------------------------------------------------------------------------
  281. //
  282. // Generic exception analysis handling.
  283. //
  284. //----------------------------------------------------------------------------
  285. struct EX_ANALYZER_ENTRY
  286. {
  287. ULONG Code;
  288. EX_STATE_ANALYZER Analyzer;
  289. };
  290. #define EXS_ANALYZER_ENTRY(Name) \
  291. Name, Exa_##Name
  292. EX_ANALYZER_ENTRY g_ExAnalyzers[] =
  293. {
  294. EXS_ANALYZER_ENTRY(STATUS_ACCESS_VIOLATION),
  295. 0, NULL,
  296. };
  297. void
  298. UeFillAnalysis(PEX_STATE ExState,
  299. UserDebugFailureAnalysis* Analysis)
  300. {
  301. HRESULT Status;
  302. //
  303. // Add common analysis entries.
  304. //
  305. Analysis->SetFailureClass(DEBUG_CLASS_USER_WINDOWS);
  306. Analysis->SetFailureType(DEBUG_FLR_USER_CRASH);
  307. Analysis->SetFailureCode(ExState->Exr.ExceptionCode);
  308. Analysis->SetUlong64(DEBUG_FLR_FAULTING_IP, ExState->Exr.ExceptionAddress);
  309. Analysis->SetUlong64(DEBUG_FLR_EXCEPTION_RECORD, -1);
  310. CHAR BugCheckStr[40];
  311. sprintf(BugCheckStr, "%lx", ExState->Exr.ExceptionCode);
  312. Analysis->SetString(DEBUG_FLR_BUGCHECK_STR, BugCheckStr);
  313. Analysis->SetString(DEBUG_FLR_DEFAULT_BUCKET_ID, "APPLICATION_FAULT");
  314. CHAR ProcessName[512];
  315. ULONG Size;
  316. PCHAR Name;
  317. Status = g_ExtSystem->GetCurrentProcessExecutableName(ProcessName,
  318. sizeof(ProcessName),
  319. &Size);
  320. if ((Status == S_OK) && (Size > 1))
  321. {
  322. if (Name = strrchr(ProcessName, '\\'))
  323. {
  324. Name++;
  325. }
  326. else
  327. {
  328. Name = ProcessName;
  329. }
  330. Analysis->SetString(DEBUG_FLR_PROCESS_NAME, Name);
  331. if (!_stricmp("iexplore.exe", Name))
  332. {
  333. Analysis->SetFailureType(DEBUG_FLR_IE_CRASH);
  334. }
  335. }
  336. if (g_TargetPlatform == VER_PLATFORM_WIN32_NT)
  337. {
  338. Analysis->CheckModuleSymbols("ntdll", "OS");
  339. if (CheckAppVerifierEnabled())
  340. {
  341. // This proces has app verifier enabled
  342. DoVerifierAnalysis(ExState, Analysis);
  343. }
  344. }
  345. //
  346. // Find an analyzer for the exception and run it.
  347. //
  348. EX_ANALYZER_ENTRY* Entry = g_ExAnalyzers;
  349. while (Entry->Analyzer)
  350. {
  351. if (Entry->Code == ExState->Exr.ExceptionCode)
  352. {
  353. Entry->Analyzer(ExState, Analysis);
  354. break;
  355. }
  356. Entry++;
  357. }
  358. Analysis->ProcessInformation();
  359. }
  360. UserDebugFailureAnalysis*
  361. UeAnalyze(
  362. PEX_STATE ExState,
  363. ULONG Flags
  364. )
  365. {
  366. ULONG EventType;
  367. DEBUG_LAST_EVENT_INFO_EXCEPTION LastEx;
  368. if (g_ExtControl->GetLastEventInformation(&EventType,
  369. &ExState->ProcId,
  370. &ExState->ThreadId,
  371. &LastEx, sizeof(LastEx), NULL,
  372. NULL, 0, NULL) != S_OK)
  373. {
  374. ExtErr("Unable to get last event information\n");
  375. return NULL;
  376. }
  377. if (EventType != DEBUG_EVENT_EXCEPTION)
  378. {
  379. ExtErr("Event is not an exception\n");
  380. return NULL;
  381. }
  382. ExState->Exr = LastEx.ExceptionRecord;
  383. ExState->FirstChance = LastEx.FirstChance;
  384. UserDebugFailureAnalysis* Analysis = new UserDebugFailureAnalysis;
  385. if (Analysis)
  386. {
  387. Analysis->SetProcessingFlags(Flags);
  388. __try
  389. {
  390. UeFillAnalysis(ExState, Analysis);
  391. }
  392. __except(FaExceptionFilter(GetExceptionInformation()))
  393. {
  394. delete Analysis;
  395. Analysis = NULL;
  396. }
  397. }
  398. return Analysis;
  399. }
  400. HRESULT
  401. AnalyzeUserException(
  402. PCSTR args
  403. )
  404. {
  405. ULONG Flags = 0;
  406. if (g_TargetClass != DEBUG_CLASS_USER_WINDOWS)
  407. {
  408. dprintf("!analyzeuexception is for user mode only\n");
  409. return E_FAIL;
  410. }
  411. for (;;)
  412. {
  413. while (*args == ' ' || *args == '\t')
  414. {
  415. args++;
  416. }
  417. if (*args == '-')
  418. {
  419. ++args;
  420. switch(*args)
  421. {
  422. case 'v':
  423. Flags |= FAILURE_ANALYSIS_VERBOSE;
  424. break;
  425. case 'f':
  426. break;
  427. default:
  428. dprintf("Unknown option %c\n", *args);
  429. break;
  430. }
  431. ++args;
  432. }
  433. else
  434. {
  435. break;
  436. }
  437. }
  438. dprintf("*******************************************************************************\n");
  439. dprintf("* *\n");
  440. dprintf("* Exception Analysis *\n");
  441. dprintf("* *\n");
  442. dprintf("*******************************************************************************\n");
  443. dprintf("\n");
  444. if (!(Flags & FAILURE_ANALYSIS_VERBOSE))
  445. {
  446. dprintf("Use !analyze -v to get detailed debugging information.\n\n");
  447. }
  448. EX_STATE ExState;
  449. UserDebugFailureAnalysis* Analysis = UeAnalyze(&ExState, Flags);
  450. if (!Analysis)
  451. {
  452. dprintf("\n\nFailure could not be analyzed\n\n");
  453. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS, ".lastevent",
  454. DEBUG_EXECUTE_DEFAULT);
  455. return E_FAIL;
  456. }
  457. Analysis->Output();
  458. delete Analysis;
  459. return S_OK;
  460. }
  461. DECLARE_API( analyzeuexception )
  462. {
  463. INIT_API();
  464. HRESULT Hr = AnalyzeUserException(args);
  465. EXIT_API();
  466. return Hr;
  467. }
  468. //----------------------------------------------------------------------------
  469. //
  470. // UserDebugFailureAnalysis.
  471. //
  472. //----------------------------------------------------------------------------
  473. UserDebugFailureAnalysis::UserDebugFailureAnalysis(void)
  474. : m_NtDllModule("ntdll"),
  475. m_Kernel32Module("kernel32"),
  476. m_Advapi32Module("advapi32")
  477. {
  478. }
  479. DEBUG_POOL_REGION
  480. UserDebugFailureAnalysis::GetPoolForAddress(ULONG64 Addr)
  481. {
  482. return DbgPoolRegionUnknown;
  483. }
  484. PCSTR
  485. UserDebugFailureAnalysis::DescribeAddress(ULONG64 Address)
  486. {
  487. // XXX drewb - QueryVirtual to say something about the address?
  488. return NULL;
  489. }
  490. FOLLOW_ADDRESS
  491. UserDebugFailureAnalysis::IsPotentialFollowupAddress(ULONG64 Address)
  492. {
  493. // XXX drewb - Check against maximum user address, but there's
  494. // no guaranteed way to get the maximum user address.
  495. return FollowYes;
  496. }
  497. FOLLOW_ADDRESS
  498. UserDebugFailureAnalysis::IsFollowupContext(ULONG64 Address1, ULONG64 Address2,
  499. ULONG64 Address3)
  500. {
  501. // XXX drewb - Check against maximum user address, but there's
  502. // no guaranteed way to get the maximum user address.
  503. return FollowYes;
  504. }
  505. FlpClasses
  506. UserDebugFailureAnalysis::GetFollowupClass(ULONG64 Address,
  507. PCSTR Module, PCSTR Routine)
  508. {
  509. if (m_NtDllModule.Contains(Address) ||
  510. m_Kernel32Module.Contains(Address) ||
  511. m_Advapi32Module.Contains(Address) ||
  512. (!_strcmpi(Module, "SharedUserData") &&
  513. Routine && !_strcmpi(Routine, "SystemCallStub")))
  514. {
  515. return FlpOSRoutine;
  516. }
  517. else if (!_strcmpi(Module, "shell32") ||
  518. !_strcmpi(Module, "user32") ||
  519. !_strcmpi(Module, "gdi32") ||
  520. !_strcmpi(Module, "mshtml") ||
  521. !_strcmpi(Module, "ole32") ||
  522. !_strcmpi(Module, "verifier") ||
  523. !_strcmpi(Module, "rpcrt4"))
  524. {
  525. return FlpOSFilterDrv;
  526. }
  527. else
  528. {
  529. return FlpUnknownDrv;
  530. }
  531. }
  532. BOOL
  533. UserDebugFailureAnalysis::CheckForCorruptionInHTE(
  534. ULONG64 hTableEntry,
  535. PCHAR Owner,
  536. ULONG OwnerSize
  537. )
  538. {
  539. return FALSE;
  540. }