winedump: Add partial COFF library support to the winedump. Take 2

Dmitry Timoshkov dmitry at codeweavers.com
Tue Nov 28 04:40:13 CST 2006


Hello,

here is a resend of the previous patch, which adds the libraries to
the list of auto-detected binaries.

---

This implementation is able to parse imports libraries from the PSDK
and hopefully should help interested parties to check/synchronize ordinal
imports between Wine and Windows.

The dumper is not able (yet) to parse import libraries with the long format
described in Portable Executable and Common Object File Format Specification
and uuid.lib.

Here is a sample output of the dumper (emulating what dumpbin emits):

  Contents of "ComCtl32.Lib": 26302 bytes

  Version      : 0
  Machine      : 14C (i386)
  TimeDateStamp: 40760E7E Fri Apr  9 11:46:22 2004
  SizeOfData   : 00000055
  DLL name     : COMCTL32.dll
  Symbol name  : ?CreateToolbar@@YGPAUHWND__@@PAU1 at KIHPAUHINSTANCE__@@IPBU_TBBUTTON@@H at Z
  Type         : code
  Name type    : ordinal
  Ordinal      : 7

  Version      : 0
  Machine      : 14C (i386)
  TimeDateStamp: 40760E7E Fri Apr  9 11:46:22 2004
  SizeOfData   : 0000001E
  DLL name     : COMCTL32.dll
  Symbol name  : _AddMRUStringW at 8
  Type         : code
  Name type    : ordinal
  Ordinal      : 401

  Version      : 0
  Machine      : 14C (i386)
  TimeDateStamp: 40760E7E Fri Apr  9 11:46:22 2004
  SizeOfData   : 0000001F
  DLL name     : COMCTL32.dll
  Symbol name  : _CreateMRUListW at 4
  Type         : code
  Name type    : ordinal
  Ordinal      : 400

  Version      : 0
  Machine      : 14C (i386)
  TimeDateStamp: 40760E7E Fri Apr  9 11:46:22 2004
  SizeOfData   : 00000024
  DLL name     : COMCTL32.dll
  Symbol name  : _CreateMappedBitmap at 20
  Type         : code
  Name type    : ordinal
  Ordinal      : 8

  Version      : 0
  Machine      : 14C (i386)
  TimeDateStamp: 40760E7E Fri Apr  9 11:46:22 2004
  SizeOfData   : 00000028
  DLL name     : COMCTL32.dll
  Symbol name  : _CreatePropertySheetPage at 4
  Type         : code
  Name type    : undecorate
  Hint         : 3

Changelog:
    winedump: Add partial COFF library support to the winedump.

---
 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(-)

diff --git a/tools/winedump/Makefile.in b/tools/winedump/Makefile.in
index 909a135..a670ceb 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 fe86190..9670a98 100644
--- a/tools/winedump/dump.c
+++ b/tools/winedump/dump.c
@@ -163,6 +163,7 @@ static	void	do_dump( enum FileSig sig, c
 
 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 @@ #endif
         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 0000000..56242e8
--- /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 <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.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 "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 36a105b..f71c49a 100644
--- a/tools/winedump/main.c
+++ b/tools/winedump/main.c
@@ -230,7 +230,7 @@ static const struct my_option option_tab
   {"-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 <mod>   Dumps the content of the module (dll, exe...) named <mod>"},
+  {"dump",  DUMP, 0, do_dump,     "dump <file>  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_tab
 void do_usage (void)
 {
     const struct my_option *opt;
-    printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <dll> | emf <emf> | lnk <lnk>]\n");
+    printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <file> | emf <emf> | lnk <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 d379534..7e87ff0 100644
--- a/tools/winedump/pe.c
+++ b/tools/winedump/pe.c
@@ -48,7 +48,7 @@ #include "pe.h"
 
 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 f12b618..bb7f966 100644
--- a/tools/winedump/winedump.h
+++ b/tools/winedump/winedump.h
@@ -221,8 +221,10 @@ const char *str_find_set (const char *st
 
 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 
 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);
 
-- 
1.4.2






More information about the wine-patches mailing list