toolkit/library/dependentlibs.py

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 '''Given a library, dependentlibs.py prints the list of libraries it depends
     6 upon that are in the same directory, followed by the library itself.
     7 '''
     9 from optparse import OptionParser
    10 import os
    11 import re
    12 import fnmatch
    13 import subprocess
    14 import sys
    15 from mozpack.executables import (
    16     get_type,
    17     ELF,
    18     MACHO,
    19 )
    21 TOOLCHAIN_PREFIX = ''
    23 def dependentlibs_dumpbin(lib):
    24     '''Returns the list of dependencies declared in the given DLL'''
    25     try:
    26         proc = subprocess.Popen(['dumpbin', '-dependents', lib], stdout = subprocess.PIPE)
    27     except OSError:
    28         # dumpbin is missing, probably mingw compilation. Try using objdump.
    29         return dependentlibs_mingw_objdump(lib)
    30     deps = []
    31     for line in proc.stdout:
    32         # Each line containing an imported library name starts with 4 spaces
    33         match = re.match('    (\S+)', line)
    34         if match:
    35              deps.append(match.group(1))
    36         elif len(deps):
    37              # There may be several groups of library names, but only the
    38              # first one is interesting. The second one is for delayload-ed
    39              # libraries.
    40              break
    41     proc.wait()
    42     return deps
    44 def dependentlibs_mingw_objdump(lib):
    45     proc = subprocess.Popen(['objdump', '-x', lib], stdout = subprocess.PIPE)
    46     deps = []
    47     for line in proc.stdout:
    48         match = re.match('\tDLL Name: (\S+)', line)
    49         if match:
    50             deps.append(match.group(1))
    51     proc.wait()
    52     return deps
    54 def dependentlibs_readelf(lib):
    55     '''Returns the list of dependencies declared in the given ELF .so'''
    56     proc = subprocess.Popen([TOOLCHAIN_PREFIX + 'readelf', '-d', lib], stdout = subprocess.PIPE)
    57     deps = []
    58     for line in proc.stdout:
    59         # Each line has the following format:
    60         #  tag (TYPE)          value
    61         # Looking for NEEDED type entries
    62         tmp = line.split(' ', 3)
    63         if len(tmp) > 3 and tmp[2] == '(NEEDED)':
    64             # NEEDED lines look like:
    65             # 0x00000001 (NEEDED)             Shared library: [libname]
    66             match = re.search('\[(.*)\]', tmp[3])
    67             if match:
    68                 deps.append(match.group(1))
    69     proc.wait()
    70     return deps
    72 def dependentlibs_otool(lib):
    73     '''Returns the list of dependencies declared in the given MACH-O dylib'''
    74     proc = subprocess.Popen(["../../../../../x-tools/x86_64-apple-darwin10/bin/" + TOOLCHAIN_PREFIX + 'otool', '-l', lib], stdout = subprocess.PIPE)
    75     deps= []
    76     cmd = None
    77     for line in proc.stdout:
    78         # otool -l output contains many different things. The interesting data
    79         # is under "Load command n" sections, with the content:
    80         #           cmd LC_LOAD_DYLIB
    81         #       cmdsize 56
    82         #          name libname (offset 24)
    83         tmp = line.split()
    84         if len(tmp) < 2:
    85             continue
    86         if tmp[0] == 'cmd':
    87             cmd = tmp[1]
    88         elif cmd == 'LC_LOAD_DYLIB' and tmp[0] == 'name':
    89             deps.append(re.sub('^@executable_path/','',tmp[1]))
    90     proc.wait()
    91     return deps
    93 def dependentlibs(lib, libpaths, func):
    94     '''For a given library, returns the list of recursive dependencies that can
    95     be found in the given list of paths, followed by the library itself.'''
    96     assert(libpaths)
    97     assert(isinstance(libpaths, list))
    98     deps = []
    99     for dep in func(lib):
   100         if dep in deps or os.path.isabs(dep):
   101             continue
   102         for dir in libpaths:
   103             deppath = os.path.join(dir, dep)
   104             if os.path.exists(deppath):
   105                 deps.extend([d for d in dependentlibs(deppath, libpaths, func) if not d in deps])
   106                 # Black list the ICU data DLL because preloading it at startup
   107                 # leads to startup performance problems because of its excessive
   108                 # size (around 10MB).
   109                 if not dep.startswith("icu"):
   110                     deps.append(dep)
   111                 break
   113     return deps
   115 def main():
   116     parser = OptionParser()
   117     parser.add_option("-L", dest="libpaths", action="append", metavar="PATH", help="Add the given path to the library search path")
   118     parser.add_option("-p", dest="toolchain_prefix", metavar="PREFIX", help="Use the given prefix to readelf")
   119     (options, args) = parser.parse_args()
   120     if options.toolchain_prefix:
   121         global TOOLCHAIN_PREFIX
   122         TOOLCHAIN_PREFIX = options.toolchain_prefix
   123     lib = args[0]
   124     binary_type = get_type(lib)
   125     if binary_type == ELF:
   126         func = dependentlibs_readelf
   127     elif binary_type == MACHO:
   128         func = dependentlibs_otool
   129     else:
   130         ext = os.path.splitext(lib)[1]
   131         assert(ext == '.dll')
   132         func = dependentlibs_dumpbin
   133     if not options.libpaths:
   134         options.libpaths = [os.path.dirname(lib)]
   136     print '\n'.join(dependentlibs(lib, options.libpaths, func) + [lib])
   138 if __name__ == '__main__':
   139     main()

mercurial