summaryrefslogtreecommitdiffstats
path: root/src/arch-syscall-validate
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch-syscall-validate')
-rwxr-xr-xsrc/arch-syscall-validate867
1 files changed, 867 insertions, 0 deletions
diff --git a/src/arch-syscall-validate b/src/arch-syscall-validate
new file mode 100755
index 0000000..3b69e9b
--- /dev/null
+++ b/src/arch-syscall-validate
@@ -0,0 +1,867 @@
+#!/bin/bash
+
+#
+# libseccomp syscall validation script
+#
+# Copyright (c) 2014 Red Hat <pmoore@redhat.com>
+# Copyright (c) 2020 Cisco Systems, Inc. <pmoore2@cisco.com>
+#
+# Author: Paul Moore <paul@paul-moore.com>
+#
+
+#
+# This library is free software; you can redistribute it and/or modify it
+# under the terms of version 2.1 of the GNU Lesser General Public License as
+# published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+# for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library; if not, see <http://www.gnu.org/licenses>.
+#
+
+LIB_SYS_DUMP="./arch-syscall-dump"
+
+####
+# functions
+
+#
+# Dependency check
+#
+# Arguments:
+# 1 Dependency to check for
+#
+function check_deps() {
+ [[ -z "$1" ]] && return
+ which "$1" >& /dev/null
+ return $?
+}
+
+#
+# Dependency verification
+#
+# Arguments:
+# 1 Dependency to check for
+#
+function verify_deps() {
+ [[ -z "$1" ]] && return
+ if ! check_deps "$1"; then
+ echo "error: install \"$1\" and include it in your \$PATH"
+ exit 1
+ fi
+}
+
+#
+# Print out script usage details
+#
+function usage() {
+cat << EOF
+usage: arch-syscall-validate [-h] [-c] [-a <arch>] <kernel_directory>
+
+libseccomp syscall validation script
+optional arguments:
+ -h show this help message and exit
+ -a architecture
+ -l output the library's syscall definitions
+ -s output the kernel's syscall definitions
+ -c generate a CSV of the kernel's syscall definitions
+EOF
+}
+
+#
+# Dump the kernel version
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the kernel's version information to stdout.
+#
+function kernel_version() {
+ local maj=$(cat $1/Makefile | \
+ grep "^VERSION =" | awk -F "= " '{ print $2 }')
+ local min=$(cat $1/Makefile | \
+ grep "^PATCHLEVEL =" | awk -F "= " '{ print $2 }')
+ local sub=$(cat $1/Makefile | \
+ grep "^SUBLEVEL =" | awk -F "= " '{ print $2 }')
+ local xtr=$(cat $1/Makefile | \
+ grep "^EXTRAVERSION =" | awk -F "= " '{ print $2 }')
+ echo "${maj}.${min}.${sub}${xtr}"
+}
+
+#
+# Dump the library syscall table for a given architecture
+#
+# Arguments:
+# 1 architecture
+# 2 offset (optional)
+#
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_arch() {
+ local offset_str=""
+
+ [[ -z $1 ]] && return
+
+ [[ -n $2 ]] && offset_str="-o $2"
+ $LIB_SYS_DUMP -a $1 $offset_str | sed 's/\t/,/' | sort
+}
+
+#
+# Mangle the library pseudo syscall values
+#
+# Arguments:
+# 1 architecture
+#
+# Mangle the supplied pseudo syscall to match the system values
+#
+function mangle_lib_syscall() {
+ local sed_filter=""
+
+ sed_filter+='s/accept4,-118/accept4,364/;'
+ sed_filter+='s/bind,-102/bind,361/;'
+ sed_filter+='s/connect,-103/connect,362/;'
+ sed_filter+='s/getpeername,-107/getpeername,368/;'
+ sed_filter+='s/getsockname,-106/getsockname,367/;'
+ sed_filter+='s/getsockopt,-115/getsockopt,365/;'
+ sed_filter+='s/listen,-104/listen,363/;'
+ sed_filter+='s/msgctl,-214/msgctl,402/;'
+ sed_filter+='s/msgget,-213/msgget,399/;'
+ sed_filter+='s/msgrcv,-212/msgrcv,401/;'
+ sed_filter+='s/msgsnd,-211/msgsnd,400/;'
+ sed_filter+='s/recvfrom,-112/recvfrom,371/;'
+ sed_filter+='s/recvmsg,-117/recvmsg,372/;'
+ sed_filter+='s/semctl,-203/semctl,394/;'
+ sed_filter+='s/semget,-202/semget,393/;'
+ sed_filter+='s/sendmsg,-116/sendmsg,370/;'
+ sed_filter+='s/sendto,-111/sendto,369/;'
+ sed_filter+='s/setsockopt,-114/setsockopt,366/;'
+ sed_filter+='s/shmat,-221/shmat,397/;'
+ sed_filter+='s/shmctl,-224/shmctl,396/;'
+ sed_filter+='s/shmdt,-222/shmdt,398/;'
+ sed_filter+='s/shmget,-223/shmget,395/;'
+ sed_filter+='s/shutdown,-113/shutdown,373/;'
+ sed_filter+='s/socket,-101/socket,359/;'
+ sed_filter+='s/socketpair,-108/socketpair,360/;'
+
+ case $1 in
+ s390|s390x)
+ sed_filter+='s/recvmmsg,-119/recvmmsg,357/;'
+ sed_filter+='s/sendmmsg,-120/sendmmsg,358/;'
+ ;;
+ *)
+ sed_filter+='s/recvmmsg,-119/recvmmsg,337/;'
+ sed_filter+='s/sendmmsg,-120/sendmmsg,345/;'
+ ;;
+ esac
+
+ sed $sed_filter | sed '/,-[0-9]\+$/d'
+}
+
+#
+# Dump the x86 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_x86() {
+ cat $1/arch/x86/entry/syscalls/syscall_32.tbl | \
+ grep -v "^#" | awk '{ print $3","$1 }' | \
+ sort
+}
+
+#
+# Dump the x86 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_x86() {
+ dump_lib_arch x86 | mangle_lib_syscall x86
+}
+
+#
+# Dump the x86_64 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_x86_64() {
+ cat $1/arch/x86/entry/syscalls/syscall_64.tbl | \
+ grep -v "^#" | sed '/^$/d' | awk '{ print $2,$3,$1 }' | \
+ sed '/^x32/d' | awk '{ print $2","$3 }' | sort
+}
+
+#
+# Dump the x86_64 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_x86_64() {
+ dump_lib_arch x86_64 | mangle_lib_syscall x86_64
+}
+
+#
+# Dump the x32 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_x32() {
+ cat $1/arch/x86/entry/syscalls/syscall_64.tbl | \
+ grep -v "^#" | sed '/^$/d' | awk '{ print $2,$3,$1 }' | \
+ sed '/^64/d' | awk '{ print $2","$3 }' | sort
+}
+
+#
+# Dump the x32 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_x32() {
+ dump_lib_arch x32 | mangle_lib_syscall x32
+}
+
+#
+# Dump the arm system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_arm() {
+ cat $1/arch/arm/tools/syscall.tbl | grep -v "^#" | \
+ sed -n "/[0-9]\+[ \t]\+\(common\|eabi\)/p" | \
+ awk '{ print $3","$1 }' | sort | (cat -; \
+ (cat $1/arch/arm/include/uapi/asm/unistd.h | \
+ grep "^#define __ARM_NR_" | \
+ grep -v "^#define __ARM_NR_BASE" | \
+ sed 's/#define __ARM_NR_\([a-z0-9_]*\)[ \t]\+(__ARM_NR_BASE+\(.*\))/\1 983040 + \2/' | \
+ awk '{ print $1","$2+$4 }')) | sort
+}
+
+#
+# Dump the arm library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_arm() {
+ # NOTE: arm_sync_file_range() and sync_file_range2() share values
+ dump_lib_arch arm | sed '/sync_file_range2,\+341/d' | \
+ mangle_lib_syscall arm
+}
+
+#
+# Dump the aarch64 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_aarch64() {
+ local sed_filter=""
+
+ sed_filter+='s/__NR3264_statfs/43/;'
+ sed_filter+='s/__NR3264_ftruncate/46/;'
+ sed_filter+='s/__NR3264_truncate/45/;'
+ sed_filter+='s/__NR3264_lseek/62/;'
+ sed_filter+='s/__NR3264_sendfile/71/;'
+ sed_filter+='s/__NR3264_fstatat/79/;'
+ sed_filter+='s/__NR3264_fstatfs/44/;'
+ sed_filter+='s/__NR3264_fcntl/25/;'
+ sed_filter+='s/__NR3264_fadvise64/223/;'
+ sed_filter+='s/__NR3264_mmap/222/;'
+ sed_filter+='s/__NR3264_fstat/80/;'
+ sed_filter+='s/__NR3264_lstat/1039/;'
+ sed_filter+='s/__NR3264_stat/1038/;'
+
+ gcc -E -dM -I$1/include/uapi \
+ -D__BITS_PER_LONG=64 -D__ARCH_WANT_RENAMEAT \
+ -D__ARCH_WANT_NEW_STAT \
+ $1/arch/arm64/include/uapi/asm/unistd.h | \
+ grep "^#define __NR_" | \
+ sed '/__NR_syscalls/d' | \
+ sed '/__NR_arch_specific_syscall/d' | \
+ sed 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+\(.*\)/\1,\2/' | \
+ sed $sed_filter | sort
+}
+
+#
+# Dump the aarch64 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_aarch64() {
+ dump_lib_arch aarch64 | mangle_lib_syscall aarch64
+}
+
+#
+# Dump the mips system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_mips() {
+ cat $1/arch/mips/kernel/syscalls/syscall_o32.tbl | \
+ grep -v "^#" | \
+ sed -e '/[ \t]\+reserved[0-9]\+[ \t]\+/d;' | \
+ sed -e '/[ \t]\+unused[0-9]\+[ \t]\+/d;' | \
+ awk '{ print $3","$1 }' | sort
+}
+
+#
+# Dump the mips library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_mips() {
+ dump_lib_arch mips | mangle_lib_syscall mips
+}
+
+#
+# Dump the mips64 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_mips64() {
+ cat $1/arch/mips/kernel/syscalls/syscall_n64.tbl | \
+ grep -v "^#" | \
+ sed -e '/[ \t]\+reserved[0-9]\+[ \t]\+/d;' | \
+ sed -e '/[ \t]\+unused[0-9]\+[ \t]\+/d;' | \
+ awk '{ print $3","$1 }' | sort
+}
+
+#
+# Dump the mips64 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_mips64() {
+ dump_lib_arch mips64 | mangle_lib_syscall mips64
+}
+
+#
+# Dump the mips64n32 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_mips64n32() {
+ cat $1/arch/mips/kernel/syscalls/syscall_n32.tbl | \
+ grep -v "^#" | \
+ sed -e '/[ \t]\+reserved[0-9]\+[ \t]\+/d;' | \
+ sed -e '/[ \t]\+unused[0-9]\+[ \t]\+/d;' | \
+ awk '{ print $3","$1 }' | sort
+}
+
+#
+# Dump the mips64n32 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_mips64n32() {
+ dump_lib_arch mips64n32 | mangle_lib_syscall mips64n32
+}
+
+#
+# Dump the parisc system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_parisc() {
+ cat $1/arch/parisc/kernel/syscalls/syscall.tbl | \
+ grep -v "^#" | \
+ sed -n "/[0-9]\+[ \t]\+\(common\|32\)/p" | \
+ awk '{ print $3","$1 }' | \
+ sort
+}
+
+#
+# Dump the parisc library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_parisc() {
+ dump_lib_arch parisc | mangle_lib_syscall parisc
+}
+
+#
+# Dump the parisc64 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_parisc64() {
+ cat $1/arch/parisc/kernel/syscalls/syscall.tbl | \
+ grep -v "^#" | \
+ sed -n "/[0-9]\+[ \t]\+\(common\|64\)/p" | \
+ awk '{ print $3","$1 }' | \
+ sort
+}
+
+#
+# Dump the parisc64 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_parisc64() {
+ dump_lib_arch parisc64 | mangle_lib_syscall parisc64
+}
+
+#
+# Dump the ppc system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_ppc() {
+ cat $1/arch/powerpc/kernel/syscalls/syscall.tbl | grep -v "^#" | \
+ sed -ne "/[0-9]\+[ \t]\+\(common\|nospu\|32\)/p" | \
+ awk '{ print $3","$1 }' | sort
+}
+
+#
+# Dump the ppc library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_ppc() {
+ dump_lib_arch ppc | mangle_lib_syscall ppc
+}
+
+#
+# Dump the ppc64 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_ppc64() {
+ cat $1/arch/powerpc/kernel/syscalls/syscall.tbl | grep -v "^#" | \
+ sed -ne "/[0-9]\+[ \t]\+\(common\|nospu\|64\)/p" | \
+ awk '{ print $3","$1 }' | sort
+}
+
+#
+# Dump the ppc64 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_ppc64() {
+ dump_lib_arch ppc64 | mangle_lib_syscall ppc64
+}
+
+#
+# Dump the riscv64 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_riscv64() {
+ local sed_filter=""
+
+ sed_filter+='s/__NR3264_fadvise64/223/;'
+ sed_filter+='s/__NR3264_fcntl/25/;'
+ sed_filter+='s/__NR3264_fstatat/79/;'
+ sed_filter+='s/__NR3264_fstatfs/44/;'
+ sed_filter+='s/__NR3264_ftruncate/46/;'
+ sed_filter+='s/__NR3264_lseek/62/;'
+ sed_filter+='s/__NR3264_mmap/222/;'
+ sed_filter+='s/__NR3264_sendfile/71/;'
+ sed_filter+='s/__NR3264_statfs/43/;'
+ sed_filter+='s/__NR3264_truncate/45/;'
+ sed_filter+='s/__NR3264_fstat/80/;'
+
+ gcc -E -dM -I$1/include/uapi \
+ -D__BITS_PER_LONG=64 -D__ARCH_WANT_NEW_STAT \
+ $1/arch/riscv/include/uapi/asm/unistd.h | \
+ grep "^#define __NR_" | \
+ sed '/__NR_syscalls/d' | \
+ sed 's/(__NR_arch_specific_syscall + 15)/259/' | \
+ sed '/__NR_arch_specific_syscall/d' | \
+ sed 's/#define[ \t]\+__NR_\([^ \t]\+\)[ \t]\+\(.*\)/\1,\2/' | \
+ sed $sed_filter | sort
+}
+
+#
+# Dump the riscv64 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_riscv64() {
+ dump_lib_arch riscv64 | mangle_lib_syscall riscv64
+}
+
+#
+# Dump the s390 system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_s390() {
+ cat $1/arch/s390/kernel/syscalls/syscall.tbl | grep -v "^#" | \
+ sed -ne "/[0-9]\+[ \t]\+\(common\|32\)/p" | \
+ awk '{ print $3","$1 }' | \
+ sort
+}
+
+#
+# Dump the s390 library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_s390() {
+ dump_lib_arch s390 | mangle_lib_syscall s390
+}
+
+#
+# Dump the s390x system syscall table
+#
+# Arguments:
+# 1 path to the kernel source
+#
+# Dump the architecture's syscall table to stdout.
+#
+function dump_sys_s390x() {
+ cat $1/arch/s390/kernel/syscalls/syscall.tbl | grep -v "^#" | \
+ sed -ne "/[0-9]\+[ \t]\+\(common\|64\)/p" | \
+ awk '{ print $3","$1 }' | \
+ sort
+}
+
+#
+# Dump the s390x library syscall table
+#
+# Dump the library's syscall table to stdout.
+#
+function dump_lib_s390x() {
+ dump_lib_arch s390x | mangle_lib_syscall s390x
+}
+
+#
+# Dump the system syscall table
+#
+# Arguments:
+# 1 architecture
+# 2 path to the kernel source
+#
+# Dump the system's syscall table to stdout using the given architecture.
+#
+function dump_sys() {
+ case $1 in
+ x86)
+ dump_sys_x86 "$2"
+ ;;
+ x86_64)
+ dump_sys_x86_64 "$2"
+ ;;
+ x32)
+ dump_sys_x32 "$2"
+ ;;
+ arm)
+ dump_sys_arm "$2"
+ ;;
+ aarch64)
+ dump_sys_aarch64 "$2"
+ ;;
+ mips)
+ dump_sys_mips "$2"
+ ;;
+ mips64)
+ dump_sys_mips64 "$2"
+ ;;
+ mips64n32)
+ dump_sys_mips64n32 "$2"
+ ;;
+ parisc)
+ dump_sys_parisc "$2"
+ ;;
+ parisc64)
+ dump_sys_parisc64 "$2"
+ ;;
+ ppc)
+ dump_sys_ppc "$2"
+ ;;
+ ppc64)
+ dump_sys_ppc64 "$2"
+ ;;
+ riscv64)
+ dump_sys_riscv64 "$2"
+ ;;
+ s390)
+ dump_sys_s390 "$2"
+ ;;
+ s390x)
+ dump_sys_s390x "$2"
+ ;;
+ *)
+ echo ""
+ return 1
+ ;;
+ esac
+
+ return 0
+}
+
+#
+# Dump the library syscall table
+#
+# Arguments:
+# 1 architecture
+#
+# Dump the library's syscall table to stdout using the given architecture.
+#
+function dump_lib() {
+ case $1 in
+ x86)
+ dump_lib_x86
+ ;;
+ x86_64)
+ dump_lib_x86_64
+ ;;
+ x32)
+ dump_lib_x32
+ ;;
+ arm)
+ dump_lib_arm
+ ;;
+ aarch64)
+ dump_lib_aarch64
+ ;;
+ mips)
+ dump_lib_mips
+ ;;
+ mips64)
+ dump_lib_mips64
+ ;;
+ mips64n32)
+ dump_lib_mips64n32
+ ;;
+ parisc)
+ dump_lib_parisc
+ ;;
+ parisc64)
+ dump_lib_parisc64
+ ;;
+ ppc)
+ dump_lib_ppc
+ ;;
+ ppc64)
+ dump_lib_ppc64
+ ;;
+ riscv64)
+ dump_lib_riscv64
+ ;;
+ s390)
+ dump_lib_s390
+ ;;
+ s390x)
+ dump_lib_s390x
+ ;;
+ *)
+ echo ""
+ return 1
+ ;;
+ esac
+
+ return 0
+}
+
+#
+# Generate the syscall csv file
+#
+# Arguments:
+# 1 path to the kernel source
+# 2 "sys" or "lib" depending on the syscall list to use
+#
+# Generare a syscall csv file from the given kernel sources.
+#
+function gen_csv() {
+
+ # sanity checks
+ [[ -z $1 ]] && return
+ [[ $2 != "sys" && $2 != "lib" ]] && return
+
+ # abi list
+ # NOTE: the ordering here is dependent on the layout of the
+ # arch_syscall_table struct in syscalls.h - BEWARE!
+ abi_list=""
+ abi_list+=" x86 x86_64 x32"
+ abi_list+=" arm aarch64"
+ abi_list+=" mips mips64 mips64n32"
+ abi_list+=" parisc parisc64"
+ abi_list+=" ppc ppc64"
+ abi_list+=" riscv64"
+ abi_list+=" s390 s390x"
+
+ # get the full syscall list
+ for abi in $abi_list; do
+ eval output_$abi=$(mktemp -t syscall_validate_XXXXXX)
+ dump_$2_$abi "$1" > $(eval echo $`eval echo output_$abi`)
+ done
+ sc_list=$((for abi in $abi_list; do
+ cat $(eval echo $`eval echo output_$abi`);
+ done) | awk -F "," '{ print $1 }' | sort -u)
+
+ # output a simple header
+ printf "#syscall (v%s %s)" \
+ "$(kernel_version "$1")" "$(TZ=UTC date "+%Y-%m-%d")"
+ for abi in $abi_list; do
+ printf ",%s" $abi
+ done
+ printf "\n"
+
+ # output the syscall csv details
+ for sc in $sc_list; do
+ printf "%s" $sc
+ for abi in $abi_list; do
+ num=$(grep "^$sc," \
+ $(eval echo $`eval echo output_$abi`) | \
+ awk -F "," '{ print $2 }' )
+ [[ -z $num ]] && num="PNR"
+ printf ",%s" $num
+ done
+ printf "\n"
+ done
+
+ # cleanup
+ for abi in $abi_list; do
+ rm -f $(eval echo $`eval echo output_$abi`)
+ done
+}
+
+####
+# main
+
+verify_deps diff
+verify_deps gcc
+verify_deps grep
+verify_deps mktemp
+verify_deps sed
+if [[ ! -x $LIB_SYS_DUMP ]]; then
+ echo "error: \"$LIB_SYS_DUMP\" is not in the current working directory"
+ exit 1
+fi
+
+opt_arches=""
+opt_csv=0
+opt_sys=0
+opt_lib=0
+
+while getopts "a:cslh" opt; do
+ case $opt in
+ a)
+ opt_arches+="$OPTARG "
+ ;;
+ c)
+ opt_csv=1
+ ;;
+ s)
+ opt_sys=1
+ opt_lib=0
+ ;;
+ l)
+ opt_sys=0
+ opt_lib=1
+ ;;
+ h|*)
+ usage
+ exit 1
+ ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+# defaults
+if [[ $opt_arches == "" ]]; then
+ opt_arches=" \
+ x86 x86_64 x32 \
+ arm aarch64 \
+ mips mips64 mips64n32 \
+ parisc parisc64 \
+ ppc ppc64 \
+ s390 s390x"
+fi
+
+# sanity checks
+kernel_dir="$1"
+if [[ -z $kernel_dir ]]; then
+ usage
+ exit 1
+fi
+if [[ ! -d $kernel_dir ]]; then
+ echo "error: \"$1\" is not a valid directory"
+ exit 1
+fi
+
+# generate some temp files
+tmp_lib=$(mktemp -t syscall_validate_XXXXXX)
+tmp_sys=$(mktemp -t syscall_validate_XXXXXX)
+
+if [[ $opt_csv -eq 1 ]]; then
+ # generate the syscall csv file
+ if [[ $opt_lib -eq 1 ]]; then
+ gen_csv $kernel_dir "lib"
+ else
+ gen_csv $kernel_dir "sys"
+ fi
+else
+ # loop through the architectures and compare
+ for i in $opt_arches; do
+ # dump the syscall tables
+ dump_lib $i > $tmp_lib
+ if [[ $? -ne 0 ]]; then
+ echo "error: unknown arch $i"
+ exit 1
+ fi
+ dump_sys $i "$kernel_dir" > $tmp_sys
+ if [[ $? -ne 0 ]]; then
+ echo "error: unknown arch $i"
+ exit 1
+ fi
+
+ if [[ $opt_lib -eq 1 ]]; then
+ cat $tmp_lib
+ elif [[ $opt_sys -eq 1 ]]; then
+ cat $tmp_sys
+ else
+ # compare the lib and sys output
+ diff -u --label="$i [library]" $tmp_lib \
+ --label "$i [system]" $tmp_sys
+ fi
+ done
+fi
+
+# cleanup and exit
+rm -f $tmp_lib $tmp_sys
+
+exit 0