Charles Wilson wrote:
> Charles Wilson wrote:
>> Peter Rosin wrote:
>>> I'm primarily trying to determine what impact this has on my
>>> MSVC branch...
> 
> Ran some experiments on the libraries shipped with the Windows SDK. The
> attached script worked ok on most of them. After eliminating the static
> libraries and the import libraries to '*.dll' and '*.DLL' (241
> "successes" in all), I'm left with the following 13 odd ducks:
> 
> These are correct, but are a reminder that import libraries exist for
> objects other than those named foo.dll. So that's 5 more successes:
> 
> KSProxy.Lib :x86 archive import FOR ksproxy.ax
> bthprops.lib :x86 archive import FOR bthprops.cpl
> irprops.lib :x86 archive import FOR irprops.cpl
> NetSh.Lib :x86 archive import FOR NETSH.EXE
> WinSpool.Lib :x86 archive import FOR WINSPOOL.DRV
> 
> These are the true failures:
> 
> For the following 6 libraries, it is the LAST archive member with a
> .idata$6 section, not the first one, that specifies the DLL.
> 
> GdiPlus.lib :x86 archive import FOR u.GdiplusStartup
> MSTask.Lib :x86 archive import FOR .._setnetscheduleaccountinformat...@12
> WS2_32.Lib :x86 archive import FOR ..inet_pton
> ksuser.lib :x86 archive import FOR ..KsCreateTopologyNode
> shell32.lib :x86 archive import FOR =.WOWShellExecute
> windowscodecs.lib :x86 archive import FOR q.WICSetEncoderFormat_Proxy
> 
> This one imports symbols from multiple DLLs. One of them happens to be
> in the last archive member, but...
> 
> Vfw32.Lib :x86 archive import FOR -.StretchDIB
> 
> I have no idea what this one is. objdump can't grok it:
> 
> MAPI.Lib :MAPI.Lib: Microsoft Visual C library
> $ objdump -f MAPI.Lib
> objdump: MAPI.Lib: File format not recognized
> 
> So that's 246 PASS, 8 FAIL.

So, I've prepared a patch for dlltool which adds an '--identify-ms'
flag, which modifies the behavior of the '--identify <implib>' option.
It searches for .idata$6 instead of .idata$7, AND attempts to
disambiguate between "the one that specifies the DLL name" and "all the
other ones that list the symbols" by inspecting the flags.

In almost all cases, "the one that specifies the DLL name" has the flag
value 0x00000123
   SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS
The "other ones" have flag values 0x00204103
   SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP

This version of dlltool was able to operate on all of the import
libraries in the Windows SDK, except for:

MAPI.Lib: MAPI.Lib: Microsoft Visual C library
  === again, because bfd has no idea how to parse this one

Vfw32.Lib: Import library `Vfw32.Lib' specifies two or more dlls:
`MSVFW32.dll' and `AVIFIL32.dll'

And the following:

WebPost.Lib: x86 archive import FOR WEBPOST.DLL
ddao35.lib: x86 archive import FOR ddao35.dll
ddao35d.lib: x86 archive import FOR ddao35d.dll
ddao35u.lib: x86 archive import FOR ddao35u.dll
ddao35ud.lib: x86 archive import FOR ddao35ud.dll
More on these, later.

Note that this dlltool /succeeded/ on
        GdiPlus.lib
        MSTask.Lib
        WS2_32.Lib
        ksuser.lib      
        shell32.lib
        windowscodecs.lib
where the script in my previous post failed. Dlltool can handle the case
where "the one that specifies the DLL name" is not first.

The five new failures (where the script succeeded) are interesting. In
each case, the "rule" above ("the one" has flag value 0x00000123, and
the others do not) was incorrect:

================================
$ ~/dlltool.exe --identify WebPost.Lib --identify-ms
flags: 0x00000123       datasize: 0000000c      data: 'WEBPOST.DLL'
00000000  5745 4250 4f53 542e 444c 4c00           WEBPOST.DLL.

flags: 0x00000123       datasize: 00000010      data: ''
00000000  0400 5770 4269 6e64 546f 5369 7465 4100 ..WpBindToSiteA.

/home/cwilson/dlltool: Import library `WebPost.Lib' specifies two or
more dlls: `WEBPOST.DLL' and `'
================================

The error message is a little confusing: `WEBPOST.DLL' and `'? The
"empty" name is because the data contains the unprintable character \004
followed by '\0'.  Recall for symbols, the first two bytes are a
little-endian count. So this is symbol 0x0004. I *guess* I could check
that both offset 0 and offset 1 contain printable characters. But that's
still just a heuristic, because a really big DLL might have
  "01my_symbol"
where the first two bytes are 0x30 0x31 ('01') representing symbol
number 0x3130 or 12352.

But this wierd case occurs only when the import library appears to NOT
follow the pattern most of them do. In fact, in these five import
libraries, ALL of the .idata$6 sections have flag 0x00000123, not just
"the one" we want.

But, what are they? Do we care?

The ddao35 libraries are the Microsoft JET 3.5 DAO C++ libraries, for
DOS-Win16 (!).  Microsoft shipped the Jet 4.0 libraries with WinME and
W2k, and recommends against using ones older than that. Do we care that
you won't be able to dlpreopen (or dlltool --identify) these ancient
import libraries?)

