#!/usr/bin/env python3
#
# Copyright (C) 2016 The Android Open Source Project
#
# 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
#
#      http://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.
#

"""utils.py: export utility functions.
"""

from __future__ import annotations
import argparse
from concurrent.futures import Future, ThreadPoolExecutor
from dataclasses import dataclass
import logging
import os
import os.path
from pathlib import Path
import re
import shutil
import subprocess
import sys
import time
from typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Union, TextIO


NDK_ERROR_MESSAGE = "Please install the Android NDK (https://developer.android.com/studio/projects/install-ndk), then set NDK path with --ndk_path option."


def get_script_dir() -> str:
    return os.path.dirname(os.path.realpath(__file__))


def is_windows() -> bool:
    return sys.platform == 'win32' or sys.platform == 'cygwin'


def is_darwin() -> bool:
    return sys.platform == 'darwin'


def get_platform() -> str:
    if is_windows():
        return 'windows'
    if is_darwin():
        return 'darwin'
    return 'linux'


def str_to_bytes(str_value: str) -> bytes:
    # In python 3, str are wide strings whereas the C api expects 8 bit strings,
    # hence we have to convert. For now using utf-8 as the encoding.
    return str_value.encode('utf-8')


def bytes_to_str(bytes_value: Optional[bytes]) -> str:
    if not bytes_value:
        return ''
    return bytes_value.decode('utf-8')


def get_target_binary_path(arch: str, binary_name: str) -> str:
    if arch == 'aarch64':
        arch = 'arm64'
    arch_dir = os.path.join(get_script_dir(), "bin", "android", arch)
    if not os.path.isdir(arch_dir):
        log_fatal("can't find arch directory: %s" % arch_dir)
    binary_path = os.path.join(arch_dir, binary_name)
    if not os.path.isfile(binary_path):
        log_fatal("can't find binary: %s" % binary_path)
    return binary_path


def get_host_binary_path(binary_name: str) -> str:
    dirname = os.path.join(get_script_dir(), 'bin')
    if is_windows():
        if binary_name.endswith('.so'):
            binary_name = binary_name[0:-3] + '.dll'
        elif '.' not in binary_name:
            binary_name += '.exe'
        dirname = os.path.join(dirname, 'windows')
    elif sys.platform == 'darwin':  # OSX
        if binary_name.endswith('.so'):
            binary_name = binary_name[0:-3] + '.dylib'
        dirname = os.path.join(dirname, 'darwin')
    else:
        dirname = os.path.join(dirname, 'linux')
    dirname = os.path.join(dirname, 'x86_64' if sys.maxsize > 2 ** 32 else 'x86')
    binary_path = os.path.join(dirname, binary_name)
    if not os.path.isfile(binary_path):
        log_fatal("can't find binary: %s" % binary_path)
    return binary_path


