#!/usr/bin/env python3

# Copyright 2023 Google LLC
# SPDX-License-Identifier: Apache-2.0

"""
Checks the initialization priorities

This script parses the object files in the specified build directory, creates a
list of known devices and their effective initialization priorities and
compares that with the device dependencies inferred from the devicetree
hierarchy.

This can be used to detect devices that are initialized in the incorrect order,
but also devices that are initialized at the same priority but depends on each
other, which can potentially break if the linking order is changed.
"""

import argparse
import logging
import os
import pathlib
import pickle
import sys

from elftools.elf.elffile import ELFFile
from elftools.elf.relocation import RelocationSection
from elftools.elf.sections import SymbolTableSection

# This is needed to load edt.pickle files.
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..",
                                "dts", "python-devicetree", "src"))
from devicetree import edtlib  # pylint: disable=unused-import

# Prefix used for relocation sections containing initialization data, as in
# sequence of "struct init_entry".
_INIT_SECTION_PREFIX = (".rel.z_init_", ".rela.z_init_")

# Prefix used for "struct device" reference initialized based on devicetree
# entries with a known ordinal.
_DEVICE_ORD_PREFIX = "__device_dts_ord_"

# File name suffix for object files to be scanned.
_OBJ_FILE_SUFFIX = ".c.obj"

# Defined init level in order of priority.
_DEVICE_INIT_LEVELS = ["EARLY", "PRE_KERNEL_1", "PRE_KERNEL_2", "POST_KERNEL",
                      "APPLICATION", "SMP"]

# File name to check for detecting and skiping nested build directories.
_BUILD_DIR_DETECT_FILE = "CMakeCache.txt"

# List of compatibles for node where the initialization priority should be the
# opposite of the device tree inferred dependency.
_INVERTED_PRIORITY_COMPATIBLES = frozenset()

class Priority:
    """Parses and holds a device initialization priority.

    Parses an ELF section name for the corresponding initialization level and
    priority, for example ".rel.z_init_PRE_KERNEL_155_" for "PRE_KERNEL_1 55".

    The object can be used for comparing levels with one another.

    Attributes:
        name: the section name
    """
    def __init__(self, name):
        for idx, level in enumerate(_DEVICE_INIT_LEVELS):
            if level in name:
                _, priority = name.strip("_").split(level)
                self._level = idx
                self._priority = int(priority)
                self._level_priority = self._level * 100 + self._priority
                return

        raise ValueError("Unknown level in %s" % name)

    def __repr__(self):
        return "<%s %s %d>" % (self.__class__.__name__,
                               _DEVICE_INIT_LEVELS[self._level], self._priority)

    def __str__(self):
        return "%s %d" % (_DEVICE_INIT_LEVELS[self._level], self._priority)

    def __lt__(self, other):
        return self._level_priority < other._level_priority

    def __eq__(self, other):
        return self._level_priority == other._level_priority

    def __hash__(self):
        return self._level_priority


class ZephyrObjectFile:
    """Load an object file and finds the device defined within it.

    Load an object file and scans the relocation sections looking for the known
    ones containing initialization callbacks. Then finds what device ordinals
    are being initialized at which priority and stores the list internally.

    A dictionary of {ordinal: Priority} is available in the defined_devices
    class variable.

    Attributes:
        file_path: path of the file to be loaded.
    """
    def __init__(self, file_path):
        self.file_path = file_path
        self._elf = ELFFile(open(file_path, "rb"))
        self._load_symbols()
        self._find_defined_devices()

    def _load_symbols(self):
        """Initialize the symbols table."""
        self._symbols = {}

        for section in self._elf.iter_sections():
            if not isinstance(section, SymbolTableSection):
                continue

            for num, sym in enumerate(section.iter_symbols()):
                if sym.name:
                    self._symbols[num] = sym.name

    def _device_ord_from_rel(self, rel):
        """Find a device ordinal from a device symbol name."""
        sym_id = rel["r_info_sym"]
        sym_name = self._symbols.get(sym_id, None)

        if not sym_name:
            return None

        if not sym_name.startswith(_DEVICE_ORD_PREFIX):
            return None

        _, device_ord = sym_name.split(_DEVICE_ORD_PREFIX)
        return int(device_ord)

    def _find_defined_devices(self):
        """Find the device structures defined in the object file."""
        self.defined_devices = {}

        for section in self._elf.iter_sections():
            if not isinstance(section, RelocationSection):
                continue

            if not section.name.startswith(_INIT_SECTION_PREFIX):
                continue

            prio = Priority(section.name)

            for rel in section.iter_relocations():
                device_ord = self._device_ord_from_rel(rel)
                if not device_ord:
                    continue

                if device_ord in self.defined_devices:
                    raise ValueError(
                            f"Device {device_ord} already defined, stale "
                            "object files in the build directory? "
                            "Try running a clean build.")

                self.defined_devices[device_ord] = prio

    def __repr__(self):
        return (f"<{self.__class__.__name__} {self.file_path} "
                f"defined_devices: {self.defined_devices}>")

