Skip to content

Commit

Permalink
Improve backtrace routine
Browse files Browse the repository at this point in the history
  • Loading branch information
ex0dus-0x committed Jan 2, 2020
1 parent 862c725 commit 78da473
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 22 deletions.
63 changes: 43 additions & 20 deletions src/include/deepstate/DeepState.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
#include <unistd.h>
#include <fnmatch.h>
#include <execinfo.h>
#include <ucontext.h>

#include <libunwind-ptrace.h>

#include <deepstate/Log.h>
#include <deepstate/Compiler.h>
Expand All @@ -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
Expand Down Expand Up @@ -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);
}


Expand Down Expand Up @@ -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);
Expand All @@ -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();
}
Expand Down
3 changes: 1 addition & 2 deletions src/lib/DeepState.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
Expand Down

0 comments on commit 78da473

Please sign in to comment.