コード例 #1
0
def gen_list(output, lib):
    libpaths = [os.path.join(substs['DIST'], 'bin')]
    binary_type = get_type(lib)
    if binary_type == ELF:
        func = dependentlibs_readelf
    elif binary_type == MACHO:
        func = dependentlibs_otool
    else:
        ext = os.path.splitext(lib)[1]
        assert(ext == '.dll')
        func = dependentlibs_dumpbin

    deps = dependentlibs(lib, libpaths, func)
    deps[lib] = mozpath.join(libpaths[0], lib)
    output.write('\n'.join(deps.keys()) + '\n')
    return set(deps.values())
コード例 #2
0
def main():
    parser = OptionParser()
    parser.add_option("-L", dest="libpaths", action="append", metavar="PATH", help="Add the given path to the library search path")
    parser.add_option("-p", dest="toolchain_prefix", metavar="PREFIX", help="Use the given prefix to readelf")
    (options, args) = parser.parse_args()
    if options.toolchain_prefix:
        global TOOLCHAIN_PREFIX
        TOOLCHAIN_PREFIX = options.toolchain_prefix
    lib = args[0]
    binary_type = get_type(lib)
    if binary_type == ELF:
        func = dependentlibs_readelf
    elif binary_type == MACHO:
        func = dependentlibs_otool
    else:
        ext = os.path.splitext(lib)[1]
        assert(ext == '.dll')
        func = dependentlibs_dumpbin
    if not options.libpaths:
        options.libpaths = [os.path.dirname(lib)]

    print '\n'.join(dependentlibs(lib, options.libpaths, func) + [lib])
コード例 #3
0
def iter_symbols(binary):
    ty = get_type(binary)
    # XXX: Static libraries on ELF, MACHO and COFF/PE systems are all
    # ar archives. So technically speaking, the following is wrong
    # but is enough for now. llvm-objdump -t can actually be used on all
    # platforms for static libraries, but its format is different for
    # Windows .obj files, so the following won't work for them, but
    # it currently doesn't matter.
    if ty == UNKNOWN and open(binary).read(8) == '!<arch>\n':
        ty = ELF
    if ty in (ELF, MACHO):
        for line in get_output(buildconfig.substs['LLVM_OBJDUMP'], '-t',
                               binary):
            m = ADDR_RE.match(line)
            if not m:
                continue
            addr = int(m.group(0), 16)
            # The second "column" is 7 one-character items that can be
            # whitespaces. We don't have use for their value, so just skip
            # those.
            rest = line[m.end() + 9:].split()
            # The number of remaining colums will vary between ELF and MACHO.
            # On ELF, we have:
            #   Section Size .hidden? Name
            # On Macho, the size is skipped.
            # In every case, the symbol name is last.
            name = rest[-1]
            if '@' in name:
                name, ver = name.rsplit('@', 1)
                while name.endswith('@'):
                    name = name[:-1]
            else:
                ver = None
            yield {
                'addr': addr,
                'size': int(rest[1], 16) if ty == ELF else 0,
                'name': name,
                'version': ver or None,
            }
    else:
        export_table = False
        for line in get_output(buildconfig.substs['LLVM_OBJDUMP'], '-p',
                               binary):
            if line.strip() == 'Export Table:':
                export_table = True
                continue
            elif not export_table:
                continue

            cols = line.split()
            # The data we're interested in comes in 3 columns, and the first
            # column is a number.
            if len(cols) != 3 or not cols[0].isdigit():
                continue
            _, rva, name = cols
            # - The MSVC mangling has some type info following `@@`
            # - Any namespacing that can happen on the symbol appears as a
            #   suffix, after a `@`.
            # - Mangled symbols are prefixed with `?`.
            name = name.split('@@')[0].split('@')[0].lstrip('?')
            yield {
                'addr': int(rva, 16),
                'size': 0,
                'name': name,
                'version': None,
            }
