aboutsummaryrefslogtreecommitdiff
path: root/gdb/syscalls/riscv-linux-canonicalize-syscall-gen.py
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/syscalls/riscv-linux-canonicalize-syscall-gen.py')
-rwxr-xr-xgdb/syscalls/riscv-linux-canonicalize-syscall-gen.py153
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()