From 8e8e8f073d9df3420a0f3f2d042cf21766fec8a0 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Tue, 28 Nov 2006 18:40:13 +0800 Subject: [PATCH] winedump: Add partial COFF library support. --- tools/winedump/Makefile.in | 1 + tools/winedump/dump.c | 30 ++++++---- tools/winedump/lib.c | 136 +++++++++++++++++++++++++++++++++++++++++++++ tools/winedump/main.c | 4 +- tools/winedump/pe.c | 2 +- tools/winedump/winedump.h | 5 +- 6 files changed, 164 insertions(+), 14 deletions(-) create mode 100644 tools/winedump/lib.c diff --git a/tools/winedump/Makefile.in b/tools/winedump/Makefile.in index 909a135000f..a670ceba44e 100644 --- a/tools/winedump/Makefile.in +++ b/tools/winedump/Makefile.in @@ -13,6 +13,7 @@ C_SRCS = \ dump.c \ emf.c \ le.c \ + lib.c \ lnk.c \ main.c \ minidump.c \ diff --git a/tools/winedump/dump.c b/tools/winedump/dump.c index fe861904c5e..9670a98fd26 100644 --- a/tools/winedump/dump.c +++ b/tools/winedump/dump.c @@ -163,6 +163,7 @@ static void do_dump( enum FileSig sig, const void* pmt ) static enum FileSig check_headers(void) { + const char *p; const WORD* pw; const DWORD* pdw; const IMAGE_DOS_HEADER* dh; @@ -204,23 +205,27 @@ static enum FileSig check_headers(void) printf("Can't get the extented signature, aborting\n"); } } - break; + return sig; + case 0x4944: /* "DI" */ - sig = SIG_DBG; - break; + return SIG_DBG; + case 0x444D: /* "MD" */ pdw = PRD(0, sizeof(DWORD)); if (pdw && *pdw == 0x504D444D) /* "MDMP" */ - sig = SIG_MDMP; - else - sig = SIG_UNKNOWN; - break; + return SIG_MDMP; + return SIG_UNKNOWN; + default: - printf("No known main signature (%.2s/%x), aborting\n", (const char *)pw, *pw); - sig = SIG_UNKNOWN; + break; } - return sig; + 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; } int dump_analysis(const char *name, file_dumper fn, enum FileSig wanted_sig) @@ -269,6 +274,11 @@ int dump_analysis(const char *name, file_dumper fn, enum FileSig wanted_sig) 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); + break; } } else diff --git a/tools/winedump/lib.c b/tools/winedump/lib.c new file mode 100644 index 00000000000..56242e8f4a1 --- /dev/null +++ b/tools/winedump/lib.c @@ -0,0 +1,136 @@ +/* + * Dump a COFF library (lib) file + * + * Copyright 2006 Dmitry Timoshkov + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* FIXME: Add support for import library with the long format described in + * Microsoft Portable Executable and Common Object File Format Specification. + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "winbase.h" +#include "winnt.h" + +#include "winedump.h" + +static void dump_import_object(const IMPORT_OBJECT_HEADER *ioh) +{ + if (ioh->Version >= 1) + { +#if 0 /* FIXME: supposed to handle uuid.lib but it doesn't */ + const ANON_OBJECT_HEADER *aoh = (const ANON_OBJECT_HEADER *)ioh; + + printf("CLSID {%08x-%04x-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}", + aoh->ClassID.Data1, aoh->ClassID.Data2, aoh->ClassID.Data3, + aoh->ClassID.Data4[0], aoh->ClassID.Data4[1], aoh->ClassID.Data4[2], aoh->ClassID.Data4[3], + aoh->ClassID.Data4[4], aoh->ClassID.Data4[5], aoh->ClassID.Data4[6], aoh->ClassID.Data4[7]); +#endif + } + else + { + static const char * const obj_type[] = { "code", "data", "const" }; + static const char * const name_type[] = { "ordinal", "name", "no prefix", "undecorate" }; + const char *name; + + printf(" Version : %X\n", ioh->Version); + printf(" Machine : %X (%s)\n", ioh->Machine, get_machine_str(ioh->Machine)); + printf(" TimeDateStamp: %08X %s\n", ioh->TimeDateStamp, get_time_str(ioh->TimeDateStamp)); + printf(" SizeOfData : %08X\n", ioh->SizeOfData); + name = (const char *)ioh + sizeof(*ioh); + printf(" DLL name : %s\n", name + strlen(name) + 1); + printf(" Symbol name : %s\n", name); + printf(" Type : %s\n", (ioh->Type < sizeof(obj_type)/sizeof(obj_type[0])) ? obj_type[ioh->Type] : "unknown"); + printf(" Name type : %s\n", (ioh->NameType < sizeof(name_type)/sizeof(name_type[0])) ? name_type[ioh->NameType] : "unknown"); + printf(" %-13s: %u\n", (ioh->NameType == IMPORT_OBJECT_ORDINAL) ? "Ordinal" : "Hint", ioh->u.Ordinal); + printf("\n"); + } +} + +void lib_dump(const char *lib_base, unsigned long lib_size) +{ + long cur_file_pos; + 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) + { + IMPORT_OBJECT_HEADER *ioh; + long size; + +#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("Name %.16s", iamh->Name); + if (!strncmp(iamh->Name, IMAGE_ARCHIVE_LINKER_MEMBER, sizeof(iamh->Name))) + { + printf(" - %s archive linker member\n", + cur_file_pos == IMAGE_ARCHIVE_START_SIZE ? "1st" : "2nd"); + } + else + printf("\n"); + printf("Date %.12s\n", iamh->Date); + printf("UserID %.6s\n", iamh->UserID); + printf("GroupID %.6s\n", iamh->GroupID); + printf("Mode %.8s\n", iamh->Mode); + printf("Size %.10s\n", iamh->Size); +#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->Sig1 == IMAGE_FILE_MACHINE_UNKNOWN && ioh->Sig2 == IMPORT_OBJECT_HDR_SIG2) + { + dump_import_object(ioh); + } + + 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)); + } +} diff --git a/tools/winedump/main.c b/tools/winedump/main.c index 36a105be83e..f71c49abca0 100644 --- a/tools/winedump/main.c +++ b/tools/winedump/main.c @@ -230,7 +230,7 @@ static const struct my_option option_table[] = { {"-S", SPEC, 1, do_symfile, "-S symfile Search only prototype names found in 'symfile'"}, {"-q", SPEC, 0, do_quiet, "-q Don't show progress (quiet)."}, {"-v", SPEC, 0, do_verbose, "-v Show lots of detail while working (verbose)."}, - {"dump", DUMP, 0, do_dump, "dump Dumps the content of the module (dll, exe...) named "}, + {"dump", DUMP, 0, do_dump, "dump Dumps the contents of the file (dll, exe, lib...)"}, {"-C", DUMP, 0, do_symdmngl, "-C Turns on symbol demangling"}, {"-f", DUMP, 0, do_dumphead, "-f Dumps file header information"}, {"-G", DUMP, 0, do_rawdebug, "-G Dumps raw debug information"}, @@ -244,7 +244,7 @@ static const struct my_option option_table[] = { void do_usage (void) { const struct my_option *opt; - printf ("Usage: winedump [-h | sym | spec | dump | emf | lnk ]\n"); + printf ("Usage: winedump [-h | sym | spec | dump | emf | lnk ]\n"); printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n"); printf ("\tWhen used in --help mode\n"); for (opt = option_table; opt->name; opt++) diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c index d37953459e7..7e87ff059db 100644 --- a/tools/winedump/pe.c +++ b/tools/winedump/pe.c @@ -48,7 +48,7 @@ static const IMAGE_NT_HEADERS32* PE_nt_headers; -static const char* get_machine_str(DWORD mach) +const char *get_machine_str(int mach) { switch (mach) { diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h index f12b618f198..bb7f9667da2 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -221,8 +221,10 @@ const char *str_find_set (const char *str, const char *findset); char *str_toupper (char *str); +const char *get_machine_str(int mach); + /* file dumping functions */ -enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_NE, SIG_LE, SIG_MDMP}; +enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_NE, SIG_LE, SIG_MDMP, SIG_COFFLIB}; const void* PRD(unsigned long prd, unsigned long len); unsigned long Offset(const void* ptr); @@ -238,6 +240,7 @@ 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 ); +void lib_dump( const char *lib_base, unsigned long lib_size ); void dump_stabs(const void* pv_stabs, unsigned szstabs, const char* stabstr, unsigned szstr); -- 2.11.4.GIT