• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh -eu
2# SPDX-License-Identifier: GPL-2.0-or-later
3# Copyright (c) Linux Test Project, 2009-2024
4# Copyright (c) Marcin Juszkiewicz, 2023-2024
5#
6# This is an adaptation of the update-tables.sh script, included in the
7# syscalls-table project (https://github.com/hrw/syscalls-table) and released
8# under the MIT license.
9#
10# Author: Andrea Cervesato <andrea.cervesato@suse.com>
11
12if [ "$#" -eq "0" ]; then
13	echo "Please provide kernel sources:"
14	echo ""
15	echo "$0 path/to/Linux/kernel/sources"
16	echo ""
17	exit 1
18fi
19
20KERNELSRC="$1"
21
22# to keep sorting in order
23export LC_ALL=C
24
25if [ ! -d "${KERNELSRC}" ]; then
26	echo "${KERNELSRC} is not a directory"
27	exit 1
28fi
29
30if [ ! -e "${KERNELSRC}/Makefile" ]; then
31	echo "No Makefile in ${KERNELSRC} directory"
32	exit 1
33fi
34
35TEMP="$(mktemp -d)"
36KVER="$(make -C ${KERNELSRC} kernelversion -s)"
37
38SCRIPT_DIR="$(realpath $(dirname "$0"))"
39SUPPORTED_ARCH="${SCRIPT_DIR}/supported-arch.txt"
40LINUX_HEADERS="${TEMP}/headers"
41
42grab_syscall_names_from_tables() {
43	for tbl_file in $(find ${KERNELSRC}/arch -name syscall*.tbl); do
44		grep -E -v "(^#|^$|sys_ni_syscall)" $tbl_file |
45			awk '{ print $3 }' >>${TEMP}/syscall-names.tosort
46	done
47
48	drop_bad_entries
49}
50
51grab_syscall_names_from_unistd_h() {
52	grep -E -h "^#define __NR_" \
53		${LINUX_HEADERS}/usr/include/asm/unistd*.h \
54		${LINUX_HEADERS}/usr/include/asm-generic/unistd.h \
55		>${TEMP}/syscall-names.tosort
56
57	drop_bad_entries
58}
59
60drop_bad_entries() {
61	grep -E -v "(unistd.h|NR3264|__NR_syscall|__SC_COMP|__NR_.*Linux|__NR_FAST)" \
62		${TEMP}/syscall-names.tosort |
63		grep -E -v "(__SYSCALL|SYSCALL_BASE|SYSCALL_MASK)" |
64		sed -e "s/#define\s*__NR_//g" -e "s/\s.*//g" |
65		sort -u >${TEMP}/syscall-names.txt
66}
67
68generate_table() {
69	echo "- $arch"
70
71	if [ "$bits" -eq "32" ]; then
72		extraflags="${extraflags} -D__BITS_PER_LONG=32"
73	fi
74
75	local uppercase_arch=$(echo "$arch" | tr '[:lower:]' '[:upper:]')
76
77	# ignore any error generated by gcc. We want to obtain all the
78	# available architecture syscalls for the current platform and to handle
79	# only supported architectures later on
80	gcc ${TEMP}/list-syscalls.c -U__LP64__ -U__ILP32__ -U__i386__ \
81		-D${uppercase_arch} \
82		-D__${arch}__ ${extraflags} \
83		-I ${LINUX_HEADERS}/usr/include/ \
84		-o ${TEMP}/list-syscalls || true
85
86	${TEMP}/list-syscalls >"${TEMP}/${arch}.in.tosort"
87
88	sort -k2,2n "${TEMP}/${arch}.in.tosort" >"${TEMP}/${arch}.in"
89}
90
91generate_list_syscalls_c() {
92	(
93		printf "
94		#include <stdio.h>
95		#include <asm/unistd.h>
96
97		int main(void)
98		{
99		"
100		for syscall in $(cat ${TEMP}/syscall-names.txt); do
101			printf "
102		#ifdef __NR_$syscall
103			printf(\"$syscall %%d"
104			# i know the following print is ugly, but dash and bash
105			# treat double quoted strings in a different way and we
106			# really need to inject '\n' character in the C code
107			# rather than carriage return
108			printf '\\n'
109			printf "\", __NR_$syscall);
110		#endif
111		"
112		done
113		printf " return 0;
114		}"
115	) >${TEMP}/list-syscalls.c
116}
117
118export_headers() {
119	make -s -C ${KERNELSRC} ARCH=${arch} O=${LINUX_HEADERS} \
120		headers_install >/dev/null 2>&1
121}
122
123do_all_tables() {
124	for archdir in ${KERNELSRC}/arch/*; do
125		arch=$(basename $archdir)
126
127		bits=64
128		extraflags=
129
130		case ${arch} in
131		Kconfig)
132			continue
133			;;
134		um)
135			continue
136			;;
137		esac
138
139		export_headers
140		grab_syscall_names_from_unistd_h
141
142		case ${arch} in
143		arm)
144			bits=32
145			arch=armoabi extraflags= generate_table
146			arch=arm extraflags=-D__ARM_EABI__ generate_table
147			;;
148		loongarch)
149			# 32-bit variant of loongarch may appear
150			arch=loongarch64 extraflags=-D_LOONGARCH_SZLONG=64 generate_table
151			;;
152		mips)
153			arch=mips64 extraflags=-D_MIPS_SIM=_MIPS_SIM_ABI64 generate_table
154			bits=32
155			arch=mipso32 extraflags=-D_MIPS_SIM=_MIPS_SIM_ABI32 generate_table
156			arch=mips64n32 extraflags=-D_MIPS_SIM=_MIPS_SIM_NABI32 generate_table
157			;;
158		powerpc)
159			generate_table
160			arch=powerpc64 generate_table
161			;;
162		riscv)
163			arch=riscv64 extraflags=-D__LP64__ generate_table
164			bits=32
165			arch=riscv32 extraflags=-D__SIZEOF_POINTER__=4 generate_table
166			;;
167		s390)
168			bits=32
169			generate_table
170			bits=64
171			arch=s390x generate_table
172			;;
173		sparc)
174			bits=32
175			extraflags=-D__32bit_syscall_numbers__ generate_table
176			bits=64
177			arch=sparc64 extraflags=-D__arch64__ generate_table
178			;;
179		x86)
180			arch=x86_64 extraflags=-D__LP64__ generate_table
181			bits=32
182			arch=i386 generate_table
183			arch=x32 extraflags=-D__ILP32__ generate_table
184			;;
185		arc | csky | hexagon | m68k | microblaze | nios2 | openrisc | sh | xtensa)
186			bits=32 generate_table
187			;;
188		*)
189			generate_table
190			;;
191		esac
192	done
193}
194
195copy_supported_arch() {
196	while IFS= read -r arch; do
197		if [ -f "${TEMP}/${arch}.in" ]; then
198			echo "- ${arch}"
199			cp "${TEMP}/${arch}.in" "${SCRIPT_DIR}/${arch}.in"
200		fi
201	done <${SUPPORTED_ARCH}
202}
203
204echo "Temporary directory ${TEMP}"
205echo "Extracting syscalls"
206
207grab_syscall_names_from_tables
208generate_list_syscalls_c
209
210do_all_tables
211
212echo "Copying supported syscalls"
213copy_supported_arch
214