-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrfollow.cpp
103 lines (96 loc) · 2.78 KB
/
rfollow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "run.h"
#include <unordered_set>
static std::unordered_set<run *> followruns;
static std::unordered_set<run *> all_followruns;
void followrun_add(run *run)
{
followruns.insert(run);
all_followruns.insert(run);
}
void followrun_del(run *run)
{
followruns.erase(run);
}
void followrun_dumpall()
{
for(auto r : followruns) {
dump(r->name, r);
}
dump(current_run.name, ¤t_run);
}
bool followrun_stats()
{
for(auto run : all_followruns) {
fprintf(stderr, "%20s: %s\n", run->name, run->fell_off ? "fell off" : "followed");
}
return 0;
}
bool followrun_step(struct thread_tr *tracee)
{
if(followruns.size() == 0) {
/* no more graphs! */
fprintf(stderr, "=== FELL OFF ALL GRAPHS ===\n");
// getchar();
return true;
}
// fprintf(stderr, "STEP\n");
if(tracee->syscall == NULL)
return false;
int last_event_idx = tracee->event_seq.size() - 1;
event *last_event = tracee->event_seq[last_event_idx];
// fprintf(stderr,
// "last_event # = %d ... %s %d\n",
// last_event_idx,
// syscall_names[last_event->sc->number],
// last_event->entry);
for(auto run : followruns) {
if((size_t)tracee->id >= run->thread_list.size()) {
run->fell_off = true;
followrun_del(run);
return followrun_step(tracee);
}
struct thread_tr *followed_thread = run->thread_list[tracee->id];
if((size_t)last_event_idx >= followed_thread->event_seq.size()) {
run->fell_off = true;
followrun_del(run);
return followrun_step(tracee);
}
event *other_event = followed_thread->event_seq[last_event_idx];
if(other_event->entry != last_event->entry || other_event->uuid != last_event->uuid
|| other_event->sc->number != last_event->sc->number
|| !other_event->sc->approx_eq(last_event->sc, !last_event->entry ? 0 : 0)) {
if(options.log_follow) {
fprintf(stderr, "== Fell off %s ==\n", run->name);
fprintf(stderr,
" :: (%d)%s (%d)%s",
tracee->id,
tracee->proc->invoke,
followed_thread->id,
followed_thread->proc->invoke);
fprintf(stderr,
" :: event: got %ld (exp %ld) %d (exp %d)\n",
last_event->sc->number,
other_event->sc->number,
last_event->uuid,
other_event->uuid);
fprintf(stderr,
" :: event->sc approx? %d\n",
other_event->sc->approx_eq(last_event->sc, !last_event->entry ? SC_EQ_RET : 0));
}
run->fell_off = true;
followrun_del(run);
return followrun_step(tracee);
}
/* this is still a valid graph */
if(other_event->fault_event) {
fprintf(stderr, ":: %d %d\n", other_event->uuid, last_event_idx);
/* inject a fault */
last_event->fault_event = true;
last_event->sc->fault();
// last_event->err_code = other_event->err_code;
// last_event->sc->ret_err = other_event->err_code;
// last_event->sc->set_return_value(other_event->err_code);
}
}
return false;
}