Commit | Line | Data |
---|---|---|
a0b1f42c JD |
1 | #!/usr/bin/env python3 |
2 | ||
3 | import sys | |
4 | import time | |
5 | import argparse | |
6 | ||
7 | NSEC_PER_SEC = 1000000000 | |
8 | ||
9 | try: | |
10 | from babeltrace import TraceCollection | |
11 | except ImportError: | |
12 | # quick fix for debian-based distros | |
13 | sys.path.append("/usr/local/lib/python%d.%d/site-packages" % | |
14 | (sys.version_info.major, sys.version_info.minor)) | |
15 | from babeltrace import TraceCollection | |
16 | ||
17 | ||
18 | class TraceParser: | |
19 | def __init__(self, trace, pid): | |
20 | self.trace = trace | |
21 | self.pid = pid | |
22 | self.expect = {} | |
23 | ||
24 | def ns_to_hour_nsec(self, ns): | |
25 | d = time.localtime(ns/NSEC_PER_SEC) | |
26 | return "%02d:%02d:%02d.%09d" % (d.tm_hour, d.tm_min, d.tm_sec, | |
27 | ns % NSEC_PER_SEC) | |
28 | ||
29 | def parse(self): | |
30 | # iterate over all the events | |
31 | for event in self.trace.events: | |
32 | if self.pid is not None and event["pid"] != self.pid: | |
33 | continue | |
34 | ||
35 | method_name = "handle_%s" % event.name.replace(":", "_").replace( | |
36 | "+", "_") | |
37 | # call the function to handle each event individually | |
38 | if hasattr(TraceParser, method_name): | |
39 | func = getattr(TraceParser, method_name) | |
40 | func(self, event) | |
41 | ||
42 | ret = 0 | |
43 | for i in self.expect.keys(): | |
44 | if self.expect[i] == 0: | |
45 | print("%s not validated" % i) | |
46 | ret = 1 | |
47 | ||
48 | return ret | |
49 | ||
50 | # epoll_ctl | |
51 | def handle_compat_syscall_entry_epoll_ctl(self, event): | |
52 | self.epoll_ctl_entry(event) | |
53 | ||
54 | def handle_compat_syscall_exit_epoll_ctl(self, event): | |
55 | self.epoll_ctl_exit(event) | |
56 | ||
57 | def handle_syscall_entry_epoll_ctl(self, event): | |
58 | self.epoll_ctl_entry(event) | |
59 | ||
60 | def handle_syscall_exit_epoll_ctl(self, event): | |
61 | self.epoll_ctl_exit(event) | |
62 | ||
63 | def epoll_ctl_entry(self, event): | |
64 | pass | |
65 | ||
66 | def epoll_ctl_exit(self, event): | |
67 | pass | |
68 | ||
69 | # epoll_wait + epoll_pwait | |
70 | def handle_compat_syscall_entry_epoll_wait(self, event): | |
71 | self.epoll_wait_entry(event) | |
72 | ||
73 | def handle_compat_syscall_exit_epoll_wait(self, event): | |
74 | self.epoll_wait_exit(event) | |
75 | ||
76 | def handle_syscall_entry_epoll_wait(self, event): | |
77 | self.epoll_wait_entry(event) | |
78 | ||
79 | def handle_syscall_exit_epoll_wait(self, event): | |
80 | self.epoll_wait_exit(event) | |
81 | ||
82 | def handle_compat_syscall_entry_epoll_pwait(self, event): | |
83 | self.epoll_wait_entry(event) | |
84 | ||
85 | def handle_compat_syscall_exit_epoll_pwait(self, event): | |
86 | self.epoll_wait_exit(event) | |
87 | ||
88 | def handle_syscall_entry_epoll_pwait(self, event): | |
89 | self.epoll_wait_entry(event) | |
90 | ||
91 | def handle_syscall_exit_epoll_pwait(self, event): | |
92 | self.epoll_wait_exit(event) | |
93 | ||
94 | def epoll_wait_entry(self, event): | |
95 | pass | |
96 | ||
97 | def epoll_wait_exit(self, event): | |
98 | pass | |
99 | ||
100 | ## poll + ppoll | |
101 | def handle_compat_syscall_entry_poll(self, event): | |
102 | self.poll_entry(event) | |
103 | ||
104 | def handle_compat_syscall_exit_poll(self, event): | |
105 | self.poll_exit(event) | |
106 | ||
107 | def handle_syscall_entry_poll(self, event): | |
108 | self.poll_entry(event) | |
109 | ||
110 | def handle_syscall_exit_poll(self, event): | |
111 | self.poll_exit(event) | |
112 | ||
113 | def handle_compat_syscall_entry_ppoll(self, event): | |
114 | self.poll_entry(event) | |
115 | ||
116 | def handle_compat_syscall_exit_ppoll(self, event): | |
117 | self.poll_exit(event) | |
118 | ||
119 | def handle_syscall_entry_ppoll(self, event): | |
120 | self.poll_entry(event) | |
121 | ||
122 | def handle_syscall_exit_ppoll(self, event): | |
123 | self.poll_exit(event) | |
124 | ||
125 | def poll_entry(self, event): | |
126 | pass | |
127 | ||
128 | def poll_exit(self, event): | |
129 | pass | |
130 | ||
131 | # epoll_create | |
132 | def handle_compat_syscall_entry_epoll_create1(self, event): | |
133 | self.epoll_create_entry(event) | |
134 | ||
135 | def handle_compat_syscall_exit_epoll_create1(self, event): | |
136 | self.epoll_create_exit(event) | |
137 | ||
138 | def handle_compat_syscall_entry_epoll_create(self, event): | |
139 | self.epoll_create_entry(event) | |
140 | ||
141 | def handle_compat_syscall_exit_epoll_create(self, event): | |
142 | self.epoll_create_exit(event) | |
143 | ||
144 | def handle_syscall_entry_epoll_create1(self, event): | |
145 | self.epoll_create_entry(event) | |
146 | ||
147 | def handle_syscall_exit_epoll_create1(self, event): | |
148 | self.epoll_create_exit(event) | |
149 | ||
150 | def handle_syscall_entry_epoll_create(self, event): | |
151 | self.epoll_create_entry(event) | |
152 | ||
153 | def handle_syscall_exit_epoll_create(self, event): | |
154 | self.epoll_create_exit(event) | |
155 | ||
156 | def epoll_create_entry(self, event): | |
157 | pass | |
158 | ||
159 | def epoll_create_exit(self, event): | |
160 | pass | |
161 | ||
162 | # select + pselect6 | |
163 | def handle_syscall_entry_pselect6(self, event): | |
164 | self.select_entry(event) | |
165 | ||
166 | def handle_syscall_exit_pselect6(self, event): | |
167 | self.select_exit(event) | |
168 | ||
169 | def handle_compat_syscall_entry_pselect6(self, event): | |
170 | self.select_entry(event) | |
171 | ||
172 | def handle_compat_syscall_exit_pselect6(self, event): | |
173 | self.select_exit(event) | |
174 | ||
175 | def handle_syscall_entry_select(self, event): | |
176 | self.select_entry(event) | |
177 | ||
178 | def handle_syscall_exit_select(self, event): | |
179 | self.select_exit(event) | |
180 | ||
181 | def handle_compat_syscall_entry_select(self, event): | |
182 | self.select_entry(event) | |
183 | ||
184 | def handle_compat_syscall_exit_select(self, event): | |
185 | self.select_exit(event) | |
186 | ||
187 | def select_entry(self, event): | |
188 | pass | |
189 | ||
190 | def select_exit(self, event): | |
191 | pass | |
192 | ||
193 | ||
194 | class Test1(TraceParser): | |
195 | def __init__(self, trace, pid): | |
196 | super().__init__(trace, pid) | |
197 | self.expect["select_in_fd0"] = 0 | |
198 | self.expect["select_in_fd1023"] = 0 | |
199 | self.expect["select_out_fd0"] = 0 | |
200 | self.expect["select_out_fd1023"] = 0 | |
201 | self.expect["poll_in_nfds1"] = 0 | |
202 | self.expect["poll_out_nfds1"] = 0 | |
203 | self.expect["epoll_ctl_in_add"] = 0 | |
204 | self.expect["epoll_ctl_out_ok"] = 0 | |
205 | self.expect["epoll_wait_in_ok"] = 0 | |
206 | self.expect["epoll_wait_out_fd0"] = 0 | |
207 | ||
208 | def select_entry(self, event): | |
209 | timestamp = event.timestamp | |
210 | cpu_id = event["cpu_id"] | |
211 | n = event["n"] | |
212 | overflow = event["overflow"] | |
213 | tvp = event["tvp"] | |
214 | _readfds_length = event["_readfds_length"] | |
215 | readfds = event["readfds"] | |
216 | _writefds_length = event["_writefds_length"] | |
217 | writefds = event["writefds"] | |
218 | _exceptfds_length = event["_exceptfds_length"] | |
219 | exceptfds = event["exceptfds"] | |
220 | ||
221 | # check that the FD 0 is actually set in the readfds | |
222 | if n == 1 and readfds[0] == 1: | |
223 | self.expect["select_in_fd0"] = 1 | |
224 | if n == 1023: | |
225 | # check that the FD 1023 is actually set in the readfds | |
226 | if readfds[127] == 0x40 and writefds[127] == 0 and \ | |
227 | exceptfds[127] == 0 and overflow == 0: | |
228 | self.expect["select_in_fd1023"] = 1 | |
229 | ||
230 | def select_exit(self, event): | |
231 | timestamp = event.timestamp | |
232 | cpu_id = event["cpu_id"] | |
233 | ret = event["ret"] | |
234 | overflow = event["overflow"] | |
235 | tvp = event["tvp"] | |
236 | _readfds_length = event["_readfds_length"] | |
237 | readfds = event["readfds"] | |
238 | _writefds_length = event["_writefds_length"] | |
239 | writefds = event["writefds"] | |
240 | _exceptfds_length = event["_exceptfds_length"] | |
241 | exceptfds = event["exceptfds"] | |
242 | ||
243 | if ret == 1: | |
244 | # check that the FD 0 is actually set in the readfds | |
245 | if readfds[0] == 1: | |
246 | self.expect["select_out_fd0"] = 1 | |
247 | # check that the FD 1023 is actually set in the readfds | |
248 | if _readfds_length == 128 and readfds[127] == 0x40 and \ | |
249 | writefds[127] == 0 and exceptfds[127] == 0 and tvp == 0: | |
250 | self.expect["select_out_fd1023"] = 1 | |
251 | ||
252 | def poll_entry(self, event): | |
253 | timestamp = event.timestamp | |
254 | cpu_id = event["cpu_id"] | |
255 | nfds = event["nfds"] | |
256 | fds_length = event["fds_length"] | |
257 | overflow = event["overflow"] | |
258 | fds = event["fds"] | |
259 | ||
260 | # check that only one FD is set, that it has the POLLIN flag and that | |
261 | # the raw value matches the events bit field. | |
262 | if nfds == 1 and fds_length == 1 and fds[0]["raw_events"] == 0x3 \ | |
263 | and fds[0]["events"]["POLLIN"] == 1 and \ | |
264 | fds[0]["events"]["padding"] == 0: | |
265 | self.expect["poll_in_nfds1"] = 1 | |
266 | ||
267 | def poll_exit(self, event): | |
268 | timestamp = event.timestamp | |
269 | cpu_id = event["cpu_id"] | |
270 | ret = event["ret"] | |
271 | nfds = event["nfds"] | |
272 | fds_length = event["fds_length"] | |
273 | fds = event["fds"] | |
274 | ||
275 | # check that only one FD is set, that it has the POLLIN flag and that | |
276 | # the raw value matches the events bit field. | |
277 | if ret == 1 and fds_length == 1 and fds[0]["raw_events"] == 0x1 \ | |
278 | and fds[0]["events"]["POLLIN"] == 1 and \ | |
279 | fds[0]["events"]["padding"] == 0: | |
280 | self.expect["poll_out_nfds1"] = 1 | |
281 | ||
282 | def epoll_ctl_entry(self, event): | |
283 | timestamp = event.timestamp | |
284 | cpu_id = event["cpu_id"] | |
285 | epfd = event["epfd"] | |
286 | op_enum = event["op_enum"] | |
287 | fd = event["fd"] | |
288 | _event = event["event"] | |
289 | ||
290 | # check that we have FD 0 waiting for EPOLLIN|EPOLLPRI and that | |
291 | # data.fd = 0 | |
292 | if epfd == 3 and op_enum == "EPOLL_CTL_ADD" and fd == 0 and \ | |
293 | _event["data_union"]["fd"] == 0 and \ | |
294 | _event["events"]["EPOLLIN"] == 1 and \ | |
295 | _event["events"]["EPOLLPRI"] == 1: | |
296 | self.expect["epoll_ctl_in_add"] = 1 | |
297 | ||
298 | def epoll_ctl_exit(self, event): | |
299 | timestamp = event.timestamp | |
300 | cpu_id = event["cpu_id"] | |
301 | ret = event["ret"] | |
302 | ||
303 | if ret == 0: | |
304 | self.expect["epoll_ctl_out_ok"] = 1 | |
305 | ||
306 | def epoll_wait_entry(self, event): | |
307 | timestamp = event.timestamp | |
308 | cpu_id = event["cpu_id"] | |
309 | epfd = event["epfd"] | |
310 | maxevents = event["maxevents"] | |
311 | timeout = event["timeout"] | |
312 | ||
313 | if epfd == 3 and maxevents == 1 and timeout == -1: | |
314 | self.expect["epoll_wait_in_ok"] = 1 | |
315 | ||
316 | def epoll_wait_exit(self, event): | |
317 | timestamp = event.timestamp | |
318 | cpu_id = event["cpu_id"] | |
319 | ret = event["ret"] | |
320 | fds_length = event["fds_length"] | |
321 | overflow = event["overflow"] | |
322 | fds = event["fds"] | |
323 | ||
324 | # check that FD 0 returned with EPOLLIN and the right data.fd | |
325 | if ret == 1 and fds_length == 1 and overflow == 0 and \ | |
326 | fds[0]["data_union"]["fd"] == 0 and \ | |
327 | fds[0]["events"]["EPOLLIN"] == 1: | |
328 | self.expect["epoll_wait_out_fd0"] = 1 | |
329 | ||
330 | ||
331 | class Test2(TraceParser): | |
332 | def __init__(self, trace, pid): | |
333 | super().__init__(trace, pid) | |
334 | self.expect["select_timeout_in_fd0"] = 0 | |
335 | self.expect["select_timeout_in_fd1023"] = 0 | |
336 | self.expect["select_timeout_out"] = 0 | |
337 | self.expect["poll_timeout_in"] = 0 | |
338 | self.expect["poll_timeout_out"] = 0 | |
339 | self.expect["epoll_ctl_timeout_in_add"] = 0 | |
340 | self.expect["epoll_ctl_timeout_out_ok"] = 0 | |
341 | self.expect["epoll_wait_timeout_in"] = 0 | |
342 | self.expect["epoll_wait_timeout_out"] = 0 | |
343 | ||
344 | def select_entry(self, event): | |
345 | timestamp = event.timestamp | |
346 | cpu_id = event["cpu_id"] | |
347 | n = event["n"] | |
348 | overflow = event["overflow"] | |
349 | tvp = event["tvp"] | |
350 | _readfds_length = event["_readfds_length"] | |
351 | readfds = event["readfds"] | |
352 | _writefds_length = event["_writefds_length"] | |
353 | writefds = event["writefds"] | |
354 | _exceptfds_length = event["_exceptfds_length"] | |
355 | exceptfds = event["exceptfds"] | |
356 | ||
357 | if n == 1 and tvp != 0: | |
358 | self.expect["select_timeout_in_fd0"] = 1 | |
359 | if n == 1023: | |
360 | if readfds[127] == 0x40 and writefds[127] == 0 and \ | |
361 | exceptfds[127] == 0 and tvp != 0: | |
362 | self.expect["select_timeout_in_fd1023"] = 1 | |
363 | ||
364 | def select_exit(self, event): | |
365 | timestamp = event.timestamp | |
366 | cpu_id = event["cpu_id"] | |
367 | ret = event["ret"] | |
368 | overflow = event["overflow"] | |
369 | tvp = event["tvp"] | |
370 | _readfds_length = event["_readfds_length"] | |
371 | readfds = event["readfds"] | |
372 | _writefds_length = event["_writefds_length"] | |
373 | writefds = event["writefds"] | |
374 | _exceptfds_length = event["_exceptfds_length"] | |
375 | exceptfds = event["exceptfds"] | |
376 | ||
377 | if ret == 0 and tvp != 0: | |
378 | self.expect["select_timeout_out"] = 1 | |
379 | ||
380 | def poll_entry(self, event): | |
381 | timestamp = event.timestamp | |
382 | cpu_id = event["cpu_id"] | |
383 | nfds = event["nfds"] | |
384 | fds_length = event["fds_length"] | |
385 | overflow = event["overflow"] | |
386 | fds = event["fds"] | |
387 | ||
388 | # check that we wait on FD 0 for POLLIN and that the raw_events | |
389 | # field matches the value of POLLIN | |
390 | if nfds == 1 and fds_length == 1 and fds[0]["raw_events"] == 0x3 \ | |
391 | and fds[0]["events"]["POLLIN"] == 1 and \ | |
392 | fds[0]["events"]["padding"] == 0: | |
393 | self.expect["poll_timeout_in"] = 1 | |
394 | ||
395 | def poll_exit(self, event): | |
396 | timestamp = event.timestamp | |
397 | cpu_id = event["cpu_id"] | |
398 | ret = event["ret"] | |
399 | nfds = event["nfds"] | |
400 | fds_length = event["fds_length"] | |
401 | fds = event["fds"] | |
402 | ||
403 | if ret == 0 and nfds == 1 and fds_length == 0: | |
404 | self.expect["poll_timeout_out"] = 1 | |
405 | ||
406 | def epoll_ctl_entry(self, event): | |
407 | timestamp = event.timestamp | |
408 | cpu_id = event["cpu_id"] | |
409 | epfd = event["epfd"] | |
410 | op_enum = event["op_enum"] | |
411 | fd = event["fd"] | |
412 | _event = event["event"] | |
413 | ||
414 | # make sure we see a EPOLLIN|EPOLLPRI | |
415 | if op_enum == "EPOLL_CTL_ADD" and \ | |
416 | _event["events"]["EPOLLIN"] == 1 and \ | |
417 | _event["events"]["EPOLLPRI"] == 1: | |
418 | self.expect["epoll_ctl_timeout_in_add"] = 1 | |
419 | ||
420 | def epoll_ctl_exit(self, event): | |
421 | timestamp = event.timestamp | |
422 | cpu_id = event["cpu_id"] | |
423 | ret = event["ret"] | |
424 | ||
425 | if ret == 0: | |
426 | self.expect["epoll_ctl_timeout_out_ok"] = 1 | |
427 | ||
428 | def epoll_wait_entry(self, event): | |
429 | timestamp = event.timestamp | |
430 | cpu_id = event["cpu_id"] | |
431 | epfd = event["epfd"] | |
432 | maxevents = event["maxevents"] | |
433 | timeout = event["timeout"] | |
434 | ||
435 | if maxevents == 1 and timeout == 1: | |
436 | self.expect["epoll_wait_timeout_in"] = 1 | |
437 | ||
438 | def epoll_wait_exit(self, event): | |
439 | timestamp = event.timestamp | |
440 | cpu_id = event["cpu_id"] | |
441 | ret = event["ret"] | |
442 | fds_length = event["fds_length"] | |
443 | overflow = event["overflow"] | |
444 | fds = event["fds"] | |
445 | ||
446 | if ret == 0 and fds_length == 0 and overflow == 0: | |
447 | self.expect["epoll_wait_timeout_out"] = 1 | |
448 | ||
449 | ||
450 | class Test3(TraceParser): | |
451 | def __init__(self, trace, pid): | |
452 | super().__init__(trace, pid) | |
cdeda5b6 FD |
453 | self.expect["select_invalid_fd_in"] = 0 |
454 | self.expect["select_invalid_fd_out"] = 0 | |
a0b1f42c JD |
455 | |
456 | def select_entry(self, event): | |
457 | timestamp = event.timestamp | |
458 | cpu_id = event["cpu_id"] | |
459 | n = event["n"] | |
460 | overflow = event["overflow"] | |
461 | tvp = event["tvp"] | |
462 | _readfds_length = event["_readfds_length"] | |
463 | readfds = event["readfds"] | |
464 | _writefds_length = event["_writefds_length"] | |
465 | writefds = event["writefds"] | |
466 | _exceptfds_length = event["_exceptfds_length"] | |
467 | exceptfds = event["exceptfds"] | |
468 | ||
cdeda5b6 FD |
469 | if n > 0 and overflow == 0: |
470 | self.expect["select_invalid_fd_in"] = 1 | |
a0b1f42c JD |
471 | |
472 | def select_exit(self, event): | |
473 | timestamp = event.timestamp | |
474 | cpu_id = event["cpu_id"] | |
475 | ret = event["ret"] | |
476 | overflow = event["overflow"] | |
477 | tvp = event["tvp"] | |
478 | _readfds_length = event["_readfds_length"] | |
479 | readfds = event["readfds"] | |
480 | _writefds_length = event["_writefds_length"] | |
481 | writefds = event["writefds"] | |
482 | _exceptfds_length = event["_exceptfds_length"] | |
483 | exceptfds = event["exceptfds"] | |
484 | ||
cdeda5b6 | 485 | # make sure the event has a ret field equal to -EBADF |
a0b1f42c | 486 | if ret == -9 and overflow == 0 and _readfds_length == 0: |
cdeda5b6 | 487 | self.expect["select_invalid_fd_out"] = 1 |
a0b1f42c JD |
488 | |
489 | ||
490 | class Test4(TraceParser): | |
491 | def __init__(self, trace, pid): | |
492 | super().__init__(trace, pid) | |
493 | self.expect["big_poll_in"] = 0 | |
494 | self.expect["big_poll_out"] = 0 | |
495 | ||
496 | def poll_entry(self, event): | |
497 | timestamp = event.timestamp | |
498 | cpu_id = event["cpu_id"] | |
499 | nfds = event["nfds"] | |
500 | fds_length = event["fds_length"] | |
501 | overflow = event["overflow"] | |
502 | fds = event["fds"] | |
503 | ||
504 | # test of big list of FDs and the behaviour of the overflow | |
505 | if nfds == 2047 and fds_length == 512 and overflow == 1 and \ | |
506 | fds[0]["raw_events"] == 0x3 \ | |
507 | and fds[0]["events"]["POLLIN"] == 1 and \ | |
508 | fds[0]["events"]["padding"] == 0 and \ | |
509 | fds[511]["events"]["POLLIN"] == 1 and \ | |
510 | fds[511]["events"]["POLLPRI"] == 1: | |
511 | self.expect["big_poll_in"] = 1 | |
512 | ||
513 | def poll_exit(self, event): | |
514 | timestamp = event.timestamp | |
515 | cpu_id = event["cpu_id"] | |
516 | ret = event["ret"] | |
517 | nfds = event["nfds"] | |
518 | fds_length = event["fds_length"] | |
519 | overflow = event["overflow"] | |
520 | fds = event["fds"] | |
521 | ||
522 | # test of big list of FDs and the behaviour of the overflow | |
523 | if ret == 2047 and nfds == 2047 and fds_length == 512 and \ | |
524 | overflow == 1 and fds[0]["events"]["POLLIN"] == 1 and \ | |
525 | fds[511]["events"]["POLLIN"] == 1: | |
526 | self.expect["big_poll_out"] = 1 | |
527 | ||
528 | ||
529 | class Test5(TraceParser): | |
530 | def __init__(self, trace, pid): | |
531 | super().__init__(trace, pid) | |
532 | self.expect["poll_overflow_in"] = 0 | |
533 | self.expect["poll_overflow_out"] = 0 | |
534 | ||
535 | def poll_entry(self, event): | |
536 | timestamp = event.timestamp | |
537 | cpu_id = event["cpu_id"] | |
538 | nfds = event["nfds"] | |
539 | fds_length = event["fds_length"] | |
540 | overflow = event["overflow"] | |
541 | fds = event["fds"] | |
542 | ||
543 | # test that event in valid even though the target buffer is too small | |
544 | # and the program segfaults | |
545 | if nfds == 100 and fds_length == 100 and overflow == 0 and \ | |
546 | fds[0]["events"]["POLLIN"] == 1: | |
547 | self.expect["poll_overflow_in"] = 1 | |
548 | ||
549 | def poll_exit(self, event): | |
550 | timestamp = event.timestamp | |
551 | cpu_id = event["cpu_id"] | |
552 | ret = event["ret"] | |
553 | nfds = event["nfds"] | |
554 | fds_length = event["fds_length"] | |
555 | overflow = event["overflow"] | |
556 | fds = event["fds"] | |
557 | ||
558 | # test that event in valid even though the target buffer is too small | |
559 | # and the program segfaults | |
560 | if nfds == 100 and overflow == 0: | |
561 | self.expect["poll_overflow_out"] = 1 | |
562 | ||
563 | ||
564 | class Test6(TraceParser): | |
565 | def __init__(self, trace, pid): | |
566 | super().__init__(trace, pid) | |
567 | self.expect["pselect_invalid_in"] = 0 | |
568 | self.expect["pselect_invalid_out"] = 0 | |
569 | ||
570 | def select_entry(self, event): | |
571 | timestamp = event.timestamp | |
572 | cpu_id = event["cpu_id"] | |
573 | n = event["n"] | |
574 | overflow = event["overflow"] | |
575 | tvp = event["tvp"] | |
576 | _readfds_length = event["_readfds_length"] | |
577 | readfds = event["readfds"] | |
578 | _writefds_length = event["_writefds_length"] | |
579 | writefds = event["writefds"] | |
580 | _exceptfds_length = event["_exceptfds_length"] | |
581 | exceptfds = event["exceptfds"] | |
582 | ||
583 | # test that event in valid even though the target buffer pointer is | |
584 | # invalid and the program segfaults | |
585 | if n == 1 and overflow == 0 and _readfds_length == 0: | |
586 | self.expect["pselect_invalid_in"] = 1 | |
587 | ||
588 | def select_exit(self, event): | |
589 | timestamp = event.timestamp | |
590 | cpu_id = event["cpu_id"] | |
591 | ret = event["ret"] | |
592 | overflow = event["overflow"] | |
593 | tvp = event["tvp"] | |
594 | _readfds_length = event["_readfds_length"] | |
595 | readfds = event["readfds"] | |
596 | _writefds_length = event["_writefds_length"] | |
597 | writefds = event["writefds"] | |
598 | _exceptfds_length = event["_exceptfds_length"] | |
599 | exceptfds = event["exceptfds"] | |
600 | ||
601 | # test that event in valid even though the target buffer pointer is | |
602 | # invalid and the program segfaults | |
603 | if ret == -14 and overflow == 0 and _readfds_length == 0: | |
604 | self.expect["pselect_invalid_out"] = 1 | |
605 | ||
606 | ||
607 | class Test7(TraceParser): | |
608 | def __init__(self, trace, pid): | |
609 | super().__init__(trace, pid) | |
610 | self.expect["poll_max_in"] = 0 | |
611 | self.expect["poll_max_out"] = 0 | |
612 | ||
613 | def poll_entry(self, event): | |
614 | timestamp = event.timestamp | |
615 | cpu_id = event["cpu_id"] | |
616 | nfds = event["nfds"] | |
617 | fds_length = event["fds_length"] | |
618 | overflow = event["overflow"] | |
619 | fds = event["fds"] | |
620 | ||
621 | # check the proper working of INT_MAX maxevent value | |
622 | if nfds == 4294967295 and overflow == 1: | |
623 | self.expect["poll_max_in"] = 1 | |
624 | ||
625 | def poll_exit(self, event): | |
626 | timestamp = event.timestamp | |
627 | cpu_id = event["cpu_id"] | |
628 | ret = event["ret"] | |
629 | nfds = event["nfds"] | |
630 | fds_length = event["fds_length"] | |
631 | overflow = event["overflow"] | |
632 | fds = event["fds"] | |
633 | ||
634 | # check the proper working of UINT_MAX maxevent value | |
635 | if ret == -22 and nfds == 4294967295 and overflow == 0: | |
636 | self.expect["poll_max_out"] = 1 | |
637 | ||
638 | ||
639 | class Test8(TraceParser): | |
640 | def __init__(self, trace, pid): | |
641 | super().__init__(trace, pid) | |
642 | self.expect["epoll_wait_invalid_in"] = 0 | |
643 | self.expect["epoll_wait_invalid_out"] = 0 | |
644 | ||
645 | def epoll_wait_entry(self, event): | |
646 | timestamp = event.timestamp | |
647 | cpu_id = event["cpu_id"] | |
648 | epfd = event["epfd"] | |
649 | maxevents = event["maxevents"] | |
650 | timeout = event["timeout"] | |
651 | ||
652 | # test that event in valid even though the target buffer pointer is | |
653 | # invalid and the program segfaults | |
654 | if epfd == 3 and maxevents == 1 and timeout == -1: | |
655 | self.expect["epoll_wait_invalid_in"] = 1 | |
656 | ||
657 | def epoll_wait_exit(self, event): | |
658 | timestamp = event.timestamp | |
659 | cpu_id = event["cpu_id"] | |
660 | ret = event["ret"] | |
661 | fds_length = event["fds_length"] | |
662 | overflow = event["overflow"] | |
663 | fds = event["fds"] | |
664 | ||
665 | # test that event in valid even though the target buffer pointer is | |
666 | # invalid and the program segfaults | |
667 | if ret == -14 and fds_length == 0 and overflow == 0: | |
668 | self.expect["epoll_wait_invalid_out"] = 1 | |
669 | ||
670 | ||
671 | class Test9(TraceParser): | |
672 | def __init__(self, trace, pid): | |
673 | super().__init__(trace, pid) | |
674 | self.expect["epoll_wait_max_in"] = 0 | |
675 | self.expect["epoll_wait_max_out"] = 0 | |
676 | ||
677 | def epoll_wait_entry(self, event): | |
678 | timestamp = event.timestamp | |
679 | cpu_id = event["cpu_id"] | |
680 | epfd = event["epfd"] | |
681 | maxevents = event["maxevents"] | |
682 | timeout = event["timeout"] | |
683 | ||
684 | # check the proper working of INT_MAX maxevent value | |
685 | if epfd == 3 and maxevents == 2147483647 and timeout == -1: | |
686 | self.expect["epoll_wait_max_in"] = 1 | |
687 | ||
688 | def epoll_wait_exit(self, event): | |
689 | timestamp = event.timestamp | |
690 | cpu_id = event["cpu_id"] | |
691 | ret = event["ret"] | |
692 | fds_length = event["fds_length"] | |
693 | overflow = event["overflow"] | |
694 | fds = event["fds"] | |
695 | ||
696 | # check the proper working of INT_MAX maxevent value | |
697 | if ret == -22 and fds_length == 0 and overflow == 0: | |
698 | self.expect["epoll_wait_max_out"] = 1 | |
699 | ||
700 | ||
701 | if __name__ == "__main__": | |
702 | parser = argparse.ArgumentParser(description='Trace parser') | |
703 | parser.add_argument('path', metavar="<path/to/trace>", help='Trace path') | |
704 | parser.add_argument('-t', '--test', type=int, help='Test to validate') | |
705 | parser.add_argument('-p', '--pid', type=int, help='PID of the app') | |
706 | args = parser.parse_args() | |
707 | ||
708 | if not args.test: | |
709 | print("Need to pass a test to validate (-t)") | |
710 | sys.exit(1) | |
711 | ||
712 | if not args.pid: | |
713 | print("Need to pass the PID to check (-p)") | |
714 | sys.exit(1) | |
715 | ||
716 | traces = TraceCollection() | |
717 | handle = traces.add_traces_recursive(args.path, "ctf") | |
718 | if handle is None: | |
719 | sys.exit(1) | |
720 | ||
721 | t = None | |
722 | ||
723 | if args.test == 1: | |
724 | t = Test1(traces, args.pid) | |
725 | elif args.test == 2: | |
726 | t = Test2(traces, args.pid) | |
727 | elif args.test == 3: | |
728 | t = Test3(traces, args.pid) | |
729 | elif args.test == 4: | |
730 | t = Test4(traces, args.pid) | |
731 | elif args.test == 5: | |
732 | t = Test5(traces, args.pid) | |
733 | elif args.test == 6: | |
734 | t = Test6(traces, args.pid) | |
735 | elif args.test == 7: | |
736 | t = Test7(traces, args.pid) | |
737 | elif args.test == 8: | |
738 | t = Test8(traces, args.pid) | |
739 | elif args.test == 9: | |
740 | t = Test9(traces, args.pid) | |
741 | elif args.test == 10: | |
742 | # stress test, nothing reliable to check | |
743 | ret = 0 | |
744 | elif args.test == 11: | |
745 | # stress test, nothing reliable to check | |
746 | ret = 0 | |
747 | else: | |
748 | print("Invalid test case") | |
749 | sys.exit(1) | |
750 | ||
751 | if t is not None: | |
752 | ret = t.parse() | |
753 | ||
754 | for h in handle.values(): | |
755 | traces.remove_trace(h) | |
756 | ||
757 | sys.exit(ret) |