#!/bin/sh -eu # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (c) Linux Test Project, 2009-2024 # Copyright (c) Marcin Juszkiewicz, 2023-2024 # # This is an adaptation of the update-tables.sh script, included in the # syscalls-table project (https://github.com/hrw/syscalls-table) and released # under the MIT license. # # Author: Andrea Cervesato if [ "$#" -eq "0" ]; then echo "Please provide kernel sources:" echo "" echo "$0 path/to/Linux/kernel/sources" echo "" exit 1 fi KERNELSRC="$1" # to keep sorting in order export LC_ALL=C if [ ! -d "${KERNELSRC}" ]; then echo "${KERNELSRC} is not a directory" exit 1 fi if [ ! -e "${KERNELSRC}/Makefile" ]; then echo "No Makefile in ${KERNELSRC} directory" exit 1 fi TEMP="$(mktemp -d)" KVER="$(make -C ${KERNELSRC} kernelversion -s)" SCRIPT_DIR="$(realpath $(dirname "$0"))" SUPPORTED_ARCH="${SCRIPT_DIR}/supported-arch.txt" LINUX_HEADERS="${TEMP}/headers" grab_syscall_names_from_tables() { for tbl_file in $(find ${KERNELSRC}/arch -name syscall*.tbl); do grep -E -v "(^#|^$|sys_ni_syscall)" $tbl_file | awk '{ print $3 }' >>${TEMP}/syscall-names.tosort done drop_bad_entries } grab_syscall_names_from_unistd_h() { grep -E -h "^#define __NR_" \ ${LINUX_HEADERS}/usr/include/asm/unistd*.h \ ${LINUX_HEADERS}/usr/include/asm-generic/unistd.h \ >${TEMP}/syscall-names.tosort drop_bad_entries } drop_bad_entries() { grep -E -v "(unistd.h|NR3264|__NR_syscall|__SC_COMP|__NR_.*Linux|__NR_FAST)" \ ${TEMP}/syscall-names.tosort | grep -E -v "(__SYSCALL|SYSCALL_BASE|SYSCALL_MASK)" | sed -e "s/#define\s*__NR_//g" -e "s/\s.*//g" | sort -u >${TEMP}/syscall-names.txt } generate_table() { echo "- $arch" if [ "$bits" -eq "32" ]; then extraflags="${extraflags} -D__BITS_PER_LONG=32" fi local uppercase_arch=$(echo "$arch" | tr '[:lower:]' '[:upper:]') # ignore any error generated by gcc. We want to obtain all the # available architecture syscalls for the current platform and to handle # only supported architectures later on gcc ${TEMP}/list-syscalls.c -U__LP64__ -U__ILP32__ -U__i386__ \ -D${uppercase_arch} \ -D__${arch}__ ${extraflags} \ -I ${LINUX_HEADERS}/usr/include/ \ -o ${TEMP}/list-syscalls || true ${TEMP}/list-syscalls >"${TEMP}/${arch}.in.tosort" sort -k2,2n "${TEMP}/${arch}.in.tosort" >"${TEMP}/${arch}.in" } generate_list_syscalls_c() { ( printf " #include #include int main(void) { " for syscall in $(cat ${TEMP}/syscall-names.txt); do printf " #ifdef __NR_$syscall printf(\"$syscall %%d" # i know the following print is ugly, but dash and bash # treat double quoted strings in a different way and we # really need to inject '\n' character in the C code # rather than carriage return printf '\\n' printf "\", __NR_$syscall); #endif " done printf " return 0; }" ) >${TEMP}/list-syscalls.c } export_headers() { make -s -C ${KERNELSRC} ARCH=${arch} O=${LINUX_HEADERS} \ headers_install >/dev/null 2>&1 } do_all_tables() { for archdir in ${KERNELSRC}/arch/*; do arch=$(basename $archdir) bits=64 extraflags= case ${arch} in Kconfig) continue ;; um) continue ;; esac export_headers grab_syscall_names_from_unistd_h case ${arch} in arm) bits=32 arch=armoabi extraflags= generate_table arch=arm extraflags=-D__ARM_EABI__ generate_table ;; loongarch) # 32-bit variant of loongarch may appear arch=loongarch64 extraflags=-D_LOONGARCH_SZLONG=64 generate_table ;; mips) arch=mips64 extraflags=-D_MIPS_SIM=_MIPS_SIM_ABI64 generate_table bits=32 arch=mipso32 extraflags=-D_MIPS_SIM=_MIPS_SIM_ABI32 generate_table arch=mips64n32 extraflags=-D_MIPS_SIM=_MIPS_SIM_NABI32 generate_table ;; powerpc) generate_table arch=powerpc64 generate_table ;; riscv) arch=riscv64 extraflags=-D__LP64__ generate_table bits=32 arch=riscv32 extraflags=-D__SIZEOF_POINTER__=4 generate_table ;; s390) bits=32 generate_table bits=64 arch=s390x generate_table ;; sparc) bits=32 extraflags=-D__32bit_syscall_numbers__ generate_table bits=64 arch=sparc64 extraflags=-D__arch64__ generate_table ;; x86) arch=x86_64 extraflags=-D__LP64__ generate_table bits=32 arch=i386 generate_table arch=x32 extraflags=-D__ILP32__ generate_table ;; arc | csky | hexagon | m68k | microblaze | nios2 | openrisc | sh | xtensa) bits=32 generate_table ;; *) generate_table ;; esac done } copy_supported_arch() { while IFS= read -r arch; do if [ -f "${TEMP}/${arch}.in" ]; then echo "- ${arch}" cp "${TEMP}/${arch}.in" "${SCRIPT_DIR}/${arch}.in" fi done <${SUPPORTED_ARCH} } echo "Temporary directory ${TEMP}" echo "Extracting syscalls" grab_syscall_names_from_tables generate_list_syscalls_c do_all_tables echo "Copying supported syscalls" copy_supported_arch