From 6290acc69aaec1ae76f2c3d7250f93868e01c063 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Sun, 17 Sep 2023 20:49:47 +0300 Subject: [PATCH] syscalls/lscmg: introduce Linux syscalls mapping generator --- src/openpower/syscalls/lscmg.py | 88 +++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/openpower/syscalls/lscmg.py diff --git a/src/openpower/syscalls/lscmg.py b/src/openpower/syscalls/lscmg.py new file mode 100644 index 00000000..d5c69872 --- /dev/null +++ b/src/openpower/syscalls/lscmg.py @@ -0,0 +1,88 @@ +import argparse +import collections +import enum +import functools +import json +import os +import pathlib +import re + + +def collect_sysnums(tree): + def parse(path): + table = collections.defaultdict(dict) + whitespace = re.compile(r"\s+") + with open(path, mode="r", encoding="UTF-8") as stream: + lines = filter(lambda line: not line.strip().startswith("#"), stream) + for line in filter(bool, map(str.strip, lines)): + (number, abi, name, *entries) = map(str.strip, whitespace.split(line)) + entries = tuple(entries) + if len(entries) > 2: + raise ValueError(line) + table[abi][number] = (name, entries) + table[abi][name] = number + + return table + + tables = ( + ("alpha", "arch/alpha/kernel/syscalls/syscall.tbl"), + ("arm", "arch/arm/tools/syscall.tbl"), + ("ia64", "arch/ia64/kernel/syscalls/syscall.tbl"), + ("m68k", "arch/m68k/kernel/syscalls/syscall.tbl"), + ("microblaze", "arch/microblaze/kernel/syscalls/syscall.tbl"), + ("mips-n32", "arch/mips/kernel/syscalls/syscall_n32.tbl"), + ("mips-n64", "arch/mips/kernel/syscalls/syscall_n64.tbl"), + ("mips-o32", "arch/mips/kernel/syscalls/syscall_o32.tbl"), + ("parisc", "arch/parisc/kernel/syscalls/syscall.tbl"), + ("ppc", "arch/powerpc/kernel/syscalls/syscall.tbl"), + ("s390", "arch/s390/kernel/syscalls/syscall.tbl"), + ("sh", "arch/sh/kernel/syscalls/syscall.tbl"), + ("sparc", "arch/sparc/kernel/syscalls/syscall.tbl"), + ("x86-32", "arch/x86/entry/syscalls/syscall_32.tbl"), + ("x86-64", "arch/x86/entry/syscalls/syscall_64.tbl"), + ("xtensa", "arch/xtensa/kernel/syscalls/syscall.tbl"), + ) + for (arch, path) in tables: + yield (arch, parse(path=(tree / path))) + + +def collect_sysargs(tree): + pattern = re.compile(r"(COMPAT_)?SYSCALL_DEFINE[0-7]\((.*?)\)", re.S | re.M) + compat_arg_u64_pattern = re.compile(r"compat_arg_u64_dual\((.+?)\)") + + for (root, _, paths) in os.walk(top=tree): + root = pathlib.Path(root) + paths = map(lambda path: (root / path), paths) + for path in filter(lambda path: path.suffix == ".c", paths): + with open(path, mode="r", encoding="UTF-8") as stream: + code = stream.read() + code = compat_arg_u64_pattern.sub(r"u32, \1_a, u32, \1_b", code) + for match in pattern.finditer(code): + compat = (match.group(1) is not None) + match = match.group(2).replace("\t", "").replace("\n", "") + (name, *arguments) = map(str.strip, match.split(",")) + if compat: + name = f"compat_{name}" + yield (name, dict(zip(arguments[1::2], arguments[0::2]))) + + +def main(): + parser = argparse.ArgumentParser("lscmg", + description="Linux system calls mapping generator") + parser.add_argument("tree", + help="path to kernel source tree", + type=pathlib.Path) + + arguments = dict(vars(parser.parse_args())) + + tree = arguments.pop("tree") + tree = tree.expanduser() + sysnums = dict(collect_sysnums(tree=tree)) + sysargs = dict(collect_sysargs(tree=tree)) + + print("SYSNUMS", "=", json.dumps(sysnums, indent=4)) + print("SYSARGS", "=", json.dumps(sysargs, indent=4)) + + +if __name__ == "__main__": + main() -- 2.30.2