コード例 #4
0
ファイル: check_binary.py プロジェクト: govage/gecko-dev
def check_nsmodules(target, binary):
    if target is HOST or not is_libxul(binary):
        raise Skip()
    symbols = []
    if buildconfig.substs.get('_MSC_VER'):
        for line in get_output('dumpbin', '-exports', binary):
            data = line.split(None, 3)
            if data and len(data) == 4 and data[0].isdigit() and \
                    ishex(data[1]) and ishex(data[2]):
                # - Some symbols in the table can be aliases, and appear as
                #   `foo = bar`.
                # - The MSVC mangling has some type info following `@@`
                # - Any namespacing that can happen on the symbol appears as a
                #   suffix, after a `@`.
                # - Mangled symbols are prefixed with `?`.
                name = data[3].split(' = ')[0].split('@@')[0].split('@')[0] \
                              .lstrip('?')
                if name.endswith('_NSModule') or name in (
                        '__start_kPStaticModules', '__stop_kPStaticModules'):
                    symbols.append((int(data[2],
                                        16), GUESSED_NSMODULE_SIZE, name))
    else:
        for line in get_output(target['nm'], '-P', binary):
            data = line.split()
            # Some symbols may not have a size listed at all.
            if len(data) == 3:
                data.append('0')
            if len(data) == 4:
                sym, _, addr, size = data
                # NSModules symbols end with _NSModule or _NSModuleE when
                # C++-mangled.
                if sym.endswith(('_NSModule', '_NSModuleE')):
                    # On mac, nm doesn't actually print anything other than 0
                    # for the size. So take our best guess.
                    size = int(size, 16) or GUESSED_NSMODULE_SIZE
                    symbols.append((int(addr, 16), size, sym))
                elif sym.endswith(
                    ('__start_kPStaticModules', '__stop_kPStaticModules')):
                    # On ELF and mac systems, these symbols have no size, such
                    # that the first actual NSModule has the same address as
                    # the start symbol.
                    symbols.append((int(addr, 16), 0, sym))
    if not symbols:
        raise RuntimeError('Could not find NSModules')

    def print_symbols(symbols):
        for addr, size, sym in symbols:
            print('%x %d %s' % (addr, size, sym))

    symbols = sorted(symbols)
    next_addr = None
    # MSVC linker, when doing incremental linking, adds padding when
    # merging sections. Allow there to be more space between the NSModule
    # symbols, as long as they are in the right order.
    if buildconfig.substs.get('_MSC_VER') and \
            buildconfig.substs.get('DEVELOPER_OPTIONS'):
        sym_cmp = lambda guessed, actual: guessed <= actual
    else:
        sym_cmp = lambda guessed, actual: guessed == actual

    for addr, size, sym in symbols:
        if next_addr is not None and not sym_cmp(next_addr, addr):
            print_symbols(symbols)
            raise RuntimeError('NSModules are not adjacent')
        next_addr = addr + size

    # The mac linker doesn't emit the start/stop symbols in the symbol table.
    # We'll just assume it did the job correctly.
    if get_type(binary) == MACHO:
        return

    first = symbols[0][2]
    last = symbols[-1][2]
    # On some platforms, there are extra underscores on symbol names.
    if first.lstrip('_') != 'start_kPStaticModules' or \
            last.lstrip('_') != 'stop_kPStaticModules':
        print_symbols(symbols)
        syms = set(sym for add, size, sym in symbols)
        if 'start_kPStaticModules' not in syms:
            raise RuntimeError('Could not find start_kPStaticModules symbol')
        if 'stop_kPStaticModules' not in syms:
            raise RuntimeError('Could not find stop_kPStaticModules symbol')
        raise RuntimeError('NSModules are not ordered appropriately')
コード例 #5
0
def check_nsmodules(target, binary):
    if target is HOST or not is_libxul(binary):
        raise Skip()
    symbols = []
    for sym in iter_symbols(binary):
        if sym['addr'] == 0:
            continue
        name = sym['name']
        # NSModules symbols end with _NSModule or _NSModuleE when C++-mangled.
        if name.endswith(('_NSModule', '_NSModuleE')):
            # We don't have a valid size in the symbol list for macho and coff.
            # Use our guesstimate.
            size = sym['size'] or GUESSED_NSMODULE_SIZE
            symbols.append((sym['addr'], size, name))
        elif name in ('__start_kPStaticModules', '__stop_kPStaticModules'):
            # For coff, these symbols have a size.
            if get_type(binary) not in (ELF, MACHO):
                size = GUESSED_NSMODULE_SIZE
            else:
                size = 0
            symbols.append((sym['addr'], size, name))
    if not symbols:
        raise RuntimeError('Could not find NSModules')

    def print_symbols(symbols):
        for addr, size, sym in symbols:
            print('%x %d %s' % (addr, size, sym))

    symbols = sorted(symbols)
    next_addr = None
    # MSVC linker, when doing incremental linking, adds padding when
    # merging sections. Allow there to be more space between the NSModule
    # symbols, as long as they are in the right order.
    test_msvc = (buildconfig.substs.get('CC_TYPE') in ('msvc', 'clang-cl') and \
        buildconfig.substs.get('DEVELOPER_OPTIONS'))
    test_clang = (buildconfig.substs.get('CC_TYPE') == 'clang' and \
        buildconfig.substs.get('OS_ARCH') == 'WINNT')
    if test_msvc or test_clang:
        sym_cmp = lambda guessed, actual: guessed <= actual
    else:
        sym_cmp = lambda guessed, actual: guessed == actual

    for addr, size, sym in symbols:
        if next_addr is not None and not sym_cmp(next_addr, addr):
            print_symbols(symbols)
            raise RuntimeError('NSModules are not adjacent')
        next_addr = addr + size

    # The mac linker doesn't emit the start/stop symbols in the symbol table.
    # We'll just assume it did the job correctly.
    if get_type(binary) == MACHO:
        return

    first = symbols[0][2]
    last = symbols[-1][2]
    # On some platforms, there are extra underscores on symbol names.
    if first.lstrip('_') != 'start_kPStaticModules' or \
            last.lstrip('_') != 'stop_kPStaticModules':
        print_symbols(symbols)
        syms = set(sym for add, size, sym in symbols)
        if 'start_kPStaticModules' not in syms:
            raise RuntimeError('Could not find start_kPStaticModules symbol')
        if 'stop_kPStaticModules' not in syms:
            raise RuntimeError('Could not find stop_kPStaticModules symbol')
        raise RuntimeError('NSModules are not ordered appropriately')