add fsm checker by Gabriel Matni
[lttv.git] / contrib / fsm_checker / FD_CHECK / fd_checker.c
1 #include <lttv/lttv.h>
2 #include <lttv/option.h>
3 #include <lttv/module.h>
4 #include <lttv/hook.h>
5 #include <lttv/attribute.h>
6 #include <lttv/iattribute.h>
7 #include <lttv/stats.h>
8 #include <lttv/filter.h>
9 #include <ltt/ltt.h>
10 #include <ltt/event.h>
11 #include <ltt/trace.h>
12 #include <stdio.h>
13 #include "fd.h"
14
15 GArray *_fsm_list;
16 GArray * _fsms_to_remove;
17 struct timeval *tv1, *tv2;
18 int max_fsms = 0;
19 int total_forks = 0;
20 int count_events = 0;
21 int skip=0;
22
23 static gboolean fs_close(void *hook_data, void *call_data){
24 count_events++;
25 LttvTracefileState *s = (LttvTracefileState *) call_data;
26 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
27 LttvTraceHook *th = (LttvTraceHook *)hook_data;
28
29 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
30 guint32 fd = ltt_event_get_long_unsigned(e, f);
31
32 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
33 LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context;
34 LttvProcessState *process = ts->running_process[tfs->cpu];
35 int pid=process->pid;
36
37 //initialize a new finite state machine
38 struct fd *fdstruct = fd_Init();
39 total_forks++;
40 //add new fsm to list
41 g_array_append_val(_fsm_list, fdstruct);
42 //call corresponding transition
43 fdContext_fs_close(&(fdstruct->_fsm), pid, fd);
44
45 if(max_fsms<_fsm_list->len)
46 max_fsms=_fsm_list->len;
47 return FALSE;
48
49 }
50
51 static gboolean fs_open(void *hook_data, void *call_data){
52 count_events++;
53 LttvTracefileState *s = (LttvTracefileState *) call_data;
54 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
55 LttvTraceHook *th = (LttvTraceHook *)hook_data;
56
57 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
58 guint32 fd = ltt_event_get_long_unsigned(e, f);
59
60 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
61 LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context;
62 LttvProcessState *process = ts->running_process[tfs->cpu];
63 int pid=process->pid;
64
65 //for every fsm in the list, call appropriate transition
66 //index i is sent as an argument in case fsm is to be freed
67 struct fd *fdstruct;
68 int i;
69 for(i=_fsm_list->len-1; i>=0; i--){
70 if (skip)
71 break;
72 fdstruct = (struct fd *) g_array_index(_fsm_list, struct fdstruct *, i);
73 fdContext_fs_open(&(fdstruct->_fsm), pid, fd, i);
74 }
75 skip=0;
76 return FALSE;
77 }
78
79 static gboolean fs_read(void *hook_data, void *call_data){
80 count_events++;
81 LttvTracefileState *s = (LttvTracefileState *) call_data;
82 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
83 LttvTraceHook *th = (LttvTraceHook *)hook_data;
84
85 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
86 guint32 fd = ltt_event_get_long_unsigned(e, f);
87
88 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
89 LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context;
90 LttvProcessState *process = ts->running_process[tfs->cpu];
91 int pid=process->pid;
92
93 LttTime time = ltt_event_time(e);
94 long ts_nsec, ts_sec;
95 ts_sec = (long) time.tv_sec;
96 ts_nsec=(long) time.tv_nsec;
97
98 //for every fsm in the list, call appropriate transition
99 struct fd *fdstruct;
100 int i;
101 for(i=0; i<_fsm_list->len; i++){
102 if (skip)
103 break;
104 fdstruct = (struct fd *)g_array_index(_fsm_list, struct fd *, i);
105 fdContext_fs_read(&(fdstruct->_fsm), pid, fd, ts_sec, ts_nsec);
106 }
107
108 skip=0;
109 return FALSE;
110 }
111 static gboolean fs_write(void *hook_data, void *call_data){
112 count_events++;
113 LttvTracefileState *s = (LttvTracefileState *) call_data;
114 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
115 LttvTraceHook *th = (LttvTraceHook *)hook_data;
116
117 struct marker_field *f = lttv_trace_get_hook_field(th, 0);
118 guint32 fd = ltt_event_get_long_unsigned(e, f);
119
120 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
121 LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context;
122 LttvProcessState *process = ts->running_process[tfs->cpu];
123 int pid=process->pid;
124
125 //for every fsm in the list, call appropriate transition
126 struct fd *fdstruct;
127 int i;
128 for(i=0; i<_fsm_list->len; i++){
129 if (skip)
130 break;
131 fdstruct = g_array_index(_fsm_list, struct fd *, i);
132 fdContext_fs_write(&(fdstruct->_fsm), pid, fd);
133 }
134 skip=0;
135 return FALSE;
136 }
137 static gboolean process_exit(void *hook_data, void *call_data){
138 count_events++;
139 LttvTracefileState *s = (LttvTracefileState *) call_data;
140 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
141 LttvTraceHook *th = (LttvTraceHook *)hook_data;
142
143 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
144 LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context;
145 LttvProcessState *process = ts->running_process[tfs->cpu];
146 int pid=process->pid;
147
148
149 //for every fsm in the list, call appropriate transition
150 struct fd *fdstruct;
151 int i;
152 for(i=_fsm_list->len-1; i>=0 ; i--){
153 fdstruct =(struct fd *) g_array_index(_fsm_list, struct fd *, i);
154 fdContext_process_exit(&(fdstruct->_fsm), pid, i);
155 }
156 skip=0;
157 return FALSE;
158 }
159 static gboolean fs_dup3(void *hook_data, void *call_data){
160 count_events++;
161 LttvTracefileState *s = (LttvTracefileState *) call_data;
162 LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
163 LttvTraceHook *th = (LttvTraceHook *)hook_data;
164
165 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
166 LttvTraceState *ts = (LttvTraceState *) tfs->parent.t_context;
167 LttvProcessState *process = ts->running_process[tfs->cpu];
168 int pid=process->pid;
169
170 struct marker_field *f = lttv_trace_get_hook_field(th, 1);
171 guint32 newfd = ltt_event_get_long_unsigned(e, f);
172
173 //for every fsm in the list, call appropriate transition
174 struct fd *fdstruct;
175 int i;
176 for(i=_fsm_list->len-1; i>=0; i--){
177 if (skip)
178 break;
179 fdstruct =(struct fd *) g_array_index(_fsm_list, struct fd *, i);
180 fdContext_fs_dup3(&(fdstruct->_fsm), pid, newfd, i);
181 }
182 skip=0;
183 return FALSE;
184
185 }
186
187 void skip_FSM(){
188 skip=1;
189 }
190
191 int removefsm(int i){
192 g_array_remove_index(_fsm_list, i);
193 }
194 static int add_events_by_id_hooks(void *hook_data, void *call_data){
195 LttvTraceContext *tc = (LttvTraceContext *) call_data;
196 LttTrace *t = tc->t;
197
198 //EVENT CHROOT
199 GQuark LTT_FACILITY_FS = g_quark_from_string("fs");
200 GQuark LTT_FACILITY_KERNEL = g_quark_from_string("kernel");
201
202 GQuark LTT_EVENT_CLOSE = g_quark_from_string("close");
203 //EVENT FIELDS
204 GQuark LTT_FIELD_FD = g_quark_from_string("fd");
205 GQuark LTT_FIELD_OLD_FD = g_quark_from_string("oldfd");
206 GQuark LTT_FIELD_NEW_FD = g_quark_from_string("newfd");
207
208 GQuark LTT_EVENT_OPEN = g_quark_from_string("open");
209
210 GQuark LTT_EVENT_READ = g_quark_from_string("read");
211
212 GQuark LTT_EVENT_WRITE = g_quark_from_string("write");
213
214 GQuark LTT_EVENT_DUP3 = g_quark_from_string("dup3");
215
216 GQuark LTT_EVENT_PROCESS_EXIT = g_quark_from_string("process_exit");
217
218 GArray *hooks = g_array_sized_new(FALSE, FALSE, sizeof(LttvTraceHook), 6);
219
220 lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_CLOSE,
221 FIELD_ARRAY(LTT_FIELD_FD),
222 fs_close,
223 NULL,
224 &hooks);
225
226 lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_OPEN,
227 FIELD_ARRAY(LTT_FIELD_FD),
228 fs_open,
229 NULL,
230 &hooks);
231
232 lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_READ,
233 FIELD_ARRAY(LTT_FIELD_FD),
234 fs_read,
235 NULL,
236 &hooks);
237
238
239 lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_WRITE,
240 FIELD_ARRAY(LTT_FIELD_FD),
241 fs_write,
242 NULL,
243 &hooks);
244
245 lttv_trace_find_hook(t, LTT_FACILITY_KERNEL, LTT_EVENT_PROCESS_EXIT,
246 NULL,
247 process_exit,
248 NULL,
249 &hooks);
250
251 lttv_trace_find_hook(t, LTT_FACILITY_FS, LTT_EVENT_DUP3,
252 FIELD_ARRAY(LTT_FIELD_OLD_FD, LTT_FIELD_NEW_FD),
253 fs_dup3,
254 NULL,
255 &hooks);
256
257 int nb_tracefiles = tc->tracefiles->len;
258 LttvTracefileContext **tfc;
259 LttvHooks *needed_hooks;
260 LttvTraceHook *th = (LttvTraceHook *)hook_data;
261 int i, j;
262 for(i=0; i<nb_tracefiles; i++){
263 tfc = &g_array_index(tc->tracefiles, LttvTracefileContext*, i);
264 for(j=0; j<hooks->len; j++){
265 th=&g_array_index(hooks, LttvTraceHook, j);
266 needed_hooks = lttv_hooks_by_id_find((*tfc)->event_by_id, th->id);
267 lttv_hooks_add(needed_hooks, th->h, th, LTTV_PRIO_DEFAULT);
268 }
269 }
270 }
271 static void init(){
272
273 gboolean result;
274
275 LttvAttributeValue value;
276
277 LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
278
279 static LttvHooks *before_trace;
280
281 result = lttv_iattribute_find_by_path(attributes, "hooks/trace/before", LTTV_POINTER, &value);
282 g_assert(result);
283 before_trace = *(value.v_pointer);
284 g_assert(before_trace);
285
286 //Register add_events_by_id_hook to be called before starting to read the trace
287 //This function will be overwritten between checkers
288 lttv_hooks_add(before_trace, add_events_by_id_hooks, NULL, LTTV_PRIO_DEFAULT);
289
290 //Initialize empty GArray for FSMs
291 _fsm_list = g_array_new(FALSE, FALSE, sizeof(struct fd *));
292
293 tv1 = (struct timeval *)malloc(sizeof(struct timeval));
294 gettimeofday(tv1, NULL);
295 }
296 static void destroy(){
297 tv2 = (struct timeval *)malloc(sizeof(struct timeval));
298 gettimeofday(tv2, NULL);
299 int seconds = tv2->tv_sec - tv1->tv_sec;
300 printf("analysis took: %d seconds \n", seconds);
301 printf("total number of coexisting fsms is: %d\n",max_fsms);
302 printf("total number of forked fsms is: %d\n", total_forks);
303 printf("size of one fsm (in bytes) is: %d\n", sizeof(struct fd));
304 printf("total number of pertinent events is %d\n", count_events);
305
306 }
307
308 LTTV_MODULE("fd_checker", "Detects improper fd usage",
309 "finds read/write access to a closed fd in a trace file",
310 init, destroy, "stats", "batchAnalysis", "option")
This page took 0.041691 seconds and 4 git commands to generate.