Skip to content

Commit

Permalink
Add script to automatically generate syscalls
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
  • Loading branch information
acerv committed Sep 23, 2024
1 parent 09489a8 commit 6e1ae6d
Show file tree
Hide file tree
Showing 2 changed files with 294 additions and 0 deletions.
6 changes: 6 additions & 0 deletions include/lapi/syscalls/blacklist-syscalls.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
arch_specific_syscall
available
ni_syscall
reserved
SYSCALL_MASK
unused
288 changes: 288 additions & 0 deletions include/lapi/syscalls/generate_syscalls.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
#!/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

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"
;;
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__"
;;
ia64)
echo "'${arch}' architecture is not supported"
echo 1
;;
*)
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

0 comments on commit 6e1ae6d

Please sign in to comment.