diff options
Diffstat (limited to 'gdb/syscalls/riscv-linux-canonicalize-syscall-gen.py')
-rwxr-xr-x | gdb/syscalls/riscv-linux-canonicalize-syscall-gen.py | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/gdb/syscalls/riscv-linux-canonicalize-syscall-gen.py b/gdb/syscalls/riscv-linux-canonicalize-syscall-gen.py new file mode 100755 index 0000000..aaf3943 --- /dev/null +++ b/gdb/syscalls/riscv-linux-canonicalize-syscall-gen.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2024-2025 Free Software Foundation, Inc. +# Contributed by Timur Golubovich + +# This file is part of GDB. + +# 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/>. + + +# To get help message for this script, run: +# ./gdb/syscalls/riscv-linux-canonicalize-syscall-gen.py --help + +# Execution result: + +# usage: riscv-linux-canonicalize-syscall-gen.py [-h] +# +# Generate file gdb/riscv-linux-canonicalize-syscall-gen.c from +# gdb/syscalls/riscv-linux.xml. +# +# options: +# -h, --help show this help message and exit + +import argparse +import re +import xml.etree.ElementTree as ET +from pathlib import Path + +FILE = Path(__file__).resolve() + +HEAD = f"""\ +/* DO NOT EDIT: Autogenerated by {FILE.name} + + Copyright (C) 2024-2025 Free Software Foundation, Inc. + + This file is part of GDB. + + 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/>. */ + +#include "defs.h" +#include "riscv-linux-tdep.h" + +/* riscv_linux_canonicalize_syscall maps from the native RISC-V Linux set + of syscall ids into a canonical set of syscall ids used by + process record. */ + +enum gdb_syscall +riscv_linux_canonicalize_syscall (int syscall) +{{ + switch (syscall) + {{ +""" + +TAIL = """\ + default: + return gdb_sys_no_syscall; + } +} +""" + +HELP_MESSAGE = """\ +Generate file gdb/riscv-linux-canonicalize-syscall-gen.c from +gdb/syscalls/riscv-linux.xml. +""" + + +class Generator: + def _get_gdb_syscalls(self, gdb_syscalls_path: Path) -> set[str]: + gdb_syscalls = set[str]() + with open(gdb_syscalls_path, "r", encoding="UTF-8") as file: + for line in file: + match = re.search(r"(gdb_sys_\S+)\s*=", line) + if match: + gdb_syscalls.add(match[1].strip()) + return gdb_syscalls + + def _get_arch_syscalls(self, xml_syscalls_path: Path) -> dict[str, int]: + arch_syscalls: dict[str, int] = {} + syscalls_info = ET.parse(xml_syscalls_path) + for syscall in syscalls_info.findall("syscall"): + sysname = syscall.attrib["name"] + sysno = int(syscall.attrib["number"]) + arch_syscalls[sysname] = sysno + return arch_syscalls + + def _get_canon_syscalls_lines( + self, + arch_syscalls: dict[str, int], + gdb_syscalls: set[str], + exceptions: dict[str, str], + ) -> list[str]: + canon_syscalls: dict[int, str] = {} + for sysname, sysno in arch_syscalls.items(): + if sysname in exceptions: + sysname = exceptions[sysname] + gdb_sysname = f"gdb_sys_{sysname}" + value = f" /* case {sysno}: return {gdb_sysname}; */\n" + if gdb_sysname in gdb_syscalls: + value = f" case {sysno}: return {gdb_sysname};\n" + canon_syscalls[sysno] = value + return [canon_syscalls[sysno] for sysno in sorted(canon_syscalls)] + + def generate(self) -> None: + repo_path = FILE.parent.parent.parent + gdb_path = repo_path / "gdb" + xml_syscalls_path = gdb_path / "syscalls" / "riscv-linux.xml" + gdb_syscalls_path = gdb_path / "linux-record.h" + arch_syscalls_path = gdb_path / "riscv-linux-canonicalize-syscall-gen.c" + exceptions = {"mmap": "old_mmap"} + + arch_syscalls = self._get_arch_syscalls(xml_syscalls_path) + gdb_syscalls = self._get_gdb_syscalls(gdb_syscalls_path) + canon_syscalls_lines = self._get_canon_syscalls_lines( + arch_syscalls, gdb_syscalls, exceptions + ) + + with open(arch_syscalls_path, "w", encoding="UTF-8") as file: + file.writelines(HEAD) + file.writelines(canon_syscalls_lines) + file.writelines(TAIL) + + +def main() -> int: + parser = argparse.ArgumentParser(description=HELP_MESSAGE) + parser.parse_args() + Generator().generate() + return 0 + + +if __name__ == "__main__": + main() |