print_syscall.c (3216B)
- // SPDX-FileCopyrightText: 2024 Haelwenn (lanodan) Monnier <contact+mstrace@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _DEFAULT_SOURCE
- #include "strsyscall.h"
- #include <assert.h>
- #include <inttypes.h> // PRIu64
- #include <limits.h> // PATH_MAX
- #include <linux/ptrace.h> // __u64
- #include <stdio.h> // fprintf
- #include <string.h> // memcpy
- #include <sys/ptrace.h> // ptrace()
- #include <sys/syscall.h> // SYS_*
- #include <time.h> // struct timespec
- #include <unistd.h> // pid_t
- extern pid_t child;
- union u8_timespec
- {
- struct timespec ts;
- uint8_t buf[sizeof(struct timespec)];
- };
- static char *
- read_str(intptr_t addr, size_t len)
- {
- static char str_buf[sizeof(unsigned long) * 128] = "";
- if(len == 0 || len > sizeof(unsigned long) * 128) len = sizeof(unsigned long) * 128;
- size_t i = 0;
- while(i < len)
- {
- unsigned long tmp = ptrace(PTRACE_PEEKDATA, child, addr + i);
- memcpy(str_buf + i, &tmp, sizeof(tmp));
- i += sizeof(tmp);
- if(memchr(&tmp, 0, sizeof(tmp)) != NULL) break;
- if(i > len)
- {
- str_buf[len - 1] = '\0';
- break;
- }
- }
- return str_buf;
- }
- static struct timespec *
- read_timespec(intptr_t addr)
- {
- static union u8_timespec local;
- for(size_t i = 0; i < sizeof(struct timespec);)
- {
- unsigned long tmp = ptrace(PTRACE_PEEKDATA, child, addr + i);
- memcpy(local.buf + i, &tmp, sizeof(tmp));
- i += sizeof(tmp);
- }
- return &(local.ts);
- }
- #define Pri_str "\"%s\""
- #define Pri_i "%" PRIi64
- #define Pri_u "%" PRIu64
- #define Pri_o "0o%" PRIo64
- #define Pri_x "0x%" PRIx64
- void
- print_syscall_entry(__u64 nr, __u64 args[6])
- {
- switch(nr)
- {
- case SYS_execve:
- fprintf(stderr, "<%s("Pri_str ", " Pri_x ", " Pri_x ")\n", str_syscalls[nr], read_str(args[0], PATH_MAX), (int64_t)args[1], (int64_t)args[2]);
- return;
- case SYS_nanosleep:
- {
- struct timespec *rqtp = read_timespec(args[0]);
- struct timespec *rmtp = read_timespec(args[1]);
- fprintf(stderr,
- "<%s({tv_sec = " Pri_i ", tv_nsec = " Pri_i "}, {tv_sec = " Pri_i ", tv_nsec = " Pri_i
- "})\n",
- str_syscalls[nr],
- rqtp->tv_sec,
- rqtp->tv_nsec,
- rmtp->tv_sec,
- rmtp->tv_nsec);
- return;
- }
- }
- }
- void
- print_syscall_exit(__u64 nr, __u64 args[6])
- {
- switch(nr)
- {
- #include "syscalls_cases.h"
- case SYS_nanosleep:
- {
- struct timespec *rqtp = read_timespec(args[0]);
- struct timespec *rmtp = read_timespec(args[1]);
- fprintf(stderr,
- ">%s({tv_sec = " Pri_i ", tv_nsec = " Pri_i "}, {tv_sec = " Pri_i ", tv_nsec = " Pri_i
- "})",
- str_syscalls[nr],
- rqtp->tv_sec,
- rqtp->tv_nsec,
- rmtp->tv_sec,
- rmtp->tv_nsec);
- break;
- }
- // fallback
- default:
- assert(nr < SYSCALLS_MAX);
- if(str_syscalls[nr] != NULL)
- {
- fprintf(stderr, ">%s(", str_syscalls[nr]);
- }
- else
- {
- fprintf(stderr, ">syscall(%" PRIu64 ", ", (uint64_t)nr);
- }
- fprintf(stderr,
- "0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64
- ")",
- (uint64_t)args[0],
- (uint64_t)args[1],
- (uint64_t)args[2],
- (uint64_t)args[3],
- (uint64_t)args[4],
- (uint64_t)args[5]);
- }
- }