[PATCH 03/10] [WineDump]: dumping internals
Eric Pouech
eric.pouech at wanadoo.fr
Wed Nov 29 14:40:12 CST 2006
- now using a uniform scheme for dumping file contents
A+
---
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 21ff22a..213baf4 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 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;
+ struct dumper* dpr;
setbuf(stdout, NULL);
@@ -250,37 +184,16 @@ #endif
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();
- break;
-
- case SIG_COFFLIB:
- printf("Contents of \"%s\": %ld bytes\n\n", name, dump_total_len);
- lib_dump(dump_base, dump_total_len);
+ if (dpr->get_kind() == dpr->kind &&
+ (wanted_sig == SIG_UNKNOWN || wanted_sig == dpr->kind))
+ {
+ if (fn) fn(); else dpr->dumper();
break;
- }
+ }
}
- else
+ if (dpr->kind == SIG_UNKNOWN)
{
printf("Can't get a suitable file signature, aborting\n");
ret = 0;
@@ -300,5 +213,5 @@ #endif
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 56242e8..bd03eb7 100644
--- a/tools/winedump/lib.c
+++ b/tools/winedump/lib.c
@@ -80,29 +80,33 @@ #endif
}
}
-void lib_dump(const char *lib_base, unsigned long lib_size)
+enum FileSig get_kind_lib(void)
{
- long cur_file_pos;
- IMAGE_ARCHIVE_MEMBER_HEADER *iamh;
+ 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;
+}
- if (strncmp(lib_base, IMAGE_ARCHIVE_START, IMAGE_ARCHIVE_START_SIZE))
- {
- printf("Not a valid COFF library file");
- return;
- }
+void lib_dump(void)
+{
+ long cur_file_pos;
+ const IMAGE_ARCHIVE_MEMBER_HEADER *iamh;
- 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 @@ #endif
/* 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 @@ #endif
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 d070c21..04f4a27 100644
--- a/tools/winedump/minidump.c
+++ b/tools/winedump/minidump.c
@@ -59,6 +59,17 @@ static const MINIDUMP_DIRECTORY* get_mdm
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 080fb42..8365432 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 d4aea07..895e655 100644
--- a/tools/winedump/winedump.h
+++ b/tools/winedump/winedump.h
@@ -229,7 +229,7 @@ enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_
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);
More information about the wine-patches
mailing list