From 321ac819c4fb534c5887a8f86af320f7f1146d7c Mon Sep 17 00:00:00 2001 From: Timur Golubovich Date: Thu, 4 Sep 2025 21:07:11 +0300 Subject: [PATCH] Rewrote riscv-canonicalize-gen.py using xml file Since catching-syscalls was added, there had been added files containing syscalls in xml format. As for now riscv-canonicalize-syscall-gen.py uses glibc for generating, it may be not so comfortable. I changed this script for reusing newly generated riscv-linux.xml file. Also, I renamed riscv64_canonicalize_syscall to riscv_linux_canonicalize_syscall as only 64 system is supported in linux. This will simplify the possible further generalization of this script to other architectures. Approved-By: Simon Marchi --- gdb/Makefile.in | 2 +- gdb/configure.tgt | 2 +- ...=> riscv-linux-canonicalize-syscall-gen.c} | 9 +- gdb/riscv-linux-tdep.c | 11 +- gdb/riscv-linux-tdep.h | 6 +- .../riscv-canonicalize-syscall-gen.py | 171 ------------------ .../riscv-linux-canonicalize-syscall-gen.py | 153 ++++++++++++++++ 7 files changed, 169 insertions(+), 185 deletions(-) rename gdb/{riscv-canonicalize-syscall-gen.c => riscv-linux-canonicalize-syscall-gen.c} (97%) delete mode 100755 gdb/syscalls/riscv-canonicalize-syscall-gen.py create mode 100755 gdb/syscalls/riscv-linux-canonicalize-syscall-gen.py diff --git a/gdb/Makefile.in b/gdb/Makefile.in index beacefcfdd5..486d3dbdc55 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -769,7 +769,7 @@ ALL_64_TARGET_OBS = \ mips-sde-tdep.o \ mips-tdep.o \ mips64-obsd-tdep.o \ - riscv-canonicalize-syscall-gen.o \ + riscv-linux-canonicalize-syscall-gen.o \ riscv-fbsd-tdep.o \ riscv-linux-tdep.o \ riscv-none-tdep.o \ diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 34ae5036340..fd9036fdd44 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -546,7 +546,7 @@ riscv*-*-freebsd*) riscv*-*-linux*) # Target: Linux/RISC-V - gdb_target_obs="riscv-linux-tdep.o riscv-canonicalize-syscall-gen.o \ + gdb_target_obs="riscv-linux-tdep.o riscv-linux-canonicalize-syscall-gen.o \ glibc-tdep.o linux-tdep.o solib-svr4.o solib-svr4-linux.o \ symfile-mem.o \ linux-record.o svr4-tls-tdep.o" diff --git a/gdb/riscv-canonicalize-syscall-gen.c b/gdb/riscv-linux-canonicalize-syscall-gen.c similarity index 97% rename from gdb/riscv-canonicalize-syscall-gen.c rename to gdb/riscv-linux-canonicalize-syscall-gen.c index 67e5410dc6d..9ba8b3f6cf4 100644 --- a/gdb/riscv-canonicalize-syscall-gen.c +++ b/gdb/riscv-linux-canonicalize-syscall-gen.c @@ -1,4 +1,4 @@ -/* DO NOT EDIT: Autogenerated by riscv-canonicalize-syscall-gen.py +/* DO NOT EDIT: Autogenerated by riscv-linux-canonicalize-syscall-gen.py Copyright (C) 2024-2025 Free Software Foundation, Inc. @@ -20,12 +20,12 @@ #include "defs.h" #include "riscv-linux-tdep.h" -/* riscv64_canonicalize_syscall maps from the native riscv 64 Linux set +/* 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 -riscv64_canonicalize_syscall (int syscall) +riscv_linux_canonicalize_syscall (int syscall) { switch (syscall) { @@ -352,6 +352,9 @@ riscv64_canonicalize_syscall (int syscall) /* case 464: return gdb_sys_getxattrat; */ /* case 465: return gdb_sys_listxattrat; */ /* case 466: return gdb_sys_removexattrat; */ + /* case 467: return gdb_sys_open_tree_attr; */ + /* case 468: return gdb_sys_file_getattr; */ + /* case 469: return gdb_sys_file_setattr; */ default: return gdb_sys_no_syscall; } diff --git a/gdb/riscv-linux-tdep.c b/gdb/riscv-linux-tdep.c index 0a946111b9d..05f92f832eb 100644 --- a/gdb/riscv-linux-tdep.c +++ b/gdb/riscv-linux-tdep.c @@ -230,7 +230,7 @@ riscv_linux_syscall_record (struct regcache *regcache, { gdb_assert (regcache != nullptr); - enum gdb_syscall syscall_gdb = riscv64_canonicalize_syscall (svc_number); + enum gdb_syscall syscall_gdb = riscv_linux_canonicalize_syscall (svc_number); if (record_debug > 1) gdb_printf (gdb_stdlog, "Made syscall %s.\n", plongest (svc_number)); @@ -261,12 +261,11 @@ riscv_linux_syscall_record (struct regcache *regcache, return 0; } -/* Initialize the riscv64_linux_record_tdep. */ +/* Initialize the riscv_linux_record_tdep. */ static void -riscv64_linux_record_tdep_init (struct gdbarch *gdbarch, - struct linux_record_tdep & - riscv_linux_record_tdep) +riscv_linux_record_tdep_init (struct gdbarch *gdbarch, + struct linux_record_tdep &riscv_linux_record_tdep) { gdb_assert (gdbarch != nullptr); @@ -561,7 +560,7 @@ riscv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->syscall_next_pc = riscv_linux_syscall_next_pc; tdep->riscv_syscall_record = riscv_linux_syscall_record; - riscv64_linux_record_tdep_init (gdbarch, riscv_linux_record_tdep); + riscv_linux_record_tdep_init (gdbarch, riscv_linux_record_tdep); /* Functions for 'catch syscall'. */ set_gdbarch_xml_syscall_file (gdbarch, "syscalls/riscv-linux.xml"); diff --git a/gdb/riscv-linux-tdep.h b/gdb/riscv-linux-tdep.h index 9dd9e373caa..9f0d95bbe8e 100644 --- a/gdb/riscv-linux-tdep.h +++ b/gdb/riscv-linux-tdep.h @@ -20,10 +20,10 @@ #include "linux-record.h" -/* riscv64_canonicalize_syscall maps from the native riscv Linux set - of syscall ids into a canonical set of syscall ids used by +/* riscv_linux_canonicalize_syscall maps from the native riscv Linux + set of syscall ids into a canonical set of syscall ids used by process record. */ -extern enum gdb_syscall riscv64_canonicalize_syscall (int syscall); +extern enum gdb_syscall riscv_linux_canonicalize_syscall (int syscall); #endif /* GDB_RISCV_LINUX_TDEP_H */ diff --git a/gdb/syscalls/riscv-canonicalize-syscall-gen.py b/gdb/syscalls/riscv-canonicalize-syscall-gen.py deleted file mode 100755 index 40039bb0f15..00000000000 --- a/gdb/syscalls/riscv-canonicalize-syscall-gen.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python3 -# pylint: disable=invalid-name - -# 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 . - - -# To get help message for this script, run: -# ./gdb/syscalls/riscv-canonicalize-syscall-gen.py --help - -# Execution result: - -# usage: riscv-canonicalize-syscall-gen.py [-h] -i INPUT -# -# Generate file gdb/riscv-canonicalize-syscall-gen.c from path to riscv linux syscalls. -# -# options: -# -h, --help show this help message and exit -# -i INPUT, --input INPUT -# path to riscv linux syscalls (glibc/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h) - -import argparse -import re -import sys -from pathlib import Path as _Path - -head = """\ -/* DO NOT EDIT: Autogenerated by riscv-canonicalize-syscall-gen.py - - 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 . */ - -#include "defs.h" -#include "riscv-linux-tdep.h" - -/* riscv64_canonicalize_syscall maps from the native riscv 64 Linux set - of syscall ids into a canonical set of syscall ids used by - process record. */ - -enum gdb_syscall -riscv64_canonicalize_syscall (int syscall) -{ - switch (syscall) - { -""" - -tail = """\ - default: - return gdb_sys_no_syscall; - } -} -""" - - -class Generator: - def _get_gdb_syscalls(self, gdb_syscalls_path: _Path) -> list[str]: - gdb_syscalls: list[str] = [] - with open(gdb_syscalls_path, "r", encoding="UTF-8") as file: - lines = file.readlines() - for line in lines: - match = re.search(r"\s*(?Pgdb_sys_[^S]+)\S*=", line) - if match: - gdb_syscalls.append(match.group("name").strip()) - return gdb_syscalls - - def _get_canon_syscalls_lines( - self, syscalls_path: _Path, gdb_syscalls: list[str] - ) -> list[str]: - canon_syscalls: dict[int, str] = {} - with open(syscalls_path, "r", encoding="UTF-8") as file: - lines = file.readlines() - for line in lines: - match = re.match( - r"#define\s+__NR_(?P[^\s]+)\s+(?P\d+)", line - ) - if match: - syscall_name = match.group("name") - syscall_num = int(match.group("number")) - gdb_syscall_name = f"gdb_sys_{syscall_name}" - if gdb_syscall_name in gdb_syscalls: - value = f" case {syscall_num}: return {gdb_syscall_name};\n" - canon_syscalls[syscall_num] = value - # this is a place for corner cases - elif syscall_name == "mmap": - gdb_old_syscall_name = "gdb_sys_old_mmap" - value = ( - f" case {syscall_num}: return {gdb_old_syscall_name};\n" - ) - canon_syscalls[syscall_num] = value - else: - value = f" /* case {syscall_num}: return {gdb_syscall_name}; */\n" - canon_syscalls[syscall_num] = value - return [canon_syscalls[syscall_num] for syscall_num in sorted(canon_syscalls)] - - def generate(self, syscalls_path: _Path) -> None: - repo_path = _Path(__file__).parent.parent.parent - gdb_syscalls_path = repo_path / "gdb" / "linux-record.h" - canon_syscalls_path = repo_path / "gdb" / "riscv-canonicalize-syscall-gen.c" - - gdb_syscalls = self._get_gdb_syscalls(gdb_syscalls_path) - canon_syscalls_lines = self._get_canon_syscalls_lines( - syscalls_path, gdb_syscalls - ) - - with open(canon_syscalls_path, "w", encoding="UTF-8") as file: - file.writelines(head) - file.writelines(canon_syscalls_lines) - file.writelines(tail) - - -help_message = """\ -Generate file gdb/riscv-canonicalize-syscall-gen.c -from path to riscv linux syscalls. -""" - - -def setup_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser(description=help_message) - parser.add_argument( - "-i", - "--input", - type=_Path, - required=True, - help="path to riscv linux syscalls (glibc/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h)", - ) - return parser - - -def main(argv: list[str]) -> int: - try: - parser = setup_parser() - args = parser.parse_args(argv) - generator = Generator() - generator.generate(args.input) - return 0 - except RuntimeError as e: - print(str(e)) - return -1 - - -if __name__ == "__main__": - sys.exit(main(sys.argv[1:])) 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 00000000000..aaf3943bb01 --- /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 . + + +# 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 . */ + +#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() -- 2.47.3