#!/usr/bin/env python2.7
# Copyright 2017 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from collections import namedtuple
import elfinfo
import glob
import os

# Copied from //zircon/system/public/zircon/driver/binding.h, which see.
ZIRCON_NOTE_DRIVER = 0x31565244  # DRV1
ZIRCON_DRIVER_IDENT = ('Zircon\0', ZIRCON_NOTE_DRIVER)

LIBCXX_SONAMES = ['libc++.so.2', 'libc++abi.so.1', 'libunwind.so.1']

FUZZER_VARIANT_SUFFIX = '-fuzzer'


def binary_info(filename):
    return elfinfo.get_elf_info(filename, [ZIRCON_DRIVER_IDENT])


def is_driver(info):
    return bool(info.notes)


class variant(namedtuple(
        'variant',
    [
        'shared_toolchain',  # GN toolchain (and thus build dir subdirectory).
        'libprefix',  # Prefix on DT_SONAME string.
        'runtime',  # SONAME of runtime, does not use libprefix.
        'aux',  # List of (file, group) required if this is used.
        'has_libcxx',  # True iff toolchain libraries have this variant.
    ])):

    def matches(self, info, assume=False):
        if self.libprefix and info.interp:
            return info.interp.startswith(self.libprefix)
        if not self.has_libcxx and info.soname in LIBCXX_SONAMES:
            # Variants without their own toolchain libraries wind up placing
            # vanilla toolchain libraries in the variant target lib directory
            # so they should be accepted even though they don't really match.
            return True
        if self.runtime:
            return self.runtime in info.needed or info.soname == self.runtime
        return assume

    def soname_target(self, soname):
        return 'lib/' + self.libprefix + soname


def make_variant(name, info):
    libprefix = ''
    runtime = None
    # All drivers need devhost; it must be in /boot (group 0).
    aux = []
    has_libcxx = False
    if name is None:
        tc = '%s-shared' % info.cpu.gn
    else:
        tc = '%s-%s-shared' % (info.cpu.gn, name)
        libprefix = name + '/'
        if 'asan' in name:
            runtime = 'libclang_rt.asan.so'
            # ASan drivers need devhost.asan.
            aux = [(file + '.asan', group) for file, group in aux]
            has_libcxx = True
        elif 'ubsan' in name or 'sancov' in name:
            runtime = 'libclang_rt.ubsan_standalone.so'
        if name.endswith(FUZZER_VARIANT_SUFFIX):
            # Fuchsia-built fuzzers don't have their own separate libprefix.
            # They just use the base variant.
            libprefix = name[:-len(FUZZER_VARIANT_SUFFIX)] + '/'
        if 'lto' in name:
            # LTO variants don't get their own libprefix like instrumented ones.
            libprefix = ''
    return variant(tc, libprefix, runtime, aux, has_libcxx)


def deduce_aux_variant(info, install_path):
    if info.interp is not None:
        deduce_from = 'lib/' + info.interp
    elif info.soname is not None:
        deduce_from = install_path
    elif 'libclang_rt.asan.so' in info.needed:
        return make_variant('asan', info)
    elif 'libclang_rt.ubsan_standalone.so' in info.needed:
        return make_variant('ubsan', info)
    else:
        return None
    pathelts = deduce_from.split('/')
    assert pathelts[0] == 'lib', (
        "Library expected in lib/, not %r: %r for %r" %
        (deduce_from, info, install_path))
    if len(pathelts) == 2:
        return None
    assert len(pathelts) == 3, (
        "Library expected to be lib/variant/libfoo.so, not %r: %r for %r" %
        (deduce_from, info, install_path))
    return make_variant(pathelts[1], info)


def find_variant(info, install_path, build_dir=os.path.curdir):
    variant = None
    variant_file = None
    abs_build_dir = os.path.abspath(build_dir)
    abs_filename = os.path.abspath(info.filename)
    variant_prefix = info.cpu.gn + '-'
    if abs_filename.startswith(os.path.join(abs_build_dir, info.cpu.gn + '-')):
        # It's in the build directory and points to a file outside of the main
        # toolchain. The file is the actual variant file.
        rel_filename = os.path.relpath(abs_filename, abs_build_dir)
        toolchain_dir = os.path.normpath(rel_filename).split(os.sep)[0]
        name = toolchain_dir[len(variant_prefix):]
        if name != 'shared':
            # loadable_module and driver_module targets are linked
            # to the variant-shared toolchain.
            if name[-7:] == '-shared':
                name = name[:-7]
            variant = make_variant(name, info)
        variant_file = rel_filename
    elif abs_filename.startswith(os.path.join(abs_build_dir, '')):
        # It's in the build directory.  If it's a variant, it's a hard link
        # into the variant toolchain root_out_dir.
        file_stat = os.stat(info.filename)
        if file_stat.st_nlink > 1:
            # Figure out which variant it's linked to.  Non-variant drivers
            # are linked to the -shared toolchain.  We match those as well
            # as actual variants so we'll replace the unadorned filename
            # with its -shared/ version, which is where the lib.unstripped/
            # subdirectory is found.  Below, we'll change the name but not
            # call it a variant.
            rel_filename = os.path.relpath(abs_filename, abs_build_dir)
            subdirs = [
                subdir for subdir in os.listdir(build_dir) if (
                    subdir.startswith(variant_prefix) and
                    os.path.exists(os.path.join(subdir, rel_filename)))
            ]
            files = [os.path.join(subdir, rel_filename) for subdir in subdirs]
            # Rust binaries have multiple links but are not variants.
            # So just ignore a multiply-linked file with no matches.
            if files:
                # A variant loadable_module (or driver_module) is actually
                # built in the variant's -shared toolchain but is also
                # linked to other variant toolchains.
                if (len(subdirs) > 1 and sum(
                        subdir.endswith('-shared') for subdir in subdirs) == 1):
                    [subdir] = [
                        subdir for subdir in subdirs
                        if subdir.endswith('-shared')
                    ]
                else:
                    assert len(files) == 1, (
                        "Multiple hard links to %r: %r" % (info, files))
                    [subdir] = subdirs
                name = subdir[len(variant_prefix):]
                file = os.path.relpath(
                    os.path.join(subdir, rel_filename), build_dir)
                if os.path.samestat(os.stat(file), file_stat):
                    # Ensure that this is actually the same file.
                    variant_file = file
                    if name != 'shared':
                        # loadable_module and driver_module targets are linked
                        # to the variant-shared toolchain.
                        if name[-7:] == '-shared':
                            name = name[:-7]
                        variant = make_variant(name, info)
    else:
        # It's from an auxiliary.
        variant = deduce_aux_variant(info, install_path)
    if variant:
        assert variant.matches(info, True), "%r vs %r" % (variant, info)
        return variant, variant_file
    return make_variant(None, info), variant_file


# Module public API.
__all__ = ['binary_info', 'find_variant', 'variant']


def test_main(build_dir, filenames):
    for filename in filenames:
        info = binary_info(filename)
        print info
        print '  Driver: %r' % is_driver(info)
        print '  %r' % (find_variant(info, None, build_dir),)


# For manual testing.
if __name__ == "__main__":
    import sys
    test_main(sys.argv[1], sys.argv[2:])
