winedbg: Fix stepping over an instruction.
[wine] / tools / winedump / minidump.c
1 /*
2  *      MiniDump dumping utility
3  *
4  *      Copyright 2005 Eric Pouech
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22 #include <stdarg.h>
23
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winver.h"
29 #include "dbghelp.h"
30 #include "winedump.h"
31
32 static void dump_mdmp_data(const MINIDUMP_LOCATION_DESCRIPTOR* md, const char* pfx)
33 {
34     if (md->DataSize)
35         dump_data(PRD(md->Rva, md->DataSize), md->DataSize, pfx);
36 }
37
38 static void dump_mdmp_string(DWORD rva)
39 {
40     MINIDUMP_STRING*    ms = PRD(rva, sizeof(MINIDUMP_STRING));
41     if (ms)
42         dump_unicode_str( ms->Buffer, ms->Length / sizeof(WCHAR) );
43     else
44         printf("<<?>>");
45 }
46
47 static MINIDUMP_DIRECTORY* get_mdmp_dir(const MINIDUMP_HEADER* hdr, int str_idx)
48 {
49     MINIDUMP_DIRECTORY* dir;
50     unsigned int        i;
51
52     for (i = 0; i < hdr->NumberOfStreams; i++)
53     {
54         dir = PRD(hdr->StreamDirectoryRva + i * sizeof(MINIDUMP_DIRECTORY), 
55                   sizeof(MINIDUMP_DIRECTORY));
56         if (!dir) continue;
57         if (dir->StreamType == str_idx) return dir;
58     }
59     return NULL;
60 }
61
62 void mdmp_dump(void)
63 {
64     MINIDUMP_HEADER*        hdr = (MINIDUMP_HEADER*)PRD(0, sizeof(MINIDUMP_HEADER));
65     ULONG                   idx, ndir = 0;
66     MINIDUMP_DIRECTORY*     dir;
67     void*                   stream;
68
69     if (!hdr)
70     {
71         printf("Cannot get Minidump header\n");
72         return;
73     }
74
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);
82
83     for (idx = 0; idx <= LastReservedStream; idx++)
84     {
85         if (!(dir = get_mdmp_dir(hdr, idx))) continue;
86
87         stream = PRD(dir->Location.Rva, dir->Location.DataSize);
88         printf("Directory [%lu]: ", ndir++);
89         switch (dir->StreamType)
90         {
91         case ThreadListStream:
92         {
93             MINIDUMP_THREAD_LIST*   mtl = (MINIDUMP_THREAD_LIST*)stream;
94             MINIDUMP_THREAD*        mt = &mtl->Threads[0];
95             unsigned int            i;
96
97             printf("Threads: %lu\n", mtl->NumberOfThreads);
98             for (i = 0; i < mtl->NumberOfThreads; i++, mt++)
99             {
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, "    ");
112             }
113         }
114         break;
115         case ModuleListStream:
116         case 0xFFF0:
117         {
118             MINIDUMP_MODULE_LIST*   mml = (MINIDUMP_MODULE_LIST*)stream;
119             MINIDUMP_MODULE*        mm = &mml->Modules[0];
120             unsigned int            i;
121             const char*             p1;
122             const char*             p2;
123
124             printf("Modules (%s): %lu\n",
125                    dir->StreamType == ModuleListStream ? "PE" : "ELF",
126                    mml->NumberOfModules);
127             for (i = 0; i < mml->NumberOfModules; i++, mm++)
128             {
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);
136                 printf("\n");
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)
161                 {
162                     switch (mm->VersionInfo.dwFileOS & 0x000F)
163                     {
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;
170                     }
171                     switch (mm->VersionInfo.dwFileOS & 0xF0000)
172                     {
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;
179                     }
180                     printf("      dwFileOS: %s running on %s\n", p1, p2);
181                 }
182                 else printf("      dwFileOS: 0\n");
183                 switch (mm->VersionInfo.dwFileType)
184                 {
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;
193                 }
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);
205             }
206         }       
207         break;
208         case MemoryListStream:
209         {
210             MINIDUMP_MEMORY_LIST*   mml = (MINIDUMP_MEMORY_LIST*)stream;
211             MINIDUMP_MEMORY_DESCRIPTOR* mmd = &mml->MemoryRanges[0];
212             unsigned int                i;
213
214             printf("Memory Ranges: %lu\n", mml->NumberOfMemoryRanges);
215             for (i = 0; i < mml->NumberOfMemoryRanges; i++, mmd++)
216             {
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, "    ");
222             }   
223         }
224         break;
225         case SystemInfoStream:
226         {
227             MINIDUMP_SYSTEM_INFO*       msi = (MINIDUMP_SYSTEM_INFO*)stream;
228             const char*                 str;
229             char                        tmp[128];
230
231             printf("System Information:\n");
232             switch (msi->ProcessorArchitecture)
233             {
234             case PROCESSOR_ARCHITECTURE_UNKNOWN: 
235                 str = "Unknown";
236                 break;
237             case PROCESSOR_ARCHITECTURE_INTEL:
238                 strcpy(tmp, "Intel ");
239                 switch (msi->ProcessorLevel)
240                 {
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;
246                 }
247                 strcat(tmp, str);
248                 if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4)
249                 {
250                     if (HIWORD(msi->ProcessorRevision) == 0xFF)
251                         sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIBYTE(LOWORD(msi->ProcessorRevision)), LOBYTE(LOWORD(msi->ProcessorRevision)));
252                     else
253                         sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision));
254                 }
255                 else sprintf(tmp + strlen(tmp), "-%d.%d", HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision));
256                 str = tmp;
257                 break;
258             case PROCESSOR_ARCHITECTURE_MIPS:
259                 str = "Mips";
260                 break;
261             case PROCESSOR_ARCHITECTURE_ALPHA:
262                 str = "Alpha";
263                 break;
264             case PROCESSOR_ARCHITECTURE_PPC:
265                 str = "PowerPC";
266                 break;
267             default:
268                 str = "???";
269                 break;
270             }
271             printf("  Processor: %s (#%d CPUs)\n", str, msi->u.s.NumberOfProcessors);
272             switch (msi->MajorVersion)
273             {
274             case 3:
275                 switch (msi->MinorVersion)
276                 {
277                 case 51: str = "NT 3.51"; break;
278                 default: str = "3-????"; break;
279                 }
280                 break;
281             case 4:
282                 switch (msi->MinorVersion)
283                 {
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;
288                 }
289                 break;
290             case 5:
291                 switch (msi->MinorVersion)
292                 {
293                 case 0: str = "2000"; break;
294                 case 1: str = "XP"; break;
295                 case 2: str = "Server 2003"; break;
296                 default: str = "5-????"; break;
297                 }
298                 break;
299             default: str = "???"; break;
300             }
301             printf("  Version: Windows %s (%lu)\n", str, msi->BuildNumber);
302             printf("  PlatformId: %lu\n", msi->PlatformId);
303             printf("  CSD: ");
304             dump_mdmp_string(msi->CSDVersionRva);
305             printf("\n");
306             printf("  Reserved1: %lu\n", msi->u1.Reserved1);
307             if (msi->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
308             {
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);
317             }
318         }
319         break;
320         case MiscInfoStream:
321         {
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)
331             {
332                 printf("  ProcessCreateTime: %lu\n", mmi->ProcessCreateTime);
333                 printf("  ProcessUserTime: %lu\n", mmi->ProcessUserTime);
334                 printf("  ProcessKernelTime: %lu\n", mmi->ProcessKernelTime);
335             }
336         }
337         break;
338         case ExceptionStream:
339         {
340             MINIDUMP_EXCEPTION_STREAM*  mes = (MINIDUMP_EXCEPTION_STREAM*)stream;
341             unsigned int                i;
342
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++)
355             {
356                 printf("    [%d]: 0x%llx\n", i, 
357                        mes->ExceptionRecord.ExceptionInformation[i]);
358             }
359             printf("  ThreadContext:\n");
360             dump_mdmp_data(&mes->ThreadContext, "    ");
361         }
362         break;
363
364         default:
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, "    ");
369             break;
370         }
371     }
372 }