def is_executable_available(executable: str, option='--help') -> bool:
    """ Run an executable to see if it exists. """
    try:
        subproc = subprocess.Popen([executable, option], stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        subproc.communicate()
        return subproc.returncode == 0
    except OSError:
        return False


class ToolFinder:
    """ Find tools in ndk or sdk. """
    DEFAULT_SDK_PATH = {
        'darwin': 'Library/Android/sdk',
        'linux': 'Android/Sdk',
        'windows': 'AppData/Local/Android/sdk',
    }

    EXPECTED_TOOLS = {
        'adb': {
            'is_binutils': False,
            'test_option': 'version',
            'path_in_sdk': 'platform-tools/adb',
        },
        'llvm-objdump': {
            'is_binutils': False,
            'path_in_ndk':
                lambda platform: 'toolchains/llvm/prebuilt/%s-x86_64/bin/llvm-objdump' % platform,
        },
        'llvm-readelf': {
            'is_binutils': False,
            'path_in_ndk':
                lambda platform: 'toolchains/llvm/prebuilt/%s-x86_64/bin/llvm-readelf' % platform,
        },
        'llvm-symbolizer': {
            'is_binutils': False,
            'path_in_ndk':
                lambda platform: 'toolchains/llvm/prebuilt/%s-x86_64/bin/llvm-symbolizer' % platform,
        },
        'llvm-strip': {
            'is_binutils': False,
            'path_in_ndk':
                lambda platform: 'toolchains/llvm/prebuilt/%s-x86_64/bin/llvm-strip' % platform,
        },
    }

    @classmethod
    def find_ndk_and_sdk_paths(cls, ndk_path: Optional[str] = None
                               ) -> Iterator[Tuple[Optional[str], Optional[str]]]:
        # Use the given ndk path.
        if ndk_path and os.path.isdir(ndk_path):
            ndk_path = os.path.abspath(ndk_path)
            yield ndk_path, cls.find_sdk_path(ndk_path)
        # Find ndk in the parent directory containing simpleperf scripts.
        ndk_path = os.path.dirname(os.path.abspath(get_script_dir()))
        yield ndk_path, cls.find_sdk_path(ndk_path)
        # Find ndk in the default sdk installation path.
        if is_windows():
            home = os.environ.get('HOMEDRIVE') + os.environ.get('HOMEPATH')
        else:
            home = os.environ.get('HOME')
        if home:
            platform = get_platform()
            sdk_path = os.path.join(home, cls.DEFAULT_SDK_PATH[platform].replace('/', os.sep))
            if os.path.isdir(sdk_path):
                path = os.path.join(sdk_path, 'ndk')
                if os.path.isdir(path):
                    # Android Studio can install multiple ndk versions in 'ndk'.
                    # Find the newest one.
                    ndk_version = None
                    for name in os.listdir(path):
                        if not ndk_version or ndk_version < name:
                            ndk_version = name
                    if ndk_version:
                        yield os.path.join(path, ndk_version), sdk_path
            ndk_path = os.path.join(sdk_path, 'ndk-bundle')
            if os.path.isdir(ndk_path):
                yield ndk_path, sdk_path

    @classmethod
    def find_sdk_path(cls, ndk_path: str) -> Optional[str]:
        path = ndk_path
        for _ in range(2):
            path = os.path.dirname(path)
            if os.path.isdir(os.path.join(path, 'platform-tools')):
                return path
        return None

    @classmethod
    def _get_binutils_path_in_ndk(cls, toolname: str, arch: Optional[str], platform: str
                                  ) -> Tuple[str, str]:
        if not arch:
            arch = 'arm64'
        if arch == 'arm64':
            name = 'aarch64-linux-android-' + toolname
        elif arch == 'arm':
            name = 'arm-linux-androideabi-' + toolname
        elif arch == 'x86_64':
            name = 'x86_64-linux-android-' + toolname
        elif arch == 'x86':
            name = 'i686-linux-android-' + toolname
        else:
            log_fatal('unexpected arch %s' % arch)
        path = 'toolchains/llvm/prebuilt/%s-x86_64/bin/%s' % (platform, name)
        return (name, path)

    @classmethod
    def find_tool_path(cls, toolname: str, ndk_path: Optional[str] = None,
                       arch: Optional[str] = None) -> Optional[str]:
        tool_info = cls.EXPECTED_TOOLS.get(toolname)
        if not tool_info:
            return None

        is_binutils = tool_info['is_binutils']
        test_option = tool_info.get('test_option', '--help')
        platform = get_platform()

        # Find tool in clang prebuilts in Android platform.
        if toolname.startswith('llvm-') and platform == 'linux' and get_script_dir().endswith(
                'system/extras/simpleperf/scripts'):
            path = str(
                Path(get_script_dir()).parents[3] / 'prebuilts' / 'clang' / 'host' / 'linux-x86' /
                'llvm-binutils-stable' / toolname)
            if is_executable_available(path, test_option):
                return path

        # Find tool in NDK or SDK.
        path_in_ndk = None
        path_in_sdk = None
        if is_binutils:
            toolname_with_arch, path_in_ndk = cls._get_binutils_path_in_ndk(
                toolname, arch, platform)
        else:
            toolname_with_arch = toolname
            if 'path_in_ndk' in tool_info:
                path_in_ndk = tool_info['path_in_ndk'](platform)
            elif 'path_in_sdk' in tool_info:
                path_in_sdk = tool_info['path_in_sdk']
        if path_in_ndk:
            path_in_ndk = path_in_ndk.replace('/', os.sep)
        elif path_in_sdk:
            path_in_sdk = path_in_sdk.replace('/', os.sep)

        for ndk_dir, sdk_dir in cls.find_ndk_and_sdk_paths(ndk_path):
            if path_in_ndk and ndk_dir:
                path = os.path.join(ndk_dir, path_in_ndk)
                if is_executable_available(path, test_option):
                    return path
            elif path_in_sdk and sdk_dir:
                path = os.path.join(sdk_dir, path_in_sdk)
                if is_executable_available(path, test_option):
                    return path

        # Find tool in $PATH.
        if is_executable_available(toolname_with_arch, test_option):
            return toolname_with_arch

        # Find tool without arch in $PATH.
        if is_binutils and tool_info.get('accept_tool_without_arch'):
            if is_executable_available(toolname, test_option):
                return toolname
        return None


class AdbHelper(object):
    def __init__(self, enable_switch_to_root: bool = True):
        adb_path = ToolFinder.find_tool_path('adb')
        if not adb_path:
            log_exit("Can't find adb in PATH environment.")
        self.adb_path: str = adb_path
        self.enable_switch_to_root = enable_switch_to_root
        self.serial_number: Optional[str] = None

    def is_device_available(self) -> bool:
        return self.run_and_return_output(['shell', 'whoami'])[0]

    def run(self, adb_args: List[str], log_output: bool = False, log_stderr: bool = False) -> bool:
        return self.run_and_return_output(adb_args, log_output, log_stderr)[0]

    def run_and_return_output(self, adb_args: List[str], log_output: bool = False,
                              log_stderr: bool = False) -> Tuple[bool, str]:
        adb_args = [self.adb_path] + adb_args
        logging.debug('run adb cmd: %s' % adb_args)
        env = None
        if self.serial_number:
            env = os.environ.copy()
            env['ANDROID_SERIAL'] = self.serial_number
        subproc = subprocess.Popen(
            adb_args, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout_data, stderr_data = subproc.communicate()
        stdout_data = bytes_to_str(stdout_data)
        stderr_data = bytes_to_str(stderr_data)
        returncode = subproc.returncode
        result = (returncode == 0)
        if log_output and stdout_data:
            logging.debug(stdout_data)
        if log_stderr and stderr_data:
            logging.warning(stderr_data)
        logging.debug('run adb cmd: %s  [result %s]' % (adb_args, result))
        return (result, stdout_data)

    def check_run(self, adb_args: List[str], log_output: bool = False):
        self.check_run_and_return_output(adb_args, log_output)

    def check_run_and_return_output(self, adb_args: List[str], log_output: bool = False,
                                    log_stderr: bool = False) -> str:
        result, stdoutdata = self.run_and_return_output(adb_args, log_output, True)
        if not result:
            log_exit('run "adb %s" failed: %s' % (adb_args, stdoutdata))
        return stdoutdata

    def _unroot(self):
        result, stdoutdata = self.run_and_return_output(['shell', 'whoami'])
        if not result:
            return
        if 'root' not in stdoutdata:
            return
        logging.info('unroot adb')
        self.run(['unroot'])
        time.sleep(1)
        self.run(['wait-for-device'])

    def switch_to_root(self) -> bool:
        if not self.enable_switch_to_root:
            self._unroot()
            return False
        result, stdoutdata = self.run_and_return_output(['shell', 'whoami'])
        if not result:
            return False
        if 'root' in stdoutdata:
            return True
        build_type = self.get_property('ro.build.type')
        if build_type == 'user':
            return False
        self.run(['root'])
        time.sleep(1)
        self.run(['wait-for-device'])
        result, stdoutdata = self.run_and_return_output(['shell', 'whoami'])
        return result and 'root' in stdoutdata

    def get_property(self, name: str) -> Optional[str]:
        result, stdoutdata = self.run_and_return_output(['shell', 'getprop', name])
        return stdoutdata.strip() if result else None

    def set_property(self, name: str, value: str) -> bool:
        return self.run(['shell', 'setprop', name, value])

    def get_device_arch(self) -> str:
        output = self.check_run_and_return_output(['shell', 'uname', '-m'])
        if 'aarch64' in output:
            return 'arm64'
        if 'arm' in output:
            return 'arm'
        if 'x86_64' in output:
            return 'x86_64'
        if '86' in output:
            return 'x86'
        if 'riscv64' in output:
            return 'riscv64'
        log_fatal('unsupported architecture: %s' % output.strip())
        return ''

    def get_android_version(self) -> int:
        """ Get Android version on device, like 7 is for Android N, 8 is for Android O."""
        build_version = self.get_property('ro.build.version.codename')
        if not build_version or build_version == 'REL':
            build_version = self.get_property('ro.build.version.release')
        android_version = 0
        if build_version:
            if build_version[0].isdigit():
                i = 1
                while i < len(build_version) and build_version[i].isdigit():
                    i += 1
                android_version = int(build_version[:i])
            else:
                c = build_version[0].upper()
                if c.isupper() and c >= 'L':
                    android_version = ord(c) - ord('L') + 5
        return android_version


def flatten_arg_list(arg_list: List[List[str]]) -> List[str]:
    res = []
    if arg_list:
        for items in arg_list:
            res += items
    return res


def remove(dir_or_file: Union[Path, str]):
    if os.path.isfile(dir_or_file):
        os.remove(dir_or_file)
    elif os.path.isdir(dir_or_file):
        shutil.rmtree(dir_or_file, ignore_errors=True)


def open_report_in_browser(report_path: str):
    if is_darwin():
        # On darwin 10.12.6, webbrowser can't open browser, so try `open` cmd first.
        try:
            subprocess.check_call(['open', report_path])
            return
        except subprocess.CalledProcessError:
            pass
    import webbrowser
    try:
        # Try to open the report with Chrome
        browser = webbrowser.get('google-chrome')
        browser.open(report_path, new=0, autoraise=True)
    except webbrowser.Error:
        # webbrowser.get() doesn't work well on darwin/windows.
        webbrowser.open_new_tab(report_path)


class BinaryFinder:
    def __init__(self, binary_cache_dir: Optional[Union[Path, str]], readelf: ReadElf):
        if isinstance(binary_cache_dir, str):
            binary_cache_dir = Path(binary_cache_dir)
        self.binary_cache_dir = binary_cache_dir
        self.readelf = readelf
        self.build_id_map = self._load_build_id_map()

    def _load_build_id_map(self) -> Dict[str, Path]:
        build_id_map: Dict[str, Path] = {}
        if self.binary_cache_dir:
            build_id_list_file = self.binary_cache_dir / 'build_id_list'
            if build_id_list_file.is_file():
                with open(self.binary_cache_dir / 'build_id_list', 'rb') as fh:
                    for line in fh.readlines():
                        # lines are in format "<build_id>=<path_in_binary_cache>".
                        items = bytes_to_str(line).strip().split('=')
                        if len(items) == 2:
                            build_id_map[items[0]] = self.binary_cache_dir / items[1]
        return build_id_map

    def find_binary(self, dso_path_in_record_file: str,
                    expected_build_id: Optional[str]) -> Optional[Path]:
        """ If expected_build_id is None, don't check build id.
            Otherwise, the build id of the found binary should match the expected one."""
        # Find binary from build id map.
        if expected_build_id:
            path = self.build_id_map.get(expected_build_id)
            if path and self._check_path(path, expected_build_id):
                return path
        # Find binary by path in binary cache.
        if self.binary_cache_dir:
            path = self.binary_cache_dir / dso_path_in_record_file[1:].replace('/', os.sep)
            if self._check_path(path, expected_build_id):
                return path
        # Find binary by its absolute path.
        path = Path(dso_path_in_record_file)
        if self._check_path(path, expected_build_id):
            return path
        return None

    def _check_path(self, path: Path, expected_build_id: Optional[str]) -> bool:
        if not self.readelf.is_elf_file(path):
            return False
        if expected_build_id is not None:
            return self.readelf.get_build_id(path) == expected_build_id
        return True


class Addr2Nearestline(object):
    """ Use llvm-symbolizer to convert (dso_path, func_addr, addr) to (source_file, line).
        For instructions generated by C++ compilers without a matching statement in source code
        (like stack corruption check, switch optimization, etc.), addr2line can't generate
        line information. However, we want to assign the instruction to the nearest line before
        the instruction (just like objdump -dl). So we use below strategy:
        Instead of finding the exact line of the instruction in an address, we find the nearest
        line to the instruction in an address. If an address doesn't have a line info, we find
        the line info of address - 1. If still no line info, then use address - 2, address - 3,
        etc.

        The implementation steps are as below:
        1. Collect all (dso_path, func_addr, addr) requests before converting. This saves the
        times to call addr2line.
        2. Convert addrs to (source_file, line) pairs for each dso_path as below:
          2.1 Check if the dso_path has .debug_line. If not, omit its conversion.
          2.2 Get arch of the dso_path, and decide the addr_step for it. addr_step is the step we
          change addr each time. For example, since instructions of arm64 are all 4 bytes long,
          addr_step for arm64 can be 4.
          2.3 Use addr2line to find line info for each addr in the dso_path.
          2.4 For each addr without line info, use addr2line to find line info for
              range(addr - addr_step, addr - addr_step * 4 - 1, -addr_step).
          2.5 For each addr without line info, use addr2line to find line info for
              range(addr - addr_step * 5, addr - addr_step * 128 - 1, -addr_step).
              (128 is a guess number. A nested switch statement in
               system/core/demangle/Demangler.cpp has >300 bytes without line info in arm64.)
    """
    class Dso(object):
        """ Info of a dynamic shared library.
            addrs: a map from address to Addr object in this dso.
        """

        def __init__(self, build_id: Optional[str]):
            self.build_id = build_id
            self.addrs: Dict[int, Addr2Nearestline.Addr] = {}
            # Saving file names for each addr takes a lot of memory. So we store file ids in Addr,
            # and provide data structures connecting file id and file name here.
            self.file_name_to_id: Dict[str, int] = {}
            self.file_id_to_name: List[str] = []
            self.func_name_to_id: Dict[str, int] = {}
            self.func_id_to_name: List[str] = []

        def get_file_id(self, file_path: str) -> int:
            file_id = self.file_name_to_id.get(file_path)
            if file_id is None:
                file_id = self.file_name_to_id[file_path] = len(self.file_id_to_name)
                self.file_id_to_name.append(file_path)
            return file_id

        def get_func_id(self, func_name: str) -> int:
            func_id = self.func_name_to_id.get(func_name)
            if func_id is None:
                func_id = self.func_name_to_id[func_name] = len(self.func_id_to_name)
                self.func_id_to_name.append(func_name)
            return func_id

    class Addr(object):
        """ Info of an addr request.
            func_addr: start_addr of the function containing addr.
            source_lines: a list of [file_id, line_number] for addr.
                          source_lines[:-1] are all for inlined functions.
        """

        def __init__(self, func_addr: int):
            self.func_addr = func_addr
            self.source_lines: Optional[List[int, int]] = None

    def __init__(
            self, ndk_path: Optional[str],
            binary_finder: BinaryFinder, with_function_name: bool):
        self.symbolizer_path = ToolFinder.find_tool_path('llvm-symbolizer', ndk_path)
        if not self.symbolizer_path:
            log_exit("Can't find llvm-symbolizer. " + NDK_ERROR_MESSAGE)
        self.readelf = ReadElf(ndk_path)
        self.dso_map: Dict[str, Addr2Nearestline.Dso] = {}  # map from dso_path to Dso.
        self.binary_finder = binary_finder
        self.with_function_name = with_function_name

    def add_addr(self, dso_path: str, build_id: Optional[str], func_addr: int, addr: int):
        dso = self.dso_map.get(dso_path)
        if dso is None:
            dso = self.dso_map[dso_path] = self.Dso(build_id)
        if addr not in dso.addrs:
            dso.addrs[addr] = self.Addr(func_addr)

    def convert_addrs_to_lines(self, jobs: int):
        with ThreadPoolExecutor(jobs) as executor:
            futures: List[Future] = []
            for dso_path, dso in self.dso_map.items():
                futures.append(executor.submit(self._convert_addrs_in_one_dso, dso_path, dso))
            for future in futures:
                # Call future.result() to report exceptions raised in the executor.
                future.result()

    def _convert_addrs_in_one_dso(self, dso_path: str, dso: Addr2Nearestline.Dso):
        real_path = self.binary_finder.find_binary(dso_path, dso.build_id)
        if not real_path:
            if dso_path not in ['//anon', 'unknown', '[kernel.kallsyms]']:
                logging.debug("Can't find dso %s" % dso_path)
            return

        if not self._check_debug_line_section(real_path):
            logging.debug("file %s doesn't contain .debug_line section." % real_path)
            return

        addr_step = self._get_addr_step(real_path)
        self._collect_line_info(dso, real_path, [0])
        self._collect_line_info(dso, real_path, range(-addr_step, -addr_step * 4 - 1, -addr_step))
        self._collect_line_info(dso, real_path,
                                range(-addr_step * 5, -addr_step * 128 - 1, -addr_step))

    def _check_debug_line_section(self, real_path: Path) -> bool:
        return '.debug_line' in self.readelf.get_sections(real_path)

    def _get_addr_step(self, real_path: Path) -> int:
        arch = self.readelf.get_arch(real_path)
        if arch == 'arm64':
            return 4
        if arch == 'arm':
            return 2
        return 1

    def _collect_line_info(
            self, dso: Addr2Nearestline.Dso, real_path: Path, addr_shifts: List[int]):
        """ Use addr2line to get line info in a dso, with given addr shifts. """
        # 1. Collect addrs to send to addr2line.
        addr_set: Set[int] = set()
        for addr in dso.addrs:
            addr_obj = dso.addrs[addr]
            if addr_obj.source_lines:  # already has source line, no need to search.
                continue
            for shift in addr_shifts:
                # The addr after shift shouldn't change to another function.
                shifted_addr = max(addr + shift, addr_obj.func_addr)
                addr_set.add(shifted_addr)
                if shifted_addr == addr_obj.func_addr:
                    break
        if not addr_set:
            return
        addr_request = '\n'.join(['0x%x' % addr for addr in sorted(addr_set)])

        # 2. Use addr2line to collect line info.
        try:
            subproc = subprocess.Popen(self._build_symbolizer_args(real_path),
                                       stdin=subprocess.PIPE, stdout=subprocess.PIPE)
            (stdoutdata, _) = subproc.communicate(str_to_bytes(addr_request))
            stdoutdata = bytes_to_str(stdoutdata)
        except OSError:
            return
        addr_map = self.parse_line_output(stdoutdata, dso)

        # 3. Fill line info in dso.addrs.
        for addr in dso.addrs:
            addr_obj = dso.addrs[addr]
            if addr_obj.source_lines:
                continue
            for shift in addr_shifts:
                shifted_addr = max(addr + shift, addr_obj.func_addr)
                lines = addr_map.get(shifted_addr)
                if lines:
                    addr_obj.source_lines = lines
                    break
                if shifted_addr == addr_obj.func_addr:
                    break

    def _build_symbolizer_args(self, binary_path: Path) -> List[str]:
        args = [self.symbolizer_path, '--print-address', '--inlining', '--obj=%s' % binary_path]
        if self.with_function_name:
            args += ['--functions=linkage', '--demangle']
        else:
            args.append('--functions=none')
        return args

    def parse_line_output(self, output: str, dso: Addr2Nearestline.Dso) -> Dict[int,
                                                                                List[Tuple[int]]]:
        """
        The output is a list of lines.
            address1
            function_name1 (the function name can be empty)
            source_location1
            function_name2
            source_location2
            ...
            (end with empty line)
        """

        addr_map: Dict[int, List[Tuple[int]]] = {}
        lines = output.strip().splitlines()
        i = 0
        while i < len(lines):
            address = self._parse_line_output_address(lines[i])
            i += 1
            if address is None:
                continue
            info = []
            while i < len(lines):
                if self.with_function_name:
                    if i + 1 == len(lines):
                        break
                    function_name = lines[i].strip()
                    if not function_name and (':' not in lines[i+1]):
                        # no more frames
                        break
                    i += 1
                elif not lines[i]:
                    i += 1
                    break

                file_path, line_number = self._parse_line_output_source_location(lines[i])
                i += 1
                if not file_path or not line_number:
                    # An addr can have a list of (file, line), when the addr belongs to an inlined
                    # function. Sometimes only part of the list has ? mark. In this case, we think
                    # the line info is valid if the first line doesn't have ? mark.
                    if not info:
                        break
                    continue
                file_id = dso.get_file_id(file_path)
                if self.with_function_name:
                    func_id = dso.get_func_id(function_name)
                    info.append((file_id, line_number, func_id))
                else:
                    info.append((file_id, line_number))
            if info:
                addr_map[address] = info
        return addr_map

    def _parse_line_output_address(self, output: str) -> Optional[int]:
        if output.startswith('0x'):
            return int(output, 16)
        return None

    def _parse_line_output_source_location(self, line: str) -> Tuple[Optional[str], Optional[int]]:
        file_path, line_number = None, None
        # Handle lines in format filename:line:column, like "runtest/two_functions.cpp:14:25".
        # Filename may contain ':' like "C:\Users\...\file".
        items = line.rsplit(':', 2)
        if len(items) == 3:
            file_path, line_number = items[:2]
        if not file_path or ('?' in file_path) or not line_number or ('?' in line_number):
            return None, None
        try:
            line_number = int(line_number)
        except ValueError:
            return None, None
        return file_path, line_number

    def get_dso(self, dso_path: str) -> Addr2Nearestline.Dso:
        return self.dso_map.get(dso_path)

    def get_addr_source(self, dso: Addr2Nearestline.Dso, addr: int) -> Optional[List[Tuple[int]]]:
        source = dso.addrs[addr].source_lines
        if source is None:
            return None
        if self.with_function_name:
            return [(dso.file_id_to_name[file_id], line, dso.func_id_to_name[func_id])
                    for (file_id, line, func_id) in source]
        return [(dso.file_id_to_name[file_id], line) for (file_id, line) in source]


class SourceFileSearcher(object):
    """ Find source file paths in the file system.
        The file paths reported by addr2line are the paths stored in debug sections
        of shared libraries. And we need to convert them to file paths in the file
        system. It is done in below steps:
        1. Collect all file paths under the provided source_dirs. The suffix of a
           source file should contain one of below:
            h: for C/C++ header files.
            c: for C/C++ source files.
            java: for Java source files.
            kt: for Kotlin source files.
        2. Given an abstract_path reported by addr2line, select the best real path
           as below:
           2.1 Find all real paths with the same file name as the abstract path.
           2.2 Select the real path having the longest common suffix with the abstract path.
    """

    SOURCE_FILE_EXTS = {'.h', '.hh', '.H', '.hxx', '.hpp', '.h++',
                        '.c', '.cc', '.C', '.cxx', '.cpp', '.c++',
                        '.java', '.kt'}

    @classmethod
    def is_source_filename(cls, filename: str) -> bool:
        ext = os.path.splitext(filename)[1]
        return ext in cls.SOURCE_FILE_EXTS

    def __init__(self, source_dirs: List[str]):
        # Map from filename to a list of reversed directory path containing filename.
        self.filename_to_rparents: Dict[str, List[str]] = {}
        self._collect_paths(source_dirs)

    def _collect_paths(self, source_dirs: List[str]):
        for source_dir in source_dirs:
            for parent, _, file_names in os.walk(source_dir):
                rparent = None
                for file_name in file_names:
                    if self.is_source_filename(file_name):
                        rparents = self.filename_to_rparents.get(file_name)
                        if rparents is None:
                            rparents = self.filename_to_rparents[file_name] = []
                        if rparent is None:
                            rparent = parent[::-1]
                        rparents.append(rparent)

    def get_real_path(self, abstract_path: str) -> Optional[str]:
        abstract_path = abstract_path.replace('/', os.sep)
        abstract_parent, file_name = os.path.split(abstract_path)
        abstract_rparent = abstract_parent[::-1]
        real_rparents = self.filename_to_rparents.get(file_name)
        if real_rparents is None:
            return None
        best_matched_rparent = None
        best_common_length = -1
        for real_rparent in real_rparents:
            length = len(os.path.commonprefix((real_rparent, abstract_rparent)))
            if length > best_common_length:
                best_common_length = length
                best_matched_rparent = real_rparent
        if best_matched_rparent is None:
            return None
        return os.path.join(best_matched_rparent[::-1], file_name)


class AddrRange:
    def __init__(self, start: int, len: int):
        self.start = start
        self.len = len

    @property
    def end(self) -> int:
        return self.start + self.len

    def is_in_range(self, addr: int) -> bool:
        return addr >= self.start and addr < self.end


class Disassembly:
    def __init__(self):
        self.lines: List[Tuple[str, int]] = []


class Objdump(object):
    """ A wrapper of objdump to disassemble code. """

    def __init__(self, ndk_path: Optional[str], binary_finder: BinaryFinder):
        self.ndk_path = ndk_path
        self.binary_finder = binary_finder
        self.readelf = ReadElf(ndk_path)
        self.objdump_paths: Dict[str, str] = {}

    def get_dso_info(self, dso_path: str, expected_build_id: Optional[str]
                     ) -> Optional[Tuple[str, str]]:
        real_path = self.binary_finder.find_binary(dso_path, expected_build_id)
        if not real_path:
            return None
        arch = self.readelf.get_arch(real_path)
        if arch == 'unknown':
            return None
        return (str(real_path), arch)

    def disassemble_function(self, dso_info, addr_range: AddrRange) -> Optional[Disassembly]:
        """ Disassemble code for an addr range in a binary.
        """
        real_path, arch = dso_info
        objdump_path = self.objdump_paths.get(arch)
        if not objdump_path:
            objdump_path = ToolFinder.find_tool_path('llvm-objdump', self.ndk_path, arch)
            if not objdump_path:
                log_exit("Can't find llvm-objdump." + NDK_ERROR_MESSAGE)
            self.objdump_paths[arch] = objdump_path

        # Run objdump.
        args = [objdump_path, '-dlC', '--no-show-raw-insn',
                '--start-address=0x%x' % addr_range.start,
                '--stop-address=0x%x' % (addr_range.end),
                real_path]
        if arch == 'arm' and 'llvm-objdump' in objdump_path:
            args += ['--print-imm-hex']
        try:
            subproc = subprocess.Popen(args, stdout=subprocess.PIPE)
            (stdoutdata, _) = subproc.communicate()
            stdoutdata = bytes_to_str(stdoutdata)
        except OSError:
            return None

        if not stdoutdata:
            return None
        result = Disassembly()
        for line in stdoutdata.split('\n'):
            line = line.rstrip()  # Remove '\r' on Windows.
            items = line.split(':', 1)
            try:
                addr = int(items[0], 16)
            except ValueError:
                addr = 0
            result.lines.append((line, addr))
        return result

    def disassemble_functions(self, dso_info, sorted_addr_ranges: List[AddrRange]
                              ) -> Optional[List[Disassembly]]:
        """ Disassemble code for multiple addr ranges in a binary. sorted_addr_ranges should be
            sorted by addr_range.start.
        """
        if not sorted_addr_ranges:
            return []
        real_path, arch = dso_info
        objdump_path = self.objdump_paths.get(arch)
        if not objdump_path:
            objdump_path = ToolFinder.find_tool_path('llvm-objdump', self.ndk_path, arch)
            if not objdump_path:
                log_exit("Can't find llvm-objdump." + NDK_ERROR_MESSAGE)
            self.objdump_paths[arch] = objdump_path

        # Run objdump.
        start_addr = sorted_addr_ranges[0].start
        stop_addr = max(addr_range.end for addr_range in sorted_addr_ranges)
        args = [objdump_path, '-dlC', '--no-show-raw-insn',
                '--start-address=0x%x' % start_addr,
                '--stop-address=0x%x' % stop_addr,
                real_path]
        if arch == 'arm' and 'llvm-objdump' in objdump_path:
            args += ['--print-imm-hex']
        try:
            proc = subprocess.Popen(args, stdout=subprocess.PIPE, text=True)
            result = self._parse_disassembly_for_functions(proc.stdout, sorted_addr_ranges)
            proc.wait()
        except OSError:
            return None
        return result

    def _parse_disassembly_for_functions(self, fh: TextIO, sorted_addr_ranges: List[AddrRange]) -> Optional[List[Disassembly]]:
        current_id = 0
        in_range = False
        result = [Disassembly() for _ in sorted_addr_ranges]
        while True:
            line = fh.readline()
            if not line:
                break
            line = line.rstrip()  # Remove '\r\n'.
            addr = self._get_addr_from_disassembly_line(line)
            if current_id >= len(sorted_addr_ranges):
                continue
            if addr:
                if in_range and not sorted_addr_ranges[current_id].is_in_range(addr):
                    in_range = False
                if not in_range:
                    # Skip addr ranges before the current address.
                    while current_id < len(sorted_addr_ranges) and sorted_addr_ranges[current_id].end <= addr:
                        current_id += 1
                    if current_id < len(sorted_addr_ranges) and sorted_addr_ranges[current_id].is_in_range(addr):
                        in_range = True
            if in_range:
                result[current_id].lines.append((line, addr))
        return result

    def _get_addr_from_disassembly_line(self, line: str) -> int:
        # line may be an instruction, like: " 24a469c: stp x29, x30, [sp, #-0x60]!" or
        #  "ffffffc0085d9664:      	paciasp".
        # line may be a function start point, like "00000000024a4698 <DoWork()>:".
        items = line.strip().split()
        if not items:
            return 0
        s = items[0]
        if s.endswith(':'):
            s = s[:-1]
        try:
            return int(s, 16)
        except ValueError:
            return 0


class ReadElf(object):
    """ A wrapper of readelf. """

    def __init__(self, ndk_path: Optional[str]):
        self.readelf_path = ToolFinder.find_tool_path('llvm-readelf', ndk_path)
        if not self.readelf_path:
            log_exit("Can't find llvm-readelf. " + NDK_ERROR_MESSAGE)

    @staticmethod
    def is_elf_file(path: Union[Path, str]) -> bool:
        if os.path.isfile(path):
            with open(path, 'rb') as fh:
                return fh.read(4) == b'\x7fELF'
        return False

    def get_arch(self, elf_file_path: Union[Path, str]) -> str:
        """ Get arch of an elf file. """
        if self.is_elf_file(elf_file_path):
            try:
                output = subprocess.check_output([self.readelf_path, '-h', str(elf_file_path)])
                output = bytes_to_str(output)
                if output.find('AArch64') != -1:
                    return 'arm64'
                if output.find('ARM') != -1:
                    return 'arm'
                if output.find('X86-64') != -1:
                    return 'x86_64'
                if output.find('80386') != -1:
                    return 'x86'
                if output.find('RISC-V') != -1:
                    return 'riscv64'
            except subprocess.CalledProcessError:
                pass
        return 'unknown'

    def get_build_id(self, elf_file_path: Union[Path, str], with_padding=True) -> str:
        """ Get build id of an elf file. """
        if self.is_elf_file(elf_file_path):
            try:
                output = subprocess.check_output([self.readelf_path, '-n', str(elf_file_path)])
                output = bytes_to_str(output)
                result = re.search(r'Build ID:\s*(\S+)', output)
                if result:
                    build_id = result.group(1)
                    if with_padding:
                        build_id = self.pad_build_id(build_id)
                    return build_id
            except subprocess.CalledProcessError:
                pass
        return ""

    @staticmethod
    def pad_build_id(build_id: str) -> str:
        """ Pad build id to 40 hex numbers (20 bytes). """
        if len(build_id) < 40:
            build_id += '0' * (40 - len(build_id))
        else:
            build_id = build_id[:40]
        return '0x' + build_id

    @staticmethod
    def unpad_build_id(build_id: str) -> str:
        if build_id.startswith('0x'):
            build_id = build_id[2:]
            # Unpad build id as TrimZeroesFromBuildIDString() in quipper.
            padding = '0' * 8
            while build_id.endswith(padding):
                build_id = build_id[:-len(padding)]
        return build_id

    def get_sections(self, elf_file_path: Union[Path, str]) -> List[str]:
        """ Get sections of an elf file. """
        section_names: List[str] = []
        if self.is_elf_file(elf_file_path):
            try:
                output = subprocess.check_output([self.readelf_path, '-SW', str(elf_file_path)])
                output = bytes_to_str(output)
                for line in output.split('\n'):
                    # Parse line like:" [ 1] .note.android.ident NOTE  0000000000400190 ...".
                    result = re.search(r'^\s+\[\s*\d+\]\s(.+?)\s', line)
                    if result:
                        section_name = result.group(1).strip()
                        if section_name:
                            section_names.append(section_name)
            except subprocess.CalledProcessError:
                pass
        return section_names


def extant_dir(arg: str) -> str:
    """ArgumentParser type that only accepts extant directories.

    Args:
        arg: The string argument given on the command line.
    Returns: The argument as a realpath.
    Raises:
        argparse.ArgumentTypeError: The given path isn't a directory.
    """
    path = os.path.realpath(arg)
    if not os.path.isdir(path):
        raise argparse.ArgumentTypeError('{} is not a directory.'.format(path))
    return path


def extant_file(arg: str) -> str:
    """ArgumentParser type that only accepts extant files.

    Args:
        arg: The string argument given on the command line.
    Returns: The argument as a realpath.
    Raises:
        argparse.ArgumentTypeError: The given path isn't a file.
    """
    path = os.path.realpath(arg)
    if not os.path.isfile(path):
        raise argparse.ArgumentTypeError('{} is not a file.'.format(path))
    return path


def log_fatal(msg: str):
    raise Exception(msg)


def log_exit(msg: str):
    sys.exit(msg)


class LogFormatter(logging.Formatter):
    """ Use custom logging format. """

    def __init__(self):
        super().__init__('%(asctime)s [%(levelname)s] (%(filename)s:%(lineno)d) %(message)s')

    def formatTime(self, record, datefmt):
        return super().formatTime(record, '%H:%M:%S') + ',%03d' % record.msecs


class Log:
    initialized = False

    @classmethod
    def init(cls, log_level: str = 'info'):
        assert not cls.initialized
        cls.initialized = True
        cls.logger = logging.root
        cls.logger.setLevel(log_level.upper())
        handler = logging.StreamHandler()
        handler.setFormatter(LogFormatter())
        cls.logger.addHandler(handler)


class ArgParseFormatter(
        argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter):
    pass


@dataclass
class ReportLibOptions:
    show_art_frames: bool
    trace_offcpu: str
    proguard_mapping_files: List[str]
    sample_filters: List[str]
    aggregate_threads: List[str]


class BaseArgumentParser(argparse.ArgumentParser):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs, formatter_class=ArgParseFormatter)
        self.has_sample_filter_options = False
        self.sample_filter_with_pid_shortcut = False
        self.has_report_lib_options = False

    def add_report_lib_options(self, group: Optional[Any] = None,
                               default_show_art_frames: bool = False,
                               sample_filter_group: Optional[Any] = None,
                               sample_filter_with_pid_shortcut: bool = True):
        self.has_report_lib_options = True
        parser = group if group else self
        parser.add_argument(
            '--proguard-mapping-file', nargs='+',
            help='Add proguard mapping file to de-obfuscate symbols')
        parser.add_argument('--show-art-frames', '--show_art_frames',
                            action=argparse.BooleanOptionalAction, default=default_show_art_frames,
                            help='Show frames of internal methods in the ART Java interpreter.')
        parser.add_argument(
            '--trace-offcpu', choices=['on-cpu', 'off-cpu', 'on-off-cpu', 'mixed-on-off-cpu'],
            help="""Set report mode for profiles recorded with --trace-offcpu option. All possible
                    modes are: on-cpu (only on-cpu samples), off-cpu (only off-cpu samples),
                    on-off-cpu (both on-cpu and off-cpu samples, can be split by event name),
                    mixed-on-off-cpu (on-cpu and off-cpu samples using the same event name).
                    If not set, mixed-on-off-cpu mode is used.
                """)
        self._add_sample_filter_options(sample_filter_group, sample_filter_with_pid_shortcut)
        parser.add_argument(
            '--aggregate-threads', nargs='+', metavar='thread_name_regex',
            help="""Aggregate threads with names matching the same regex. As a result, samples from
                    different threads (like a thread pool) can be shown in one flamegraph.
                """)

    def _add_sample_filter_options(
            self, group: Optional[Any] = None, with_pid_shortcut: bool = True):
        if not group:
            group = self.add_argument_group('Sample filter options')
        group.add_argument('--cpu', nargs='+', help="""only include samples for the selected cpus.
                            cpu can be a number like 1, or a range like 0-3""")
        group.add_argument('--exclude-pid', metavar='pid', nargs='+', type=int,
                           help='exclude samples for selected processes')
        group.add_argument('--exclude-tid', metavar='tid', nargs='+', type=int,
                           help='exclude samples for selected threads')
        group.add_argument(
            '--exclude-process-name', metavar='process_name_regex', nargs='+',
            help='exclude samples for processes with name containing the regular expression')
        group.add_argument(
            '--exclude-thread-name', metavar='thread_name_regex', nargs='+',
            help='exclude samples for threads with name containing the regular expression')

        if with_pid_shortcut:
            group.add_argument('--pid', metavar='pid', nargs='+', type=int,
                               help='only include samples for selected processes')
            group.add_argument('--tid', metavar='tid', nargs='+', type=int,
                               help='only include samples for selected threads')
        group.add_argument('--include-pid', metavar='pid', nargs='+', type=int,
                           help='only include samples for selected processes')
        group.add_argument('--include-tid', metavar='tid', nargs='+', type=int,
                           help='only include samples for selected threads')
        group.add_argument(
            '--include-process-name', metavar='process_name_regex', nargs='+',
            help='only include samples for processes with name containing the regular expression')
        group.add_argument(
            '--comm', '--include-thread-name', metavar='thread_name_regex',
            dest='include_thread_name', nargs='+',
            help='only include samples for threads with name containing the regular expression')
        group.add_argument(
            '--filter-file', metavar='file',
            help='use filter file to filter samples based on timestamps. ' +
            'The file format is in doc/sampler_filter.md.')
        self.has_sample_filter_options = True
        self.sample_filter_with_pid_shortcut = with_pid_shortcut

    def _build_sample_filter(self, args: argparse.Namespace) -> List[str]:
        """ Build sample filters, which can be passed to ReportLib.SetSampleFilter(). """
        filters = []
        if args.cpu:
            filters.extend(['--cpu', ','.join(args.cpu)])
        if args.exclude_pid:
            filters.extend(['--exclude-pid', ','.join(str(pid) for pid in args.exclude_pid)])
        if args.exclude_tid:
            filters.extend(['--exclude-tid', ','.join(str(tid) for tid in args.exclude_tid)])
        if args.exclude_process_name:
            for name in args.exclude_process_name:
                filters.extend(['--exclude-process-name', name])
        if args.exclude_thread_name:
            for name in args.exclude_thread_name:
                filters.extend(['--exclude-thread-name', name])

        if args.include_pid:
            filters.extend(['--include-pid', ','.join(str(pid) for pid in args.include_pid)])
        if args.include_tid:
            filters.extend(['--include-tid', ','.join(str(tid) for tid in args.include_tid)])
        if self.sample_filter_with_pid_shortcut:
            if args.pid:
                filters.extend(['--include-pid', ','.join(str(pid) for pid in args.pid)])
            if args.tid:
                filters.extend(['--include-tid', ','.join(str(pid) for pid in args.tid)])
        if args.include_process_name:
            for name in args.include_process_name:
                filters.extend(['--include-process-name', name])
        if args.include_thread_name:
            for name in args.include_thread_name:
                filters.extend(['--include-thread-name', name])
        if args.filter_file:
            filters.extend(['--filter-file', args.filter_file])
        return filters

    def parse_known_args(self, *args, **kwargs):
        self.add_argument(
            '--log', choices=['debug', 'info', 'warning'],
            default='info', help='set log level')
        namespace, left_args = super().parse_known_args(*args, **kwargs)

        if self.has_report_lib_options:
            sample_filters = self._build_sample_filter(namespace)
            report_lib_options = ReportLibOptions(
                namespace.show_art_frames, namespace.trace_offcpu, namespace.proguard_mapping_file,
                sample_filters, namespace.aggregate_threads)
            setattr(namespace, 'report_lib_options', report_lib_options)

        if not Log.initialized:
            Log.init(namespace.log)
        return namespace, left_args