class Validator():
    """Validates the initialization priorities.

    Scans through a build folder for object files and list all the device
    initialization priorities. Then compares that against the EDT derived
    dependency list and log any found priority issue.

    Attributes:
        build_dir: the build directory to scan
        edt_pickle_path: path of the EDT pickle file
        log: a logging.Logger object
    """
    def __init__(self, build_dir, edt_pickle_path, log):
        self.log = log

        edtser = pathlib.Path(build_dir, edt_pickle_path)
        with open(edtser, "rb") as f:
            edt = pickle.load(f)

        self._ord2node = edt.dep_ord2node

        self._objs = []
        for file in self._find_build_objfiles(build_dir, is_root=True):
            obj = ZephyrObjectFile(file)
            if obj.defined_devices:
                self._objs.append(obj)

        self._dev_priorities = {}
        for obj in self._objs:
            for dev, prio in obj.defined_devices.items():
                if dev in self._dev_priorities:
                    dev_path = self._ord2node[dev].path
                    raise ValueError(
                            f"ERROR: device {dev} ({dev_path}) already defined")
                self._dev_priorities[dev] = prio

        self.warnings = 0
        self.errors = 0

    def _find_build_objfiles(self, build_dir, is_root=False):
        """Find all project object files, skip sub-build directories."""
        if not is_root and pathlib.Path(build_dir, _BUILD_DIR_DETECT_FILE).exists():
            return

        for file in pathlib.Path(build_dir).iterdir():
            if file.is_file() and file.name.endswith(_OBJ_FILE_SUFFIX):
                yield file
            if file.is_dir():
                for file in self._find_build_objfiles(file.resolve()):
                    yield file

    def _check_dep(self, dev_ord, dep_ord):
        """Validate the priority between two devices."""
        if dev_ord == dep_ord:
            return

        dev_node = self._ord2node[dev_ord]
        dep_node = self._ord2node[dep_ord]

        if dev_node._binding and dep_node._binding:
            dev_compat = dev_node._binding.compatible
            dep_compat = dep_node._binding.compatible
            if (dev_compat, dep_compat) in _INVERTED_PRIORITY_COMPATIBLES:
                self.log.info(f"Swapped priority: {dev_compat}, {dep_compat}")
                dev_ord, dep_ord = dep_ord, dev_ord

        dev_prio = self._dev_priorities.get(dev_ord, None)
        dep_prio = self._dev_priorities.get(dep_ord, None)

        if not dev_prio or not dep_prio:
            return

        if dev_prio == dep_prio:
            self.warnings += 1
            self.log.warning(
                    f"{dev_node.path} {dev_prio} == {dep_node.path} {dep_prio}")
        elif dev_prio < dep_prio:
            self.errors += 1
            self.log.error(
                    f"{dev_node.path} {dev_prio} < {dep_node.path} {dep_prio}")
        else:
            self.log.info(
                    f"{dev_node.path} {dev_prio} > {dep_node.path} {dep_prio}")

    def _check_edt_r(self, dev_ord, dev):
        """Recursively check for dependencies of a device."""
        for dep in dev.depends_on:
            self._check_dep(dev_ord, dep.dep_ordinal)
        if dev._binding and dev._binding.child_binding:
            for child in dev.children.values():
                if "compatible" in child.props:
                    continue
                if dev._binding.path != child._binding.path:
                    continue
                self._check_edt_r(dev_ord, child)

    def check_edt(self):
        """Scan through all known devices and validate the init priorities."""
        for dev_ord in self._dev_priorities:
            dev = self._ord2node[dev_ord]
            self._check_edt_r(dev_ord, dev)

def _parse_args(argv):
    """Parse the command line arguments."""
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter,
        allow_abbrev=False)

    parser.add_argument("-d", "--build-dir", default="build",
                        help="build directory to use")
    parser.add_argument("-v", "--verbose", action="store_true",
                        help="enable verbose Output")
    parser.add_argument("-w", "--fail-on-warning", action="store_true",
                        help="fail on both warnings and errors")
    parser.add_argument("--always-succeed", action="store_true",
                        help="always exit with a return code of 0, used for testing")
    parser.add_argument("-o", "--output",
                        help="write the output to a file in addition to stdout")
    parser.add_argument("--edt-pickle", default=pathlib.Path("zephyr", "edt.pickle"),
                        help="path to read the pickled edtlib.EDT object from",
                        type=pathlib.Path)

    return parser.parse_args(argv)

def _init_log(verbose, output):
    """Initialize a logger object."""
    log = logging.getLogger(__file__)

    console = logging.StreamHandler()
    console.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
    log.addHandler(console)

    if output:
        file = logging.FileHandler(output)
        file.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
        log.addHandler(file)

    if verbose:
        log.setLevel(logging.INFO)
    else:
        log.setLevel(logging.WARNING)

    return log

def main(argv=None):
    args = _parse_args(argv)

    log = _init_log(args.verbose, args.output)

    log.info(f"check_init_priorities build_dir: {args.build_dir}")

    validator = Validator(args.build_dir, args.edt_pickle, log)
    validator.check_edt()

    if args.always_succeed:
        return 0

    if args.fail_on_warning and validator.warnings:
        return 1

    if validator.errors:
        return 1

    return 0

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