# Copyright (C) 2025-2026 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import pathlib

import gdb


class Mapping:
    def __init__(self, mapping, region):
        self._mapping = mapping
        self._region = region

    @property
    def start(self):
        return self._region.start

    @property
    def end(self):
        return self._region.end

    @property
    def offset(self):
        return self._region.file_offset

    @property
    def filename(self):
        return self._mapping.filename


def info_proc_mappings():
    ptr_size = gdb.lookup_type("void").pointer().sizeof

    print("Mapped address spaces:")
    print("")
    if ptr_size == 4:
        format_str = "%-10s %-10s %-10s %-10s %s "
    else:
        format_str = "%-18s %-18s %-18s %-18s %s "
    print(format_str % ("Start Addr", "End Addr", "Size", "Offset", "File"))

    core = gdb.selected_inferior().corefile
    mappings = core.mapped_files()

    result = []
    for m in mappings:
        for r in m.regions:
            result.append(Mapping(m, r))

    result.sort(key=lambda x: x.start)
    for r in result:
        sz = r.end - r.start
        if ptr_size == 4:
            t = (
                "0x%08x" % r.start,
                "0x%08x" % r.end,
                "0x%-8x" % sz,
                "0x%-8x" % r.offset,
                "%s" % r.filename,
            )
        else:
            t = (
                "0x%016x" % r.start,
                "0x%016x" % r.end,
                "0x%-16x" % sz,
                "0x%-16x" % r.offset,
                "%s" % r.filename,
            )
        print(format_str % t)


class InfoProcPyMappings(gdb.Command):
    def __init__(self):
        gdb.Command.__init__(self, "info proc py-mappings", gdb.COMMAND_DATA)

    def invoke(self, args, from_tty):
        info_proc_mappings()


InfoProcPyMappings()


# Assume that a core file is currently loaded.
#
# Look through all the objfiles for the current inferior, and record
# any that have a build-id.
#
# Then look through the core file mapped files.  Look for entries that
# correspond with the loaded objfiles.  For these matching entries,
# capture the build-id extracted from the core file.
#
# Finally, print a table with the build-id from the objfile, the
# build-id from the core file, and the file name.
#
# This is then processed from the test script to check the build-ids
# match.
class ShowBuildIds(gdb.Command):
    def __init__(self):
        gdb.Command.__init__(self, "show-build-ids", gdb.COMMAND_DATA)

    def invoke(self, args, from_tty):
        inf = gdb.selected_inferior()
        objfiles = inf.progspace.objfiles()

        path_to_build_id = {}

        # Initial length based on column headings.
        longest_build_id = 18

        for o in objfiles:
            if not o.is_file or o.build_id is None or o.owner is not None:
                continue
            p = pathlib.Path(o.filename).resolve()
            b = o.build_id
            path_to_build_id[p] = {"objfile": b, "corefile": "missing"}
            if len(b) > longest_build_id:
                longest_build_id = len(b)

        core_mapped_files = inf.corefile.mapped_files()
        for m in core_mapped_files:
            p = pathlib.Path(m.filename).resolve()
            b = m.build_id

            if b is not None and len(b) > longest_build_id:
                longest_build_id = len(b)

            if p in path_to_build_id:
                path_to_build_id[p]["corefile"] = b

        format_str = (
            "%-" + str(longest_build_id) + "s  %-" + str(longest_build_id) + "s  %s"
        )

        def make_title(string, length=0):
            if length > 0:
                padding_len = length - len(string)
            else:
                padding_len = 0

            padding = " " * padding_len
            style = gdb.Style("title")
            return style.apply(string) + padding

        print(
            "%s  %s  %s"
            % (
                make_title("Objfile Build-Id", longest_build_id),
                make_title("Core File Build-Id", longest_build_id),
                make_title("File Name"),
            )
        )
        for p, b in path_to_build_id.items():
            print(format_str % (b["objfile"], b["corefile"], p))


ShowBuildIds()


class CheckMainExec(gdb.Command):
    def __init__(self):
        gdb.Command.__init__(self, "check-main-executable", gdb.COMMAND_DATA)

    def invoke(self, args, from_tty):
        inf = gdb.selected_inferior()
        pspace = inf.progspace
        exec_filename = pathlib.Path(pspace.executable_filename).resolve()

        count = 0
        core_mapped_files = inf.corefile.mapped_files()
        for m in core_mapped_files:
            if not m.is_main_executable:
                continue

            p = pathlib.Path(m.filename).resolve()

            count += 1
            assert exec_filename == p, "main exec filename mismatch"

        assert count == 1, "invalid main executable count"

        print("PASS")


CheckMainExec()


print("Success")
