winewayland.drv: Update desktop window size on display changes.
[wine.git] / tools / winedump / minidump.c
blob8190df937af70196464079385787bbc941625fd0
1 /*
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include <stdarg.h>
24 #include "winedump.h"
25 #include "winver.h"
26 #include "dbghelp.h"
28 static void dump_mdmp_data(const MINIDUMP_LOCATION_DESCRIPTOR* md, const char* pfx)
30 if (md->DataSize)
31 dump_data(PRD(md->Rva, md->DataSize), md->DataSize, pfx);
34 static void dump_mdmp_string(DWORD rva)
36 const MINIDUMP_STRING* ms = PRD(rva, sizeof(MINIDUMP_STRING));
37 if (!rva)
38 printf("<<rva=0>>");
39 else if (ms)
40 dump_unicode_str( ms->Buffer, ms->Length / sizeof(WCHAR) );
41 else
42 printf("<<?>>");
45 enum FileSig get_kind_mdmp(void)
47 const DWORD* pdw;
49 pdw = PRD(0, sizeof(DWORD));
50 if (!pdw) {printf("Can't get main signature, aborting\n"); return SIG_UNKNOWN;}
52 if (*pdw == 0x504D444D /* "MDMP" */) return SIG_MDMP;
53 return SIG_UNKNOWN;
56 static inline void print_longlong(const char *title, ULONG64 value)
58 printf("%s: 0x", title);
59 if (sizeof(value) > sizeof(unsigned long) && value >> 32)
60 printf("%lx%08lx\n", (unsigned long)(value >> 32), (unsigned long)value);
61 else
62 printf("%lx\n", (unsigned long)value);
65 static inline void print_longlong_range(const char *title, ULONG64 start, ULONG64 length)
67 ULONG64 value = start;
68 printf("%s: 0x", title);
69 if (sizeof(value) > sizeof(unsigned long) && value >> 32)
70 printf("%lx%08lx-", (unsigned long)(value >> 32), (unsigned long)value);
71 else
72 printf("%lx-", (unsigned long)value);
73 value = start + length;
74 if (sizeof(value) > sizeof(unsigned long) && value >> 32)
75 printf("0x%lx%08lx\n", (unsigned long)(value >> 32), (unsigned long)value);
76 else
77 printf("0x%lx\n", (unsigned long)value);
80 void mdmp_dump(void)
82 const MINIDUMP_HEADER* hdr = PRD(0, sizeof(MINIDUMP_HEADER));
83 const MINIDUMP_DIRECTORY* dir;
84 const void* stream;
85 unsigned int i, idx;
86 const BYTE *ptr;
88 if (!hdr)
90 printf("Cannot get Minidump header\n");
91 return;
94 printf("Signature: %#x (%.4s)\n", hdr->Signature, (const char*)&hdr->Signature);
95 printf("Version: %#x\n", hdr->Version);
96 printf("NumberOfStreams: %u\n", hdr->NumberOfStreams);
97 printf("StreamDirectoryRva: %u\n", (UINT)hdr->StreamDirectoryRva);
98 printf("CheckSum: %u\n", hdr->CheckSum);
99 printf("TimeDateStamp: %s\n", get_time_str(hdr->TimeDateStamp));
100 print_longlong("Flags", hdr->Flags);
102 for (idx = 0; idx < hdr->NumberOfStreams; ++idx)
104 dir = PRD(hdr->StreamDirectoryRva + idx * sizeof(MINIDUMP_DIRECTORY), sizeof(*dir));
105 if (!dir) break;
107 stream = PRD(dir->Location.Rva, dir->Location.DataSize);
109 printf("Stream [%u]: ", idx);
110 switch (dir->StreamType)
112 case ThreadListStream:
114 const MINIDUMP_THREAD_LIST *mtl = stream;
115 const MINIDUMP_THREAD *mt = mtl->Threads;
117 printf("Threads: %u\n", (UINT)mtl->NumberOfThreads);
118 for (i = 0; i < mtl->NumberOfThreads; i++, mt++)
120 printf("Thread: #%d\n", i);
121 printf(" ThreadId: %u\n", mt->ThreadId);
122 printf(" SuspendCount: %u\n", mt->SuspendCount);
123 printf(" PriorityClass: %u\n", mt->PriorityClass);
124 printf(" Priority: %u\n", mt->Priority);
125 print_longlong(" Teb", mt->Teb);
126 print_longlong_range(" Stack", mt->Stack.StartOfMemoryRange, mt->Stack.Memory.DataSize);
127 dump_mdmp_data(&mt->Stack.Memory, " ");
128 printf(" ThreadContext:\n");
129 dump_mdmp_data(&mt->ThreadContext, " ");
132 break;
133 case ModuleListStream:
134 case 0xFFF0:
136 const MINIDUMP_MODULE_LIST *mml = stream;
137 const MINIDUMP_MODULE* mm = mml->Modules;
138 const char* p1;
139 const char* p2;
141 printf("Modules (%s): %u\n",
142 dir->StreamType == ModuleListStream ? "PE" : "ELF",
143 mml->NumberOfModules);
144 for (i = 0; i < mml->NumberOfModules; i++, mm++)
146 printf(" Module #%d:\n", i);
147 print_longlong(" BaseOfImage", mm->BaseOfImage);
148 printf(" SizeOfImage: %u\n", mm->SizeOfImage);
149 printf(" CheckSum: %#x\n", mm->CheckSum);
150 printf(" TimeDateStamp: %s\n", get_time_str(mm->TimeDateStamp));
151 printf(" ModuleName: ");
152 dump_mdmp_string(mm->ModuleNameRva);
153 printf("\n");
154 printf(" VersionInfo:\n");
155 printf(" dwSignature: %x\n", (UINT)mm->VersionInfo.dwSignature);
156 printf(" dwStrucVersion: %x\n", (UINT)mm->VersionInfo.dwStrucVersion);
157 printf(" dwFileVersion: %d,%d,%d,%d\n",
158 HIWORD(mm->VersionInfo.dwFileVersionMS),
159 LOWORD(mm->VersionInfo.dwFileVersionMS),
160 HIWORD(mm->VersionInfo.dwFileVersionLS),
161 LOWORD(mm->VersionInfo.dwFileVersionLS));
162 printf(" dwProductVersion %d,%d,%d,%d\n",
163 HIWORD(mm->VersionInfo.dwProductVersionMS),
164 LOWORD(mm->VersionInfo.dwProductVersionMS),
165 HIWORD(mm->VersionInfo.dwProductVersionLS),
166 LOWORD(mm->VersionInfo.dwProductVersionLS));
167 printf(" dwFileFlagsMask: %u\n", (UINT)mm->VersionInfo.dwFileFlagsMask);
168 printf(" dwFileFlags: %s%s%s%s%s%s\n",
169 mm->VersionInfo.dwFileFlags & VS_FF_DEBUG ? "Debug " : "",
170 mm->VersionInfo.dwFileFlags & VS_FF_INFOINFERRED ? "Inferred " : "",
171 mm->VersionInfo.dwFileFlags & VS_FF_PATCHED ? "Patched " : "",
172 mm->VersionInfo.dwFileFlags & VS_FF_PRERELEASE ? "PreRelease " : "",
173 mm->VersionInfo.dwFileFlags & VS_FF_PRIVATEBUILD ? "PrivateBuild " : "",
174 mm->VersionInfo.dwFileFlags & VS_FF_SPECIALBUILD ? "SpecialBuild " : "");
175 if (mm->VersionInfo.dwFileOS)
177 switch (mm->VersionInfo.dwFileOS & 0x000F)
179 case VOS__BASE: p1 = "_base"; break;
180 case VOS__WINDOWS16:p1 = "16 bit Windows"; break;
181 case VOS__PM16: p1 = "16 bit Presentation Manager"; break;
182 case VOS__PM32: p1 = "32 bit Presentation Manager"; break;
183 case VOS__WINDOWS32:p1 = "32 bit Windows"; break;
184 default: p1 = "---"; break;
186 switch (mm->VersionInfo.dwFileOS & 0xF0000)
188 case VOS_UNKNOWN: p2 = "unknown"; break;
189 case VOS_DOS: p2 = "DOS"; break;
190 case VOS_OS216: p2 = "16 bit OS/2"; break;
191 case VOS_OS232: p2 = "32 bit OS/2"; break;
192 case VOS_NT: p2 = "Windows NT"; break;
193 default: p2 = "---"; break;
195 printf(" dwFileOS: %s running on %s\n", p1, p2);
197 else printf(" dwFileOS: 0\n");
198 switch (mm->VersionInfo.dwFileType)
200 case VFT_UNKNOWN: p1 = "Unknown"; break;
201 case VFT_APP: p1 = "Application"; break;
202 case VFT_DLL: p1 = "DLL"; break;
203 case VFT_DRV: p1 = "Driver"; break;
204 case VFT_FONT: p1 = "Font"; break;
205 case VFT_VXD: p1 = "VxD"; break;
206 case VFT_STATIC_LIB: p1 = "Static Library"; break;
207 default: p1 = "---"; break;
209 printf(" dwFileType: %s\n", p1);
210 printf(" dwFileSubtype: %u\n", (UINT)mm->VersionInfo.dwFileSubtype);
211 printf(" dwFileDate: %x%08x\n",
212 (UINT)mm->VersionInfo.dwFileDateMS, (UINT)mm->VersionInfo.dwFileDateLS);
213 printf(" CvRecord: <%u>\n", (UINT)mm->CvRecord.DataSize);
214 dump_mdmp_data(&mm->CvRecord, " ");
215 printf(" MiscRecord: <%u>\n", (UINT)mm->MiscRecord.DataSize);
216 dump_mdmp_data(&mm->MiscRecord, " ");
217 printf(" Reserved0: 0x%x%08x\n",
218 (UINT)(mm->Reserved0 >> 32), (UINT)mm->Reserved0);
219 printf(" Reserved1: 0x%x%08x\n",
220 (UINT)(mm->Reserved1 >> 32), (UINT)mm->Reserved1);
223 break;
224 case MemoryListStream:
226 const MINIDUMP_MEMORY_LIST *mml = stream;
227 const MINIDUMP_MEMORY_DESCRIPTOR* mmd = mml->MemoryRanges;
229 printf("Memory Ranges: %u\n", mml->NumberOfMemoryRanges);
230 for (i = 0; i < mml->NumberOfMemoryRanges; i++, mmd++)
232 printf(" Memory Range #%d:\n", i);
233 print_longlong_range(" Range", mmd->StartOfMemoryRange, mmd->Memory.DataSize);
234 dump_mdmp_data(&mmd->Memory, " ");
237 break;
238 case SystemInfoStream:
240 const MINIDUMP_SYSTEM_INFO *msi = stream;
241 const char* str;
242 char tmp[128];
244 printf("System Information:\n");
245 switch (msi->ProcessorArchitecture)
247 case PROCESSOR_ARCHITECTURE_UNKNOWN:
248 str = "Unknown";
249 break;
250 case PROCESSOR_ARCHITECTURE_INTEL:
251 strcpy(tmp, "Intel ");
252 switch (msi->ProcessorLevel)
254 case 3: str = "80386"; break;
255 case 4: str = "80486"; break;
256 case 5: str = "Pentium"; break;
257 case 6: str = "Pentium Pro/II or AMD Athlon"; break;
258 case 15: str = "Pentium 4 or AMD Athlon64"; break;
259 default: str = "???"; break;
261 strcat(tmp, str);
262 strcat(tmp, " (");
263 if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4)
265 if (HIBYTE(msi->ProcessorRevision) == 0xFF)
266 sprintf(tmp + strlen(tmp), "%c%d", 'A' + ((msi->ProcessorRevision>>4)&0xf)-0x0a, msi->ProcessorRevision&0xf);
267 else
268 sprintf(tmp + strlen(tmp), "%c%d", 'A' + HIBYTE(msi->ProcessorRevision), LOBYTE(msi->ProcessorRevision));
270 else sprintf(tmp + strlen(tmp), "%d.%d", HIBYTE(msi->ProcessorRevision), LOBYTE(msi->ProcessorRevision));
271 str = tmp;
272 break;
273 case PROCESSOR_ARCHITECTURE_MIPS:
274 str = "Mips";
275 break;
276 case PROCESSOR_ARCHITECTURE_ALPHA:
277 str = "Alpha";
278 break;
279 case PROCESSOR_ARCHITECTURE_PPC:
280 str = "PowerPC";
281 break;
282 case PROCESSOR_ARCHITECTURE_ARM:
283 str = "ARM";
284 break;
285 case PROCESSOR_ARCHITECTURE_ARM64:
286 str = "ARM64";
287 break;
288 case PROCESSOR_ARCHITECTURE_AMD64:
289 str = "X86_64";
290 break;
291 case PROCESSOR_ARCHITECTURE_MSIL:
292 str = "MSIL";
293 break;
294 case PROCESSOR_ARCHITECTURE_NEUTRAL:
295 str = "Neutral";
296 break;
297 default:
298 str = "???";
299 break;
301 printf(" Processor: %s (#%d CPUs)\n", str, msi->NumberOfProcessors);
302 switch (msi->MajorVersion)
304 case 3:
305 switch (msi->MinorVersion)
307 case 51: str = "NT 3.51"; break;
308 default: str = "3-????"; break;
310 break;
311 case 4:
312 switch (msi->MinorVersion)
314 case 0: str = (msi->PlatformId == VER_PLATFORM_WIN32_NT) ? "NT 4.0" : "95"; break;
315 case 10: str = "98"; break;
316 case 90: str = "ME"; break;
317 default: str = "4-????"; break;
319 break;
320 case 5:
321 switch (msi->MinorVersion)
323 case 0: str = "2000"; break;
324 case 1: str = "XP"; break;
325 case 2:
326 if (msi->ProductType == 1) str = "XP";
327 else if (msi->ProductType == 3) str = "Server 2003";
328 else str = "5-????";
329 break;
330 default: str = "5-????"; break;
332 break;
333 case 6:
334 switch (msi->MinorVersion)
336 case 0:
337 if (msi->ProductType == 1) str = "Vista";
338 else if (msi->ProductType == 3) str = "Server 2008";
339 else str = "6-????";
340 break;
341 case 1:
342 if (msi->ProductType == 1) str = "Win7";
343 else if (msi->ProductType == 3) str = "Server 2008 R2";
344 else str = "6-????";
345 break;
346 case 2:
347 if (msi->ProductType == 1) str = "Win8";
348 else if (msi->ProductType == 3) str = "Server 2012";
349 else str = "6-????";
350 break;
351 case 3:
352 if (msi->ProductType == 1) str = "Win8.1";
353 else if (msi->ProductType == 3) str = "Server 2012 R2";
354 else str = "6-????";
355 break;
356 default: str = "6-????"; break;
358 break;
359 case 10:
360 switch (msi->MinorVersion)
362 case 0:
363 if (msi->ProductType == 1) str = "Win10";
364 else str = "10-????";
365 break;
366 default: str = "10-????"; break;
368 break;
369 default: str = "???"; break;
371 printf(" Version: Windows %s (%u)\n", str, msi->BuildNumber);
372 printf(" PlatformId: %u\n", msi->PlatformId);
373 printf(" CSD: ");
374 dump_mdmp_string(msi->CSDVersionRva);
375 printf("\n");
376 printf(" Reserved1: %u\n", msi->Reserved1);
377 if (msi->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
379 printf(" x86.VendorId: %.12s\n",
380 (const char*)msi->Cpu.X86CpuInfo.VendorId);
381 printf(" x86.VersionInformation: %x\n", msi->Cpu.X86CpuInfo.VersionInformation);
382 printf(" x86.FeatureInformation: %x\n", msi->Cpu.X86CpuInfo.FeatureInformation);
383 printf(" x86.AMDExtendedCpuFeatures: %x\n", msi->Cpu.X86CpuInfo.AMDExtendedCpuFeatures);
385 if (sizeof(MINIDUMP_SYSTEM_INFO) + 4 > dir->Location.DataSize &&
386 msi->CSDVersionRva >= dir->Location.Rva + 4)
388 const char* code = PRD(dir->Location.Rva + sizeof(MINIDUMP_SYSTEM_INFO), 4);
389 const DWORD* wes;
390 if (code && code[0] == 'W' && code[1] == 'I' && code[2] == 'N' && code[3] == 'E' &&
391 *(wes = (const DWORD*)(code += 4)) >= 3)
393 /* assume we have wine extensions */
394 printf(" Wine details:\n");
395 printf(" build-id: %s\n", code + wes[1]);
396 printf(" system: %s\n", code + wes[2]);
397 printf(" release: %s\n", code + wes[3]);
401 break;
402 case MiscInfoStream:
404 const MINIDUMP_MISC_INFO *mmi = stream;
406 printf("Misc Information\n");
407 printf(" Size: %u\n", mmi->SizeOfInfo);
408 printf(" Flags: %#x\n", mmi->Flags1);
409 if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID)
410 printf(" ProcessId: %u\n", mmi->ProcessId);
411 if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES)
413 printf(" ProcessCreateTime: %s\n", get_time_str(mmi->ProcessCreateTime));
414 printf(" ProcessUserTime: %u\n", mmi->ProcessUserTime);
415 printf(" ProcessKernelTime: %u\n", mmi->ProcessKernelTime);
418 break;
419 case ExceptionStream:
421 const MINIDUMP_EXCEPTION_STREAM *mes = stream;
423 printf("Exception:\n");
424 printf(" ThreadId: %#x\n", mes->ThreadId);
425 printf(" ExceptionRecord:\n");
426 printf(" ExceptionCode: %#x\n", mes->ExceptionRecord.ExceptionCode);
427 printf(" ExceptionFlags: %#x\n", mes->ExceptionRecord.ExceptionFlags);
428 print_longlong(" ExceptionRecord", mes->ExceptionRecord.ExceptionRecord);
429 print_longlong(" ExceptionAddress", mes->ExceptionRecord.ExceptionAddress);
430 printf(" ExceptionNumberParameters: %u\n", mes->ExceptionRecord.NumberParameters);
431 for (i = 0; i < mes->ExceptionRecord.NumberParameters; i++)
433 printf(" [%d]", i);
434 print_longlong(" ", mes->ExceptionRecord.ExceptionInformation[i]);
436 printf(" ThreadContext:\n");
437 dump_mdmp_data(&mes->ThreadContext, " ");
439 break;
440 case HandleDataStream:
442 const MINIDUMP_HANDLE_DATA_STREAM *mhd = stream;
444 printf("Handle data:\n");
445 printf(" SizeOfHeader: %u\n", mhd->SizeOfHeader);
446 printf(" SizeOfDescriptor: %u\n", mhd->SizeOfDescriptor);
447 printf(" NumberOfDescriptors: %u\n", mhd->NumberOfDescriptors);
449 ptr = (BYTE *)mhd + sizeof(*mhd);
450 for (i = 0; i < mhd->NumberOfDescriptors; ++i)
452 const MINIDUMP_HANDLE_DESCRIPTOR_2 *hd = (void *)ptr;
454 printf(" Handle [%u]:\n", i);
455 print_longlong(" Handle", hd->Handle);
456 printf(" TypeName: ");
457 dump_mdmp_string(hd->TypeNameRva);
458 printf("\n");
459 printf(" ObjectName: ");
460 dump_mdmp_string(hd->ObjectNameRva);
461 printf("\n");
462 printf(" Attributes: %#x\n", hd->Attributes);
463 printf(" GrantedAccess: %#x\n", hd->GrantedAccess);
464 printf(" HandleCount: %u\n", hd->HandleCount);
465 printf(" PointerCount: %#x\n", hd->PointerCount);
467 if (mhd->SizeOfDescriptor >= sizeof(MINIDUMP_HANDLE_DESCRIPTOR_2))
469 printf(" ObjectInfo: ");
470 dump_mdmp_string(hd->ObjectInfoRva);
471 printf("\n");
472 printf(" Reserved0: %#x\n", hd->Reserved0);
475 ptr += mhd->SizeOfDescriptor;
478 break;
479 case ThreadInfoListStream:
481 const MINIDUMP_THREAD_INFO_LIST *til = stream;
483 printf("Thread Info List:\n");
484 printf(" SizeOfHeader: %u\n", (UINT)til->SizeOfHeader);
485 printf(" SizeOfEntry: %u\n", (UINT)til->SizeOfEntry);
486 printf(" NumberOfEntries: %u\n", (UINT)til->NumberOfEntries);
488 ptr = (BYTE *)til + sizeof(*til);
489 for (i = 0; i < til->NumberOfEntries; ++i)
491 const MINIDUMP_THREAD_INFO *ti = (void *)ptr;
493 printf(" Thread [%u]:\n", i);
494 printf(" ThreadId: %u\n", ti->ThreadId);
495 printf(" DumpFlags: %#x\n", ti->DumpFlags);
496 printf(" DumpError: %u\n", ti->DumpError);
497 printf(" ExitStatus: %u\n", ti->ExitStatus);
498 print_longlong(" CreateTime", ti->CreateTime);
499 print_longlong(" ExitTime", ti->ExitTime);
500 print_longlong(" KernelTime", ti->KernelTime);
501 print_longlong(" UserTime", ti->UserTime);
502 print_longlong(" StartAddress", ti->StartAddress);
503 print_longlong(" Affinity", ti->Affinity);
505 ptr += til->SizeOfEntry;
508 break;
510 case UnloadedModuleListStream:
512 const MINIDUMP_UNLOADED_MODULE_LIST *uml = stream;
514 printf("Unloaded module list:\n");
515 printf(" SizeOfHeader: %u\n", uml->SizeOfHeader);
516 printf(" SizeOfEntry: %u\n", uml->SizeOfEntry);
517 printf(" NumberOfEntries: %u\n", uml->NumberOfEntries);
519 ptr = (BYTE *)uml + sizeof(*uml);
520 for (i = 0; i < uml->NumberOfEntries; ++i)
522 const MINIDUMP_UNLOADED_MODULE *mod = (void *)ptr;
524 printf(" Module [%u]:\n", i);
525 print_longlong(" BaseOfImage", mod->BaseOfImage);
526 printf(" SizeOfImage: %u\n", mod->SizeOfImage);
527 printf(" CheckSum: %#x\n", mod->CheckSum);
528 printf(" TimeDateStamp: %s\n", get_time_str(mod->TimeDateStamp));
529 printf(" ModuleName: ");
530 dump_mdmp_string(mod->ModuleNameRva);
531 printf("\n");
533 ptr += uml->SizeOfEntry;
536 break;
538 default:
539 printf("NIY %d\n", dir->StreamType);
540 printf(" RVA: %u\n", (UINT)dir->Location.Rva);
541 printf(" Size: %u\n", dir->Location.DataSize);
542 dump_mdmp_data(&dir->Location, " ");
543 break;