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 MINIDUMP_STRING
* ms
= PRD(rva
, sizeof(MINIDUMP_STRING
));
42 dump_unicode_str( ms
->Buffer
, ms
->Length
/ sizeof(WCHAR
) );
47 static MINIDUMP_DIRECTORY
* get_mdmp_dir(const MINIDUMP_HEADER
* hdr
, int str_idx
)
49 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 MINIDUMP_HEADER
* hdr
= (MINIDUMP_HEADER
*)PRD(0, sizeof(MINIDUMP_HEADER
));
66 MINIDUMP_DIRECTORY
* dir
;
71 printf("Cannot get Minidump header\n");
75 printf("Signature: %lu (%.4s)\n", hdr
->Signature
, (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 MINIDUMP_THREAD_LIST
* mtl
= (MINIDUMP_THREAD_LIST
*)stream
;
94 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 MINIDUMP_MODULE_LIST
* mml
= (MINIDUMP_MODULE_LIST
*)stream
;
119 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 MINIDUMP_MEMORY_LIST
* mml
= (MINIDUMP_MEMORY_LIST
*)stream
;
211 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 MINIDUMP_SYSTEM_INFO
* msi
= (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 (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 MINIDUMP_MISC_INFO
* mmi
= (MINIDUMP_MISC_INFO
*)stream
;
323 printf("Misc Information\n");
324 printf(" Size: %lu\n", mmi
->SizeOfInfo
);
325 printf(" Flags: %s%s\n",
326 mmi
->Flags1
& MINIDUMP_MISC1_PROCESS_ID
? "ProcessId " : "",
327 mmi
->Flags1
& MINIDUMP_MISC1_PROCESS_TIMES
? "ProcessTimes " : "");
328 if (mmi
->Flags1
& MINIDUMP_MISC1_PROCESS_ID
)
329 printf(" ProcessId: %lu\n", mmi
->ProcessId
);
330 if (mmi
->Flags1
& MINIDUMP_MISC1_PROCESS_TIMES
)
332 printf(" ProcessCreateTime: %lu\n", mmi
->ProcessCreateTime
);
333 printf(" ProcessUserTime: %lu\n", mmi
->ProcessUserTime
);
334 printf(" ProcessKernelTime: %lu\n", mmi
->ProcessKernelTime
);
338 case ExceptionStream
:
340 MINIDUMP_EXCEPTION_STREAM
* mes
= (MINIDUMP_EXCEPTION_STREAM
*)stream
;
343 printf("Exception:\n");
344 printf(" ThreadId: %08lx\n", mes
->ThreadId
);
345 printf(" ExceptionRecord:\n");
346 printf(" ExceptionCode: %lu\n", mes
->ExceptionRecord
.ExceptionCode
);
347 printf(" ExceptionFlags: %lu\n", mes
->ExceptionRecord
.ExceptionFlags
);
348 printf(" ExceptionRecord: 0x%llx\n",
349 mes
->ExceptionRecord
.ExceptionRecord
);
350 printf(" ExceptionAddress: 0x%llx\n",
351 mes
->ExceptionRecord
.ExceptionAddress
);
352 printf(" ExceptionNumberParameters: %lu\n",
353 mes
->ExceptionRecord
.NumberParameters
);
354 for (i
= 0; i
< mes
->ExceptionRecord
.NumberParameters
; i
++)
356 printf(" [%d]: 0x%llx\n", i
,
357 mes
->ExceptionRecord
.ExceptionInformation
[i
]);
359 printf(" ThreadContext:\n");
360 dump_mdmp_data(&mes
->ThreadContext
, " ");
365 printf("NIY %ld\n", dir
->StreamType
);
366 printf(" RVA: %lu\n", dir
->Location
.Rva
);
367 printf(" Size: %lu\n", dir
->Location
.DataSize
);
368 dump_mdmp_data(&dir
->Location
, " ");