2 #include <lttv/option.h>
3 #include <lttv/module.h>
5 #include <lttv/attribute.h>
6 #include <lttv/iattribute.h>
7 #include <lttv/stats.h>
8 #include <lttv/filter.h>
10 #include <ltt/event.h>
11 #include <ltt/trace.h>
16 GArray
* _fsms_to_remove
;
17 struct timeval
*tv1
, *tv2
;
23 static gboolean
fs_close(void *hook_data
, void *call_data
){
25 LttvTracefileState
*s
= (LttvTracefileState
*) call_data
;
26 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
27 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
29 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
30 guint32 fd
= ltt_event_get_long_unsigned(e
, f
);
32 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
33 LttvTraceState
*ts
= (LttvTraceState
*) tfs
->parent
.t_context
;
34 LttvProcessState
*process
= ts
->running_process
[tfs
->cpu
];
37 //initialize a new finite state machine
38 struct fd
*fdstruct
= fd_Init();
41 g_array_append_val(_fsm_list
, fdstruct
);
42 //call corresponding transition
43 fdContext_fs_close(&(fdstruct
->_fsm
), pid
, fd
);
45 if(max_fsms
<_fsm_list
->len
)
46 max_fsms
=_fsm_list
->len
;
51 static gboolean
fs_open(void *hook_data
, void *call_data
){
53 LttvTracefileState
*s
= (LttvTracefileState
*) call_data
;
54 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
55 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
57 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
58 guint32 fd
= ltt_event_get_long_unsigned(e
, f
);
60 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
61 LttvTraceState
*ts
= (LttvTraceState
*) tfs
->parent
.t_context
;
62 LttvProcessState
*process
= ts
->running_process
[tfs
->cpu
];
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
69 for(i
=_fsm_list
->len
-1; i
>=0; i
--){
72 fdstruct
= (struct fd
*) g_array_index(_fsm_list
, struct fdstruct
*, i
);
73 fdContext_fs_open(&(fdstruct
->_fsm
), pid
, fd
, i
);
79 static gboolean
fs_read(void *hook_data
, void *call_data
){
81 LttvTracefileState
*s
= (LttvTracefileState
*) call_data
;
82 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
83 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
85 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
86 guint32 fd
= ltt_event_get_long_unsigned(e
, f
);
88 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
89 LttvTraceState
*ts
= (LttvTraceState
*) tfs
->parent
.t_context
;
90 LttvProcessState
*process
= ts
->running_process
[tfs
->cpu
];
93 LttTime time
= ltt_event_time(e
);
95 ts_sec
= (long) time
.tv_sec
;
96 ts_nsec
=(long) time
.tv_nsec
;
98 //for every fsm in the list, call appropriate transition
101 for(i
=0; i
<_fsm_list
->len
; i
++){
104 fdstruct
= (struct fd
*)g_array_index(_fsm_list
, struct fd
*, i
);
105 fdContext_fs_read(&(fdstruct
->_fsm
), pid
, fd
, ts_sec
, ts_nsec
);
111 static gboolean
fs_write(void *hook_data
, void *call_data
){
113 LttvTracefileState
*s
= (LttvTracefileState
*) call_data
;
114 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
115 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
117 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 0);
118 guint32 fd
= ltt_event_get_long_unsigned(e
, f
);
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
;
125 //for every fsm in the list, call appropriate transition
128 for(i
=0; i
<_fsm_list
->len
; i
++){
131 fdstruct
= g_array_index(_fsm_list
, struct fd
*, i
);
132 fdContext_fs_write(&(fdstruct
->_fsm
), pid
, fd
);
137 static gboolean
process_exit(void *hook_data
, void *call_data
){
139 LttvTracefileState
*s
= (LttvTracefileState
*) call_data
;
140 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
141 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
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
;
149 //for every fsm in the list, call appropriate transition
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
);
159 static gboolean
fs_dup3(void *hook_data
, void *call_data
){
161 LttvTracefileState
*s
= (LttvTracefileState
*) call_data
;
162 LttEvent
*e
= ltt_tracefile_get_event(s
->parent
.tf
);
163 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
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
;
170 struct marker_field
*f
= lttv_trace_get_hook_field(th
, 1);
171 guint32 newfd
= ltt_event_get_long_unsigned(e
, f
);
173 //for every fsm in the list, call appropriate transition
176 for(i
=_fsm_list
->len
-1; i
>=0; i
--){
179 fdstruct
=(struct fd
*) g_array_index(_fsm_list
, struct fd
*, i
);
180 fdContext_fs_dup3(&(fdstruct
->_fsm
), pid
, newfd
, i
);
191 int removefsm(int i
){
192 g_array_remove_index(_fsm_list
, i
);
194 static int add_events_by_id_hooks(void *hook_data
, void *call_data
){
195 LttvTraceContext
*tc
= (LttvTraceContext
*) call_data
;
199 GQuark LTT_FACILITY_FS
= g_quark_from_string("fs");
200 GQuark LTT_FACILITY_KERNEL
= g_quark_from_string("kernel");
202 GQuark LTT_EVENT_CLOSE
= g_quark_from_string("close");
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");
208 GQuark LTT_EVENT_OPEN
= g_quark_from_string("open");
210 GQuark LTT_EVENT_READ
= g_quark_from_string("read");
212 GQuark LTT_EVENT_WRITE
= g_quark_from_string("write");
214 GQuark LTT_EVENT_DUP3
= g_quark_from_string("dup3");
216 GQuark LTT_EVENT_PROCESS_EXIT
= g_quark_from_string("process_exit");
218 GArray
*hooks
= g_array_sized_new(FALSE
, FALSE
, sizeof(LttvTraceHook
), 6);
220 lttv_trace_find_hook(t
, LTT_FACILITY_FS
, LTT_EVENT_CLOSE
,
221 FIELD_ARRAY(LTT_FIELD_FD
),
226 lttv_trace_find_hook(t
, LTT_FACILITY_FS
, LTT_EVENT_OPEN
,
227 FIELD_ARRAY(LTT_FIELD_FD
),
232 lttv_trace_find_hook(t
, LTT_FACILITY_FS
, LTT_EVENT_READ
,
233 FIELD_ARRAY(LTT_FIELD_FD
),
239 lttv_trace_find_hook(t
, LTT_FACILITY_FS
, LTT_EVENT_WRITE
,
240 FIELD_ARRAY(LTT_FIELD_FD
),
245 lttv_trace_find_hook(t
, LTT_FACILITY_KERNEL
, LTT_EVENT_PROCESS_EXIT
,
251 lttv_trace_find_hook(t
, LTT_FACILITY_FS
, LTT_EVENT_DUP3
,
252 FIELD_ARRAY(LTT_FIELD_OLD_FD
, LTT_FIELD_NEW_FD
),
257 int nb_tracefiles
= tc
->tracefiles
->len
;
258 LttvTracefileContext
**tfc
;
259 LttvHooks
*needed_hooks
;
260 LttvTraceHook
*th
= (LttvTraceHook
*)hook_data
;
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
);
275 LttvAttributeValue value
;
277 LttvIAttribute
*attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
279 static LttvHooks
*before_trace
;
281 result
= lttv_iattribute_find_by_path(attributes
, "hooks/trace/before", LTTV_POINTER
, &value
);
283 before_trace
= *(value
.v_pointer
);
284 g_assert(before_trace
);
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
);
290 //Initialize empty GArray for FSMs
291 _fsm_list
= g_array_new(FALSE
, FALSE
, sizeof(struct fd
*));
293 tv1
= (struct timeval
*)malloc(sizeof(struct timeval
));
294 gettimeofday(tv1
, NULL
);
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
);
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")