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.

524 lines
9.9 KiB

  1. /*++
  2. Copyright(c) 1999 Microsoft Corporation
  3. Module Name:
  4. triage.c
  5. Abstract:
  6. Triage dump support.
  7. Author:
  8. Matthew D. Hendel (math) 20-Jan-1999
  9. Comments:
  10. Do not merge this file with some other file. By leaving it in it's own
  11. compiland, we avoid having to link with all the other random variables
  12. in crashlib.
  13. --*/
  14. #include "iomgr.h"
  15. #include "dumpctl.h"
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <windef.h>
  19. #include <stdio.h>
  20. #include <malloc.h>
  21. #include <triage.h>
  22. #include <ntverp.h>
  23. #ifndef NtBuildNumber
  24. # if DBG
  25. # define NtBuildNumber (VER_PRODUCTBUILD | 0xC0000000)
  26. # else
  27. # define NtBuildNumber (VER_PRODUCTBUILD | 0xF0000000)
  28. # endif
  29. #endif
  30. //
  31. // NOTE: Pages sizes copied from ntos\inc. These must be kept in sync with
  32. // global header files.
  33. //
  34. #define PAGE_SIZE_I386 0x1000
  35. #define PAGE_SIZE_ALPHA 0x2000
  36. #define PAGE_SIZE_IA64 0x2000
  37. ULONG TriageImagePageSize = -1;
  38. BOOLEAN
  39. TriagepVerifyDump(
  40. IN LPVOID TriageDumpBlock
  41. );
  42. ULONG
  43. TriagepGetPageSize(
  44. ULONG Architecture
  45. );
  46. PTRIAGE_DUMP
  47. TriagepGetTriagePointer(
  48. IN PVOID TriageDumpBlock
  49. );
  50. #ifdef ALLOC_PRAGMA
  51. #pragma alloc_text (INIT, TriagepVerifyDump)
  52. #pragma alloc_text (INIT, TriagepGetPageSize)
  53. #pragma alloc_text (INIT, TriagepGetTriagePointer)
  54. #pragma alloc_text (INIT, TriageGetVersion)
  55. #pragma alloc_text (INIT, TriageGetDriverCount)
  56. #pragma alloc_text (INIT, TriageGetContext)
  57. #pragma alloc_text (INIT, TriageGetExceptionRecord)
  58. #pragma alloc_text (INIT, TriageGetBugcheckData)
  59. #pragma alloc_text (INIT, TriageGetDriverEntry)
  60. #endif
  61. //++
  62. //
  63. // PULONG
  64. // IndexByUlong(
  65. // PVOID Pointer,
  66. // ULONG Index
  67. // )
  68. //
  69. // Routine Description:
  70. //
  71. // Return the address Index ULONGs into Pointer. That is,
  72. // Index * sizeof (ULONG) bytes into Pointer.
  73. //
  74. // Arguments:
  75. //
  76. // Pointer - Start of region.
  77. //
  78. // Index - Number of ULONGs to index into.
  79. //
  80. // Return Value:
  81. //
  82. // PULONG representing the pointer described above.
  83. //
  84. //--
  85. #define IndexByUlong(Pointer,Index) (&(((ULONG*) (Pointer)) [Index]))
  86. //++
  87. //
  88. // PBYTE
  89. // IndexByByte(
  90. // PVOID Pointer,
  91. // ULONG Index
  92. // )
  93. //
  94. // Routine Description:
  95. //
  96. // Return the address Index BYTEs into Pointer. That is,
  97. // Index * sizeof (BYTE) bytes into Pointer.
  98. //
  99. // Arguments:
  100. //
  101. // Pointer - Start of region.
  102. //
  103. // Index - Number of BYTEs to index into.
  104. //
  105. // Return Value:
  106. //
  107. // PBYTE representing the pointer described above.
  108. //
  109. //--
  110. #define IndexByByte(Pointer, Index) (&(((BYTE*) (Pointer)) [Index]))
  111. ULONG
  112. TriagepGetPageSize(
  113. ULONG Architecture
  114. )
  115. {
  116. switch (Architecture) {
  117. case IMAGE_FILE_MACHINE_I386:
  118. return PAGE_SIZE_I386;
  119. case IMAGE_FILE_MACHINE_ALPHA:
  120. return PAGE_SIZE_ALPHA;
  121. case IMAGE_FILE_MACHINE_IA64:
  122. return PAGE_SIZE_IA64;
  123. default:
  124. return -1;
  125. }
  126. }
  127. BOOLEAN
  128. TriagepVerifyDump(
  129. IN LPVOID TriageDumpBlock
  130. )
  131. {
  132. BOOLEAN Succ = FALSE;
  133. PMEMORY_DUMP MemoryDump = NULL;
  134. if (!TriageDumpBlock) {
  135. return FALSE;
  136. }
  137. MemoryDump = (PMEMORY_DUMP) TriageDumpBlock;
  138. try {
  139. if (MemoryDump->Header.ValidDump != 'PMUD' ||
  140. MemoryDump->Header.Signature != 'EGAP' ||
  141. TriagepGetPageSize (MemoryDump->Header.MachineImageType) == -1) {
  142. Succ = FALSE;
  143. leave;
  144. }
  145. TriageImagePageSize = TriagepGetPageSize (MemoryDump->Header.MachineImageType);
  146. if ( MemoryDump->Header.DumpType != DUMP_TYPE_TRIAGE ||
  147. *(ULONG*)IndexByByte (MemoryDump, MemoryDump->Triage.SizeOfDump - sizeof (DWORD)) != TRIAGE_DUMP_VALID ) {
  148. Succ = FALSE;
  149. leave;
  150. }
  151. // else
  152. Succ = TRUE;
  153. }
  154. except (EXCEPTION_EXECUTE_HANDLER) {
  155. Succ = FALSE;
  156. }
  157. return Succ;
  158. }
  159. PTRIAGE_DUMP
  160. TriagepGetTriagePointer(
  161. IN PVOID TriageDumpBlock
  162. )
  163. {
  164. ASSERT (TriageImagePageSize != -1);
  165. ASSERT (TriagepVerifyDump (TriageDumpBlock));
  166. return (PTRIAGE_DUMP) IndexByByte (TriageDumpBlock, TriageImagePageSize);
  167. }
  168. NTSTATUS
  169. TriageGetVersion(
  170. IN LPVOID TriageDumpBlock,
  171. OUT ULONG * MajorVersion,
  172. OUT ULONG * MinorVersion,
  173. OUT ULONG * ServicePackBuild
  174. )
  175. {
  176. PTRIAGE_DUMP TriageDump;
  177. PDUMP_HEADER DumpHeader;
  178. if (!TriagepVerifyDump (TriageDumpBlock)) {
  179. return STATUS_INVALID_PARAMETER;
  180. }
  181. TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
  182. if (!TriageDump) {
  183. return STATUS_INVALID_PARAMETER;
  184. }
  185. DumpHeader = (PDUMP_HEADER) TriageDumpBlock;
  186. if (MajorVersion) {
  187. *MajorVersion = DumpHeader->MajorVersion;
  188. }
  189. if (MinorVersion) {
  190. *MinorVersion = DumpHeader->MinorVersion;
  191. }
  192. if (ServicePackBuild) {
  193. *ServicePackBuild = TriageDump->ServicePackBuild;
  194. }
  195. return STATUS_SUCCESS;
  196. }
  197. NTSTATUS
  198. TriageGetDriverCount(
  199. IN LPVOID TriageDumpBlock,
  200. OUT ULONG * DriverCount
  201. )
  202. {
  203. PTRIAGE_DUMP TriageDump;
  204. if (!TriagepVerifyDump (TriageDumpBlock)) {
  205. return STATUS_INVALID_PARAMETER;
  206. }
  207. TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
  208. if (!TriageDump) {
  209. return STATUS_INVALID_PARAMETER;
  210. }
  211. *DriverCount = TriageDump->DriverCount;
  212. return STATUS_SUCCESS;
  213. }
  214. #if 0
  215. NTSTATUS
  216. TriageGetContext(
  217. IN LPVOID TriageDumpBlock,
  218. OUT LPVOID Context,
  219. IN ULONG SizeInBytes
  220. )
  221. {
  222. PTRIAGE_DUMP TriageDump;
  223. if (!TriagepVerifyDump (TriageDumpBlock)) {
  224. return STATUS_INVALID_PARAMETER;
  225. }
  226. TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
  227. if (!TriageDump) {
  228. return STATUS_INVALID_PARAMETER;
  229. }
  230. //
  231. // Copy the CONTEXT record.
  232. //
  233. if (SizeInBytes == -1) {
  234. SizeInBytes = sizeof (CONTEXT);
  235. }
  236. RtlCopyMemory (Context,
  237. IndexByUlong (TriageDumpBlock, TriageDump->ContextOffset),
  238. SizeInBytes
  239. );
  240. return STATUS_SUCCESS;
  241. }
  242. NTSTATUS
  243. TriageGetExceptionRecord(
  244. IN LPVOID TriageDumpBlock,
  245. OUT EXCEPTION_RECORD * ExceptionRecord
  246. )
  247. {
  248. PTRIAGE_DUMP TriageDump;
  249. if (!TriagepVerifyDump (TriageDumpBlock)) {
  250. return STATUS_INVALID_PARAMETER;
  251. }
  252. TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
  253. if (!TriageDump) {
  254. return STATUS_INVALID_PARAMETER;
  255. }
  256. RtlCopyMemory (ExceptionRecord,
  257. IndexByUlong (TriageDumpBlock, TriageDump->ExceptionOffset),
  258. sizeof (*ExceptionRecord)
  259. );
  260. return STATUS_SUCCESS;
  261. }
  262. #endif
  263. LOGICAL
  264. TriageActUpon(
  265. IN PVOID TriageDumpBlock
  266. )
  267. {
  268. PTRIAGE_DUMP TriageDump;
  269. if (!TriagepVerifyDump (TriageDumpBlock)) {
  270. return FALSE;
  271. }
  272. TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
  273. if (!TriageDump) {
  274. return FALSE;
  275. }
  276. if ((TriageDump->TriageOptions & DCB_TRIAGE_DUMP_ACT_UPON_ENABLED) == 0) {
  277. return FALSE;
  278. }
  279. return TRUE;
  280. }
  281. NTSTATUS
  282. TriageGetBugcheckData(
  283. IN LPVOID TriageDumpBlock,
  284. OUT ULONG * BugCheckCode,
  285. OUT UINT_PTR * BugCheckParam1,
  286. OUT UINT_PTR * BugCheckParam2,
  287. OUT UINT_PTR * BugCheckParam3,
  288. OUT UINT_PTR * BugCheckParam4
  289. )
  290. {
  291. PDUMP_HEADER DumpHeader;
  292. if (!TriagepVerifyDump (TriageDumpBlock)) {
  293. return STATUS_INVALID_PARAMETER;
  294. }
  295. DumpHeader = (PDUMP_HEADER) TriageDumpBlock;
  296. *BugCheckCode = DumpHeader->BugCheckCode;
  297. *BugCheckParam1 = DumpHeader->BugCheckParameter1;
  298. *BugCheckParam2 = DumpHeader->BugCheckParameter2;
  299. *BugCheckParam3 = DumpHeader->BugCheckParameter3;
  300. *BugCheckParam4 = DumpHeader->BugCheckParameter4;
  301. return STATUS_SUCCESS;
  302. }
  303. PKLDR_DATA_TABLE_ENTRY
  304. TriageGetLoaderEntry(
  305. IN PVOID TriageDumpBlock,
  306. IN ULONG ModuleIndex
  307. )
  308. /*++
  309. Routine Description:
  310. This function retrieves a loaded module list entry.
  311. Arguments:
  312. TriageDumpBlock - Supplies the triage dump to reference.
  313. ModuleIndex - Supplies the driver index number to locate.
  314. Return Value:
  315. A pointer to a loader data table entry if one is available, NULL if not.
  316. Environment:
  317. Kernel mode, APC_LEVEL or below. Phase 0 only.
  318. N.B. This function is for use by memory management ONLY.
  319. --*/
  320. {
  321. PDUMP_STRING DriverName;
  322. PDUMP_DRIVER_ENTRY DriverList;
  323. PTRIAGE_DUMP TriageDump;
  324. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  325. if (!TriagepVerifyDump (TriageDumpBlock)) {
  326. return NULL;
  327. }
  328. TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
  329. if (ModuleIndex >= TriageDump->DriverCount) {
  330. return NULL;
  331. }
  332. DriverList = (PDUMP_DRIVER_ENTRY)
  333. IndexByByte (TriageDumpBlock, TriageDump->DriverListOffset);
  334. DataTableEntry = (PKLDR_DATA_TABLE_ENTRY) (&DriverList[ModuleIndex].LdrEntry);
  335. //
  336. // Repoint the module driver name into the triage buffer.
  337. //
  338. DriverName = (PDUMP_STRING)
  339. IndexByByte (TriageDumpBlock,
  340. DriverList [ ModuleIndex ].DriverNameOffset);
  341. DataTableEntry->BaseDllName.Length = (USHORT) (DriverName->Length * sizeof (WCHAR));
  342. DataTableEntry->BaseDllName.MaximumLength = DataTableEntry->BaseDllName.Length;
  343. DataTableEntry->BaseDllName.Buffer = DriverName->Buffer;
  344. return DataTableEntry;
  345. }
  346. PVOID
  347. TriageGetMmInformation(
  348. IN PVOID TriageDumpBlock
  349. )
  350. /*++
  351. Routine Description:
  352. This function retrieves a loaded module list entry.
  353. Arguments:
  354. TriageDumpBlock - Supplies the triage dump to reference.
  355. Return Value:
  356. A pointer to an opaque Mm information structure.
  357. Environment:
  358. Kernel mode, APC_LEVEL or below. Phase 0 only.
  359. N.B. This function is for use by memory management ONLY.
  360. --*/
  361. {
  362. PTRIAGE_DUMP TriageDump;
  363. if (!TriagepVerifyDump (TriageDumpBlock)) {
  364. return NULL;
  365. }
  366. TriageDump = TriagepGetTriagePointer (TriageDumpBlock);
  367. if (!TriageDump) {
  368. return NULL;
  369. }
  370. return (PVOID)IndexByByte (TriageDumpBlock, TriageDump->MmOffset);
  371. }