srcanamdw/codescanner/pyinstaller/bindepend.py
author noe\swadi
Thu, 18 Feb 2010 12:29:02 +0530
changeset 1 22878952f6e2
permissions -rw-r--r--
Committing the CodeScanner Core tool This component has been moved from the StaticAnaApps package. BUG : 5889 (http://developer.symbian.org/webbugs/show_bug.cgi?id=5889).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     1
#! /usr/bin/env python
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     2
# Find external dependencies of binary libraries.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     3
# Copyright (C) 2005, Giovanni Bajo
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     4
# Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     5
#
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     6
# This program is free software; you can redistribute it and/or
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     7
# modify it under the terms of the GNU General Public License
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     8
# as published by the Free Software Foundation; either version 2
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
     9
# of the License, or (at your option) any later version.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    10
#
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    11
# This program is distributed in the hope that it will be useful,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    14
# GNU General Public License for more details.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    15
#
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    16
# You should have received a copy of the GNU General Public License
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    17
# along with this program; if not, write to the Free Software
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    19
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    20
# use dumpbin.exe (if present) to find the binary
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    21
# dependencies of an extension module.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    22
# if dumpbin not available, pick apart the PE hdr of the binary
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    23
# while this appears to work well, it is complex and subject to
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    24
# problems with changes to PE hdrs (ie, this works only on 32 bit Intel
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    25
# Windows format binaries)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    26
#
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    27
# Note also that you should check the results to make sure that the
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    28
# dlls are redistributable. I've listed most of the common MS dlls
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    29
# under "excludes" below; add to this list as necessary (or use the
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    30
# "excludes" option in the INSTALL section of the config file).
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    31
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    32
import os
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    33
import time
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    34
import string
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    35
import sys
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    36
import re
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    37
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    38
seen = {}
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    39
_bpath = None
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    40
iswin = sys.platform[:3] == 'win'
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    41
cygwin = sys.platform == 'cygwin'
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    42
excludes = {'KERNEL32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    43
      'ADVAPI.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    44
      'MSVCRT.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    45
      'ADVAPI32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    46
      'COMCTL32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    47
      'CRTDLL.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    48
      'GDI32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    49
      'MFC42.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    50
      'NTDLL.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    51
      'OLE32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    52
      'OLEAUT32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    53
      'RPCRT4.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    54
      'SHELL32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    55
      'USER32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    56
      'WINSPOOL.DRV':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    57
      'WS2HELP.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    58
      'WS2_32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    59
      'WSOCK32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    60
      'MSWSOCK.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    61
      'WINMM.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    62
      'COMDLG32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    63
##      'ZLIB.DLL':1,   # test with python 1.5.2
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    64
      'ODBC32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    65
      'VERSION.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    66
      'IMM32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    67
      'DDRAW.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    68
      'DCIMAN32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    69
      'OPENGL32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    70
      'GLU32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    71
      'GLUB32.DLL':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    72
      '/usr/lib':1,
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    73
      '/lib':1,}
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    74
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    75
def getfullnameof(mod, xtrapath = None):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    76
  """Return the full path name of MOD.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    77
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    78
      MOD is the basename of a dll or pyd.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    79
      XTRAPATH is a path or list of paths to search first.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    80
      Return the full path name of MOD.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    81
      Will search the full Windows search path, as well as sys.path"""
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    82
  epath = getWindowsPath() + sys.path
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    83
  if xtrapath is not None:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    84
    if type(xtrapath) == type(''):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    85
      epath.insert(0, xtrapath)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    86
    else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    87
      epath = xtrapath + epath
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    88
  for p in epath:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    89
    npth = os.path.join(p, mod)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    90
    if os.path.exists(npth):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    91
      return npth
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    92
  return ''
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    93
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    94
def getImports1(pth):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    95
    """Find the binary dependencies of PTH.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    96
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    97
        This implementation (not used right now) uses the MSVC utility dumpbin"""
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    98
    import tempfile
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
    99
    rslt = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   100
    tmpf = tempfile.mktemp()
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   101
    os.system('dumpbin /IMPORTS "%s" >%s' %(pth, tmpf))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   102
    time.sleep(0.1)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   103
    txt = open(tmpf,'r').readlines()
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   104
    os.remove(tmpf)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   105
    i = 0
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   106
    while i < len(txt):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   107
        tokens = string.split(txt[i])
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   108
        if len(tokens) == 1 and string.find(tokens[0], '.') > 0:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   109
            rslt.append(string.strip(tokens[0]))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   110
        i = i + 1
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   111
    return rslt
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   112
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   113
def getImports2x(pth):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   114
    """Find the binary dependencies of PTH.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   115
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   116
        This implementation walks through the PE header"""
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   117
    import struct
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   118
    rslt = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   119
    try:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   120
      f = open(pth, 'rb').read()
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   121
      pehdrd = struct.unpack('l', f[60:64])[0]  #after the MSDOS loader is the offset of the peheader
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   122
      magic = struct.unpack('l', f[pehdrd:pehdrd+4])[0] # pehdr starts with magic 'PE\000\000' (or 17744)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   123
                                                        # then 20 bytes of COFF header
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   124
      numsecs = struct.unpack('h', f[pehdrd+6:pehdrd+8])[0] # whence we get number of sections
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   125
      opthdrmagic = struct.unpack('h', f[pehdrd+24:pehdrd+26])[0]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   126
      if opthdrmagic == 0x10b: # PE32 format
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   127
          numdictoffset = 116
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   128
          importoffset = 128
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   129
      elif opthdrmagic == 0x20b: # PE32+ format
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   130
          numdictoffset = 132
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   131
          importoffset = 148
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   132
      else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   133
          print "E: bindepend cannot analyze %s - unknown header format! %x" % (pth, opthdrmagic)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   134
          return rslt
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   135
      numdirs = struct.unpack('l', f[pehdrd+numdictoffset:pehdrd+numdictoffset+4])[0]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   136
      idata = ''
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   137
      if magic == 17744:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   138
          importsec, sz = struct.unpack('2l', f[pehdrd+importoffset:pehdrd+importoffset+8])
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   139
          if sz == 0:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   140
              return rslt
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   141
          secttbl = pehdrd + numdictoffset + 4 + 8*numdirs
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   142
          secttblfmt = '8s7l2h'
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   143
          seclist = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   144
          for i in range(numsecs):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   145
              seclist.append(struct.unpack(secttblfmt, f[secttbl+i*40:secttbl+(i+1)*40]))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   146
              #nm, vsz, va, rsz, praw, preloc, plnnums, qrelocs, qlnnums, flags \
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   147
              # = seclist[-1]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   148
          for i in range(len(seclist)-1):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   149
              if seclist[i][2] <= importsec < seclist[i+1][2]:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   150
                  break
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   151
          vbase = seclist[i][2]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   152
          raw = seclist[i][4]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   153
          idatastart = raw + importsec - vbase
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   154
          idata = f[idatastart:idatastart+seclist[i][1]]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   155
          i = 0
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   156
          while 1:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   157
              chunk = idata[i*20:(i+1)*20]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   158
              if len(chunk) != 20:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   159
                  print "E: premature end of import table (chunk is %d, not 20)" % len(chunk)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   160
                  break
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   161
              vsa =  struct.unpack('5l', chunk)[3]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   162
              if vsa == 0:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   163
                  break
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   164
              sa = raw + vsa - vbase
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   165
              end = string.find(f, '\000', sa)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   166
              nm = f[sa:end]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   167
              if nm:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   168
                  rslt.append(nm)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   169
              i = i + 1
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   170
      else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   171
          print "E: bindepend cannot analyze %s - file is not in PE format!" % pth
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   172
    except IOError:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   173
        print "E: bindepend cannot analyze %s - file not found!" % pth
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   174
    #except struct.error:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   175
    #    print "E: bindepend cannot analyze %s - error walking thru pehdr" % pth
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   176
    return rslt
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   177
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   178
def getImports2(path):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   179
    """Find the binary dependencies of PTH.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   180
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   181
        This implementation walks through the PE header"""
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   182
    import struct
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   183
    f = open(path, 'rb')
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   184
    # skip the MSDOS loader
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   185
    f.seek(60)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   186
    # get offset to PE header
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   187
    offset = struct.unpack('l', f.read(4))[0]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   188
    f.seek(offset)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   189
    signature = struct.unpack('l', f.read(4))[0]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   190
    coffhdrfmt = 'hhlllhh'
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   191
    rawcoffhdr = f.read(struct.calcsize(coffhdrfmt))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   192
    coffhdr = struct.unpack(coffhdrfmt, rawcoffhdr)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   193
    coffhdr_numsections = coffhdr[1]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   194
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   195
    opthdrfmt = 'hbblllllllllhhhhhhllllhhllllll'
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   196
    rawopthdr = f.read(struct.calcsize(opthdrfmt))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   197
    opthdr = struct.unpack(opthdrfmt, rawopthdr)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   198
    opthdr_numrvas = opthdr[-1]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   199
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   200
    datadirs = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   201
    datadirsize = struct.calcsize('ll') # virtual address, size
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   202
    for i in range(opthdr_numrvas):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   203
        rawdatadir = f.read(datadirsize)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   204
        datadirs.append(struct.unpack('ll', rawdatadir))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   205
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   206
    sectionfmt = '8s6l2hl'
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   207
    sectionsize = struct.calcsize(sectionfmt)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   208
    sections = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   209
    for i in range(coffhdr_numsections):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   210
        rawsection = f.read(sectionsize)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   211
        sections.append(struct.unpack(sectionfmt, rawsection))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   212
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   213
    importva, importsz = datadirs[1]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   214
    if importsz == 0:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   215
        return []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   216
    # figure out what section it's in
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   217
    NAME, MISC, VIRTADDRESS, RAWSIZE, POINTERTORAW = range(5)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   218
    for j in range(len(sections)-1):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   219
        if sections[j][VIRTADDRESS] <= importva < sections[j+1][VIRTADDRESS]:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   220
            importsection = sections[j]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   221
            break
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   222
    else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   223
        if importva >= sections[-1][VIRTADDRESS]:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   224
            importsection = sections[-1]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   225
        else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   226
            print "E: import section is unavailable"
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   227
            return []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   228
    f.seek(importsection[POINTERTORAW] + importva - importsection[VIRTADDRESS])
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   229
    data = f.read(importsz)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   230
    iidescrfmt = 'lllll'
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   231
    CHARACTERISTICS, DATETIME, FWDRCHAIN, NAMERVA, FIRSTTHUNK = range(5)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   232
    iidescrsz = struct.calcsize(iidescrfmt)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   233
    dlls = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   234
    while data:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   235
        iid = struct.unpack(iidescrfmt, data[:iidescrsz])
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   236
        if iid[NAMERVA] == 0:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   237
            break
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   238
        f.seek(importsection[POINTERTORAW] + iid[NAMERVA] - importsection[VIRTADDRESS])
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   239
        nm = f.read(256)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   240
        nm, jnk = string.split(nm, '\0', 1)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   241
        if nm:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   242
            dlls.append(nm)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   243
        data = data[iidescrsz:]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   244
    return dlls
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   245
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   246
def Dependencies(lTOC):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   247
  """Expand LTOC to include all the closure of binary dependencies.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   248
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   249
     LTOC is a logical table of contents, ie, a seq of tuples (name, path).
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   250
     Return LTOC expanded by all the binary dependencies of the entries
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   251
     in LTOC, except those listed in the module global EXCLUDES"""
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   252
  for nm, pth, typ in lTOC:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   253
    fullnm = string.upper(os.path.basename(pth))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   254
    if seen.get(string.upper(nm),0):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   255
      continue
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   256
    #print "I: analyzing", pth
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   257
    seen[string.upper(nm)] = 1
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   258
    dlls = getImports(pth)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   259
    for lib in dlls:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   260
        #print "I: found", lib
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   261
        if not iswin and not cygwin:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   262
            npth = lib
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   263
            dir, lib = os.path.split(lib)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   264
            if excludes.get(dir,0):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   265
                continue
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   266
        if excludes.get(string.upper(lib),0):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   267
            continue
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   268
        if seen.get(string.upper(lib),0):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   269
            continue
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   270
        if iswin or cygwin:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   271
            npth = getfullnameof(lib, os.path.dirname(pth))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   272
        if npth:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   273
            lTOC.append((lib, npth, 'BINARY'))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   274
        else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   275
            print "E: lib not found:", lib, "dependency of", pth
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   276
  return lTOC
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   277
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   278
def getImports3(pth):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   279
    """Find the binary dependencies of PTH.
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   280
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   281
        This implementation is for ldd platforms"""
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   282
    rslt = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   283
    for line in os.popen('ldd "%s"' % pth).readlines():
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   284
        m = re.search(r"\s+(.*?)\s+=>\s+(.*?)\s+\(.*\)", line)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   285
        if m:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   286
            name, lib = m.group(1), m.group(2)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   287
            if name[:10] == 'linux-gate':
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   288
                # linux-gate is a fake library which does not exist and
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   289
                # should be ignored. See also:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   290
                # http://www.trilithium.com/johan/2005/08/linux-gate/
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   291
                continue
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   292
            if os.path.exists(lib):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   293
                rslt.append(lib)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   294
            else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   295
                print 'E: cannot find %s in path %s (needed by %s)' % \
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   296
                      (name, lib, pth)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   297
    return rslt
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   298
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   299
def getImports(pth):
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   300
    """Forwards to either getImports2 or getImports3
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   301
    """
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   302
    if sys.platform[:3] == 'win' or sys.platform == 'cygwin':
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   303
        return getImports2(pth)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   304
    return getImports3(pth)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   305
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   306
def getWindowsPath():
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   307
    """Return the path that Windows will search for dlls."""
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   308
    global _bpath
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   309
    if _bpath is None:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   310
        _bpath = []
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   311
        if iswin:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   312
            try:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   313
                import win32api
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   314
            except ImportError:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   315
                print "W: Cannot determine your Windows or System directories"
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   316
                print "W: Please add them to your PATH if .dlls are not found"
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   317
                print "W: or install starship.python.net/skippy/win32/Downloads.html"
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   318
            else:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   319
                sysdir = win32api.GetSystemDirectory()
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   320
                sysdir2 = os.path.normpath(os.path.join(sysdir, '..', 'SYSTEM'))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   321
                windir = win32api.GetWindowsDirectory()
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   322
                _bpath = [sysdir, sysdir2, windir]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   323
        _bpath.extend(string.split(os.environ.get('PATH', ''), os.pathsep))
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   324
    return _bpath
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   325
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   326
if __name__ == "__main__":
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   327
  if len(sys.argv) < 2:
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   328
    print "Usage: python %s BINARYFILE" % sys.argv[0]
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   329
    sys.exit(0)
22878952f6e2 Committing the CodeScanner Core tool
noe\swadi
parents:
diff changeset
   330
  print getImports(sys.argv[1])