Skip to content

Commit

Permalink
contrib/plugins: Add syscalls_logger plugin
Browse files Browse the repository at this point in the history
Syscalls_logger consumes QPP events from the syscalls plugin and logs
this information in a variety of formats.

Signed-off-by: Andrew Fasano <[email protected]>
  • Loading branch information
Andrew Fasano committed Sep 12, 2024
1 parent bf1a803 commit 193c182
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
1 change: 1 addition & 0 deletions contrib/plugins/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ NAMES += stoptrigger
NAMES += cflow
NAMES += stringsearch
NAMES += syscalls
NAMES += syscalls_logger

ifeq ($(CONFIG_WIN32),y)
SO_SUFFIX := .dll
Expand Down
91 changes: 91 additions & 0 deletions contrib/plugins/syscalls_logger.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <qemu-plugin.h>
#include <plugin-qpp.h>
#include "syscalls.h"

QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
QEMU_PLUGIN_EXPORT const char *qemu_plugin_name = "syscalls_logger";

typedef enum { CSV, TEXT } LogFormat;

static FILE *log_file = NULL;
static LogFormat log_format = TEXT;

static void log_syscall(gpointer evdata, gpointer udata)
{
SyscallDetails *details = (SyscallDetails*)evdata;
g_autoptr(GString) report = g_string_new(NULL);

if (log_format == CSV) {
g_string_append_printf(report, "%lx,%lx", details->pc, details->callno);
for (int i = 0; i < SYSCALLS_MAX_ARGS; i++) {
g_string_append_printf(report, ",%lx", details->args[i]);
}
g_string_append_c(report, '\n');
} else {
g_string_append_printf(report, "PC %lx: syscall %lx(", details->pc, details->callno);
for (int i = 0; i < SYSCALLS_MAX_ARGS - 1; i++) {
g_string_append_printf(report, "%lx, ", details->args[i]);
}
g_string_append_printf(report, "%lx)\n", details->args[SYSCALLS_MAX_ARGS - 1]);
}

fprintf(log_file, "%s", report->str);
fflush(log_file);
}

static bool parse_arguments(int argc, char **argv)
{
for (int i = 0; i < argc; i++) {
char *opt = argv[i];
g_autofree char **tokens = g_strsplit(opt, "=", 2);
if (tokens[0] == NULL || tokens[1] == NULL) {
fprintf(stderr, "Invalid argument format: %s\n", opt);
return false;
}

if (g_strcmp0(tokens[0], "filename") == 0) {
if (log_file != NULL && log_file != stdout) {
fclose(log_file);
}
log_file = fopen(tokens[1], "w");
if (log_file == NULL) {
fprintf(stderr, "Failed to open log file: %s\n", tokens[1]);
return false;
}
} else if (g_strcmp0(tokens[0], "format") == 0) {
if (g_strcmp0(tokens[1], "csv") == 0) {
log_format = CSV;
} else if (g_strcmp0(tokens[1], "text") == 0) {
log_format = TEXT;
} else {
fprintf(stderr, "Invalid format option: %s\n", tokens[1]);
return false;
}
} else {
fprintf(stderr, "Unknown option: %s\n", tokens[0]);
fprintf(stderr, "Available options: filename, format\n");
return false;
}
}

if (log_file == NULL) {
log_file = stdout;
}

return true;
}

QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
const qemu_info_t *info,
int argc, char **argv)
{
if (!parse_arguments(argc, argv)) {
return -1;
}

qemu_plugin_reg_callback("syscalls", "on_all_sys_enter", log_syscall);
return 0;
}

0 comments on commit 193c182

Please sign in to comment.