Webpost.Lib (--> webpost.dll) seems to be part of the Web Publishing
Wizard API. I can't find any other useful information.

So, if it's worth pursing, we have all the pieces to (a) teach dlltool
how to deal with MS-style implibs, (b) create a fallback script when new
dlltool is not available.  However, this all presupposes that your
libtool/MSVC support is allowed to use binutils programs...otherwise,
things get tricky. I have a 'dllname' program that can be adapted for
this purpose, but again: can we ship/embed non-standard binary tools?
Assume/require that they are present? I really don't know how your
MSVC/libtool stuff is set up.

But...I also dislike for fixes to existing bugs, in existing platforms,
to be held up by not-yet-in-master support for other compilers. So, can
we get back to discussing the original patch, under the predicates of
cygwin and mingw (not msvc) $hosts?

--
Chuck

Index: binutils/dlltool.c
===================================================================
RCS file: /cvs/src/src/binutils/dlltool.c,v
retrieving revision 1.86
diff -u -r1.86 dlltool.c
--- binutils/dlltool.c  25 Nov 2008 08:48:49 -0000      1.86
+++ binutils/dlltool.c  5 Jan 2009 05:21:40 -0000
@@ -354,6 +354,7 @@
 static char *imp_name;
 static char *identify_imp_name;
 static char *identify_dll_name;
+static bfd_boolean identify_ms;
 static char *head_label;
 static char *imp_name_lab;
 static char *dll_name;
@@ -3037,7 +3038,8 @@
 /* identify_process_section_p
 
    This predicate returns true if section->name
-   is .idata$7 (.idata$6 on PPC).
+   matches the desired value. By default, this is
+   .idata$7 (.idata$6 on PPC, or when --identify-ms)
 */   
 static bfd_boolean
 identify_process_section_p (asection * section)
@@ -3049,8 +3051,12 @@
 #else
   ".idata$7";
 #endif
+  static const char * MS_SECTION_NAME = ".idata$6";
 
-  if (strcmp (SECTION_NAME, section->name) == 0)
+  const char * section_name =
+    (identify_ms ? MS_SECTION_NAME : SECTION_NAME);
+  
+  if (strcmp (section_name, section->name) == 0)
     return TRUE;
   return FALSE;
 }
@@ -3080,6 +3086,19 @@
   if (! identify_process_section_p (section))
     return;
 
+  /* binutils import libs distinguish the .idata$7 section that 
+     contains the  DLL name from other .idata$7 sections by
+     the absence of the SEC_RELOC flag
+  */
+  if (!identify_ms && ((section->flags & SEC_RELOC) == SEC_RELOC))
+    return;
+
+  /* MS import libs distinguish the .idata$6 section that
+     contains the  DLL name from other .idata$6 sections by
+     the presence of the SEC_DATA flag */
+  if (identify_ms && ((section->flags & SEC_DATA) == 0))
+    return;
+
   if ((datasize = bfd_section_size (abfd, section)) == 0)
     return;
 
@@ -3367,6 +3386,7 @@
   fprintf (file, _("   -n --no-delete            Keep temp files (repeat for 
extra preservation).\n"));
   fprintf (file, _("   -t --temp-prefix <prefix> Use <prefix> to construct 
temp file names.\n"));
   fprintf (file, _("   -I --identify <implib>    Report the name of the DLL 
associated with <implib>.\n"));
+  fprintf (file, _("      --identify-ms          Modify the behavior of -I to 
work with MS implibs.\n"));
   fprintf (file, _("   -v --verbose              Be verbose.\n"));
   fprintf (file, _("   -V --version              Display the program 
version.\n"));
   fprintf (file, _("   -h --help                 Display this 
information.\n"));
@@ -3386,6 +3406,7 @@
 #define OPTION_EXCLUDE_SYMS            (OPTION_NO_EXPORT_ALL_SYMS + 1)
 #define OPTION_NO_DEFAULT_EXCLUDES     (OPTION_EXCLUDE_SYMS + 1)
 #define OPTION_ADD_STDCALL_UNDERSCORE  (OPTION_NO_DEFAULT_EXCLUDES + 1)
+#define OPTION_IDENTIFY_MS             (OPTION_ADD_STDCALL_UNDERSCORE + 1)
 
 static const struct option long_options[] =
 {
@@ -3408,6 +3429,7 @@
   {"add-stdcall-alias", no_argument, NULL, 'A'},
   {"ext-prefix-alias", required_argument, NULL, 'p'},
   {"identify", required_argument, NULL, 'I'},
+  {"identify-ms", no_argument, NULL, OPTION_IDENTIFY_MS},
   {"verbose", no_argument, NULL, 'v'},
   {"version", no_argument, NULL, 'V'},
   {"help", no_argument, NULL, 'h'},
@@ -3470,6 +3492,9 @@
        case OPTION_ADD_STDCALL_UNDERSCORE:
          add_stdcall_underscore = 1;
          break;
+       case OPTION_IDENTIFY_MS:
+         identify_ms = 1;
+         break;
        case 'x':
          no_idata4 = 1;
          break;

Reply via email to