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

Reply via email to