From 627aeca259f9acef23838434c5079ee97e7f632c Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Mon, 7 Mar 2005 11:03:53 +0000 Subject: [PATCH] Created dump.c as a central point for file dumping (includes header analysis, utility funcs...). Added support for dumping minidump files. --- tools/winedump/Makefile.in | 12 +- tools/winedump/debug.c | 10 +- tools/winedump/dump.c | 297 +++++++++++++++++++++++++++++ tools/winedump/minidump.c | 372 +++++++++++++++++++++++++++++++++++++ tools/winedump/pe.c | 261 ++------------------------ tools/winedump/pe.h | 7 +- tools/winedump/winedump.h | 20 +- 7 files changed, 711 insertions(+), 268 deletions(-) create mode 100644 tools/winedump/dump.c create mode 100644 tools/winedump/minidump.c diff --git a/tools/winedump/Makefile.in b/tools/winedump/Makefile.in index 1f82fd77e73..18aac731501 100644 --- a/tools/winedump/Makefile.in +++ b/tools/winedump/Makefile.in @@ -10,16 +10,18 @@ MODULE = none 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 0df9cf522a9..4eb67869959 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 @@ static const char* get_coff_name( PIMAGE_SYMBOL coff_sym, const char* coff_str 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 @@ void dump_coff(unsigned long coffbase, unsigned long len) 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 00000000000..4a269ab80b2 --- /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 +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include + +#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("<<<<= (char*)dump_base + dump_total_len) {printf("<<<<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 00000000000..fa11b8b85b4 --- /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 + +#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 f6f2a7c8c85..062eafe2689 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 @@ static const char* get_machine_str(DWORD mach) 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("<<<<= (char*)PE_base + PE_total_len) {printf("<<<<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 @@ static void dump_dir_tls(void) 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_separate_dbg(void) } } -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 @@ static const char *get_resource_type( unsigned int id ) 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 @@ static void dump_dir_resource(void) 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 void do_dump( enum FileSig sig ) } } -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 dll_close (void) } */ -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 @@ static void do_grab_sym( enum FileSig sig ) 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 @@ static void do_grab_sym( enum FileSig sig ) */ 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 a258b2967cd..ef0a269decf 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 ca5b2ce8efc..144c8c420ac 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -89,6 +89,8 @@ typedef struct __parsed_symbol 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 @@ const char *str_find_set (const char *str, const char *findset); 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);