# Copyright 2021 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Library that parses an ELF file for a GNU build-id."""

import argparse
import logging
from pathlib import Path
import sys
from typing import BinaryIO, Optional
import elftools  # type: ignore
from elftools.elf import elffile, notes, sections  # type: ignore

_LOG = logging.getLogger('build_id_parser')
_PW_BUILD_ID_SYM_NAME = 'gnu_build_id_begin'


class GnuBuildIdError(Exception):
    """An exception raised when a GNU build ID is malformed."""


def read_build_id_from_section(elf_file: BinaryIO) -> Optional[bytes]:
    """Reads a build ID from a .note.gnu.build-id section."""
    parsed_elf_file = elffile.ELFFile(elf_file)
    build_id_section = parsed_elf_file.get_section_by_name(
        '.note.gnu.build-id')

    if build_id_section is None:
        return None

    section_notes = list(n for n in notes.iter_notes(
        parsed_elf_file, build_id_section['sh_offset'],
        build_id_section['sh_size']))

    if len(section_notes) != 1:
        raise GnuBuildIdError('GNU build ID section contains multiple notes')

    build_id_note = section_notes[0]
    if build_id_note['n_name'] != 'GNU':
        raise GnuBuildIdError('GNU build ID note name invalid')

    if build_id_note['n_type'] != 'NT_GNU_BUILD_ID':
        raise GnuBuildIdError('GNU build ID note type invalid')

    return bytes.fromhex(build_id_note['n_desc'])


def _addr_is_in_segment(addr: int, segment) -> bool:
    """Checks if the provided address resides within the provided segment."""
    # Address references uninitialized memory. Can't read.
    if addr >= segment['p_vaddr'] + segment['p_filesz']:
        raise GnuBuildIdError('GNU build ID is runtime-initialized')

    return addr in range(segment['p_vaddr'], segment['p_memsz'])


def _read_build_id_from_offset(elf, offset: int) -> bytes:
    """Attempts to read a GNU build ID from an offset in an elf file."""
    note = elftools.common.utils.struct_parse(elf.structs.Elf_Nhdr,
                                              elf.stream,
                                              stream_pos=offset)
    elf.stream.seek(offset + elf.structs.Elf_Nhdr.sizeof())
    name = elf.stream.read(note['n_namesz'])

    if name != b'GNU\0':
        raise GnuBuildIdError('GNU build ID note name invalid')

    return elf.stream.read(note['n_descsz'])


def read_build_id_from_symbol(elf_file: BinaryIO) -> Optional[bytes]:
    """Reads a GNU build ID using gnu_build_id_begin to locate the data."""
    parsed_elf_file = elffile.ELFFile(elf_file)

    matching_syms = None
    for section in parsed_elf_file.iter_sections():
        if not isinstance(section, sections.SymbolTableSection):
            continue
        matching_syms = section.get_symbol_by_name(_PW_BUILD_ID_SYM_NAME)
        if matching_syms is not None:
            break
    if matching_syms is None:
        return None

    if len(matching_syms) != 1:
        raise GnuBuildIdError('Multiple GNU build ID start symbols defined')

    gnu_build_id_sym = matching_syms[0]
    section_number = gnu_build_id_sym['st_shndx']

    if section_number == 'SHN_UNDEF':
        raise GnuBuildIdError('GNU build ID start symbol undefined')

    matching_section = parsed_elf_file.get_section(section_number)

    build_id_start_addr = gnu_build_id_sym['st_value']
    for segment in parsed_elf_file.iter_segments():
        if segment.section_in_segment(matching_section):
            offset = build_id_start_addr - segment['p_vaddr'] + segment[
                'p_offset']
            return _read_build_id_from_offset(parsed_elf_file, offset)

    return None


def read_build_id(elf_file: BinaryIO) -> Optional[bytes]:
    """Reads a GNU build ID from an ELF binary."""
    # Prefer to read the build ID from a dedicated section.
    maybe_build_id = read_build_id_from_section(elf_file)
    if maybe_build_id is not None:
        return maybe_build_id

    # If there's no dedicated section, try and use symbol information to find
    # the build info.
    return read_build_id_from_symbol(elf_file)


def find_matching_elf(uuid: bytes, search_dir: Path) -> Optional[Path]:
    """Recursively searches a directory for an ELF file with a matching UUID."""
    elf_file_paths = search_dir.glob('**/*.elf')
    for elf_file in elf_file_paths:
        try:
            candidate_id = read_build_id(open(elf_file, 'rb'))
        except GnuBuildIdError:
            continue
        if candidate_id is None:
            continue
        if candidate_id == uuid:
            return elf_file

    return None


def _main(elf_file: BinaryIO) -> int:
    logging.basicConfig(format='%(message)s', level=logging.INFO)
    build_id = read_build_id(elf_file)
    if build_id is None:
        _LOG.error('Error: No GNU build ID found.')
        return 1

    _LOG.info(build_id.hex())
    return 0


def _parse_args():
    """Parses command-line arguments."""

    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('elf_file',
                        type=argparse.FileType('rb'),
                        help='The .elf to parse build info from')

    return parser.parse_args()


if __name__ == '__main__':
    sys.exit(_main(**vars(_parse_args())))
