From 9ef9d62d4ced222dd8fb05d77224291fb2a68b70 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Wed, 29 Nov 2006 21:40:12 +0100 Subject: [PATCH] winedump: Use a uniform scheme for dumping file contents. --- tools/winedump/dump.c | 133 +++++++------------------------------- tools/winedump/lib.c | 33 +++++----- tools/winedump/minidump.c | 11 ++++ tools/winedump/pe.c | 39 ++++++++++- tools/winedump/winedump.h | 10 ++- 5 files changed, 97 insertions(+), 129 deletions(-) diff --git a/tools/winedump/dump.c b/tools/winedump/dump.c index 21ff22a2521..d99a7833292 100644 --- a/tools/winedump/dump.c +++ b/tools/winedump/dump.c @@ -143,96 +143,30 @@ unsigned long Offset(const void* ptr) return (const char *)ptr - (const char *)dump_base; } -static void do_dump( enum FileSig sig ) +static const struct dumper { - if (sig == SIG_NE) - { - ne_dump(); - return; - } - - if (sig == SIG_LE) - { - le_dump(); - return; - } - - pe_dump(); + enum FileSig kind; + enum FileSig (*get_kind)(void); + file_dumper dumper; /* default dump tool */ } - -static enum FileSig check_headers(void) +dumpers[] = { - const char *p; - const WORD* pw; - const DWORD* pdw; - const 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) - { - /* the signature is the first DWORD */ - pdw = PRD(dh->e_lfanew, sizeof(DWORD)); - if (pdw) - { - if (*pdw == IMAGE_NT_SIGNATURE) - { - sig = SIG_PE; - } - else if (*(const WORD *)pdw == IMAGE_OS2_SIGNATURE) - { - sig = SIG_NE; - } - else if (*(const 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"); - } - } - return sig; - - case 0x4944: /* "DI" */ - return SIG_DBG; - - case 0x444D: /* "MD" */ - pdw = PRD(0, sizeof(DWORD)); - if (pdw && *pdw == 0x504D444D) /* "MDMP" */ - return SIG_MDMP; - return SIG_UNKNOWN; - - default: - break; - } - - p = PRD(0, IMAGE_ARCHIVE_START_SIZE); - if (p && !strncmp(p, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE)) - return SIG_COFFLIB; - - printf("No known main signature (%.2s/%x), aborting\n", (const char *)pw, *pw); - return SIG_UNKNOWN; -} + {SIG_DOS, get_kind_exec, NULL}, + {SIG_PE, get_kind_exec, pe_dump}, + {SIG_DBG, get_kind_dbg, dbg_dump}, + {SIG_NE, get_kind_exec, ne_dump}, + {SIG_LE, get_kind_exec, le_dump}, + {SIG_COFFLIB, get_kind_lib, lib_dump}, + {SIG_MDMP, get_kind_mdmp, mdmp_dump}, + {SIG_UNKNOWN, NULL, NULL} /* sentinel */ +}; int dump_analysis(const char *name, file_dumper fn, enum FileSig wanted_sig) { int fd; - enum FileSig effective_sig; int ret = 1; struct stat s; + const struct dumper *dpr; setbuf(stdout, NULL); @@ -250,37 +184,16 @@ int dump_analysis(const char *name, file_dumper fn, enum FileSig wanted_sig) if ((unsigned long)read( fd, dump_base, dump_total_len ) != dump_total_len) fatal( "Cannot read file" ); } - effective_sig = check_headers(); - - if (wanted_sig == SIG_UNKNOWN || wanted_sig == effective_sig) + for (dpr = dumpers; dpr->kind != SIG_UNKNOWN; dpr++) { - switch (effective_sig) - { - case SIG_UNKNOWN: /* shouldn't happen... */ - printf("Can't get a recognized file signature, aborting\n"); - 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); - break; - case SIG_DBG: - dbg_dump(); - break; - case SIG_DOS: - ret = 0; break; - case SIG_MDMP: - mdmp_dump(); + if (dpr->get_kind() == dpr->kind && + (wanted_sig == SIG_UNKNOWN || wanted_sig == dpr->kind)) + { + if (fn) fn(); else dpr->dumper(); break; - - case SIG_COFFLIB: - printf("Contents of \"%s\": %ld bytes\n\n", name, dump_total_len); - lib_dump(dump_base, dump_total_len); - break; - } + } } - else + if (dpr->kind == SIG_UNKNOWN) { printf("Can't get a suitable file signature, aborting\n"); ret = 0; @@ -300,5 +213,5 @@ int dump_analysis(const char *name, file_dumper fn, enum FileSig wanted_sig) void dump_file(const char* name) { - dump_analysis(name, do_dump, SIG_UNKNOWN); + dump_analysis(name, NULL, SIG_UNKNOWN); } diff --git a/tools/winedump/lib.c b/tools/winedump/lib.c index 56242e8f4a1..bd03eb7ed55 100644 --- a/tools/winedump/lib.c +++ b/tools/winedump/lib.c @@ -80,29 +80,33 @@ static void dump_import_object(const IMPORT_OBJECT_HEADER *ioh) } } -void lib_dump(const char *lib_base, unsigned long lib_size) +enum FileSig get_kind_lib(void) +{ + const char* arch = PRD(0, IMAGE_ARCHIVE_START_SIZE); + if (arch && !strncmp(arch, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE)) + return SIG_COFFLIB; + return SIG_UNKNOWN; +} + +void lib_dump(void) { long cur_file_pos; - IMAGE_ARCHIVE_MEMBER_HEADER *iamh; + const IMAGE_ARCHIVE_MEMBER_HEADER *iamh; - if (strncmp(lib_base, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE)) - { - printf("Not a valid COFF library file"); - return; - } - - iamh = (IMAGE_ARCHIVE_MEMBER_HEADER *)(lib_base + IMAGE_ARCHIVE_START_SIZE); cur_file_pos = IMAGE_ARCHIVE_START_SIZE; - while (cur_file_pos < lib_size) + for (;;) { - IMPORT_OBJECT_HEADER *ioh; + const IMPORT_OBJECT_HEADER *ioh; long size; + if (!(iamh = PRD(cur_file_pos, sizeof(*iamh)))) break; + cur_file_pos += sizeof(IMAGE_ARCHIVE_MEMBER_HEADER); + #if 0 /* left here for debugging purposes, also should be helpful for * adding support for new library formats. */ - printf("cur_file_pos %08lx\n", (ULONG_PTR)iamh - (ULONG_PTR)lib_base); + printf("cur_file_pos %08lx\n", Offset(iamh)); printf("Name %.16s", iamh->Name); if (!strncmp(iamh->Name, IMAGE_ARCHIVE_LINKER_MEMBER, sizeof(iamh->Name))) @@ -121,7 +125,7 @@ void lib_dump(const char *lib_base, unsigned long lib_size) /* FIXME: only import library contents with the short format are * recognized. */ - ioh = (IMPORT_OBJECT_HEADER *)((char *)iamh + sizeof(IMAGE_ARCHIVE_MEMBER_HEADER)); + if (!(ioh = PRD(cur_file_pos + sizeof(*iamh), sizeof(*ioh)))) break; if (ioh->Sig1 == IMAGE_FILE_MACHINE_UNKNOWN && ioh->Sig2 == IMPORT_OBJECT_HDR_SIG2) { dump_import_object(ioh); @@ -130,7 +134,6 @@ void lib_dump(const char *lib_base, unsigned long lib_size) size = strtoul((const char *)iamh->Size, NULL, 10); size = (size + 1) & ~1; /* align to an even address */ - cur_file_pos += size + sizeof(IMAGE_ARCHIVE_MEMBER_HEADER); - iamh = (IMAGE_ARCHIVE_MEMBER_HEADER *)((char *)iamh + size + sizeof(IMAGE_ARCHIVE_MEMBER_HEADER)); + cur_file_pos += size; } } diff --git a/tools/winedump/minidump.c b/tools/winedump/minidump.c index d070c21a3e0..04f4a27447c 100644 --- a/tools/winedump/minidump.c +++ b/tools/winedump/minidump.c @@ -59,6 +59,17 @@ static const MINIDUMP_DIRECTORY* get_mdmp_dir(const MINIDUMP_HEADER* hdr, int st 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 == 0x444D /* "MDMP" */) return SIG_MDMP; + return SIG_UNKNOWN; +} + void mdmp_dump(void) { const MINIDUMP_HEADER* hdr = (const MINIDUMP_HEADER*)PRD(0, sizeof(MINIDUMP_HEADER)); diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c index 080fb42397f..836543234bf 100644 --- a/tools/winedump/pe.c +++ b/tools/winedump/pe.c @@ -784,6 +784,17 @@ static void dump_dir_tls(void) printf(" }\n\n"); } +enum FileSig get_kind_dbg(void) +{ + const WORD* pw; + + pw = PRD(0, sizeof(WORD)); + if (!pw) {printf("Can't get main signature, aborting\n"); return 0;} + + if (*pw == 0x4944 /* "DI" */) return SIG_DBG; + return SIG_UNKNOWN; +} + void dbg_dump(void) { const IMAGE_SEPARATE_DEBUG_HEADER* separateDebugHead; @@ -1111,6 +1122,32 @@ static void dump_debug(void) dump_stabs(stabs, szstabs, stabstr, szstr); } +enum FileSig get_kind_exec(void) +{ + const WORD* pw; + const DWORD* pdw; + const IMAGE_DOS_HEADER* dh; + + pw = PRD(0, sizeof(WORD)); + if (!pw) {printf("Can't get main signature, aborting\n"); return 0;} + + if (*pw != IMAGE_DOS_SIGNATURE) return SIG_UNKNOWN; + + if ((dh = PRD(0, sizeof(IMAGE_DOS_HEADER)))) + { + /* the signature is the first DWORD */ + pdw = PRD(dh->e_lfanew, sizeof(DWORD)); + if (pdw) + { + if (*pdw == IMAGE_NT_SIGNATURE) return SIG_PE; + if (*(const WORD *)pdw == IMAGE_OS2_SIGNATURE) return SIG_NE; + if (*(const WORD *)pdw == IMAGE_VXD_SIGNATURE) return SIG_LE; + return SIG_DOS; + } + } + return 0; +} + void pe_dump(void) { int all = (globals.dumpsect != NULL) && strcmp(globals.dumpsect, "ALL") == 0; @@ -1191,7 +1228,7 @@ static void dll_close (void) } */ -static void do_grab_sym( enum FileSig sig ) +static void do_grab_sym( void ) { const IMAGE_EXPORT_DIRECTORY*exportDir; unsigned i, j; diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h index d4aea075d2f..895e6552228 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -229,7 +229,7 @@ enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_NE, SIG_LE, SIG_MDMP, S const void* PRD(unsigned long prd, unsigned long len); unsigned long Offset(const void* ptr); -typedef void (*file_dumper)(enum FileSig sig); +typedef void (*file_dumper)(void); int dump_analysis(const char*, file_dumper, enum FileSig); void dump_data( const unsigned char *ptr, unsigned int size, const char *prefix ); @@ -237,12 +237,16 @@ const char* get_time_str( unsigned long ); unsigned int strlenW( const unsigned short *str ); void dump_unicode_str( const unsigned short *str, int len ); +enum FileSig get_kind_exec(void); +void pe_dump( void ); void ne_dump( void ); void le_dump( void ); +enum FileSig get_kind_mdmp(void); void mdmp_dump( void ); -void lib_dump( const char *lib_base, unsigned long lib_size ); +enum FileSig get_kind_lib(void); +void lib_dump( void ); +enum FileSig get_kind_dbg(void); void dbg_dump( void ); -void pe_dump( void ); void dump_stabs(const void* pv_stabs, unsigned szstabs, const char* stabstr, unsigned szstr); void dump_codeview(unsigned long ptr, unsigned long len);