#!/usr/bin/env python3
#
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Creates a compressed archive of unstripped binaries cataloged by
"ids.txt"."""

import argparse
import os
import subprocess
import sys
import tarfile


def main(args):
    parser = argparse.ArgumentParser()
    parser.add_argument(
        'ids_txt', type=str, nargs=1, help='Path to ids.txt files.'
    )
    parser.add_argument(
        '-o',
        '--output_tarball',
        nargs=1,
        type=str,
        help='Path which the tarball will be written to.',
    )
    parser.add_argument(
        '--fuchsia-build-id-dir',
        type=str,
        required=True,
        help='Directory containing symbols for SDK prebuilts.',
    )
    args = parser.parse_args(args)

    ids_txt = args.ids_txt[0]
    build_ids_archive = tarfile.open(args.output_tarball[0], 'w:bz2')
    for line in open(ids_txt, 'r'):
        build_id, binary_path = line.strip().split(' ')

        # Look for prebuilt symbols in the SDK first.
        symbol_source_path = os.path.join(
            args.fuchsia_build_id_dir, build_id[:2], build_id[2:] + '.debug'
        )
        if not os.path.exists(symbol_source_path):
            symbol_source_path = os.path.abspath(
                os.path.join(os.path.dirname(ids_txt), binary_path)
            )

            if os.path.getsize(symbol_source_path) == 0:
                # This is a prebuilt which wasn't accompanied by SDK symbols.
                continue

        # Exclude stripped binaries (indicated by their lack of symbol tables).
        readelf_output = subprocess.check_output(
            ['readelf', '-S', symbol_source_path], universal_newlines=True
        )
        if not '.symtab' in readelf_output:
            continue

        # Archive the unstripped ELF binary, placing it in a hierarchy keyed to the
        # GNU build ID. The binary resides in a directory whose name is the first
        # two characters of the build ID, with the binary file itself named after
        # the remaining characters of the build ID. So, a binary file with the build
        # ID "deadbeef" would be located at the path 'de/adbeef.debug'.
        build_ids_archive.add(
            symbol_source_path, '%s/%s.debug' % (build_id[:2], build_id[2:])
        )

    return 0


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
