123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- /*
- * MiniDump dumping utility
- *
- * Copyright 2005 Eric Pouech
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
- #include "config.h"
- #include <stdarg.h>
- #define NONAMELESSUNION
- #define NONAMELESSSTRUCT
- #include "winedump.h"
- #include "winver.h"
- #include "dbghelp.h"
- static void dump_mdmp_data(const MINIDUMP_LOCATION_DESCRIPTOR* md, const char* pfx)
- {
- if (md->DataSize)
- dump_data(PRD(md->Rva, md->DataSize), md->DataSize, pfx);
- }
- static void dump_mdmp_string(DWORD rva)
- {
- const MINIDUMP_STRING* ms = PRD(rva, sizeof(MINIDUMP_STRING));
- if (ms)
- dump_unicode_str( ms->Buffer, ms->Length / sizeof(WCHAR) );
- else
- printf("<<?>>");
- }
- static const MINIDUMP_DIRECTORY* get_mdmp_dir(const MINIDUMP_HEADER* hdr, unsigned int str_idx)
- {
- const MINIDUMP_DIRECTORY* dir;
- unsigned int i;
- for (i = 0; i < hdr->NumberOfStreams; i++)
- {
- dir = PRD(hdr->StreamDirectoryRva + i * sizeof(MINIDUMP_DIRECTORY),
- sizeof(MINIDUMP_DIRECTORY));
- if (!dir) continue;
- if (dir->StreamType == str_idx) return dir;
- }
- return NULL;
- }
- enum FileSig get_kind_mdmp(void)
- {
- const DWORD* pdw;
- pdw = PRD(0, sizeof(DWORD));
- if (!pdw) {printf("Can't get main signature, aborting\n"); return SIG_UNKNOWN;}
- if (*pdw == 0x504D444D /* "MDMP" */) return SIG_MDMP;
- return SIG_UNKNOWN;
- }
- void mdmp_dump(void)
- {
- const MINIDUMP_HEADER* hdr = PRD(0, sizeof(MINIDUMP_HEADER));
- ULONG idx, ndir = 0;
- const MINIDUMP_DIRECTORY* dir;
- const void* stream;
- if (!hdr)
- {
- printf("Cannot get Minidump header\n");
- return;
- }
- printf("Signature: %u (%.4s)\n", hdr->Signature, (const char*)&hdr->Signature);
- printf("Version: %x\n", hdr->Version);
- printf("NumberOfStreams: %u\n", hdr->NumberOfStreams);
- printf("StreamDirectoryRva: %u\n", hdr->StreamDirectoryRva);
- printf("CheckSum: %u\n", hdr->CheckSum);
- printf("TimeDateStamp: %s\n", get_time_str(hdr->u.TimeDateStamp));
- printf("Flags: %x%08x\n", (DWORD)(hdr->Flags >> 32), (DWORD)hdr->Flags);
- for (idx = 0; idx <= LastReservedStream; idx++)
- {
- if (!(dir = get_mdmp_dir(hdr, idx))) continue;
- stream = PRD(dir->Location.Rva, dir->Location.DataSize);
- printf("Directory [%u]: ", ndir++);
- switch (dir->StreamType)
- {
- case ThreadListStream:
- {
- const MINIDUMP_THREAD_LIST* mtl = (const MINIDUMP_THREAD_LIST*)stream;
- const MINIDUMP_THREAD* mt = mtl->Threads;
- unsigned int i;
- printf("Threads: %u\n", mtl->NumberOfThreads);
- for (i = 0; i < mtl->NumberOfThreads; i++, mt++)
- {
- printf(" Thread: #%d\n", i);
- printf(" ThreadId: %u\n", mt->ThreadId);
- printf(" SuspendCount: %u\n", mt->SuspendCount);
- printf(" PriorityClass: %u\n", mt->PriorityClass);
- printf(" Priority: %u\n", mt->Priority);
- printf(" Teb: 0x%x%08x\n", (DWORD)(mt->Teb >> 32), (DWORD)mt->Teb);
- printf(" Stack: 0x%x%08x-0x%x%08x\n",
- (DWORD)(mt->Stack.StartOfMemoryRange >> 32),
- (DWORD)mt->Stack.StartOfMemoryRange,
- (DWORD)((mt->Stack.StartOfMemoryRange + mt->Stack.Memory.DataSize) >> 32),
- (DWORD)(mt->Stack.StartOfMemoryRange + mt->Stack.Memory.DataSize));
- dump_mdmp_data(&mt->Stack.Memory, " ");
- printf(" ThreadContext:\n");
- dump_mdmp_data(&mt->ThreadContext, " ");
- }
- }
- break;
- case ModuleListStream:
- case 0xFFF0:
- {
- const MINIDUMP_MODULE_LIST* mml = (const MINIDUMP_MODULE_LIST*)stream;
- const MINIDUMP_MODULE* mm = mml->Modules;
- unsigned int i;
- const char* p1;
- const char* p2;
- printf("Modules (%s): %u\n",
- dir->StreamType == ModuleListStream ? "PE" : "ELF",
- mml->NumberOfModules);
- for (i = 0; i < mml->NumberOfModules; i++, mm++)
- {
- printf(" Module #%d:\n", i);
- printf(" BaseOfImage: 0x%x%08x\n",
- (DWORD)(mm->BaseOfImage >> 32), (DWORD) mm->BaseOfImage);
- printf(" SizeOfImage: %u\n", mm->SizeOfImage);
- printf(" CheckSum: %u\n", mm->CheckSum);
- printf(" TimeDateStamp: %s\n", get_time_str(mm->TimeDateStamp));
- printf(" ModuleName: ");
- dump_mdmp_string(mm->ModuleNameRva);
- printf("\n");
- printf(" VersionInfo:\n");
- printf(" dwSignature: %x\n", mm->VersionInfo.dwSignature);
- printf(" dwStrucVersion: %x\n",
- mm->VersionInfo.dwStrucVersion);
- printf(" dwFileVersion: %d,%d,%d,%d\n",
- HIWORD(mm->VersionInfo.dwFileVersionMS),
- LOWORD(mm->VersionInfo.dwFileVersionMS),
- HIWORD(mm->VersionInfo.dwFileVersionLS),
- LOWORD(mm->VersionInfo.dwFileVersionLS));
- printf(" dwProductVersion %d,%d,%d,%d\n",
- HIWORD(mm->VersionInfo.dwProductVersionMS),
- LOWORD(mm->VersionInfo.dwProductVersionMS),
- HIWORD(mm->VersionInfo.dwProductVersionLS),
- LOWORD(mm->VersionInfo.dwProductVersionLS));
- printf(" dwFileFlagsMask: %u\n",
- mm->VersionInfo.dwFileFlagsMask);
- printf(" dwFileFlags: %s%s%s%s%s%s\n",
- mm->VersionInfo.dwFileFlags & VS_FF_DEBUG ? "Debug " : "",
- mm->VersionInfo.dwFileFlags & VS_FF_INFOINFERRED ? "Inferred " : "",
- mm->VersionInfo.dwFileFlags & VS_FF_PATCHED ? "Patched " : "",
- mm->VersionInfo.dwFileFlags & VS_FF_PRERELEASE ? "PreRelease " : "",
- mm->VersionInfo.dwFileFlags & VS_FF_PRIVATEBUILD ? "PrivateBuild " : "",
- mm->VersionInfo.dwFileFlags & VS_FF_SPECIALBUILD ? "SpecialBuild " : "");
- if (mm->VersionInfo.dwFileOS)
- {
- switch (mm->VersionInfo.dwFileOS & 0x000F)
- {
- case VOS__BASE: p1 = "_base"; break;
- case VOS__WINDOWS16:p1 = "16 bit Windows"; break;
- case VOS__PM16: p1 = "16 bit Presentation Manager"; break;
- case VOS__PM32: p1 = "32 bit Presentation Manager"; break;
- case VOS__WINDOWS32:p1 = "32 bit Windows"; break;
- default: p1 = "---"; break;
- }
- switch (mm->VersionInfo.dwFileOS & 0xF0000)
- {
- case VOS_UNKNOWN: p2 = "unknown"; break;
- case VOS_DOS: p2 = "DOS"; break;
- case VOS_OS216: p2 = "16 bit OS/2"; break;
- case VOS_OS232: p2 = "32 bit OS/2"; break;
- case VOS_NT: p2 = "Windows NT"; break;
- default: p2 = "---"; break;
- }
- printf(" dwFileOS: %s running on %s\n", p1, p2);
- }
- else printf(" dwFileOS: 0\n");
- switch (mm->VersionInfo.dwFileType)
- {
- case VFT_UNKNOWN: p1 = "Unknown"; break;
- case VFT_APP: p1 = "Application"; break;
- case VFT_DLL: p1 = "DLL"; break;
- case VFT_DRV: p1 = "Driver"; break;
- case VFT_FONT: p1 = "Font"; break;
- case VFT_VXD: p1 = "VxD"; break;
- case VFT_STATIC_LIB: p1 = "Static Library"; break;
- default: p1 = "---"; break;
- }
- printf(" dwFileType: %s\n", p1);
- printf(" dwFileSubtype: %u\n",
- mm->VersionInfo.dwFileSubtype);
- printf(" dwFileDate: %x%08x\n",
- mm->VersionInfo.dwFileDateMS, mm->VersionInfo.dwFileDateLS);
- printf(" CvRecord: <%u>\n", mm->CvRecord.DataSize);
- dump_mdmp_data(&mm->CvRecord, " ");
- printf(" MiscRecord: <%u>\n", mm->MiscRecord.DataSize);
- dump_mdmp_data(&mm->MiscRecord, " ");
- printf(" Reserved0: 0x%x%08x\n",
- (DWORD)(mm->Reserved0 >> 32), (DWORD)mm->Reserved0);
- printf(" Reserved1: 0x%x%08x\n",
- (DWORD)(mm->Reserved1 >> 32), (DWORD)mm->Reserved1);
- }
- }
- break;
- case MemoryListStream:
- {
- const MINIDUMP_MEMORY_LIST* mml = (const MINIDUMP_MEMORY_LIST*)stream;
- const MINIDUMP_MEMORY_DESCRIPTOR* mmd = mml->MemoryRanges;
- unsigned int i;
- printf("Memory Ranges: %u\n", mml->NumberOfMemoryRanges);
- for (i = 0; i < mml->NumberOfMemoryRanges; i++, mmd++)
- {
- printf(" Memory Range #%d:\n", i);
- printf(" Range: 0x%x%08x-0x%x%08x\n",
- (DWORD)(mmd->StartOfMemoryRange >> 32),
- (DWORD)mmd->StartOfMemoryRange,
- (DWORD)((mmd->StartOfMemoryRange + mmd->Memory.DataSize) >> 32),
- (DWORD)(mmd->StartOfMemoryRange + mmd->Memory.DataSize));
- dump_mdmp_data(&mmd->Memory, " ");
- }
- }
- break;
- case SystemInfoStream:
- {
- const MINIDUMP_SYSTEM_INFO* msi = (const MINIDUMP_SYSTEM_INFO*)stream;
- const char* str;
- char tmp[128];
- printf("System Information:\n");
- switch (msi->ProcessorArchitecture)
- {
- case PROCESSOR_ARCHITECTURE_UNKNOWN:
- str = "Unknown";
- break;
- case PROCESSOR_ARCHITECTURE_INTEL:
- strcpy(tmp, "Intel ");
- switch (msi->ProcessorLevel)
- {
- case 3: str = "80386"; break;
- case 4: str = "80486"; break;
- case 5: str = "Pentium"; break;
- case 6: str = "Pentium Pro/II or AMD Athlon"; break;
- case 15: str = "Pentium 4 or AMD Athlon64"; break;
- default: str = "???"; break;
- }
- strcat(tmp, str);
- strcat(tmp, " (");
- if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4)
- {
- if (HIBYTE(msi->ProcessorRevision) == 0xFF)
- sprintf(tmp + strlen(tmp), "%c%d", 'A' + ((msi->ProcessorRevision>>4)&0xf)-0x0a, msi->ProcessorRevision&0xf);
- else
- sprintf(tmp + strlen(tmp), "%c%d", 'A' + HIBYTE(msi->ProcessorRevision), LOBYTE(msi->ProcessorRevision));
- }
- else sprintf(tmp + strlen(tmp), "%d.%d", HIBYTE(msi->ProcessorRevision), LOBYTE(msi->ProcessorRevision));
- str = tmp;
- break;
- case PROCESSOR_ARCHITECTURE_MIPS:
- str = "Mips";
- break;
- case PROCESSOR_ARCHITECTURE_ALPHA:
- str = "Alpha";
- break;
- case PROCESSOR_ARCHITECTURE_PPC:
- str = "PowerPC";
- break;
- case PROCESSOR_ARCHITECTURE_ARM:
- str = "ARM";
- break;
- case PROCESSOR_ARCHITECTURE_ARM64:
- str = "ARM64";
- break;
- case PROCESSOR_ARCHITECTURE_AMD64:
- str = "X86_64";
- break;
- case PROCESSOR_ARCHITECTURE_MSIL:
- str = "MSIL";
- break;
- case PROCESSOR_ARCHITECTURE_NEUTRAL:
- str = "Neutral";
- break;
- default:
- str = "???";
- break;
- }
- printf(" Processor: %s (#%d CPUs)\n", str, msi->u.s.NumberOfProcessors);
- switch (msi->MajorVersion)
- {
- case 3:
- switch (msi->MinorVersion)
- {
- case 51: str = "NT 3.51"; break;
- default: str = "3-????"; break;
- }
- break;
- case 4:
- switch (msi->MinorVersion)
- {
- case 0: str = (msi->PlatformId == VER_PLATFORM_WIN32_NT) ? "NT 4.0" : "95"; break;
- case 10: str = "98"; break;
- case 90: str = "ME"; break;
- default: str = "4-????"; break;
- }
- break;
- case 5:
- switch (msi->MinorVersion)
- {
- case 0: str = "2000"; break;
- case 1: str = "XP"; break;
- case 2:
- if (msi->u.s.ProductType == 1) str = "XP";
- else if (msi->u.s.ProductType == 3) str = "Server 2003";
- else str = "5-????";
- break;
- default: str = "5-????"; break;
- }
- break;
- case 6:
- switch (msi->MinorVersion)
- {
- case 0:
- if (msi->u.s.ProductType == 1) str = "Vista";
- else if (msi->u.s.ProductType == 3) str = "Server 2008";
- else str = "6-????";
- break;
- case 1:
- if (msi->u.s.ProductType == 1) str = "Win7";
- else if (msi->u.s.ProductType == 3) str = "Server 2008 R2";
- else str = "6-????";
- break;
- case 2:
- if (msi->u.s.ProductType == 1) str = "Win8";
- else if (msi->u.s.ProductType == 3) str = "Server 2012";
- else str = "6-????";
- break;
- case 3:
- if (msi->u.s.ProductType == 1) str = "Win8.1";
- else if (msi->u.s.ProductType == 3) str = "Server 2012 R2";
- else str = "6-????";
- break;
- default: str = "6-????"; break;
- }
- break;
- case 10:
- switch (msi->MinorVersion)
- {
- case 0:
- if (msi->u.s.ProductType == 1) str = "Win10";
- else str = "10-????";
- break;
- default: str = "10-????"; break;
- }
- break;
- default: str = "???"; break;
- }
- printf(" Version: Windows %s (%u)\n", str, msi->BuildNumber);
- printf(" PlatformId: %u\n", msi->PlatformId);
- printf(" CSD: ");
- dump_mdmp_string(msi->CSDVersionRva);
- printf("\n");
- printf(" Reserved1: %u\n", msi->u1.Reserved1);
- if (msi->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
- {
- printf(" x86.VendorId: %.12s\n",
- (const char*)msi->Cpu.X86CpuInfo.VendorId);
- printf(" x86.VersionInformation: %x\n",
- msi->Cpu.X86CpuInfo.VersionInformation);
- printf(" x86.FeatureInformation: %x\n",
- msi->Cpu.X86CpuInfo.FeatureInformation);
- printf(" x86.AMDExtendedCpuFeatures: %x\n",
- msi->Cpu.X86CpuInfo.AMDExtendedCpuFeatures);
- }
- if (sizeof(MINIDUMP_SYSTEM_INFO) + 4 > dir->Location.DataSize &&
- msi->CSDVersionRva >= dir->Location.Rva + 4)
- {
- const char* code = PRD(dir->Location.Rva + sizeof(MINIDUMP_SYSTEM_INFO), 4);
- const DWORD* wes;
- if (code && code[0] == 'W' && code[1] == 'I' && code[2] == 'N' && code[3] == 'E' &&
- *(wes = (const DWORD*)(code += 4)) >= 3)
- {
- /* assume we have wine extensions */
- printf(" Wine details:\n");
- printf(" build-id: %s\n", code + wes[1]);
- printf(" system: %s\n", code + wes[2]);
- printf(" release: %s\n", code + wes[3]);
- }
- }
- }
- break;
- case MiscInfoStream:
- {
- const MINIDUMP_MISC_INFO* mmi = (const MINIDUMP_MISC_INFO*)stream;
- printf("Misc Information\n");
- printf(" Size: %u\n", mmi->SizeOfInfo);
- printf(" Flags: %s%s\n",
- mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID ? "ProcessId " : "",
- mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES ? "ProcessTimes " : "");
- if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_ID)
- printf(" ProcessId: %u\n", mmi->ProcessId);
- if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES)
- {
- printf(" ProcessCreateTime: %u\n", mmi->ProcessCreateTime);
- printf(" ProcessUserTime: %u\n", mmi->ProcessUserTime);
- printf(" ProcessKernelTime: %u\n", mmi->ProcessKernelTime);
- }
- }
- break;
- case ExceptionStream:
- {
- const MINIDUMP_EXCEPTION_STREAM* mes = (const MINIDUMP_EXCEPTION_STREAM*)stream;
- unsigned int i;
- printf("Exception:\n");
- printf(" ThreadId: %08x\n", mes->ThreadId);
- printf(" ExceptionRecord:\n");
- printf(" ExceptionCode: %u\n", mes->ExceptionRecord.ExceptionCode);
- printf(" ExceptionFlags: %u\n", mes->ExceptionRecord.ExceptionFlags);
- printf(" ExceptionRecord: 0x%x%08x\n",
- (DWORD)(mes->ExceptionRecord.ExceptionRecord >> 32),
- (DWORD)mes->ExceptionRecord.ExceptionRecord);
- printf(" ExceptionAddress: 0x%x%08x\n",
- (DWORD)(mes->ExceptionRecord.ExceptionAddress >> 32),
- (DWORD)(mes->ExceptionRecord.ExceptionAddress));
- printf(" ExceptionNumberParameters: %u\n",
- mes->ExceptionRecord.NumberParameters);
- for (i = 0; i < mes->ExceptionRecord.NumberParameters; i++)
- {
- printf(" [%d]: 0x%x%08x\n", i,
- (DWORD)(mes->ExceptionRecord.ExceptionInformation[i] >> 32),
- (DWORD)mes->ExceptionRecord.ExceptionInformation[i]);
- }
- printf(" ThreadContext:\n");
- dump_mdmp_data(&mes->ThreadContext, " ");
- }
- break;
- default:
- printf("NIY %d\n", dir->StreamType);
- printf(" RVA: %u\n", dir->Location.Rva);
- printf(" Size: %u\n", dir->Location.DataSize);
- dump_mdmp_data(&dir->Location, " ");
- break;
- }
- }
- }
|