Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # syscount Summarize syscall counts and latencies. |
| 4 | # |
| 5 | # USAGE: syscount [-p PID] [-i INTERVAL] [-T TOP] [-x] [-L] [-m] [-P] [-l] |
| 6 | # |
| 7 | # Copyright 2017, Sasha Goldshtein. |
| 8 | # Licensed under the Apache License, Version 2.0 (the "License") |
| 9 | # |
| 10 | # 15-Feb-2017 Sasha Goldshtein Created this. |
| 11 | |
| 12 | from bcc import BPF |
Gary Lin | 3a45935 | 2018-03-27 15:54:09 +0800 | [diff] [blame] | 13 | from bcc.utils import printb |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 14 | from time import sleep, strftime |
| 15 | import argparse |
Lucian Adrian Grijincu | 5426ef2 | 2018-01-11 12:07:42 -0800 | [diff] [blame] | 16 | import errno |
Sasha Goldshtein | 6545390 | 2017-03-26 13:06:51 +0000 | [diff] [blame] | 17 | import itertools |
Sasha Goldshtein | 51803bf | 2017-03-09 13:43:27 +0000 | [diff] [blame] | 18 | import subprocess |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 19 | import sys |
Akilesh Kailash | 8996719 | 2018-05-18 13:36:54 -0700 | [diff] [blame] | 20 | import signal |
Sandipan Das | a068a03 | 2017-10-10 14:46:29 +0530 | [diff] [blame] | 21 | import platform |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 22 | |
Sasha Goldshtein | 6545390 | 2017-03-26 13:06:51 +0000 | [diff] [blame] | 23 | if sys.version_info.major < 3: |
| 24 | izip_longest = itertools.izip_longest |
| 25 | else: |
| 26 | izip_longest = itertools.zip_longest |
| 27 | |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 28 | # |
| 29 | # Syscall table for Linux x86_64, not very recent. |
| 30 | # Automatically generated from strace/linux/x86_64/syscallent.h using the |
| 31 | # following command: |
| 32 | # |
| 33 | # cat syscallent.h | awk -F, '{ gsub(/[ \t"}]/, "", $4); |
| 34 | # gsub(/[ \t/*]/, "", $5); |
| 35 | # print " "$5": \""$4"\","; } |
Paul Chaignon | 956ca1c | 2017-03-04 20:07:56 +0100 | [diff] [blame] | 36 | # BEGIN { print "syscalls = {" } |
| 37 | # END { print "}" }' |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 38 | # |
| 39 | syscalls = { |
Gary Lin | 3a45935 | 2018-03-27 15:54:09 +0800 | [diff] [blame] | 40 | 0: b"read", |
| 41 | 1: b"write", |
| 42 | 2: b"open", |
| 43 | 3: b"close", |
| 44 | 4: b"stat", |
| 45 | 5: b"fstat", |
| 46 | 6: b"lstat", |
| 47 | 7: b"poll", |
| 48 | 8: b"lseek", |
| 49 | 9: b"mmap", |
| 50 | 10: b"mprotect", |
| 51 | 11: b"munmap", |
| 52 | 12: b"brk", |
| 53 | 13: b"rt_sigaction", |
| 54 | 14: b"rt_sigprocmask", |
| 55 | 15: b"rt_sigreturn", |
| 56 | 16: b"ioctl", |
| 57 | 17: b"pread", |
| 58 | 18: b"pwrite", |
| 59 | 19: b"readv", |
| 60 | 20: b"writev", |
| 61 | 21: b"access", |
| 62 | 22: b"pipe", |
| 63 | 23: b"select", |
| 64 | 24: b"sched_yield", |
| 65 | 25: b"mremap", |
| 66 | 26: b"msync", |
| 67 | 27: b"mincore", |
| 68 | 28: b"madvise", |
| 69 | 29: b"shmget", |
| 70 | 30: b"shmat", |
| 71 | 31: b"shmctl", |
| 72 | 32: b"dup", |
| 73 | 33: b"dup2", |
| 74 | 34: b"pause", |
| 75 | 35: b"nanosleep", |
| 76 | 36: b"getitimer", |
| 77 | 37: b"alarm", |
| 78 | 38: b"setitimer", |
| 79 | 39: b"getpid", |
| 80 | 40: b"sendfile", |
| 81 | 41: b"socket", |
| 82 | 42: b"connect", |
| 83 | 43: b"accept", |
| 84 | 44: b"sendto", |
| 85 | 45: b"recvfrom", |
| 86 | 46: b"sendmsg", |
| 87 | 47: b"recvmsg", |
| 88 | 48: b"shutdown", |
| 89 | 49: b"bind", |
| 90 | 50: b"listen", |
| 91 | 51: b"getsockname", |
| 92 | 52: b"getpeername", |
| 93 | 53: b"socketpair", |
| 94 | 54: b"setsockopt", |
| 95 | 55: b"getsockopt", |
| 96 | 56: b"clone", |
| 97 | 57: b"fork", |
| 98 | 58: b"vfork", |
| 99 | 59: b"execve", |
| 100 | 60: b"_exit", |
| 101 | 61: b"wait4", |
| 102 | 62: b"kill", |
| 103 | 63: b"uname", |
| 104 | 64: b"semget", |
| 105 | 65: b"semop", |
| 106 | 66: b"semctl", |
| 107 | 67: b"shmdt", |
| 108 | 68: b"msgget", |
| 109 | 69: b"msgsnd", |
| 110 | 70: b"msgrcv", |
| 111 | 71: b"msgctl", |
| 112 | 72: b"fcntl", |
| 113 | 73: b"flock", |
| 114 | 74: b"fsync", |
| 115 | 75: b"fdatasync", |
| 116 | 76: b"truncate", |
| 117 | 77: b"ftruncate", |
| 118 | 78: b"getdents", |
| 119 | 79: b"getcwd", |
| 120 | 80: b"chdir", |
| 121 | 81: b"fchdir", |
| 122 | 82: b"rename", |
| 123 | 83: b"mkdir", |
| 124 | 84: b"rmdir", |
| 125 | 85: b"creat", |
| 126 | 86: b"link", |
| 127 | 87: b"unlink", |
| 128 | 88: b"symlink", |
| 129 | 89: b"readlink", |
| 130 | 90: b"chmod", |
| 131 | 91: b"fchmod", |
| 132 | 92: b"chown", |
| 133 | 93: b"fchown", |
| 134 | 94: b"lchown", |
| 135 | 95: b"umask", |
| 136 | 96: b"gettimeofday", |
| 137 | 97: b"getrlimit", |
| 138 | 98: b"getrusage", |
| 139 | 99: b"sysinfo", |
| 140 | 100: b"times", |
| 141 | 101: b"ptrace", |
| 142 | 102: b"getuid", |
| 143 | 103: b"syslog", |
| 144 | 104: b"getgid", |
| 145 | 105: b"setuid", |
| 146 | 106: b"setgid", |
| 147 | 107: b"geteuid", |
| 148 | 108: b"getegid", |
| 149 | 109: b"setpgid", |
| 150 | 110: b"getppid", |
| 151 | 111: b"getpgrp", |
| 152 | 112: b"setsid", |
| 153 | 113: b"setreuid", |
| 154 | 114: b"setregid", |
| 155 | 115: b"getgroups", |
| 156 | 116: b"setgroups", |
| 157 | 117: b"setresuid", |
| 158 | 118: b"getresuid", |
| 159 | 119: b"setresgid", |
| 160 | 120: b"getresgid", |
| 161 | 121: b"getpgid", |
| 162 | 122: b"setfsuid", |
| 163 | 123: b"setfsgid", |
| 164 | 124: b"getsid", |
| 165 | 125: b"capget", |
| 166 | 126: b"capset", |
| 167 | 127: b"rt_sigpending", |
| 168 | 128: b"rt_sigtimedwait", |
| 169 | 129: b"rt_sigqueueinfo", |
| 170 | 130: b"rt_sigsuspend", |
| 171 | 131: b"sigaltstack", |
| 172 | 132: b"utime", |
| 173 | 133: b"mknod", |
| 174 | 134: b"uselib", |
| 175 | 135: b"personality", |
| 176 | 136: b"ustat", |
| 177 | 137: b"statfs", |
| 178 | 138: b"fstatfs", |
| 179 | 139: b"sysfs", |
| 180 | 140: b"getpriority", |
| 181 | 141: b"setpriority", |
| 182 | 142: b"sched_setparam", |
| 183 | 143: b"sched_getparam", |
| 184 | 144: b"sched_setscheduler", |
| 185 | 145: b"sched_getscheduler", |
| 186 | 146: b"sched_get_priority_max", |
| 187 | 147: b"sched_get_priority_min", |
| 188 | 148: b"sched_rr_get_interval", |
| 189 | 149: b"mlock", |
| 190 | 150: b"munlock", |
| 191 | 151: b"mlockall", |
| 192 | 152: b"munlockall", |
| 193 | 153: b"vhangup", |
| 194 | 154: b"modify_ldt", |
| 195 | 155: b"pivot_root", |
| 196 | 156: b"_sysctl", |
| 197 | 157: b"prctl", |
| 198 | 158: b"arch_prctl", |
| 199 | 159: b"adjtimex", |
| 200 | 160: b"setrlimit", |
| 201 | 161: b"chroot", |
| 202 | 162: b"sync", |
| 203 | 163: b"acct", |
| 204 | 164: b"settimeofday", |
| 205 | 165: b"mount", |
| 206 | 166: b"umount", |
| 207 | 167: b"swapon", |
| 208 | 168: b"swapoff", |
| 209 | 169: b"reboot", |
| 210 | 170: b"sethostname", |
| 211 | 171: b"setdomainname", |
| 212 | 172: b"iopl", |
| 213 | 173: b"ioperm", |
| 214 | 174: b"create_module", |
| 215 | 175: b"init_module", |
| 216 | 176: b"delete_module", |
| 217 | 177: b"get_kernel_syms", |
| 218 | 178: b"query_module", |
| 219 | 179: b"quotactl", |
| 220 | 180: b"nfsservctl", |
| 221 | 181: b"getpmsg", |
| 222 | 182: b"putpmsg", |
| 223 | 183: b"afs_syscall", |
| 224 | 184: b"tuxcall", |
| 225 | 185: b"security", |
| 226 | 186: b"gettid", |
| 227 | 187: b"readahead", |
| 228 | 188: b"setxattr", |
| 229 | 189: b"lsetxattr", |
| 230 | 190: b"fsetxattr", |
| 231 | 191: b"getxattr", |
| 232 | 192: b"lgetxattr", |
| 233 | 193: b"fgetxattr", |
| 234 | 194: b"listxattr", |
| 235 | 195: b"llistxattr", |
| 236 | 196: b"flistxattr", |
| 237 | 197: b"removexattr", |
| 238 | 198: b"lremovexattr", |
| 239 | 199: b"fremovexattr", |
| 240 | 200: b"tkill", |
| 241 | 201: b"time", |
| 242 | 202: b"futex", |
| 243 | 203: b"sched_setaffinity", |
| 244 | 204: b"sched_getaffinity", |
| 245 | 205: b"set_thread_area", |
| 246 | 206: b"io_setup", |
| 247 | 207: b"io_destroy", |
| 248 | 208: b"io_getevents", |
| 249 | 209: b"io_submit", |
| 250 | 210: b"io_cancel", |
| 251 | 211: b"get_thread_area", |
| 252 | 212: b"lookup_dcookie", |
| 253 | 213: b"epoll_create", |
| 254 | 214: b"epoll_ctl_old", |
| 255 | 215: b"epoll_wait_old", |
| 256 | 216: b"remap_file_pages", |
| 257 | 217: b"getdents64", |
| 258 | 218: b"set_tid_address", |
| 259 | 219: b"restart_syscall", |
| 260 | 220: b"semtimedop", |
| 261 | 221: b"fadvise64", |
| 262 | 222: b"timer_create", |
| 263 | 223: b"timer_settime", |
| 264 | 224: b"timer_gettime", |
| 265 | 225: b"timer_getoverrun", |
| 266 | 226: b"timer_delete", |
| 267 | 227: b"clock_settime", |
| 268 | 228: b"clock_gettime", |
| 269 | 229: b"clock_getres", |
| 270 | 230: b"clock_nanosleep", |
| 271 | 231: b"exit_group", |
| 272 | 232: b"epoll_wait", |
| 273 | 233: b"epoll_ctl", |
| 274 | 234: b"tgkill", |
| 275 | 235: b"utimes", |
| 276 | 236: b"vserver", |
| 277 | 237: b"mbind", |
| 278 | 238: b"set_mempolicy", |
| 279 | 239: b"get_mempolicy", |
| 280 | 240: b"mq_open", |
| 281 | 241: b"mq_unlink", |
| 282 | 242: b"mq_timedsend", |
| 283 | 243: b"mq_timedreceive", |
| 284 | 244: b"mq_notify", |
| 285 | 245: b"mq_getsetattr", |
| 286 | 246: b"kexec_load", |
| 287 | 247: b"waitid", |
| 288 | 248: b"add_key", |
| 289 | 249: b"request_key", |
| 290 | 250: b"keyctl", |
| 291 | 251: b"ioprio_set", |
| 292 | 252: b"ioprio_get", |
| 293 | 253: b"inotify_init", |
| 294 | 254: b"inotify_add_watch", |
| 295 | 255: b"inotify_rm_watch", |
| 296 | 256: b"migrate_pages", |
| 297 | 257: b"openat", |
| 298 | 258: b"mkdirat", |
| 299 | 259: b"mknodat", |
| 300 | 260: b"fchownat", |
| 301 | 261: b"futimesat", |
| 302 | 262: b"newfstatat", |
| 303 | 263: b"unlinkat", |
| 304 | 264: b"renameat", |
| 305 | 265: b"linkat", |
| 306 | 266: b"symlinkat", |
| 307 | 267: b"readlinkat", |
| 308 | 268: b"fchmodat", |
| 309 | 269: b"faccessat", |
| 310 | 270: b"pselect6", |
| 311 | 271: b"ppoll", |
| 312 | 272: b"unshare", |
| 313 | 273: b"set_robust_list", |
| 314 | 274: b"get_robust_list", |
| 315 | 275: b"splice", |
| 316 | 276: b"tee", |
| 317 | 277: b"sync_file_range", |
| 318 | 278: b"vmsplice", |
| 319 | 279: b"move_pages", |
| 320 | 280: b"utimensat", |
| 321 | 281: b"epoll_pwait", |
| 322 | 282: b"signalfd", |
| 323 | 283: b"timerfd_create", |
| 324 | 284: b"eventfd", |
| 325 | 285: b"fallocate", |
| 326 | 286: b"timerfd_settime", |
| 327 | 287: b"timerfd_gettime", |
| 328 | 288: b"accept4", |
| 329 | 289: b"signalfd4", |
| 330 | 290: b"eventfd2", |
| 331 | 291: b"epoll_create1", |
| 332 | 292: b"dup3", |
| 333 | 293: b"pipe2", |
| 334 | 294: b"inotify_init1", |
| 335 | 295: b"preadv", |
| 336 | 296: b"pwritev", |
| 337 | 297: b"rt_tgsigqueueinfo", |
| 338 | 298: b"perf_event_open", |
| 339 | 299: b"recvmmsg", |
| 340 | 300: b"fanotify_init", |
| 341 | 301: b"fanotify_mark", |
| 342 | 302: b"prlimit64", |
| 343 | 303: b"name_to_handle_at", |
| 344 | 304: b"open_by_handle_at", |
| 345 | 305: b"clock_adjtime", |
| 346 | 306: b"syncfs", |
| 347 | 307: b"sendmmsg", |
| 348 | 308: b"setns", |
| 349 | 309: b"getcpu", |
| 350 | 310: b"process_vm_readv", |
| 351 | 311: b"process_vm_writev", |
| 352 | 312: b"kcmp", |
| 353 | 313: b"finit_module", |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 354 | } |
| 355 | |
Sasha Goldshtein | 51803bf | 2017-03-09 13:43:27 +0000 | [diff] [blame] | 356 | # Try to use ausyscall if it is available, because it can give us an up-to-date |
| 357 | # list of syscalls for various architectures, rather than the x86-64 hardcoded |
| 358 | # list above. |
| 359 | def parse_syscall(line): |
| 360 | parts = line.split() |
| 361 | return (int(parts[0]), parts[1].strip()) |
| 362 | |
| 363 | try: |
| 364 | # Skip the first line, which is a header. The rest of the lines are simply |
| 365 | # SYSCALL_NUM\tSYSCALL_NAME pairs. |
| 366 | out = subprocess.check_output('ausyscall --dump | tail -n +2', shell=True) |
Gary Lin | 3a45935 | 2018-03-27 15:54:09 +0800 | [diff] [blame] | 367 | syscalls = dict(map(parse_syscall, out.strip().split(b'\n'))) |
Sasha Goldshtein | 51803bf | 2017-03-09 13:43:27 +0000 | [diff] [blame] | 368 | except Exception as e: |
Sandipan Das | a068a03 | 2017-10-10 14:46:29 +0530 | [diff] [blame] | 369 | if platform.machine() == "x86_64": |
| 370 | pass |
| 371 | else: |
| 372 | raise Exception("ausyscall: command not found") |
Sasha Goldshtein | 51803bf | 2017-03-09 13:43:27 +0000 | [diff] [blame] | 373 | |
Akilesh Kailash | 8996719 | 2018-05-18 13:36:54 -0700 | [diff] [blame] | 374 | # signal handler |
| 375 | def signal_ignore(signal, frame): |
| 376 | print() |
Lucian Adrian Grijincu | 5426ef2 | 2018-01-11 12:07:42 -0800 | [diff] [blame] | 377 | |
| 378 | def handle_errno(errstr): |
| 379 | try: |
| 380 | return abs(int(errstr)) |
| 381 | except ValueError: |
| 382 | pass |
| 383 | |
| 384 | try: |
| 385 | return getattr(errno, errstr) |
| 386 | except AttributeError: |
| 387 | raise argparse.ArgumentTypeError("couldn't map %s to an errno" % errstr) |
| 388 | |
| 389 | |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 390 | parser = argparse.ArgumentParser( |
| 391 | description="Summarize syscall counts and latencies.") |
| 392 | parser.add_argument("-p", "--pid", type=int, help="trace only this pid") |
| 393 | parser.add_argument("-i", "--interval", type=int, |
| 394 | help="print summary at this interval (seconds)") |
Akilesh Kailash | 8996719 | 2018-05-18 13:36:54 -0700 | [diff] [blame] | 395 | parser.add_argument("-d", "--duration", type=int, |
| 396 | help="total duration of trace, in seconds") |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 397 | parser.add_argument("-T", "--top", type=int, default=10, |
| 398 | help="print only the top syscalls by count or latency") |
| 399 | parser.add_argument("-x", "--failures", action="store_true", |
| 400 | help="trace only failed syscalls (return < 0)") |
Lucian Adrian Grijincu | 5426ef2 | 2018-01-11 12:07:42 -0800 | [diff] [blame] | 401 | parser.add_argument("-e", "--errno", type=handle_errno, |
| 402 | help="trace only syscalls that return this error (numeric or EPERM, etc.)") |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 403 | parser.add_argument("-L", "--latency", action="store_true", |
| 404 | help="collect syscall latency") |
| 405 | parser.add_argument("-m", "--milliseconds", action="store_true", |
| 406 | help="display latency in milliseconds (default: microseconds)") |
| 407 | parser.add_argument("-P", "--process", action="store_true", |
| 408 | help="count by process and not by syscall") |
| 409 | parser.add_argument("-l", "--list", action="store_true", |
| 410 | help="print list of recognized syscalls and exit") |
Nathan Scott | cf0792f | 2018-02-02 16:56:50 +1100 | [diff] [blame] | 411 | parser.add_argument("--ebpf", action="store_true", |
| 412 | help=argparse.SUPPRESS) |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 413 | args = parser.parse_args() |
Akilesh Kailash | 8996719 | 2018-05-18 13:36:54 -0700 | [diff] [blame] | 414 | if args.duration and not args.interval: |
| 415 | args.interval = args.duration |
| 416 | if not args.interval: |
| 417 | args.interval = 99999999 |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 418 | |
| 419 | if args.list: |
| 420 | for grp in izip_longest(*(iter(sorted(syscalls.values())),) * 4): |
| 421 | print(" ".join(["%-20s" % s for s in grp if s is not None])) |
| 422 | sys.exit(0) |
| 423 | |
| 424 | text = """ |
| 425 | #ifdef LATENCY |
| 426 | struct data_t { |
| 427 | u64 count; |
| 428 | u64 total_ns; |
| 429 | }; |
| 430 | |
| 431 | BPF_HASH(start, u64, u64); |
| 432 | BPF_HASH(data, u32, struct data_t); |
| 433 | #else |
| 434 | BPF_HASH(data, u32, u64); |
| 435 | #endif |
| 436 | |
| 437 | #ifdef LATENCY |
| 438 | TRACEPOINT_PROBE(raw_syscalls, sys_enter) { |
| 439 | u64 pid_tgid = bpf_get_current_pid_tgid(); |
| 440 | |
| 441 | #ifdef FILTER_PID |
| 442 | if (pid_tgid >> 32 != FILTER_PID) |
| 443 | return 0; |
| 444 | #endif |
| 445 | |
| 446 | u64 t = bpf_ktime_get_ns(); |
| 447 | start.update(&pid_tgid, &t); |
| 448 | return 0; |
| 449 | } |
| 450 | #endif |
| 451 | |
| 452 | TRACEPOINT_PROBE(raw_syscalls, sys_exit) { |
| 453 | u64 pid_tgid = bpf_get_current_pid_tgid(); |
| 454 | |
| 455 | #ifdef FILTER_PID |
| 456 | if (pid_tgid >> 32 != FILTER_PID) |
| 457 | return 0; |
| 458 | #endif |
| 459 | |
| 460 | #ifdef FILTER_FAILED |
| 461 | if (args->ret >= 0) |
| 462 | return 0; |
| 463 | #endif |
| 464 | |
Lucian Adrian Grijincu | 5426ef2 | 2018-01-11 12:07:42 -0800 | [diff] [blame] | 465 | #ifdef FILTER_ERRNO |
| 466 | if (args->ret != -FILTER_ERRNO) |
| 467 | return 0; |
| 468 | #endif |
| 469 | |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 470 | #ifdef BY_PROCESS |
| 471 | u32 key = pid_tgid >> 32; |
| 472 | #else |
| 473 | u32 key = args->id; |
| 474 | #endif |
| 475 | |
| 476 | #ifdef LATENCY |
| 477 | struct data_t *val, zero = {}; |
| 478 | u64 *start_ns = start.lookup(&pid_tgid); |
| 479 | if (!start_ns) |
| 480 | return 0; |
| 481 | |
| 482 | val = data.lookup_or_init(&key, &zero); |
| 483 | val->count++; |
| 484 | val->total_ns = bpf_ktime_get_ns() - *start_ns; |
| 485 | #else |
| 486 | u64 *val, zero = 0; |
| 487 | val = data.lookup_or_init(&key, &zero); |
| 488 | ++(*val); |
| 489 | #endif |
| 490 | return 0; |
| 491 | } |
| 492 | """ |
| 493 | |
| 494 | if args.pid: |
| 495 | text = ("#define FILTER_PID %d\n" % args.pid) + text |
| 496 | if args.failures: |
| 497 | text = "#define FILTER_FAILED\n" + text |
Lucian Adrian Grijincu | 5426ef2 | 2018-01-11 12:07:42 -0800 | [diff] [blame] | 498 | if args.errno: |
| 499 | text = "#define FILTER_ERRNO %d\n" % abs(args.errno) + text |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 500 | if args.latency: |
| 501 | text = "#define LATENCY\n" + text |
| 502 | if args.process: |
| 503 | text = "#define BY_PROCESS\n" + text |
Nathan Scott | cf0792f | 2018-02-02 16:56:50 +1100 | [diff] [blame] | 504 | if args.ebpf: |
| 505 | print(text) |
| 506 | exit() |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 507 | |
| 508 | bpf = BPF(text=text) |
| 509 | |
| 510 | def print_stats(): |
| 511 | if args.latency: |
| 512 | print_latency_stats() |
| 513 | else: |
| 514 | print_count_stats() |
| 515 | |
| 516 | agg_colname = "PID COMM" if args.process else "SYSCALL" |
| 517 | time_colname = "TIME (ms)" if args.milliseconds else "TIME (us)" |
| 518 | |
| 519 | def comm_for_pid(pid): |
| 520 | try: |
Gary Lin | 3a45935 | 2018-03-27 15:54:09 +0800 | [diff] [blame] | 521 | return open("/proc/%d/comm" % pid, "rb").read().strip() |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 522 | except Exception: |
Gary Lin | 3a45935 | 2018-03-27 15:54:09 +0800 | [diff] [blame] | 523 | return b"[unknown]" |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 524 | |
| 525 | def agg_colval(key): |
| 526 | if args.process: |
Gary Lin | 3a45935 | 2018-03-27 15:54:09 +0800 | [diff] [blame] | 527 | return b"%-6d %-15s" % (key.value, comm_for_pid(key.value)) |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 528 | else: |
Gary Lin | 3a45935 | 2018-03-27 15:54:09 +0800 | [diff] [blame] | 529 | return syscalls.get(key.value, b"[unknown: %d]" % key.value) |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 530 | |
| 531 | def print_count_stats(): |
| 532 | data = bpf["data"] |
| 533 | print("[%s]" % strftime("%H:%M:%S")) |
| 534 | print("%-22s %8s" % (agg_colname, "COUNT")) |
| 535 | for k, v in sorted(data.items(), key=lambda kv: -kv[1].value)[:args.top]: |
| 536 | if k.value == 0xFFFFFFFF: |
| 537 | continue # happens occasionally, we don't need it |
Gary Lin | 3a45935 | 2018-03-27 15:54:09 +0800 | [diff] [blame] | 538 | printb(b"%-22s %8d" % (agg_colval(k), v.value)) |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 539 | print("") |
| 540 | data.clear() |
| 541 | |
| 542 | def print_latency_stats(): |
| 543 | data = bpf["data"] |
| 544 | print("[%s]" % strftime("%H:%M:%S")) |
| 545 | print("%-22s %8s %16s" % (agg_colname, "COUNT", time_colname)) |
Paul Chaignon | 956ca1c | 2017-03-04 20:07:56 +0100 | [diff] [blame] | 546 | for k, v in sorted(data.items(), |
| 547 | key=lambda kv: -kv[1].total_ns)[:args.top]: |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 548 | if k.value == 0xFFFFFFFF: |
| 549 | continue # happens occasionally, we don't need it |
Gary Lin | 3a45935 | 2018-03-27 15:54:09 +0800 | [diff] [blame] | 550 | printb((b"%-22s %8d " + (b"%16.6f" if args.milliseconds else b"%16.3f")) % |
| 551 | (agg_colval(k), v.count, |
| 552 | v.total_ns / (1e6 if args.milliseconds else 1e3))) |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 553 | print("") |
| 554 | data.clear() |
| 555 | |
| 556 | print("Tracing %ssyscalls, printing top %d... Ctrl+C to quit." % |
| 557 | ("failed " if args.failures else "", args.top)) |
Akilesh Kailash | 8996719 | 2018-05-18 13:36:54 -0700 | [diff] [blame] | 558 | exiting = 0 if args.interval else 1 |
| 559 | seconds = 0 |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 560 | while True: |
| 561 | try: |
Akilesh Kailash | 8996719 | 2018-05-18 13:36:54 -0700 | [diff] [blame] | 562 | sleep(args.interval) |
| 563 | seconds += args.interval |
Sasha Goldshtein | 8e583cc | 2017-02-09 10:11:50 -0500 | [diff] [blame] | 564 | except KeyboardInterrupt: |
Akilesh Kailash | 8996719 | 2018-05-18 13:36:54 -0700 | [diff] [blame] | 565 | exiting = 1 |
| 566 | signal.signal(signal.SIGINT, signal_ignore) |
| 567 | if args.duration and seconds >= args.duration: |
| 568 | exiting = 1 |
| 569 | |
| 570 | print_stats() |
| 571 | |
| 572 | if exiting: |
| 573 | print("Detaching...") |
| 574 | exit() |