Skip to content

Commit 5ef415e

Browse files
committed
scripts: Introduce seccompiler.py
`seccompiler.py` contains functions used to extract `syscall_table` from headers installed by `kernel_source.py` and generate according Rust code for specific architecture. Signed-off-by: Ruoqing He <[email protected]>
1 parent 29e549f commit 5ef415e

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

scripts/lib/seccompiler.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Copyright 2025 © Institute of Software, CAS. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import subprocess
5+
import os
6+
import re
7+
from lib.kernel_source import prepare_source
8+
from lib import MAP_RUST_ARCH, SUPPORT_ARCHS
9+
from pathlib import Path
10+
11+
SECCOMPILER_SYSCALL_DIR = "src/syscall_table"
12+
13+
14+
def generate_seccompiler(args):
15+
installed_header_path = prepare_source(args)
16+
17+
# If arch is not provided, install headers for all supported archs
18+
if args.arch is None:
19+
for arch in SUPPORT_ARCHS:
20+
generate_rust_code(installed_header_path, arch, args.output_path)
21+
else:
22+
generate_rust_code(installed_header_path, args.arch, args.output_path)
23+
24+
25+
def generate_rust_code(installed_header_path: str, arch: str, output_path: str):
26+
# Generate syscall table
27+
arch_headers = os.path.join(installed_header_path, f"{arch}_headers")
28+
syscall_header = Path(os.path.join(arch_headers, f"include/asm/unistd_64.h"))
29+
if not syscall_header.is_file():
30+
raise FileNotFoundError(f"syscall headers missing at {syscall_header}")
31+
syscalls = generate_syscall_table(syscall_header)
32+
33+
arch = MAP_RUST_ARCH[arch]
34+
output_file_path = f"{output_path}/{arch}.rs"
35+
36+
"""Generate Rust code and format with rustfmt"""
37+
print(f"Generating to: {output_file_path}")
38+
code = f"""use std::collections::HashMap;
39+
pub(crate) fn make_syscall_table() -> HashMap<&'static str, i64> {{
40+
vec![
41+
{syscalls}
42+
].into_iter().collect()
43+
}}
44+
"""
45+
try:
46+
with open(output_file_path, "w") as f:
47+
f.write(code)
48+
49+
# Format with rustfmt
50+
subprocess.run(["rustfmt", output_file_path], check=True)
51+
print(f"Generation succeeded: {output_file_path}")
52+
except subprocess.CalledProcessError:
53+
raise RuntimeError("rustfmt formatting failed")
54+
except IOError as e:
55+
raise RuntimeError(f"File write error: {str(e)}")
56+
57+
58+
def generate_syscall_table(syscall_header_path: str):
59+
"""Generate syscall table from specified header file"""
60+
try:
61+
with open(syscall_header_path, "r") as f:
62+
syscalls = []
63+
pattern = re.compile(r"^#define __NR_(\w+)\s+(\d+)")
64+
65+
for line in f:
66+
line = line.strip()
67+
if line.startswith("#define __NR_"):
68+
match = pattern.match(line)
69+
if match:
70+
name = match.group(1)
71+
num = int(match.group(2))
72+
syscalls.append((name, num))
73+
74+
# Sort alphabetically by syscall name
75+
syscalls.sort(key=lambda x: x[0])
76+
syscall_list = [f'("{name}", {num}),' for name, num in syscalls]
77+
return " ".join(syscall_list)
78+
79+
except Exception as e:
80+
raise RuntimeError(f"File processing failed: {str(e)}")

0 commit comments

Comments
 (0)