logo

mstrace

Small Linux strace(1) implementation
commit: b1ab1aca67934866324807306176375f4e08b06c
parent 76b8c037209b30660ccb2cc4f7de533de648ab5c
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Wed, 27 Nov 2024 09:29:38 +0100

Use a simple DSL to generate syscall case-handles

Means a slightly bigger binary but likely could be optimised later
into something like a table describing each syscall.

Diffstat:

M.gitignore2++
MMakefile11++++++++---
Mprint_syscall.c182+------------------------------------------------------------------------------
Asyscalls.sh56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asyscalls.txt46++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 113 insertions(+), 184 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -5,3 +5,5 @@ /strsyscall.c /strsyscall.h /tmp_strsyscall.h +/syscalls_cases.h +/print_syscall.o diff --git a/Makefile b/Makefile @@ -1,8 +1,13 @@ # SPDX-FileCopyrightText: 2024 Haelwenn (lanodan) Monnier <contact+ministrace@hacktivis.me> # SPDX-License-Identifier: MPL-2.0 -ministrace: ministrace.c strsyscall.c print_syscall.c - ${CC} -std=c99 ${CFLAGS} -o ministrace ministrace.c strsyscall.c print_syscall.c ${LDFLAGS} ${LDSTATIC} +ministrace: ministrace.c strsyscall.c print_syscall.o + ${CC} -std=c99 ${CFLAGS} -o ministrace ministrace.c strsyscall.c print_syscall.o ${LDFLAGS} ${LDSTATIC} + +print_syscall.o: print_syscall.c syscalls_cases.h + +syscalls_cases.h: syscalls.txt syscalls.sh + ./syscalls.sh tmp_strsyscall.h: ${CC} -undef -E -P -fdirectives-only -o tmp_strsyscall.h - <<<'#include <sys/syscall.h>' @@ -12,7 +17,7 @@ strsyscall.c: strsyscall.sh tmp_strsyscall.h .PHONY: clean clean: - rm ministrace tmp_strsyscall.h strsyscall.c + rm -f ministrace tmp_strsyscall.h strsyscall.c print_syscall.o .PHONY: format format: diff --git a/print_syscall.c b/print_syscall.c @@ -52,189 +52,9 @@ read_str(intptr_t addr, size_t len) void print_syscall(__u64 nr, __u64 args[6]) { - // * Non-exhaustive - // * Doesn't handles special cases like structures or arrays - - // Ordered by number-of-arguments/complexity switch(nr) { - // int, path, buf, size - case SYS_readlinkat: - fprintf(stderr, - "%s(" Pri_i ", " Pri_str ", " Pri_x ", %zd)", - str_syscalls[nr], - (int64_t)args[0], - read_str(args[1], PATH_MAX), - (int64_t)args[2], - (size_t)args[3]); - return; - // int, path, oct, oct - case SYS_openat: - case SYS_faccessat: - fprintf(stderr, - "%s(" Pri_i ", " Pri_str ", " Pri_o ", " Pri_o ")", - str_syscalls[nr], - (int64_t)args[0], - read_str(args[1], PATH_MAX), - (int64_t)args[2], - (int64_t)args[3]); - return; - // path, hex, hex - case SYS_execve: - fprintf(stderr, - "%s(" Pri_str ", " Pri_x ", " Pri_x ")", - str_syscalls[nr], - read_str(args[0], PATH_MAX), - (uint64_t)args[1], - (uint64_t)args[2]); - return; - // int, buf, size - case SYS_write: - case SYS_read: - // Need handling of non-printable characters to print buf - fprintf(stderr, - "%s(" Pri_i ", " Pri_x ", %zd)", - str_syscalls[nr], - (int64_t)args[0], - (int64_t)args[1], - (size_t)args[2]); - return; - // int, path, path - case SYS_linkat: - case SYS_symlinkat: - fprintf(stderr, - "%s(" Pri_i ", " Pri_str ", " Pri_str ")", - str_syscalls[nr], - (int64_t)args[0], - read_str(args[1], PATH_MAX), - read_str(args[2], PATH_MAX)); - return; - // path, buf, size - case SYS_readlink: - fprintf(stderr, - "%s(" Pri_str ", " Pri_x ", %zd)", - str_syscalls[nr], - read_str(args[0], PATH_MAX), - (int64_t)args[1], - (size_t)args[2]); - return; - // path, oct, oct - case SYS_open: - fprintf(stderr, - "%s(" Pri_str ", " Pri_o ", " Pri_o ")", - str_syscalls[nr], - read_str(args[0], PATH_MAX), - (int64_t)args[1], - (int64_t)args[2]); - return; - // path, int, int - case SYS_chown: - case SYS_lchown: - fprintf(stderr, - "%s(" Pri_str ", " Pri_i ", " Pri_o ")", - str_syscalls[nr], - read_str(args[0], PATH_MAX), - (int64_t)args[1], - (int64_t)args[2]); - return; - // path, path - case SYS_link: - case SYS_symlink: - case SYS_rename: - fprintf(stderr, - "%s(" Pri_str ", " Pri_str ")", - str_syscalls[nr], - read_str(args[0], PATH_MAX), - read_str(args[1], PATH_MAX)); - return; - // path, off_t - case SYS_truncate: - fprintf(stderr, - "%s(" Pri_str ", " Pri_u ")", - str_syscalls[nr], - read_str(args[0], PATH_MAX), - (off_t)args[1]); - return; - // path, size - case SYS_getcwd: - fprintf(stderr, - "%s(" Pri_str ", %zd)", - str_syscalls[nr], - read_str(args[0], PATH_MAX), - (size_t)args[1]); - return; - // path, oct - case SYS_access: - case SYS_stat: - case SYS_lstat: - case SYS_mkdir: - case SYS_creat: - case SYS_chmod: - fprintf(stderr, - "%s(" Pri_str ", " Pri_o ")", - str_syscalls[nr], - read_str(args[0], PATH_MAX), - (int64_t)args[1]); - return; - // int, path - case SYS_unlinkat: - fprintf(stderr, - "%s(" Pri_i ", " Pri_str ")", - str_syscalls[nr], - (int64_t)args[0], - read_str(args[1], PATH_MAX)); - return; - // int, off_t - case SYS_ftruncate: - fprintf(stderr, "%s(" Pri_i ", " Pri_u ")", str_syscalls[nr], (int64_t)args[0], (off_t)args[1]); - return; - // int, oct - case SYS_fchmod: - fprintf( - stderr, "%s(" Pri_i ", " Pri_o ")", str_syscalls[nr], (int64_t)args[0], (int64_t)args[1]); - return; - // int, int - case SYS_kill: - case SYS_dup2: - fprintf( - stderr, "%s(" Pri_i ", " Pri_i ")", str_syscalls[nr], (int64_t)args[0], (int64_t)args[1]); - return; - // path - case SYS_unlink: - case SYS_rmdir: - case SYS_chdir: - fprintf(stderr, "%s(" Pri_str ")", str_syscalls[nr], read_str(args[0], PATH_MAX)); - return; - // hex - case SYS_brk: - fprintf(stderr, "%s(" Pri_x ")", str_syscalls[nr], (int64_t)args[0]); - return; - // oct - case SYS_umask: - fprintf(stderr, "%s(" Pri_o ")", str_syscalls[nr], (int64_t)args[0]); - return; - // int - case SYS_dup: - case SYS_close: - case SYS_fsync: - case SYS_fdatasync: - fprintf(stderr, "%s(" Pri_i ")", str_syscalls[nr], (int64_t)args[0]); - return; - // uint - case SYS_alarm: - fprintf(stderr, "%s(" Pri_u ")", str_syscalls[nr], (uint64_t)args[0]); - return; - // syscall0 - case SYS_getpid: - case SYS_getppid: - case SYS_munlockall: - case SYS_setsid: - case SYS_sync: - case SYS_fork: - case SYS_vfork: - case SYS_pause: - fprintf(stderr, "%s()", str_syscalls[nr]); - return; +#include "syscalls_cases.h" // fallback default: assert(nr < SYSCALLS_MAX); diff --git a/syscalls.sh b/syscalls.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +while read syscall args +do + fmt='"%s("' + fmt_args='str_syscalls[nr]' + fmt_sep='' + + n=0 + for i in $args; do + case $i in + "") + break + ;; + "size") + fmt="${fmt}${fmt_sep}\"%zd\"" + fmt_args="${fmt_args}, (size_t)args[$n]" + ;; + "off") + fmt="${fmt}${fmt_sep}Pri_u" + fmt_args="${fmt_args}, (off_t)args[$n]" + ;; + "uint") + fmt="${fmt}${fmt_sep}Pri_u" + fmt_args="${fmt_args}, (uint64_t)args[$n]" + ;; + "int") + fmt="${fmt}${fmt_sep}Pri_i" + fmt_args="${fmt_args}, (int64_t)args[$n]" + ;; + "oct") + fmt="${fmt}${fmt_sep}Pri_o" + fmt_args="${fmt_args}, (int64_t)args[$n]" + ;; + "hex"|"buf") + fmt="${fmt}${fmt_sep}Pri_x" + fmt_args="${fmt_args}, (int64_t)args[$n]" + ;; + "path") + fmt="${fmt}${fmt_sep}Pri_str" + fmt_args="${fmt_args}, read_str(args[$n], PATH_MAX)" + ;; + *) + echo "syscalls.sh: error: Unhandled type ${i}" >&2 + exit 1 + esac + : $((n+=1)) + fmt_sep=' ", " ' + done + + fmt="${fmt}"' ")"' + + printf ' case SYS_%s:\n' "$syscall" + printf ' fprintf(stderr, %s, %s);\n' "$fmt" "$fmt_args" + printf ' return;\n' +done <syscalls.txt >syscalls_cases.h diff --git a/syscalls.txt b/syscalls.txt @@ -0,0 +1,46 @@ +access path oct +alarm uint +brk hex +chdir path +chmod path oct +chown path int int +close int +creat path oct +dup int +dup2 int int +execve path hex hex +faccessat int path oct oct +fchmod int oct +fdatasync int +fork +fsync int +ftruncate int off +getcwd path size +getpid +getppid +kill int int +lchown path int int +link path path +linkat int path path +lstat path hex +mkdir path oct +munlockall +open path oct oct +openat int path oct oct +pause +read int buf size +readlink path buf size +readlinkat int path buf size +rename path path +rmdir path +setsid +stat path hex +symlink path path +symlinkat int path path +sync +truncate path off +umask oct +unlink path +unlinkat int path +vfork +write int buf size