2 * MiniDump dumping utility
4 * Copyright 2005 Eric Pouech
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
32 static void dump_mdmp_data(const MINIDUMP_LOCATION_DESCRIPTOR* md, const char* pfx)
35 dump_data(PRD(md->Rva, md->DataSize), md->DataSize, pfx);
38 static void dump_mdmp_string(DWORD rva)
40 const MINIDUMP_STRING* ms = PRD(rva, sizeof(MINIDUMP_STRING));
42 dump_unicode_str( ms->Buffer, ms->Length / sizeof(WCHAR) );
47 static const MINIDUMP_DIRECTORY* get_mdmp_dir(const MINIDUMP_HEADER* hdr, int str_idx)
49 const MINIDUMP_DIRECTORY* dir;
52 for (i = 0; i < hdr->NumberOfStreams; i++)
54 dir = PRD(hdr->StreamDirectoryRva + i * sizeof(MINIDUMP_DIRECTORY),
55 sizeof(MINIDUMP_DIRECTORY));
57 if (dir->StreamType == str_idx) return dir;
64 const MINIDUMP_HEADER* hdr = (const MINIDUMP_HEADER*)PRD(0, sizeof(MINIDUMP_HEADER));
66 const MINIDUMP_DIRECTORY* dir;
71 printf("Cannot get Minidump header\n");
75 printf("Signature: %lu (%.4s)\n", hdr->Signature, (const char*)&hdr->Signature);
76 printf("Version: %lx\n", hdr->Version);
77 printf("NumberOfStreams: %lu\n", hdr->NumberOfStreams);
78 printf("StreamDirectoryRva: %lu\n", hdr->StreamDirectoryRva);
79 printf("CheckSum: %lu\n", hdr->CheckSum);
80 printf("TimeDateStamp: %s\n", get_time_str(hdr->u.TimeDateStamp));
81 printf("Flags: %llx\n", hdr->Flags);
83 for (idx = 0; idx <= LastReservedStream; idx++)
85 if (!(dir = get_mdmp_dir(hdr, idx))) continue;
87 stream = PRD(dir->Location.Rva, dir->Location.DataSize);
88 printf("Directory [%lu]: ", ndir++);
89 switch (dir->StreamType)
91 case ThreadListStream:
93 const MINIDUMP_THREAD_LIST* mtl = (const MINIDUMP_THREAD_LIST*)stream;
94 const MINIDUMP_THREAD* mt = &mtl->Threads[0];
97 printf("Threads: %lu\n", mtl->NumberOfThreads);
98 for (i = 0; i < mtl->NumberOfThreads; i++, mt++)
100 printf(" Thread: #%d\n", i);
101 printf(" ThreadId: %lu\n", mt->ThreadId);
102 printf(" SuspendCount: %lu\n", mt->SuspendCount);
103 printf(" PriorityClass: %lu\n", mt->PriorityClass);
104 printf(" Priority: %lu\n", mt->Priority);
105 printf(" Teb: 0x%llx\n", mt->Teb);
106 printf(" Stack: 0x%llx-0x%llx\n",
107 mt->Stack.StartOfMemoryRange,
108 mt->Stack.StartOfMemoryRange + mt->Stack.Memory.DataSize);
109 dump_mdmp_data(&mt->Stack.Memory, " ");
110 printf(" ThreadContext:\n");
111 dump_mdmp_data(&mt->ThreadContext, " ");
115 case ModuleListStream:
118 const MINIDUMP_MODULE_LIST* mml = (const MINIDUMP_MODULE_LIST*)stream;
119 const MINIDUMP_MODULE* mm = &mml->Modules[0];
124 printf("Modules (%s): %lu\n",
125 dir->StreamType == ModuleListStream ? "PE" : "ELF",
126 mml->NumberOfModules);
127 for (i = 0; i < mml->NumberOfModules; i++, mm++)
129 printf(" Module #%d:\n", i);
130 printf(" BaseOfImage: 0x%llx\n", mm->BaseOfImage);
131 printf(" SizeOfImage: %lu\n", mm->SizeOfImage);
132 printf(" CheckSum: %lu\n", mm->CheckSum);
133 printf(" TimeDateStamp: %s\n", get_time_str(mm->TimeDateStamp));
134 printf(" ModuleName: ");
135 dump_mdmp_string(mm->ModuleNameRva);
137 printf(" VersionInfo:\n");
138 printf(" dwSignature: %lx\n", mm->VersionInfo.dwSignature);
139 printf(" dwStrucVersion: %lx\n",
140 mm->VersionInfo.dwStrucVersion);
141 printf(" dwFileVersion: %d,%d,%d,%d\n",
142 HIWORD(mm->VersionInfo.dwFileVersionMS),
143 LOWORD(mm->VersionInfo.dwFileVersionMS),
144 HIWORD(mm->VersionInfo.dwFileVersionLS),
145 LOWORD(mm->VersionInfo.dwFileVersionLS));
146 printf(" dwProductVersion %d,%d,%d,%d\n",
147 HIWORD(mm->VersionInfo.dwProductVersionMS),
148 LOWORD(mm->VersionInfo.dwProductVersionMS),
149 HIWORD(mm->VersionInfo.dwProductVersionLS),
150 LOWORD(mm->VersionInfo.dwProductVersionLS));
151 printf(" dwFileFlagsMask: %lu\n",
152 mm->VersionInfo.dwFileFlagsMask);
153 printf(" dwFileFlags: %s%s%s%s%s%s\n",
154 mm->VersionInfo.dwFileFlags & VS_FF_DEBUG ? "Debug " : "",
155 mm->VersionInfo.dwFileFlags & VS_FF_INFOINFERRED ? "Inferred " : "",
156 mm->VersionInfo.dwFileFlags & VS_FF_PATCHED ? "Patched " : "",
157 mm->VersionInfo.dwFileFlags & VS_FF_PRERELEASE ? "PreRelease " : "",
158 mm->VersionInfo.dwFileFlags & VS_FF_PRIVATEBUILD ? "PrivateBuild " : "",
159 mm->VersionInfo.dwFileFlags & VS_FF_SPECIALBUILD ? "SpecialBuild " : "");
160 if (mm->VersionInfo.dwFileOS)
162 switch (mm->VersionInfo.dwFileOS & 0x000F)
164 case VOS__BASE: p1 = "_base"; break;
165 case VOS__WINDOWS16:p1 = "16 bit Windows"; break;
166 case VOS__PM16: p1 = "16 bit Presentation Manager"; break;
167 case VOS__PM32: p1 = "32 bit Presentation Manager"; break;
168 case VOS__WINDOWS32:p1 = "32 bit Windows"; break;
169 default: p1 = "---"; break;
171 switch (mm->VersionInfo.dwFileOS & 0xF0000)
173 case VOS_UNKNOWN: p2 = "unknown"; break;
174 case VOS_DOS: p2 = "DOS"; break;
175 case VOS_OS216: p2 = "16 bit OS/2"; break;
176 case VOS_OS232: p2 = "32 bit OS/2"; break;
177 case VOS_NT: p2 = "Windows NT"; break;
178 default: p2 = "---"; break;
180 printf(" dwFileOS: %s running on %s\n", p1, p2);
182 else printf(" dwFileOS: 0\n");
183 switch (mm->VersionInfo.dwFileType)
185 case VFT_UNKNOWN: p1 = "Unknown"; break;
186 case VFT_APP: p1 = "Application"; break;
187 case VFT_DLL: p1 = "DLL"; break;
188 case VFT_DRV: p1 = "Driver"; break;
189 case VFT_FONT: p1 = "Font"; break;
190 case VFT_VXD: p1 = "VxD"; break;
191 case VFT_STATIC_LIB: p1 = "Static Library"; break;
192 default: p1 = "---"; break;
194 printf(" dwFileType: %s\n", p1);
195 printf(" dwFileSubtype: %lu\n",
196 mm->VersionInfo.dwFileSubtype);
197 printf(" dwFileDate: %lx%08lx\n",
198 mm->VersionInfo.dwFileDateMS, mm->VersionInfo.dwFileDateLS);
199 printf(" CvRecord: <%lu>\n", mm->CvRecord.DataSize);
200 dump_mdmp_data(&mm->CvRecord, " ");
201 printf(" MiscRecord: <%lu>\n", mm->MiscRecord.DataSize);
202 dump_mdmp_data(&mm->MiscRecord, " ");
203 printf(" Reserved0: %llu\n", mm->Reserved0);
204 printf(" Reserved1: %llu\n", mm->Reserved1);
208 case MemoryListStream:
210 const MINIDUMP_MEMORY_LIST* mml = (const MINIDUMP_MEMORY_LIST*)stream;
211 const MINIDUMP_MEMORY_DESCRIPTOR* mmd = &mml->MemoryRanges[0];
214 printf("Memory Ranges: %lu\n", mml->NumberOfMemoryRanges);
215 for (i = 0; i < mml->NumberOfMemoryRanges; i++, mmd++)
217 printf(" Memory Range #%d:\n", i);
218 printf(" Range: 0x%llx-0x%llx\n",
219 mmd->StartOfMemoryRange,
220 mmd->StartOfMemoryRange + mmd->Memory.DataSize);
221 dump_mdmp_data(&mmd->Memory, " ");
225 case SystemInfoStream:
227 const MINIDUMP_SYSTEM_INFO* msi = (const MINIDUMP_SYSTEM_INFO*)stream;
231 printf("System Information:\n");
232 switch (msi->ProcessorArchitecture)
234 case PROCESSOR_ARCHITECTURE_UNKNOWN:
237 case PROCESSOR_ARCHITECTURE_INTEL:
238 strcpy(tmp, "Intel ");
239 switch (msi->ProcessorLevel)
241 case 3: str = "80386"; break;
242 case 4: str = "80486"; break;
243 case 5: str = "Pentium"; break;
244 case 6: str = "Pentium Pro/II"; break;
245 default: str = "???"; break;
248 if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4)
250 if (HIWORD(msi->ProcessorRevision) == 0xFF)
251 sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIBYTE(LOWORD(msi->ProcessorRevision)), LOBYTE(LOWORD(msi->ProcessorRevision)));
253 sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision));
255 else sprintf(tmp + strlen(tmp), "-%d.%d", HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision));
258 case PROCESSOR_ARCHITECTURE_MIPS:
261 case PROCESSOR_ARCHITECTURE_ALPHA:
264 case PROCESSOR_ARCHITECTURE_PPC:
271 printf(" Processor: %s (#%d CPUs)\n", str, msi->u.s.NumberOfProcessors);
272 switch (msi->MajorVersion)
275 switch (msi->MinorVersion)
277 case 51: str = "NT 3.51"; break;
278 default: str = "3-????"; break;
282 switch (msi->MinorVersion)
284 case 0: str = (msi->PlatformId == VER_PLATFORM_WIN32_NT) ? "NT 4.0" : "95"; break;
285 case 10: str = "98"; break;
286 case 90: str = "ME"; break;
287 default: str = "5-????"; break;
291 switch (msi->MinorVersion)
293 case 0: str = "2000"; break;
294 case 1: str = "XP"; break;
295 case 2: str = "Server 2003"; break;
296 default: str = "5-????"; break;
299 default: str = "???"; break;
301 printf(" Version: Windows %s (%lu)\n", str, msi->BuildNumber);
302 printf(" PlatformId: %lu\n", msi->PlatformId);
304 dump_mdmp_string(msi->CSDVersionRva);
306 printf(" Reserved1: %lu\n", msi->u1.Reserved1);
307 if (msi->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
309 printf(" x86.VendorId: %.12s\n",
310 (const char*)&msi->Cpu.X86CpuInfo.VendorId[0]);
311 printf(" x86.VersionInformation: %lx\n",
312 msi->Cpu.X86CpuInfo.VersionInformation);
313 printf(" x86.FeatureInformation: %lx\n",
314 msi->Cpu.X86CpuInfo.FeatureInformation);
315 printf(" x86.AMDExtendedCpuFeatures: %lu\n",
316 msi->Cpu.X86CpuInfo.AMDExtendedCpuFeatures);
322 const MINIDUMP_MISC_INFO* mmi = (const MINIDUMP_MISC_INFO*)stream;
324 printf("Misc Information\n");
325 printf(" Size: %lu\n", mmi->SizeOfInfo);
326 printf(" Flags: %s%s\n",
327 mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID ? "ProcessId " : "",
328 mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES ? "ProcessTimes " : "");
329 if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID)
330 printf(" ProcessId: %lu\n", mmi->ProcessId);
331 if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES)
333 printf(" ProcessCreateTime: %lu\n", mmi->ProcessCreateTime);
334 printf(" ProcessUserTime: %lu\n", mmi->ProcessUserTime);
335 printf(" ProcessKernelTime: %lu\n", mmi->ProcessKernelTime);
339 case ExceptionStream:
341 const MINIDUMP_EXCEPTION_STREAM* mes = (const MINIDUMP_EXCEPTION_STREAM*)stream;
344 printf("Exception:\n");
345 printf(" ThreadId: %08lx\n", mes->ThreadId);
346 printf(" ExceptionRecord:\n");
347 printf(" ExceptionCode: %lu\n", mes->ExceptionRecord.ExceptionCode);
348 printf(" ExceptionFlags: %lu\n", mes->ExceptionRecord.ExceptionFlags);
349 printf(" ExceptionRecord: 0x%llx\n",
350 mes->ExceptionRecord.ExceptionRecord);
351 printf(" ExceptionAddress: 0x%llx\n",
352 mes->ExceptionRecord.ExceptionAddress);
353 printf(" ExceptionNumberParameters: %lu\n",
354 mes->ExceptionRecord.NumberParameters);
355 for (i = 0; i < mes->ExceptionRecord.NumberParameters; i++)
357 printf(" [%d]: 0x%llx\n", i,
358 mes->ExceptionRecord.ExceptionInformation[i]);
360 printf(" ThreadContext:\n");
361 dump_mdmp_data(&mes->ThreadContext, " ");
366 printf("NIY %ld\n", dir->StreamType);
367 printf(" RVA: %lu\n", dir->Location.Rva);
368 printf(" Size: %lu\n", dir->Location.DataSize);
369 dump_mdmp_data(&dir->Location, " ");