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. But I wonder if these 8 failures are just pathological cases, and the code embodied in the attached script is "good enough" -- assuming an msvc-configured libtool is allowed to use "file", "objdump", "nm", etc. "Doctor, func_dll_from_imp fails for library shell32.lib, so I can't dlpreopen it"..."Ok, don't do that then." NOTE: I had to change the grep expression: *ar\ archive*) # could be an import, or static if objdump -f "$1" | sed -e '10q' 2>/dev/null | grep -E 'file format pei?-i386(.*architecture: i386)?' >/dev/null ; then from ...pe-i386(... to ...pei?-i386(... so that some of the import libraries were recognized as such. I'm not sure what the distinction between pe-i386 and pei-i386 is, or what the implications of this particular change would be. FWIW, I think this sed script is safer than the other one, even at the cost of an extra fork. Keeping the contents of each archive member on a separate line, rather than merging them all together, just seems better. -- Chuck
#!/bin/sh DLLNAME_SECTION=.idata\$6 # mostly the same as libtool's function of the same name, # except that it stores the result in an explicitly-accessible # *_result variable. Still echos, tho. Also, the grep -E # expression is slightly different: pe-i386 -> pei?-i386 func_win32_libid () { func_win32_libid_result=unknown win32_fileres=`file -L "$1" 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import func_win32_libid_result="x86 archive import" ;; *ar\ archive*) # could be an import, or static if objdump -f "$1" | sed -e '10q' 2>/dev/null | grep -E 'file format pei?-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval nm -f posix -A "$1" 2>/dev/null | sed -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) func_win32_libid_result="x86 archive import" ;; *) func_win32_libid_result="x86 archive static";; esac fi ;; *DLL*) func_win32_libid_result="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) func_win32_libid_result="x86 DLL" ;; esac ;; esac echo "$func_win32_libid_result" } # same as libtool's, from master func_win32_import_lib_p () { case `func_win32_libid "$1" 2>/dev/null | sed -e 10q` in *import*) : ;; *) false ;; esac } # Odd. For some reason I can't capture this directly in # backticks. So, use a level of indirection: func_dll_for_imp_core () { objdump -s --section "$DLLNAME_SECTION" "$1" 2>/dev/null | sed '/^Contents of section '"$DLLNAME_SECTION"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ \t]*file format pe[i]\{,1\}-i386$/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remoaining lines, remove first 43 characters s/^.\{43\}//' | sed -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p ' | # we now have a list, one entry per line, of the stringified # contents of the $DLLNAME_SECTION of all members of the archive # which possess that section. Choose the first one. sed -n -e 1p } # indirection... func_dll_for_imp () { func_dll_for_imp_result=`func_dll_for_imp_core "$1"` } if func_win32_import_lib_p "$1" ; then func_win32_libid "$1" >/dev/null func_dll_for_imp "$1" echo "$func_win32_libid_result FOR $func_dll_for_imp_result" else func_win32_libid "$1" >/dev/null case "$func_win32_libid_result" in unknown ) file -L "$1" ;; * ) echo "$func_win32_libid_result" ;; esac fi