Created dump.c as a central point for file dumping (includes header
analysis, utility funcs...).
Added support for dumping minidump files.
diff --git a/tools/winedump/Makefile.in b/tools/winedump/Makefile.in
index 1f82fd7..18aac73 100644
--- a/tools/winedump/Makefile.in
+++ b/tools/winedump/Makefile.in
@@ -10,16 +10,18 @@
C_SRCS = \
debug.c \
+ dump.c \
emf.c \
le.c \
lnk.c \
- main.c \
- misc.c \
- msmangle.c \
+ main.c \
+ minidump.c \
+ misc.c \
+ msmangle.c \
ne.c \
- output.c \
+ output.c \
pe.c \
- search.c \
+ search.c \
symbol.c
all: $(PROGRAMS)
diff --git a/tools/winedump/debug.c b/tools/winedump/debug.c
index 0df9cf5..4eb67869 100644
--- a/tools/winedump/debug.c
+++ b/tools/winedump/debug.c
@@ -99,8 +99,6 @@
* (OMFDirHeader.cDir)
*/
-extern void *PE_base;
-
extern IMAGE_NT_HEADERS* PE_nt_headers;
static void* cv_base /* = 0 */;
@@ -509,14 +507,14 @@
return nampnt;
}
-void dump_coff(unsigned long coffbase, unsigned long len)
+void dump_coff(unsigned long coffbase, unsigned long len, void* pmt)
{
PIMAGE_COFF_SYMBOLS_HEADER coff;
PIMAGE_SYMBOL coff_sym;
PIMAGE_SYMBOL coff_symbols;
PIMAGE_LINENUMBER coff_linetab;
char * coff_strtab;
- IMAGE_SECTION_HEADER *sectHead = (IMAGE_SECTION_HEADER*)((char*)PE_nt_headers + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + PE_nt_headers->FileHeader.SizeOfOptionalHeader);
+ IMAGE_SECTION_HEADER * sectHead = pmt;
unsigned int i;
const char * nampnt;
int naux;
@@ -527,9 +525,9 @@
coff_linetab = (PIMAGE_LINENUMBER) ((unsigned int) coff + coff->LvaToFirstLinenumber);
coff_strtab = (char *) (coff_symbols + coff->NumberOfSymbols);
- printf("\nDebug table: COFF format. modbase %p, coffbase %p\n", PE_base, coff);
+ printf("\nDebug table: COFF format. modbase %p, coffbase %p\n", PRD(0, 0), coff);
printf(" ID | seg:offs [ abs ] | symbol/function name\n");
- for(i=0; i < coff->NumberOfSymbols; i++ )
+ for(i=0; i < coff->NumberOfSymbols; i++ )
{
coff_sym = coff_symbols + i;
naux = coff_sym->NumberOfAuxSymbols;
diff --git a/tools/winedump/dump.c b/tools/winedump/dump.c
new file mode 100644
index 0000000..4a269ab
--- /dev/null
+++ b/tools/winedump/dump.c
@@ -0,0 +1,297 @@
+/*
+ * File dumping utility
+ *
+ * Copyright 2001,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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <time.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <fcntl.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winedump.h"
+#include "pe.h"
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+static void* dump_base;
+static unsigned long dump_total_len;
+
+void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix )
+{
+ unsigned int i, j;
+
+ printf( "%s", prefix );
+ if (!ptr)
+ {
+ printf("NULL\n");
+ return;
+ }
+ for (i = 0; i < size; i++)
+ {
+ printf( "%02x%c", ptr[i], (i % 16 == 7) ? '-' : ' ' );
+ if ((i % 16) == 15)
+ {
+ printf( " " );
+ for (j = 0; j < 16; j++)
+ printf( "%c", isprint(ptr[i-15+j]) ? ptr[i-15+j] : '.' );
+ if (i < size-1) printf( "\n%s", prefix );
+ }
+ }
+ if (i % 16)
+ {
+ printf( "%*s ", 3 * (16-(i%16)), "" );
+ for (j = 0; j < i % 16; j++)
+ printf( "%c", isprint(ptr[i-(i%16)+j]) ? ptr[i-(i%16)+j] : '.' );
+ }
+ printf( "\n" );
+}
+
+const char* get_time_str(DWORD _t)
+{
+ time_t t = (time_t)_t;
+ static char buf[128];
+
+ /* FIXME: I don't get the same values from MS' pedump running under Wine...
+ * I wonder if Wine isn't broken wrt to GMT settings...
+ */
+ strncpy(buf, ctime(&t), sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ if (buf[strlen(buf)-1] == '\n')
+ buf[strlen(buf)-1] = '\0';
+ return buf;
+}
+
+unsigned int strlenW( const WCHAR *str )
+{
+ const WCHAR *s = str;
+ while (*s) s++;
+ return s - str;
+}
+
+void dump_unicode_str( const WCHAR *str, int len )
+{
+ if (len == -1) len = strlenW( str );
+ printf( "L\"");
+ while (len-- > 0 && *str)
+ {
+ WCHAR c = *str++;
+ switch (c)
+ {
+ case '\n': printf( "\\n" ); break;
+ case '\r': printf( "\\r" ); break;
+ case '\t': printf( "\\t" ); break;
+ case '"': printf( "\\\"" ); break;
+ case '\\': printf( "\\\\" ); break;
+ default:
+ if (c >= ' ' && c <= 126) putchar(c);
+ else printf( "\\u%04x",c);
+ }
+ }
+ printf( "\"" );
+}
+
+void* PRD(unsigned long prd, unsigned long len)
+{
+ return (prd + len > dump_total_len) ? NULL : (char*)dump_base + prd;
+}
+
+unsigned long Offset(void* ptr)
+{
+ if (ptr < dump_base) {printf("<<<<<ptr below\n");return 0;}
+ if ((char *)ptr >= (char*)dump_base + dump_total_len) {printf("<<<<<ptr above\n");return 0;}
+ return (char*)ptr - (char*)dump_base;
+}
+
+static void do_dump( enum FileSig sig, void* pmt )
+{
+ if (sig == SIG_NE)
+ {
+ ne_dump( dump_base, dump_total_len );
+ return;
+ }
+
+ if (sig == SIG_LE)
+ {
+ le_dump( dump_base, dump_total_len );
+ return;
+ }
+
+ pe_dump(pmt);
+}
+
+static enum FileSig check_headers(void** pmt)
+{
+ WORD* pw;
+ DWORD* pdw;
+ IMAGE_DOS_HEADER* dh;
+ enum FileSig sig;
+
+ pw = PRD(0, sizeof(WORD));
+ if (!pw) {printf("Can't get main signature, aborting\n"); return 0;}
+
+ *pmt = NULL;
+ switch (*pw)
+ {
+ case IMAGE_DOS_SIGNATURE:
+ sig = SIG_DOS;
+ dh = PRD(0, sizeof(IMAGE_DOS_HEADER));
+ if (dh && dh->e_lfanew >= sizeof(*dh)) /* reasonable DOS header ? */
+ {
+ /* the signature is the first DWORD */
+ pdw = PRD(dh->e_lfanew, sizeof(DWORD));
+ if (pdw)
+ {
+ if (*pdw == IMAGE_NT_SIGNATURE)
+ {
+ *pmt = PRD(dh->e_lfanew, sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER));
+ sig = SIG_PE;
+ }
+ else if (*(WORD *)pdw == IMAGE_OS2_SIGNATURE)
+ {
+ sig = SIG_NE;
+ }
+ else if (*(WORD *)pdw == IMAGE_VXD_SIGNATURE)
+ {
+ sig = SIG_LE;
+ }
+ else
+ {
+ printf("No PE Signature found\n");
+ }
+ }
+ else
+ {
+ printf("Can't get the extented signature, aborting\n");
+ }
+ }
+ break;
+ case 0x4944: /* "DI" */
+ sig = SIG_DBG;
+ break;
+ case 0x444D: /* "MD" */
+ pdw = PRD(0, sizeof(DWORD));
+ if (pdw && *pdw == 0x504D444D) /* "MDMP" */
+ sig = SIG_MDMP;
+ else
+ sig = SIG_UNKNOWN;
+ break;
+ default:
+ printf("No known main signature (%.2s/%x), aborting\n", (char*)pw, *pw);
+ sig = SIG_UNKNOWN;
+ }
+
+ return sig;
+}
+
+int dump_analysis(const char* name, void (*fn)(enum FileSig, void*), enum FileSig wanted_sig)
+{
+ int fd;
+ enum FileSig effective_sig;
+ int ret = 1;
+ struct stat s;
+ void* pmt;
+
+ setbuf(stdout, NULL);
+
+ fd = open(name, O_RDONLY | O_BINARY);
+ if (fd == -1) fatal("Can't open file");
+
+ if (fstat(fd, &s) < 0) fatal("Can't get size");
+ dump_total_len = s.st_size;
+
+#ifdef HAVE_MMAP
+ if ((dump_base = mmap(NULL, dump_total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
+#endif
+ {
+ if (!(dump_base = malloc( dump_total_len ))) fatal( "Out of memory" );
+ if ((unsigned long)read( fd, dump_base, dump_total_len ) != dump_total_len) fatal( "Cannot read file" );
+ }
+
+ effective_sig = check_headers(&pmt);
+
+ if (effective_sig == SIG_UNKNOWN)
+ {
+ printf("Can't get a recognized file signature, aborting\n");
+ ret = 0;
+ }
+ else if (wanted_sig == SIG_UNKNOWN || wanted_sig == effective_sig)
+ {
+ switch (effective_sig)
+ {
+ case SIG_UNKNOWN: /* shouldn't happen... */
+ ret = 0; break;
+ case SIG_PE:
+ case SIG_NE:
+ case SIG_LE:
+ printf("Contents of \"%s\": %ld bytes\n\n", name, dump_total_len);
+ (*fn)(effective_sig, pmt);
+ break;
+ case SIG_DBG:
+ dump_separate_dbg();
+ break;
+ case SIG_DOS:
+ ret = 0; break;
+ case SIG_MDMP:
+ mdmp_dump();
+ break;
+ }
+ }
+ else
+ {
+ printf("Can't get a suitable file signature, aborting\n");
+ ret = 0;
+ }
+
+ if (ret) printf("Done dumping %s\n", name);
+#ifdef HAVE_MMAP
+ if (munmap(dump_base, dump_total_len) == -1)
+#endif
+ {
+ free( dump_base );
+ }
+ close(fd);
+
+ return ret;
+}
+
+void dump_file(const char* name)
+{
+ dump_analysis(name, do_dump, SIG_UNKNOWN);
+}
diff --git a/tools/winedump/minidump.c b/tools/winedump/minidump.c
new file mode 100644
index 0000000..fa11b8b
--- /dev/null
+++ b/tools/winedump/minidump.c
@@ -0,0 +1,372 @@
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winver.h"
+#include "dbghelp.h"
+#include "winedump.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)
+{
+ MINIDUMP_STRING* ms = PRD(rva, sizeof(MINIDUMP_STRING));
+ if (ms)
+ dump_unicode_str( ms->Buffer, ms->Length / sizeof(WCHAR) );
+ else
+ printf("<<?>>");
+}
+
+static MINIDUMP_DIRECTORY* get_mdmp_dir(const MINIDUMP_HEADER* hdr, int str_idx)
+{
+ MINIDUMP_DIRECTORY* dir;
+ 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;
+}
+
+void mdmp_dump(void)
+{
+ MINIDUMP_HEADER* hdr = (MINIDUMP_HEADER*)PRD(0, sizeof(MINIDUMP_HEADER));
+ ULONG idx, ndir = 0;
+ MINIDUMP_DIRECTORY* dir;
+ void* stream;
+
+ if (!hdr)
+ {
+ printf("Cannot get Minidump header\n");
+ return;
+ }
+
+ printf("Signature: %lu (%.4s)\n", hdr->Signature, (char*)&hdr->Signature);
+ printf("Version: %lx\n", hdr->Version);
+ printf("NumberOfStreams: %lu\n", hdr->NumberOfStreams);
+ printf("StreamDirectoryRva: %lu\n", hdr->StreamDirectoryRva);
+ printf("CheckSum: %lu\n", hdr->CheckSum);
+ printf("TimeDateStamp: %s\n", get_time_str(hdr->u.TimeDateStamp));
+ printf("Flags: %llx\n", 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 [%lu]: ", ndir++);
+ switch (dir->StreamType)
+ {
+ case ThreadListStream:
+ {
+ MINIDUMP_THREAD_LIST* mtl = (MINIDUMP_THREAD_LIST*)stream;
+ MINIDUMP_THREAD* mt = &mtl->Threads[0];
+ int i;
+
+ printf("Threads: %lu\n", mtl->NumberOfThreads);
+ for (i = 0; i < mtl->NumberOfThreads; i++, mt++)
+ {
+ printf(" Thread: #%d\n", i);
+ printf(" ThreadId: %lu\n", mt->ThreadId);
+ printf(" SuspendCount: %lu\n", mt->SuspendCount);
+ printf(" PriorityClass: %lu\n", mt->PriorityClass);
+ printf(" Priority: %lu\n", mt->Priority);
+ printf(" Teb: 0x%llx\n", mt->Teb);
+ printf(" Stack: 0x%llx-0x%llx\n",
+ mt->Stack.StartOfMemoryRange,
+ 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:
+ {
+ MINIDUMP_MODULE_LIST* mml = (MINIDUMP_MODULE_LIST*)stream;
+ MINIDUMP_MODULE* mm = &mml->Modules[0];
+ int i;
+ const char* p1;
+ const char* p2;
+
+ printf("Modules (%s): %lu\n",
+ dir->StreamType == ModuleListStream ? "PE" : "ELF",
+ mml->NumberOfModules);
+ for (i = 0; i < mml->NumberOfModules; i++, mm++)
+ {
+ printf(" Module #%d:\n", i);
+ printf(" BaseOfImage: 0x%llx\n", mm->BaseOfImage);
+ printf(" SizeOfImage: %lu\n", mm->SizeOfImage);
+ printf(" CheckSum: %lu\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: %lx\n", mm->VersionInfo.dwSignature);
+ printf(" dwStrucVersion: %lx\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: %lu\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: %lu\n",
+ mm->VersionInfo.dwFileSubtype);
+ printf(" dwFileDate: %lx%08lx\n",
+ mm->VersionInfo.dwFileDateMS, mm->VersionInfo.dwFileDateLS);
+ printf(" CvRecord: <%lu>\n", mm->CvRecord.DataSize);
+ dump_mdmp_data(&mm->CvRecord, " ");
+ printf(" MiscRecord: <%lu>\n", mm->MiscRecord.DataSize);
+ dump_mdmp_data(&mm->MiscRecord, " ");
+ printf(" Reserved0: %llu\n", mm->Reserved0);
+ printf(" Reserved1: %llu\n", mm->Reserved1);
+ }
+ }
+ break;
+ case MemoryListStream:
+ {
+ MINIDUMP_MEMORY_LIST* mml = (MINIDUMP_MEMORY_LIST*)stream;
+ MINIDUMP_MEMORY_DESCRIPTOR* mmd = &mml->MemoryRanges[0];
+ int i;
+
+ printf("Memory Ranges: %lu\n", mml->NumberOfMemoryRanges);
+ for (i = 0; i < mml->NumberOfMemoryRanges; i++, mmd++)
+ {
+ printf(" Memory Range #%d:\n", i);
+ printf(" Range: 0x%llx-0x%llx\n",
+ mmd->StartOfMemoryRange,
+ mmd->StartOfMemoryRange + mmd->Memory.DataSize);
+ dump_mdmp_data(&mmd->Memory, " ");
+ }
+ }
+ break;
+ case SystemInfoStream:
+ {
+ MINIDUMP_SYSTEM_INFO* msi = (MINIDUMP_SYSTEM_INFO*)stream;
+ 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"; break;
+ default: str = "???"; break;
+ }
+ strcat(tmp, str);
+ if (msi->ProcessorLevel == 3 || msi->ProcessorLevel == 4)
+ {
+ if (HIWORD(msi->ProcessorRevision) == 0xFF)
+ sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIBYTE(LOWORD(msi->ProcessorRevision)), LOBYTE(LOWORD(msi->ProcessorRevision)));
+ else
+ sprintf(tmp + strlen(tmp), "-%c%d", 'A' + HIWORD(msi->ProcessorRevision), LOWORD(msi->ProcessorRevision));
+ }
+ else sprintf(tmp + strlen(tmp), "-%d.%d", HIWORD(msi->ProcessorRevision), LOWORD(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;
+ 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 = "5-????"; break;
+ }
+ break;
+ case 5:
+ switch (msi->MinorVersion)
+ {
+ case 0: str = "2000"; break;
+ case 1: str = "XP"; break;
+ case 2: str = "Server 2003"; break;
+ default: str = "5-????"; break;
+ }
+ break;
+ default: str = "???"; break;
+ }
+ printf(" Version: Windows %s (%lu)\n", str, msi->BuildNumber);
+ printf(" PlatformId: %lu\n", msi->PlatformId);
+ printf(" CSD: ");
+ dump_mdmp_string(msi->CSDVersionRva);
+ printf("\n");
+ printf(" Reserved1: %lu\n", msi->u1.Reserved1);
+ if (msi->ProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+ {
+ printf(" x86.VendorId: %.12s\n",
+ (char*)&msi->Cpu.X86CpuInfo.VendorId[0]);
+ printf(" x86.VersionInformation: %lx\n",
+ msi->Cpu.X86CpuInfo.VersionInformation);
+ printf(" x86.FeatureInformation: %lx\n",
+ msi->Cpu.X86CpuInfo.FeatureInformation);
+ printf(" x86.AMDExtendedCpuFeatures: %lu\n",
+ msi->Cpu.X86CpuInfo.AMDExtendedCpuFeatures);
+ }
+ }
+ break;
+ case MiscInfoStream:
+ {
+ MINIDUMP_MISC_INFO* mmi = (MINIDUMP_MISC_INFO*)stream;
+ printf("Misc Information\n");
+ printf(" Size: %lu\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: %lu\n", mmi->ProcessId);
+ if (mmi->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES)
+ {
+ printf(" ProcessCreateTime: %lu\n", mmi->ProcessCreateTime);
+ printf(" ProcessUserTime: %lu\n", mmi->ProcessUserTime);
+ printf(" ProcessKernelTime: %lu\n", mmi->ProcessKernelTime);
+ }
+ }
+ break;
+ case ExceptionStream:
+ {
+ MINIDUMP_EXCEPTION_STREAM* mes = (MINIDUMP_EXCEPTION_STREAM*)stream;
+ int i;
+
+ printf("Exception:\n");
+ printf(" ThreadId: %08lx\n", mes->ThreadId);
+ printf(" ExceptionRecord:\n");
+ printf(" ExceptionCode: %lu\n", mes->ExceptionRecord.ExceptionCode);
+ printf(" ExceptionFlags: %lu\n", mes->ExceptionRecord.ExceptionFlags);
+ printf(" ExceptionRecord: 0x%llx\n",
+ mes->ExceptionRecord.ExceptionRecord);
+ printf(" ExceptionAddress: 0x%llx\n",
+ mes->ExceptionRecord.ExceptionAddress);
+ printf(" ExceptionNumberParameters: %lu\n",
+ mes->ExceptionRecord.NumberParameters);
+ for (i = 0; i < mes->ExceptionRecord.NumberParameters; i++)
+ {
+ printf(" [%d]: 0x%llx\n", i,
+ mes->ExceptionRecord.ExceptionInformation[i]);
+ }
+ printf(" ThreadContext:\n");
+ dump_mdmp_data(&mes->ThreadContext, " ");
+ }
+ break;
+
+ default:
+ printf("NIY %ld\n", dir->StreamType);
+ printf(" RVA: %lu\n", dir->Location.Rva);
+ printf(" Size: %lu\n", dir->Location.DataSize);
+ dump_mdmp_data(&dir->Location, " ");
+ break;
+ }
+ }
+}
diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c
index f6f2a7c..062eafe 100644
--- a/tools/winedump/pe.c
+++ b/tools/winedump/pe.c
@@ -46,37 +46,7 @@
#include "winedump.h"
#include "pe.h"
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-void* PE_base;
-unsigned long PE_total_len;
-IMAGE_NT_HEADERS* PE_nt_headers;
-
-enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_NE, SIG_LE};
-
-static inline unsigned int strlenW( const WCHAR *str )
-{
- const WCHAR *s = str;
- while (*s) s++;
- return s - str;
-}
-
-char* get_time_str(DWORD _t)
-{
- time_t t = (time_t)_t;
- static char buf[128];
-
- /* FIXME: I don't get the same values from MS' pedump running under Wine...
- * I wonder if Wine isn't broken wrt to GMT settings...
- */
- strncpy(buf, ctime(&t), sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
- if (buf[strlen(buf)-1] == '\n')
- buf[strlen(buf)-1] = '\0';
- return buf;
-}
+static IMAGE_NT_HEADERS* PE_nt_headers;
static const char* get_machine_str(DWORD mach)
{
@@ -94,18 +64,6 @@
return "???";
}
-void* PRD(unsigned long prd, unsigned long len)
-{
- return (prd + len > PE_total_len) ? NULL : (char*)PE_base + prd;
-}
-
-unsigned long Offset(void* ptr)
-{
- if (ptr < PE_base) {printf("<<<<<ptr below\n");return 0;}
- if ((char *)ptr >= (char*)PE_base + PE_total_len) {printf("<<<<<ptr above\n");return 0;}
- return (char*)ptr - (char*)PE_base;
-}
-
static void* RVA(unsigned long rva, unsigned long len)
{
IMAGE_SECTION_HEADER* sectHead;
@@ -515,7 +473,8 @@
case IMAGE_DEBUG_TYPE_UNKNOWN:
break;
case IMAGE_DEBUG_TYPE_COFF:
- dump_coff(idd->PointerToRawData, idd->SizeOfData);
+ dump_coff(idd->PointerToRawData, idd->SizeOfData,
+ (char*)PE_nt_headers + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + PE_nt_headers->FileHeader.SizeOfOptionalHeader);
break;
case IMAGE_DEBUG_TYPE_CODEVIEW:
dump_codeview(idd->PointerToRawData, idd->SizeOfData);
@@ -597,7 +556,7 @@
printf(" }\n\n");
}
-static void dump_separate_dbg(void)
+void dump_separate_dbg(void)
{
IMAGE_SEPARATE_DEBUG_HEADER*separateDebugHead = PRD(0, sizeof(separateDebugHead));
unsigned nb_dbg;
@@ -643,28 +602,6 @@
}
}
-static void dump_unicode_str( const WCHAR *str, int len )
-{
- if (len == -1) for (len = 0; str[len]; len++) ;
- printf( "L\"");
- while (len-- > 0 && *str)
- {
- WCHAR c = *str++;
- switch (c)
- {
- case '\n': printf( "\\n" ); break;
- case '\r': printf( "\\r" ); break;
- case '\t': printf( "\\t" ); break;
- case '"': printf( "\\\"" ); break;
- case '\\': printf( "\\\\" ); break;
- default:
- if (c >= ' ' && c <= 126) putchar(c);
- else printf( "\\u%04x",c);
- }
- }
- printf( "\"" );
-}
-
static const char *get_resource_type( unsigned int id )
{
static const char *types[] =
@@ -699,36 +636,6 @@
return NULL;
}
-void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix )
-{
- unsigned int i, j;
-
- printf( "%s", prefix );
- if (!ptr)
- {
- printf("NULL\n");
- return;
- }
- for (i = 0; i < size; i++)
- {
- printf( "%02x%c", ptr[i], (i % 16 == 7) ? '-' : ' ' );
- if ((i % 16) == 15)
- {
- printf( " " );
- for (j = 0; j < 16; j++)
- printf( "%c", isprint(ptr[i-15+j]) ? ptr[i-15+j] : '.' );
- if (i < size-1) printf( "\n%s", prefix );
- }
- }
- if (i % 16)
- {
- printf( "%*s ", 3 * (16-(i%16)), "" );
- for (j = 0; j < i % 16; j++)
- printf( "%c", isprint(ptr[i-(i%16)+j]) ? ptr[i-(i%16)+j] : '.' );
- }
- printf( "\n" );
-}
-
/* dump an ASCII string with proper escaping */
static int dump_strA( const unsigned char *str, size_t len )
{
@@ -944,22 +851,11 @@
printf( "\n\n" );
}
-static void do_dump( enum FileSig sig )
+void pe_dump(void* pmt)
{
int all = (globals.dumpsect != NULL) && strcmp(globals.dumpsect, "ALL") == 0;
- if (sig == SIG_NE)
- {
- ne_dump( PE_base, PE_total_len );
- return;
- }
-
- if (sig == SIG_LE)
- {
- le_dump( PE_base, PE_total_len );
- return;
- }
-
+ PE_nt_headers = pmt;
if (globals.do_dumpheader)
{
dump_pe_header();
@@ -994,142 +890,6 @@
}
}
-static enum FileSig check_headers(void)
-{
- WORD* pw;
- DWORD* pdw;
- IMAGE_DOS_HEADER* dh;
- enum FileSig sig;
-
- pw = PRD(0, sizeof(WORD));
- if (!pw) {printf("Can't get main signature, aborting\n"); return 0;}
-
- switch (*pw)
- {
- case IMAGE_DOS_SIGNATURE:
- sig = SIG_DOS;
- dh = PRD(0, sizeof(IMAGE_DOS_HEADER));
- if (dh && dh->e_lfanew >= sizeof(*dh)) /* reasonable DOS header ? */
- {
- /* the signature is the first DWORD */
- pdw = PRD(dh->e_lfanew, sizeof(DWORD));
- if (pdw)
- {
- if (*pdw == IMAGE_NT_SIGNATURE)
- {
- PE_nt_headers = PRD(dh->e_lfanew, sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER));
- sig = SIG_PE;
- }
- else if (*(WORD *)pdw == IMAGE_OS2_SIGNATURE)
- {
- sig = SIG_NE;
- }
- else if (*(WORD *)pdw == IMAGE_VXD_SIGNATURE)
- {
- sig = SIG_LE;
- }
- else
- {
- printf("No PE Signature found\n");
- }
- }
- else
- {
- printf("Can't get the extented signature, aborting\n");
- }
- }
- break;
- case 0x4944: /* "DI" */
- sig = SIG_DBG;
- break;
- default:
- printf("No known main signature (%.2s/%x), aborting\n", (char*)pw, *pw);
- sig = SIG_UNKNOWN;
- }
-
- return sig;
-}
-
-static int pe_analysis(const char* name, void (*fn)(enum FileSig), enum FileSig wanted_sig)
-{
- int fd;
- enum FileSig effective_sig;
- int ret = 1;
- struct stat s;
-
- setbuf(stdout, NULL);
-
- fd = open(name, O_RDONLY | O_BINARY);
- if (fd == -1) fatal("Can't open file");
-
- if (fstat(fd, &s) < 0) fatal("Can't get size");
- PE_total_len = s.st_size;
-
-#ifdef HAVE_MMAP
- if ((PE_base = mmap(NULL, PE_total_len, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)-1)
-#endif
- {
- if (!(PE_base = malloc( PE_total_len ))) fatal( "Out of memory" );
- if ((unsigned long)read( fd, PE_base, PE_total_len ) != PE_total_len) fatal( "Cannot read file" );
- }
-
- effective_sig = check_headers();
-
- if (effective_sig == SIG_UNKNOWN)
- {
- printf("Can't get a recognized file signature, aborting\n");
- ret = 0;
- }
- else if (wanted_sig == SIG_UNKNOWN || wanted_sig == effective_sig)
- {
- switch (effective_sig)
- {
- case SIG_UNKNOWN: /* shouldn't happen... */
- ret = 0; break;
- case SIG_PE:
- case SIG_NE:
- case SIG_LE:
- printf("Contents of \"%s\": %ld bytes\n\n", name, PE_total_len);
- (*fn)(effective_sig);
- break;
- case SIG_DBG:
- dump_separate_dbg();
- break;
- case SIG_DOS:
- ret = 0; break;
- }
- }
- else
- {
- printf("Can't get a suitable file signature, aborting\n");
- ret = 0;
- }
-
- if (ret) printf("Done dumping %s\n", name);
-#ifdef HAVE_MMAP
- if (munmap(PE_base, PE_total_len) == -1)
-#endif
- {
- free( PE_base );
- }
- close(fd);
-
- return ret;
-}
-
-void dump_file(const char* name)
-{
- pe_analysis(name, do_dump, SIG_UNKNOWN);
-}
-
-#if 0
-int main(int argc, char* argv[])
-{
- if (argc != 2) fatal("usage");
- pe_analysis(argv[1], do_dump);
-}
-#endif
-
typedef struct _dll_symbol {
size_t ordinal;
char *symbol;
@@ -1164,9 +924,9 @@
}
*/
-static void do_grab_sym( enum FileSig sig )
+static void do_grab_sym( enum FileSig sig, void* pmt )
{
- IMAGE_EXPORT_DIRECTORY *exportDir = get_dir(IMAGE_FILE_EXPORT_DIRECTORY);
+ IMAGE_EXPORT_DIRECTORY *exportDir;
unsigned i, j;
DWORD* pName;
DWORD* pFunc;
@@ -1174,7 +934,8 @@
char* ptr;
DWORD* map;
- if (!exportDir) return;
+ PE_nt_headers = pmt;
+ if (!(exportDir = get_dir(IMAGE_FILE_EXPORT_DIRECTORY))) return;
pName = RVA(exportDir->AddressOfNames, exportDir->NumberOfNames * sizeof(DWORD));
if (!pName) {printf("Can't grab functions' name table\n"); return;}
@@ -1242,7 +1003,7 @@
*/
int dll_open (const char *dll_name)
{
- return pe_analysis(dll_name, do_grab_sym, SIG_PE);
+ return dump_analysis(dll_name, do_grab_sym, SIG_PE);
}
/*******************************************************************
diff --git a/tools/winedump/pe.h b/tools/winedump/pe.h
index a258b29..ef0a269 100644
--- a/tools/winedump/pe.h
+++ b/tools/winedump/pe.h
@@ -19,8 +19,7 @@
*/
extern void dump_codeview(unsigned long ptr, unsigned long len);
-extern void dump_coff(unsigned long coffbase, unsigned long len);
+extern void dump_coff(unsigned long coffbase, unsigned long len, void* sect_map);
extern void dump_frame_pointer_omission(unsigned long base, unsigned long len);
-extern void* PRD(unsigned long prd, unsigned long len);
-extern unsigned long Offset(void* ptr);
-extern char* get_time_str(DWORD _t);
+extern void dump_separate_dbg(void);
+extern void pe_dump(void*);
diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h
index ca5b2ce..144c8c4 100644
--- a/tools/winedump/winedump.h
+++ b/tools/winedump/winedump.h
@@ -89,6 +89,8 @@
char arg_flag [MAX_FUNCTION_ARGS];
char *arg_text [MAX_FUNCTION_ARGS];
char *arg_name [MAX_FUNCTION_ARGS];
+ unsigned int n_u_refs;
+ char *u_ref [MAX_FUNCTION_ARGS];
} parsed_symbol;
/* FIXME: Replace with some hash such as GHashTable */
@@ -220,11 +222,23 @@
char *str_toupper (char *str);
-void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix );
+/* file dumping functions */
+enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_NE, SIG_LE, SIG_MDMP};
-void ne_dump( const void *exe, size_t exe_size );
+void* PRD(unsigned long prd, unsigned long len);
+unsigned long Offset(void* ptr);
-void le_dump( const void *exe, size_t exe_size );
+typedef void (*file_dumper)(enum FileSig, void*);
+int dump_analysis(const char*, file_dumper, enum FileSig);
+
+void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix );
+const char* get_time_str( unsigned long );
+unsigned int strlenW( const unsigned short *str );
+void dump_unicode_str( const unsigned short *str, int len );
+
+void ne_dump( const void *exe, size_t exe_size );
+void le_dump( const void *exe, size_t exe_size );
+void mdmp_dump( void );
FILE *open_file (const char *name, const char *ext, const char *mode);