Skip to content

Commit 78da473

Browse files
author
ex0dus-0x
committed
Improve backtrace routine
1 parent 862c725 commit 78da473

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

src/include/deepstate/DeepState.h

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
#include <unistd.h>
3737
#include <fnmatch.h>
3838
#include <execinfo.h>
39+
#include <ucontext.h>
40+
41+
#include <libunwind-ptrace.h>
3942

4043
#include <deepstate/Log.h>
4144
#include <deepstate/Compiler.h>
@@ -59,6 +62,10 @@
5962
#define DEEPSTATE_SIZE 8192
6063
#endif
6164

65+
#ifndef DEEPSTATE_CRASH_MAX_FRAMES
66+
#define DEEPSTATE_CRASH_MAX_FRAMES 63
67+
#endif
68+
6269
#ifndef DEEPSTATE_MAX_SWARM_CONFIGS
6370
#define DEEPSTATE_MAX_SWARM_CONFIGS 1024
6471
#endif
@@ -524,21 +531,38 @@ extern void DeepState_SaveFailingTest(void);
524531
extern void DeepState_SaveCrashingTest(void);
525532

526533
/* Emit test function backtrace after test crashes. */
527-
static void DeepState_EmitBacktrace(int signum, siginfo_t *sig, void *context) {
534+
static void DeepState_EmitBacktrace(int signum, siginfo_t *sig, void *_context) {
535+
536+
/* output information about the signal caught and the exception that occurred */
537+
const char *result;
538+
if (!sig->si_status)
539+
result = sys_siglist[signum];
540+
else
541+
result = sys_siglist[sig->si_status];
542+
DeepState_LogFormat(DeepState_LogError, "Signal caught in test: %s (error: %d)", result, sig->si_signo);
528543

529-
DeepState_LogFormat(DeepState_LogInfo, "Test crashed with: %s", sys_siglist[sig->si_status]);
544+
ucontext_t *context = (ucontext_t *) _context;
545+
//printf("%lx", context->uc_mcontext.gregs[REG_RIP]);
530546

531-
void *array[10];
547+
/* return a backtrace */
532548
size_t size;
533-
char **strings;
549+
void *back_addrs[DEEPSTATE_CRASH_MAX_FRAMES];
550+
char **symbols;
534551

535-
size = backtrace(array, 10);
536-
strings = backtrace_symbols(array, size);
552+
size = backtrace(back_addrs, DEEPSTATE_CRASH_MAX_FRAMES);
553+
if (size == 0)
554+
DeepState_Abandon("Cannot retrieve backtrace stack addresses");
537555

556+
symbols = backtrace_symbols(back_addrs, size);
557+
if (symbols == NULL)
558+
DeepState_Abandon("Cannot retrieve symbols for stack addresses");
559+
560+
DeepState_LogFormat(DeepState_LogTrace, "======= Backtrace: =========");
538561
for (size_t i = 0; i < size; i++)
539-
DeepState_LogFormat(DeepState_LogTrace, "%s", strings[i]);
562+
DeepState_LogFormat(DeepState_LogTrace, "%s", symbols[i]);
563+
DeepState_LogFormat(DeepState_LogTrace, "===========================");
540564

541-
free(strings);
565+
free(symbols);
542566
}
543567

544568

@@ -712,21 +736,18 @@ static int DeepState_RunTestNoFork(struct DeepState_TestInfo *test) {
712736
/* Fork and run `test`. */
713737
static enum DeepState_TestRunResult
714738
DeepState_ForkAndRunTest(struct DeepState_TestInfo *test) {
739+
pid_t test_pid;
740+
if (FLAGS_fork) {
715741

716-
/* If flag is set, install a signal handler for SIGCHLD */
717-
/* TODO(alan): use handler as "multiplexer" and handle child signal */
718-
if (FLAGS_verbose_crash_trace) {
719-
struct sigaction sigact, oldact;
720-
721-
sigact.sa_flags = SA_SIGINFO | SA_NOCLDWAIT;
722-
sigact.sa_sigaction = DeepState_EmitBacktrace;
723-
724-
sigaction(SIGCHLD, &sigact, &oldact);
725-
}
742+
/* If flag is set, install a signal handler for SIGCHLD */
743+
if (FLAGS_verbose_crash_trace) {
744+
struct sigaction sigact;
745+
sigact.sa_flags = SA_SIGINFO | SA_NODEFER;
746+
sigact.sa_sigaction = DeepState_EmitBacktrace;
726747

748+
sigaction(SIGCHLD, &sigact, 0);
749+
}
727750

728-
pid_t test_pid;
729-
if (FLAGS_fork) {
730751
test_pid = fork();
731752
if (!test_pid) {
732753
DeepState_RunTest(test);
@@ -737,6 +758,8 @@ DeepState_ForkAndRunTest(struct DeepState_TestInfo *test) {
737758
if (FLAGS_fork) {
738759
waitpid(test_pid, &wstatus, 0);
739760
} else {
761+
762+
/* TODO: install multiplexer signal handler, since we need to handle more than SIGCHLD */
740763
wstatus = DeepState_RunTestNoFork(test);
741764
DeepState_CleanUp();
742765
}

src/lib/DeepState.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ DEFINE_bool(abort_on_fail, ExecutionGroup, false, "Abort on file replay failure
4343
DEFINE_bool(exit_on_fail, ExecutionGroup, false, "Exit with status 255 on test failure.");
4444
DEFINE_int(min_log_level, ExecutionGroup, 0, "Minimum level of logging to output (default 2, 0=debug, 1=trace, 2=info, ...).");
4545
DEFINE_int(timeout, ExecutionGroup, 120, "Timeout for brute force fuzzing.");
46-
DEFINE_uint(num_workers, ExecutionGroup, 1, "Number of workers to spawn for testing and test generation.");
4746
DEFINE_bool(verbose_reads, ExecutionGroup, false, "Report on bytes being read during execution of test.");
48-
DEFINE_bool(verbose_crash_trace, ExecutionGroup, false, "If test crashes, report an execution backtrace after abrupt exit.");
47+
DEFINE_bool(verbose_crash_trace, ExecutionGroup, false, "If test crashes on a fork, report an execution backtrace after abrupt exit.");
4948

5049
/* Fuzzing and symex related options, baked in to perform analysis-related tasks without auxiliary tools */
5150
DEFINE_bool(fuzz, AnalysisGroup, false, "Perform brute force unguided fuzzing.");

0 commit comments

Comments
 (0)