25#if defined(__APPLE__) || defined(__FreeBSD__)
29#define fgetc_unlocked(x) fgetc (x)
33#define fputc_unlocked(x,y) fputc (x,y)
37#include <sys/signal.h>
40#ifdef HAVE_SYS_CAPABILITY_H
41#include <sys/capability.h>
55 {
"create-files-only", required_argument, 0,
'f'},
56 {
"chroot-to-dir", required_argument, 0,
'r'},
57 {
"help", no_argument, 0,
'h'},
58 {
"keep-replay-dir", no_argument, 0,
'k'},
63 fputs(
"KLEE-REPLAY: NOTE: TIMEOUT: ATTEMPTING GDB EXIT\n", stderr);
66 fputs(
"KLEE-REPLAY: ERROR: gdb_exit: fork failed\n", stderr);
67 }
else if (pid == 0) {
69 const char *gdbargs[] = {
74 "--eval-command=call exit(1)",
79 snprintf(pids,
sizeof(pids),
"%d", process);
85 fputs(
"KLEE-REPLAY: NOTE: RUNNING GDB: ", stderr);
87 for (i = 0; i != 5; ++i)
88 fprintf(stderr,
"%s ", gdbargs[i]);
91 execvp(gdbargs[0], (
char *
const *) gdbargs);
98 res = waitpid(pid, &status, 0);
99 }
while (res < 0 && errno == EINTR);
109 fprintf(stderr,
"KLEE-REPLAY: NOTE: %s: Received signal %d. Killing monitored process(es)\n",
123 fprintf(stderr,
"KLEE-REPLAY: NOTE: EXIT STATUS: TIMED OUT (%d seconds)\n",
138 fprintf(stderr,
"KLEE-REPLAY: NOTE: %s: ", pfx);
139 if (WIFSIGNALED(status)) {
140 fprintf(stderr,
"KLEE-REPLAY: NOTE: EXIT STATUS: CRASHED signal %d (%d seconds)\n",
141 WTERMSIG(status), (
int) elapsed);
143 }
else if (WIFEXITED(status)) {
144 int rc = WEXITSTATUS(status);
148 strcpy(msg,
"NORMAL");
150 snprintf(msg,
sizeof(msg),
"ABNORMAL %d", rc);
152 fprintf(stderr,
"KLEE-REPLAY: NOTE: EXIT STATUS: %s (%d seconds)\n", msg, (
int) elapsed);
155 fprintf(stderr,
"KLEE-REPLAY: NOTE: EXIT STATUS: NONE (%d seconds)\n", (
int) elapsed);
164 return executable + strlen(
rootdir);
169 const char *t = getenv(
"KLEE_REPLAY_TIMEOUT");
175 fprintf(stderr,
"KLEE-REPLAY: ERROR: invalid timeout (%s)\n", t);
188 }
else if (pid == 0) {
207 execv(executable, argv);
212 fprintf(stderr,
"KLEE-REPLAY: NOTE: rootdir: %s\n",
rootdir);
214 if ((msg =
"chdir", chdir(
rootdir) == 0) &&
215 (msg =
"chroot", chroot(
rootdir) == 0)) {
219 execv(executable, argv);
226 time_t start = time(0);
229 sigemptyset(&masked);
230 sigaddset(&masked, SIGALRM);
235 res = waitpid(pid, &status, 0);
236 }
while (res < 0 && errno == EINTR);
250#ifdef HAVE_SYS_CAPABILITY_H
252void ensure_capsyschroot(
const char *executable) {
253 cap_t caps = cap_get_proc();
254 cap_flag_value_t chroot_permitted, chroot_effective;
257 perror(
"cap_get_proc");
259 cap_get_flag(caps, CAP_SYS_CHROOT, CAP_PERMITTED, &chroot_permitted);
260 cap_get_flag(caps, CAP_SYS_CHROOT, CAP_EFFECTIVE, &chroot_effective);
261 if (chroot_permitted != CAP_SET || chroot_effective != CAP_SET) {
262 fputs(
"KLEE-REPLAY: ERROR: chroot: No CAP_SYS_CHROOT capability.\n", stderr);
271 "Usage: %s [option]... <executable> <ktest-file>...\n"
272 " or: %s --create-files-only <ktest-file>\n"
274 "-r, --chroot-to-dir=DIR use chroot jail, requires CAP_SYS_CHROOT\n"
275 "-k, --keep-replay-dir do not delete replay directory\n"
276 "-h, --help display this help and exit\n"
278 "Use KLEE_REPLAY_TIMEOUT environment variable to set a timeout (in seconds).\n",
286int main(
int argc,
char** argv) {
296 while ((c = getopt_long(argc, argv,
"f:r:k",
long_options, &opt_index)) != -1) {
304 char *input_fname = optarg;
308 fprintf(stderr,
"KLEE-REPLAY: ERROR: input file %s not valid.\n", input_fname);
314 prg_argv[0] = argv[1];
315 klee_init_env(&prg_argc, &prg_argv);
333 char executable[PATH_MAX];
334 if (!realpath(argv[optind], executable)) {
335 snprintf(executable, PATH_MAX,
"KLEE-REPLAY: ERROR: executable %s:",
343#ifdef HAVE_SYS_CAPABILITY_H
350 fputs(
"KLEE-REPLAY: ERROR: chroot: root dir should be a parent dir of executable.\n", stderr);
355 for (idx = optind + 1; idx != argc; ++idx) {
356 char* input_fname = argv[idx];
361 fprintf(stderr,
"KLEE-REPLAY: ERROR: input file %s not valid.\n",
369 prg_argv[0] = argv[optind];
370 klee_init_env(&prg_argc, &prg_argv);
373 fprintf(stderr,
"KLEE-REPLAY: NOTE: Test file: %s\n"
374 "KLEE-REPLAY: NOTE: Arguments: ", input_fname);
375 for (i=0; i != (unsigned) prg_argc; ++i) {
376 char *s = prg_argv[i];
377 if (s[0]==
'A' && s[1] && !s[2]) s[1] =
'\0';
378 fprintf(stderr,
"\"%s\" ", prg_argv[i]);
392 }
else if (pid == 0) {
401 res = waitpid(pid, &status, 0);
402 }
while (res < 0 && errno == EINTR);
421 return fputc_unlocked(c, f);
425 return fgetc_unlocked(f);
433 fprintf(stderr,
"KLEE-REPLAY: klee_warning: %s\n", name);
437 fprintf(stderr,
"KLEE-REPLAY: klee_warning_once: %s\n", name);
442 fputs(
"KLEE-REPLAY: klee_assume(0)!\n", stderr);
462 if (strcmp(
"model_version", name) == 0) {
471 if (strcmp(
"model_version", name) == 0 &&
472 strcmp(
"model_version", boo->
name) != 0) {
477 fprintf(stderr,
"KLEE-REPLAY: ERROR: make_symbolic mismatch, different sizes: "
478 "%d in input file, %lu in code\n", boo->
numBytes, (
unsigned long)nbytes);
481 memcpy(addr, boo->
bytes, nbytes);
493 fputs(
"KLEE-REPLAY: ERROR: klee_range: invalid range\n", stderr);
502 if (r < start || r >= end) {
503 fprintf(stderr,
"KLEE-REPLAY: ERROR: klee_range(%d, %d, %s) returned invalid result: %d\n",
504 start, end, name, r);
524 fprintf(stderr,
"KLEE-REPLAY: ERROR: %s\n", msg);
KTest * kTest_fromFile(const char *path)
void replay_delete_files()
void replay_create_files(exe_file_system_t *exe_fs)
void klee_mark_global(void *object)
unsigned klee_assume(uintptr_t x)
static void run_monitored(char *executable, int argc, char **argv)
int __fgetc_unlocked(FILE *f)
static void timeout_handler(int signal)
int main(int argc, char **argv)
static unsigned monitored_timeout
void klee_warning(char *name)
void klee_warning_once(char *name)
int __fputc_unlocked(int c, FILE *f)
static void stop_monitored(int process)
void klee_prefer_cex(void *buffer, uintptr_t condition)
static struct option long_options[]
static unsigned monitored_pid
static char * strip_root_dir(char *executable, char *rootdir)
static void int_handler(int signal)
unsigned klee_is_symbolic(uintptr_t x)
static unsigned obj_index
static void __emit_error(const char *msg)
void klee_make_symbolic(void *addr, size_t nbytes, const char *name)
static const char * progname
void process_status(int status, time_t elapsed, const char *pfx)
int klee_range(int start, int end, const char *name)
void klee_report_error(const char *file, int line, const char *message, const char *suffix)
void klee_posix_prefer_cex(void *buffer, uintptr_t condition)
int const char const char * suffix