From 78da473e77562001262017ab9e0041e34a0ce912 Mon Sep 17 00:00:00 2001 From: ex0dus-0x Date: Fri, 27 Dec 2019 10:44:13 -0500 Subject: [PATCH] Improve backtrace routine --- src/include/deepstate/DeepState.h | 63 +++++++++++++++++++++---------- src/lib/DeepState.c | 3 +- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/include/deepstate/DeepState.h b/src/include/deepstate/DeepState.h index b531c92f..4f67ecaf 100644 --- a/src/include/deepstate/DeepState.h +++ b/src/include/deepstate/DeepState.h @@ -36,6 +36,9 @@ #include #include #include +#include + +#include #include #include @@ -59,6 +62,10 @@ #define DEEPSTATE_SIZE 8192 #endif +#ifndef DEEPSTATE_CRASH_MAX_FRAMES +#define DEEPSTATE_CRASH_MAX_FRAMES 63 +#endif + #ifndef DEEPSTATE_MAX_SWARM_CONFIGS #define DEEPSTATE_MAX_SWARM_CONFIGS 1024 #endif @@ -524,21 +531,38 @@ extern void DeepState_SaveFailingTest(void); extern void DeepState_SaveCrashingTest(void); /* Emit test function backtrace after test crashes. */ -static void DeepState_EmitBacktrace(int signum, siginfo_t *sig, void *context) { +static void DeepState_EmitBacktrace(int signum, siginfo_t *sig, void *_context) { + + /* output information about the signal caught and the exception that occurred */ + const char *result; + if (!sig->si_status) + result = sys_siglist[signum]; + else + result = sys_siglist[sig->si_status]; + DeepState_LogFormat(DeepState_LogError, "Signal caught in test: %s (error: %d)", result, sig->si_signo); - DeepState_LogFormat(DeepState_LogInfo, "Test crashed with: %s", sys_siglist[sig->si_status]); + ucontext_t *context = (ucontext_t *) _context; + //printf("%lx", context->uc_mcontext.gregs[REG_RIP]); - void *array[10]; + /* return a backtrace */ size_t size; - char **strings; + void *back_addrs[DEEPSTATE_CRASH_MAX_FRAMES]; + char **symbols; - size = backtrace(array, 10); - strings = backtrace_symbols(array, size); + size = backtrace(back_addrs, DEEPSTATE_CRASH_MAX_FRAMES); + if (size == 0) + DeepState_Abandon("Cannot retrieve backtrace stack addresses"); + symbols = backtrace_symbols(back_addrs, size); + if (symbols == NULL) + DeepState_Abandon("Cannot retrieve symbols for stack addresses"); + + DeepState_LogFormat(DeepState_LogTrace, "======= Backtrace: ========="); for (size_t i = 0; i < size; i++) - DeepState_LogFormat(DeepState_LogTrace, "%s", strings[i]); + DeepState_LogFormat(DeepState_LogTrace, "%s", symbols[i]); + DeepState_LogFormat(DeepState_LogTrace, "==========================="); - free(strings); + free(symbols); } @@ -712,21 +736,18 @@ static int DeepState_RunTestNoFork(struct DeepState_TestInfo *test) { /* Fork and run `test`. */ static enum DeepState_TestRunResult DeepState_ForkAndRunTest(struct DeepState_TestInfo *test) { + pid_t test_pid; + if (FLAGS_fork) { - /* If flag is set, install a signal handler for SIGCHLD */ - /* TODO(alan): use handler as "multiplexer" and handle child signal */ - if (FLAGS_verbose_crash_trace) { - struct sigaction sigact, oldact; - - sigact.sa_flags = SA_SIGINFO | SA_NOCLDWAIT; - sigact.sa_sigaction = DeepState_EmitBacktrace; - - sigaction(SIGCHLD, &sigact, &oldact); - } + /* If flag is set, install a signal handler for SIGCHLD */ + if (FLAGS_verbose_crash_trace) { + struct sigaction sigact; + sigact.sa_flags = SA_SIGINFO | SA_NODEFER; + sigact.sa_sigaction = DeepState_EmitBacktrace; + sigaction(SIGCHLD, &sigact, 0); + } - pid_t test_pid; - if (FLAGS_fork) { test_pid = fork(); if (!test_pid) { DeepState_RunTest(test); @@ -737,6 +758,8 @@ DeepState_ForkAndRunTest(struct DeepState_TestInfo *test) { if (FLAGS_fork) { waitpid(test_pid, &wstatus, 0); } else { + + /* TODO: install multiplexer signal handler, since we need to handle more than SIGCHLD */ wstatus = DeepState_RunTestNoFork(test); DeepState_CleanUp(); } diff --git a/src/lib/DeepState.c b/src/lib/DeepState.c index 5cbf281f..24649995 100644 --- a/src/lib/DeepState.c +++ b/src/lib/DeepState.c @@ -43,9 +43,8 @@ DEFINE_bool(abort_on_fail, ExecutionGroup, false, "Abort on file replay failure DEFINE_bool(exit_on_fail, ExecutionGroup, false, "Exit with status 255 on test failure."); DEFINE_int(min_log_level, ExecutionGroup, 0, "Minimum level of logging to output (default 2, 0=debug, 1=trace, 2=info, ...)."); DEFINE_int(timeout, ExecutionGroup, 120, "Timeout for brute force fuzzing."); -DEFINE_uint(num_workers, ExecutionGroup, 1, "Number of workers to spawn for testing and test generation."); DEFINE_bool(verbose_reads, ExecutionGroup, false, "Report on bytes being read during execution of test."); -DEFINE_bool(verbose_crash_trace, ExecutionGroup, false, "If test crashes, report an execution backtrace after abrupt exit."); +DEFINE_bool(verbose_crash_trace, ExecutionGroup, false, "If test crashes on a fork, report an execution backtrace after abrupt exit."); /* Fuzzing and symex related options, baked in to perform analysis-related tasks without auxiliary tools */ DEFINE_bool(fuzz, AnalysisGroup, false, "Perform brute force unguided fuzzing.");