forked from linux-test-project/ltp
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add script to automatically generate syscalls
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
- Loading branch information
Showing
2 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
arch_specific_syscall | ||
available | ||
ni_syscall | ||
reserved | ||
SYSCALL_MASK | ||
unused |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|