mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
syscall log: support for selective syscall tracing
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
#include <arch/cpu.h>
|
||||
#include <kernel/syscalls.h>
|
||||
#include <arch/msr.h>
|
||||
#include <errno.h>
|
||||
@@ -6,6 +7,11 @@
|
||||
#define ARCH_CTL_SET_FSBASE 1
|
||||
#define ARCH_CTL_GET_GSBASE 2
|
||||
#define ARCH_CTL_GET_FSBASE 3
|
||||
#define ARCH_CTL_SET_SYSTRACE 4
|
||||
|
||||
#define ARCH_CTL_SYSTRACE_OFF 0
|
||||
#define ARCH_CTL_SYSTRACE_SELF 1
|
||||
#define ARCH_CTL_SYSTRACE_ALL 2
|
||||
|
||||
static inline int copy_u64_to_user(void *ptr, uint64_t v) {
|
||||
return usercopy_touser(ptr, &v, sizeof(v));
|
||||
@@ -36,6 +42,28 @@ syscallret_t syscall_archctl(context_t *context, int func, void *arg) {
|
||||
case ARCH_CTL_GET_FSBASE:
|
||||
ret.errno = copy_u64_to_user(arg, rdmsr(MSR_FSBASE));
|
||||
break;
|
||||
case ARCH_CTL_SET_SYSTRACE:
|
||||
#ifdef SYSCALL_LOGGING
|
||||
switch ((uint64_t)arg) {
|
||||
case ARCH_CTL_SYSTRACE_OFF:
|
||||
current_thread()->proc->flags &= ~(PROC_FLAG_SYSTRACE | PROC_FLAG_SYSTRACE_SELF);
|
||||
break;
|
||||
case ARCH_CTL_SYSTRACE_SELF:
|
||||
current_thread()->proc->flags |= PROC_FLAG_SYSTRACE | PROC_FLAG_SYSTRACE_SELF;
|
||||
break;
|
||||
case ARCH_CTL_SYSTRACE_ALL:
|
||||
current_thread()->proc->flags |= PROC_FLAG_SYSTRACE;
|
||||
current_thread()->proc->flags &= ~PROC_FLAG_SYSTRACE_SELF;
|
||||
break;
|
||||
default:
|
||||
ret.errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
// signal that syscall logging is not supported
|
||||
ret.errno = ENOTSUP;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ret.errno = EINVAL;
|
||||
break;
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
#ifdef SYSCALL_LOGGING
|
||||
|
||||
void arch_interrupt_disable();
|
||||
void arch_interrupt_enable();
|
||||
|
||||
#define SYSCALL_COUNT 99
|
||||
#define LOGSTR(x) arch_e9_puts(x)
|
||||
|
||||
@@ -225,6 +228,9 @@ __attribute__((no_caller_saved_registers)) void arch_syscall_log(int syscall, ui
|
||||
|
||||
thread_t *thread = current_thread();
|
||||
proc_t *proc = thread->proc;
|
||||
if (!(proc->flags & PROC_FLAG_SYSTRACE))
|
||||
return;
|
||||
|
||||
snprintf(argbuff, 768, syscall < SYSCALL_COUNT ? args[syscall] : "N/A", a1, a2, a3, a4, a5, a6);
|
||||
snprintf(printbuff, 1024, "\e[92msyscall: pid %d tid %d: %s: %s (%lu cached pages, %lu free pages)\n\e[0m", proc->pid, thread->tid, syscall < SYSCALL_COUNT ? name[syscall] : "invalid syscall", argbuff, vmmcache_cachedpages, freepagecount);
|
||||
|
||||
@@ -242,6 +248,8 @@ __attribute__((no_caller_saved_registers)) void arch_syscall_log_return(uint64_t
|
||||
|
||||
thread_t *thread = current_thread();
|
||||
proc_t *proc = thread->proc;
|
||||
if (!(proc->flags & PROC_FLAG_SYSTRACE))
|
||||
return;
|
||||
|
||||
snprintf(printbuff, 1024, "\e[94msyscall return: pid %d tid %d: %lu %s (%lu cached pages, %lu free pages)\n\e[0m", proc->pid, thread->tid, ret, strerror(errno), vmmcache_cachedpages, freepagecount);
|
||||
arch_interrupt_disable();
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#define PROC_STATE_NORMAL 0
|
||||
#define PROC_STATE_ZOMBIE 1
|
||||
|
||||
#define PROC_FLAG_SYSTRACE (1 << 0)
|
||||
#define PROC_FLAG_SYSTRACE_SELF (1 << 1)
|
||||
|
||||
typedef struct proc_t {
|
||||
mutex_t mutex;
|
||||
int refcount;
|
||||
|
||||
@@ -50,6 +50,9 @@ syscallret_t syscall_fork(context_t *ctx) {
|
||||
nproc->root = proc_get_root();
|
||||
nproc->cwd = proc_get_cwd();
|
||||
nproc->threadlist = nthread;
|
||||
if (proc->flags & PROC_FLAG_SYSTRACE && !(proc->flags & PROC_FLAG_SYSTRACE_SELF))
|
||||
nproc->flags |= PROC_FLAG_SYSTRACE;
|
||||
|
||||
nthread->procnext = NULL;
|
||||
|
||||
ARCH_CONTEXT_THREADSAVE(nthread, ctx);
|
||||
|
||||
@@ -105,3 +105,19 @@ index 939925e..5ee7fad 100644
|
||||
int sys_readv(int fd, const struct iovec *iovs, int iovc, ssize_t *bytes_read) {
|
||||
long r;
|
||||
int error = syscall(SYSCALL_READV, &r, fd, (uint64_t)iovs, iovc);
|
||||
diff --git mlibc-clean/sysdeps/astral/include/astral/archctl.h mlibc-workdir/sysdeps/astral/include/astral/archctl.h
|
||||
index 7e4f2a1..a5f382d 100644
|
||||
--- mlibc-clean/sysdeps/astral/include/astral/archctl.h
|
||||
+++ mlibc-workdir/sysdeps/astral/include/astral/archctl.h
|
||||
@@ -5,6 +5,11 @@
|
||||
#define ARCH_CTL_SET_FSBASE 1
|
||||
#define ARCH_CTL_GET_GSBASE 2
|
||||
#define ARCH_CTL_GET_FSBASE 3
|
||||
+#define ARCH_CTL_SET_SYSTRACE 4
|
||||
+
|
||||
+#define ARCH_CTL_SYSTRACE_OFF 0
|
||||
+#define ARCH_CTL_SYSTRACE_SELF 1
|
||||
+#define ARCH_CTL_SYSTRACE_ALL 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
name=systrace
|
||||
revision=1
|
||||
from_source=systrace
|
||||
imagedeps="build-essential"
|
||||
hostdeps="xbinutils xgcc"
|
||||
deps="base"
|
||||
|
||||
build() {
|
||||
make -C ${source_dir} -j ${parallelism}
|
||||
}
|
||||
|
||||
package() {
|
||||
make -C ${source_dir} install PREFIX=${prefix} DESTDIR=${dest_dir}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
name=systrace
|
||||
version=0
|
||||
source_dir="tools/systrace"
|
||||
|
||||
prepare() {
|
||||
true
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
.phony: all install
|
||||
CC=x86_64-astral-gcc
|
||||
LD=x86_64-astral-gcc
|
||||
all: systrace
|
||||
|
||||
install:
|
||||
mkdir -p "$(DESTDIR)/$(PREFIX)/sbin/"
|
||||
cp systrace "$(DESTDIR)/$(PREFIX)/sbin/systrace"
|
||||
|
||||
systrace: main.o
|
||||
$(LD) $(LDFLAGS) -g -o $@ $^
|
||||
|
||||
main.o: main.c
|
||||
$(CC) -c $(CFLAGS) -g -o $@ $<
|
||||
@@ -0,0 +1,62 @@
|
||||
#include <astral/archctl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int arch_ctl_systrace(uint64_t mode) {
|
||||
return arch_ctl(ARCH_CTL_SET_SYSTRACE, (void *)mode);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// make sure syscall tracing is supported
|
||||
if (arch_ctl_systrace(ARCH_CTL_SYSTRACE_OFF) != 0) {
|
||||
if (errno == ENOTSUP) {
|
||||
fprintf(stderr, "%s: compile the kernel with syscall tracing enabled\n", argv[0]);
|
||||
} else {
|
||||
perror("arch_ctl failed");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t mode = ARCH_CTL_SYSTRACE_SELF;
|
||||
|
||||
// check for -ff flag
|
||||
if (argc > 1 && strcmp(argv[1], "-ff") == 0) {
|
||||
mode = ARCH_CTL_SYSTRACE_ALL;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s [-ff] <command> [args...]\n", argv[0]);
|
||||
fprintf(stderr, "example: %s ls -l /\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fork failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
// enable syscall tracing for the child process
|
||||
if (arch_ctl_systrace(mode) != 0) {
|
||||
perror("failed to enable syscall tracing");
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "%s: tracee is pid %d\n", argv[0], getpid());
|
||||
if (execvp(argv[1], &argv[1]) != 0) {
|
||||
arch_ctl_systrace(ARCH_CTL_SYSTRACE_OFF);
|
||||
perror("execvp failed");
|
||||
return 1;
|
||||
}
|
||||
// not reached
|
||||
} else {
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
return WIFEXITED(status) ? WEXITSTATUS(status) : 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user