aboutgitcodelistschat:MatrixIRC
path: root/transform.sh
diff options
context:
space:
mode:
Diffstat (limited to 'transform.sh')
-rwxr-xr-xtransform.sh160
1 files changed, 160 insertions, 0 deletions
diff --git a/transform.sh b/transform.sh
new file mode 100755
index 0000000..1e9eaeb
--- /dev/null
+++ b/transform.sh
@@ -0,0 +1,160 @@
+#!/bin/sh -eu
+#
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#
+# SEITAN - Syscall Expressive Interpreter, Transformer and Notifier
+#
+# transform.sh - Build syscall transformation table headers
+#
+# Copyright (c) 2022 Red Hat GmbH
+# Author: Stefano Brivio <sbrivio@redhat.com>
+
+TMP="$(mktemp)"
+IN="${@}"
+OUT="transform.h"
+
+HEADER="/* This file was automatically generated by $(basename ${0}) */
+
+struct table {
+ int type;
+ long number;
+ char arg[1024][6];
+};"
+
+# Prefix for each profile
+PRE='
+struct table table_@PROFILE@[] = {'
+
+# Suffix for each profile
+POST='};
+'
+
+# cleanup() - Remove temporary file if it exists
+cleanup() {
+ rm -f "${TMP}"
+}
+trap "cleanup" EXIT
+
+# sub() - Substitute in-place file line with processed template line
+# $1: Line number
+# $2: Template name (variable name)
+# $@: Replacement for @KEY@ in the form KEY:value
+sub() {
+ IFS=
+ __line_no="${1}"
+ __template="$(eval printf '%s' "\${${2}}")"
+ shift; shift
+
+ sed -i "${__line_no}s#.*#${__template}#" "${TMP}"
+
+ IFS=' '
+ for __def in ${@}; do
+ __key="@${__def%%:*}@"
+ __value="${__def#*:}"
+ sed -i "${__line_no}s/${__key}/${__value}/" "${TMP}"
+ done
+ unset IFS
+}
+
+# finish() - Finalise header file from temporary files with prefix and suffix
+# $1: Variable name of prefix
+# $@: Replacements for prefix variable
+finish() {
+ IFS=
+ __out="$(eval printf '%s' "\${${1}}")"
+ shift
+
+ IFS=' '
+ for __def in ${@}; do
+ __key="@${__def%%:*}@"
+ __value="${__def#*:}"
+ __out="$(printf '%s' "${__out}" | sed "s#${__key}#${__value}#")"
+ done
+
+ printf '%s\n' "${__out}" >> "${OUT}"
+ cat "${TMP}" >> "${OUT}"
+ rm "${TMP}"
+ printf '%s' "${POST}" >> "${OUT}"
+ unset IFS
+}
+
+# syscall_nr - Get syscall number from compiler
+# $1: Name of syscall
+syscall_nr() {
+ __in="$(printf "#include <asm-generic/unistd.h>\n#include <sys/syscall.h>\n__NR_%s" ${1})"
+ __out="$(echo "${__in}" | cc -E -xc - -o - | tail -1)"
+ [ "${__out}" = "__NR_$1" ] && return 1
+
+ # Output might be in the form "(x + y)" (seen on armv6l, armv7l)
+ __out="$(eval echo $((${__out})))"
+ echo "${__out}"
+}
+
+filter() {
+ __filtered=
+ for __c in ${@}; do
+ __arch_match=0
+ case ${__c} in
+ *:*)
+ case ${__c} in
+ $(uname -m):*)
+ __arch_match=1
+ __c=${__c##*:}
+ ;;
+ esac
+ ;;
+ *)
+ __arch_match=1
+ ;;
+ esac
+ [ ${__arch_match} -eq 0 ] && continue
+
+ IFS='| '
+ __found=0
+ for __name in ${__c}; do
+ syscall_nr "${__name}" >/dev/null && __found=1 && break
+ done
+ unset IFS
+
+ if [ ${__found} -eq 0 ]; then
+ echo
+ echo "Warning: no syscall number for ${__c}" >&2
+ echo " none of these syscalls will be allowed" >&2
+ continue
+ fi
+
+ __filtered="${__filtered} ${__name}"
+ done
+
+ echo "${__filtered}" | tr ' ' '\n' | sort -u
+}
+
+printf '%s\n' "${HEADER}" > "${OUT}"
+__profiles="${IN}"
+for __p in ${__profiles}; do
+ IFS='
+'
+ for __l in $(grep "^[a-z].*" "${__p}" | tr -s '\t'); do
+ unset IFS
+ __syscall_token="$(echo "${__l}" | cut -f1)"
+ __type_token="$(echo "${__l}" | cut -f2)"
+ __arg1_token="$(echo "${__l}" | cut -f3)"
+ __arg2_token="$(echo "${__l}" | cut -f4)"
+ __arg3_token="$(echo "${__l}" | cut -f5)"
+ __arg4_token="$(echo "${__l}" | cut -f6)"
+ __arg5_token="$(echo "${__l}" | cut -f7)"
+ __arg6_token="$(echo "${__l}" | cut -f8)"
+
+ __syscall_nr="$(syscall_nr "${__syscall_token}")"
+ __type_enum="$(echo ${__type_token} | tr [a-z] [A-Z])"
+
+ printf "\t{ %i, %s, \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", },\n" \
+ ${__syscall_nr} "${__type_enum}" \
+ "${__arg1_token}" "${__arg2_token}" "${__arg3_token}" \
+ "${__arg4_token}" "${__arg5_token}" "${__arg6_token}" \
+ >> "${TMP}"
+ IFS='
+'
+ done
+ finish PRE "PROFILE:${__p}"
+done