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;