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