[LTP] [PATCH 2/4] Add script to generate syscalls.h
Andrea Cervesato
andrea.cervesato@suse.de
Tue Sep 24 10:06:27 CEST 2024
From: Andrea Cervesato <andrea.cervesato@suse.com>
Replicate the https://github.com/hrw/syscalls-table project way, by
creating a script that automatically generate syscalls input files,
merge them like regen.sh script does and to create syscalls.h header
file which can be used by LTP tests to access syscalls values accoring
to the architecture.
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
include/lapi/syscalls/blacklist-syscalls.txt | 6 +
include/lapi/syscalls/generate_syscalls.sh | 292 +++++++++++++++++++++++++++
2 files changed, 298 insertions(+)
diff --git a/include/lapi/syscalls/blacklist-syscalls.txt b/include/lapi/syscalls/blacklist-syscalls.txt
new file mode 100644
index 000000000..e1ae5f76f
--- /dev/null
+++ b/include/lapi/syscalls/blacklist-syscalls.txt
@@ -0,0 +1,6 @@
+arch_specific_syscall
+available
+ni_syscall
+reserved
+SYSCALL_MASK
+unused
diff --git a/include/lapi/syscalls/generate_syscalls.sh b/include/lapi/syscalls/generate_syscalls.sh
new file mode 100755
index 000000000..f7bcbd50e
--- /dev/null
+++ b/include/lapi/syscalls/generate_syscalls.sh
@@ -0,0 +1,292 @@
+#!/bin/sh
+#
+# Script to generate the syscalls file for supported architectures.
+# Based on https://github.com/hrw/syscalls-table/
+#
+# Author: Andrea Cervesato <andrea.cervesato@suse.com>
+
+TEMP=$(mktemp -d)
+LINUX_SRC="$1"
+SYSCALLS_FILE="$2"
+
+if [ -z "${LINUX_SRC}" ]; then
+ echo "Give the path of Linux kernel sources:"
+ echo ""
+ echo "$0 linux/kernel/sources path/to/syscalls.h"
+ echo ""
+ exit 1
+fi
+
+if [ ! -e "${LINUX_SRC}/Makefile" ]; then
+ echo "No Makefile in ${LINUX_SRC} directory!"
+ exit 1
+fi
+
+if [ -z "${SYSCALLS_FILE}" ]; then
+ echo "No syscalls.h file location has been provided:"
+ echo ""
+ echo "$0 linux/kernel/sources path/to/syscalls.h"
+ echo ""
+ exit 1
+fi
+
+export LC_ALL=C
+
+SUPPORTED_ARCH="${PWD}/supported-arch.txt"
+LINUX_HEADERS="${TEMP}/headers"
+SYSCALLS_NAMES="${TEMP}/syscalls-names.txt"
+GENERATOR_BIN="${TEMP}/list-syscalls"
+GENERATOR_SRC="${GENERATOR_BIN}.c"
+
+build_headers() {
+ local arch="$1"
+
+ echo "Building linux headers..."
+
+ make -s -C ${LINUX_SRC} \
+ ARCH=${arch} \
+ O=${LINUX_HEADERS} \
+ headers_install >/dev/null
+}
+
+extract_syscalls() {
+ local arch="$1"
+ local flags="$2"
+
+ echo "Extracting syscalls names..."
+
+ grep -E -h "^#define __NR_" \
+ ${LINUX_HEADERS}/usr/include/asm/unistd*.h \
+ ${LINUX_HEADERS}/usr/include/asm-generic/unistd.h > \
+ ${TEMP}/syscalls-names.tosort
+
+ grep -E -v "(unistd.h|NR3264|__NR_syscall|__SC_COMP|__NR_.*Linux|__NR_FAST)" \
+ ${TEMP}/syscalls-names.tosort |
+ grep -E -vi "(not implemented|available|unused|reserved|xtensa|spill)" |
+ grep -E -v "(__SYSCALL|SYSCALL_BASE|SYSCALL_MASK)" |
+ sed -e "s/#define\s*__NR_//g" -e "s/\s.*//g" |
+ sort -u >${SYSCALLS_NAMES}
+
+ grep -w -v -f ${PWD}/blacklist-syscalls.txt ${TEMP}/syscall-names.txt |
+ sort -u >${TEMP}/syscall-names.txt
+
+ (
+ echo
+ echo "
+ #include <stdio.h>
+ #include <asm/unistd.h>
+
+ int main(void) {"
+ while IFS= read -r syscall; do
+ echo "
+ #ifdef __NR_$syscall
+ printf(\"$syscall\\t%d\\n\", __NR_$syscall);
+ #endif"
+ done < ${SYSCALLS_NAMES}
+ echo "return 0; }"
+ ) >> ${GENERATOR_SRC}
+
+ local uppercase_arch=$(echo "$arch" | tr '[:lower:]' '[:upper:]')
+
+ gcc ${GENERATOR_SRC} -U__LP64__ -U__ILP32__ -U__i386__ \
+ -D${uppercase_arch} -D__${arch}__ ${flags} \
+ -I ${LINUX_HEADERS}/usr/include/ \
+ -o ${GENERATOR_BIN} &>/dev/null
+
+ echo "Generating ${arch}.in ..."
+
+ ${GENERATOR_BIN} > "${TEMP}/${arch}.in"
+}
+
+generate_syscalls() {
+ while IFS= read -r arch; do
+ echo "Preparing syscalls for ${arch} architecture..."
+
+ case ${arch} in
+ aarch64)
+ build_headers "arm64"
+ extract_syscalls "${arch}" "-D__ARM_EABI__"
+ ;;
+ arc)
+ build_headers "arc"
+ extract_syscalls "${arch}" "-D__BITS_PER_LONG=32"
+ ;;
+ arm)
+ build_headers "arm"
+ extract_syscalls "${arch}" "-D__BITS_PER_LONG=32"
+ ;;
+ hppa)
+ build_headers "parisc"
+ extract_syscalls "${arch}" ""
+ ;;
+ i386)
+ build_headers "x86"
+ extract_syscalls "${arch}" "-D__BITS_PER_LONG=32"
+ ;;
+ ia64)
+ # ia64 has been removed from the kernel, so we copy its
+ # last generated input file
+ echo "Copying ia64.in ..."
+ cp ${PWD}/ia64.in ${TEMP}/ia64.in
+ ;;
+ loongarch)
+ build_headers "loongarch"
+ extract_syscalls "${arch}" "-D_LOONGARCH_SZLONG=64"
+ ;;
+ mips_n32)
+ build_headers "mips"
+ extract_syscalls "${arch}" "-D_MIPS_SIM=_MIPS_SIM_NABI32"
+ ;;
+ mips_n64)
+ build_headers "mips"
+ extract_syscalls "${arch}" "-D_MIPS_SIM=_MIPS_SIM_ABI64"
+ ;;
+ mips_o32)
+ build_headers "mips"
+ extract_syscalls "${arch}" "-D_MIPS_SIM=_MIPS_SIM_ABI32"
+ ;;
+ powerpc)
+ build_headers "powerpc"
+ extract_syscalls "${arch}" "-D__BITS_PER_LONG=32"
+ ;;
+ powerpc64)
+ build_headers "powerpc"
+ extract_syscalls "${arch}" ""
+ ;;
+ s390)
+ build_headers "s390"
+ extract_syscalls "${arch}" "-D__BITS_PER_LONG=32"
+ ;;
+ s390x)
+ build_headers "s390"
+ extract_syscalls "${arch}" ""
+ ;;
+ sh)
+ build_headers "sh"
+ extract_syscalls "${arch}" "-D__BITS_PER_LONG=32"
+ ;;
+ sparc)
+ build_headers "sparc"
+ extract_syscalls "${arch}" "-D__32bit_syscall_numbers__ -D__BITS_PER_LONG=32"
+ ;;
+ sparc64)
+ build_headers "sparc64"
+ extract_syscalls "${arch}" "-D__arch64__"
+ ;;
+ x86_64)
+ build_headers "x86_64"
+ extract_syscalls "${arch}" "-D__LP64__"
+ ;;
+ *)
+ echo "Can't find '${arch}' architecture"
+ exit 1
+ ;;
+ esac
+ done < ${SUPPORTED_ARCH}
+}
+
+merge_syscalls() {
+ echo "Merging syscalls files..."
+
+ echo '
+/************************************************
+ * GENERATED FILE: DO NOT EDIT/PATCH THIS FILE *
+ * change your arch specific .in file instead *
+ ************************************************/
+
+/*
+ * Here we stick all the ugly *fallback* logic for linux
+ * system call numbers (those __NR_ thingies).
+ *
+ * Licensed under the GPLv2 or later, see the COPYING file.
+ */
+
+#ifndef LAPI_SYSCALLS_H__
+#define LAPI_SYSCALLS_H__
+
+#include <errno.h>
+#include <sys/syscall.h>
+#include <asm/unistd.h>
+
+#ifdef TST_TEST_H__
+#define TST_SYSCALL_BRK__(NR, SNR) ({ \
+ tst_brk(TCONF, \
+ "syscall(%d) " SNR " not supported on your arch", NR); \
+})
+#else
+inline static void dummy_cleanup(void) {}
+
+#define TST_SYSCALL_BRK__(NR, SNR) ({ \
+ tst_brkm(TCONF, dummy_cleanup, \
+ "syscall(%d) " SNR " not supported on your arch", NR); \
+})
+#endif
+
+#define tst_syscall(NR, ...) ({ \
+ intptr_t tst_ret; \
+ if (NR == __LTP__NR_INVALID_SYSCALL) { \
+ errno = ENOSYS; \
+ tst_ret = -1; \
+ } else { \
+ tst_ret = syscall(NR, ##__VA_ARGS__); \
+ } \
+ if (tst_ret == -1 && errno == ENOSYS) { \
+ TST_SYSCALL_BRK__(NR, #NR); \
+ } \
+ tst_ret; \
+})
+
+#define __LTP__NR_INVALID_SYSCALL -1' > ${SYSCALLS_FILE}
+
+ local syscall_nr=""
+
+ while IFS= read -r arch; do
+ (
+ echo
+ case ${arch} in
+ sparc64) echo "#if defined(__sparc__) && defined(__arch64__)" ;;
+ sparc) echo "#if defined(__sparc__) && !defined(__arch64__)" ;;
+ s390) echo "#if defined(__s390__) && !defined(__s390x__)" ;;
+ mips_n32) echo "#if defined(__mips__) && defined(_ABIN32)" ;;
+ mips_n64) echo "#if defined(__mips__) && defined(_ABI64)" ;;
+ mips_o32) echo "#if defined(__mips__) && defined(_ABIO32) && _MIPS_SZLONG == 32" ;;
+ *) echo "#ifdef __${arch}__" ;;
+ esac
+
+ while read -r line; do
+ set -- ${line}
+ syscall_nr="__NR_$1"
+ shift
+
+ echo "# ifndef ${syscall_nr}"
+ echo "# define ${syscall_nr} $*"
+ echo "# endif"
+ done <"${TEMP}/${arch}.in"
+ echo "#endif"
+ echo
+ ) >> ${SYSCALLS_FILE}
+ done < ${SUPPORTED_ARCH}
+
+ (
+ echo
+ echo "/* Common stubs */"
+ while IFS= read -r arch; do
+ while IFS= read -r line; do
+ set -- ${line}
+ syscall_nr="__NR_$1"
+ shift
+
+ echo "# ifndef ${syscall_nr}"
+ echo "# define ${syscall_nr} __LTP__NR_INVALID_SYSCALL"
+ echo "# endif"
+ done < ${TEMP}/${arch}.in
+ done < ${SUPPORTED_ARCH}
+ echo "#endif"
+ ) >> ${SYSCALLS_FILE}
+}
+
+echo "Temporary folder: ${TEMP}"
+
+generate_syscalls
+merge_syscalls
+
--
2.43.0
More information about the ltp
mailing list