blob: 3746b354e26e8a72b4fe72a7e6cbfb48e9145c7d [file] [log] [blame]
Brendan Greggbedd1502015-09-17 21:52:52 -07001#!/usr/bin/python
2#
3# opensnoop Trace open() syscalls.
4# For Linux, uses BCC, eBPF. Embedded C.
5#
6# USAGE: opensnoop [-h] [-t] [-x] [-p PID]
7#
8# Copyright (c) 2015 Brendan Gregg.
9# Licensed under the Apache License, Version 2.0 (the "License")
10#
11# 17-Sep-2015 Brendan Gregg Created this.
12
13from __future__ import print_function
14from bcc import BPF
15import argparse
16
17# arguments
18examples = """examples:
19 ./opensnoop # trace all open() syscalls
20 ./opensnoop -t # include timestamps
21 ./opensnoop -x # only show failed opens
22 ./opensnoop -p 181 # only trace PID 181
23"""
24parser = argparse.ArgumentParser(
25 description="Trace open() syscalls",
26 formatter_class=argparse.RawDescriptionHelpFormatter,
27 epilog=examples)
28parser.add_argument("-t", "--timestamp", action="store_true",
29 help="include timestamp on output")
30parser.add_argument("-x", "--failed", action="store_true",
31 help="only show failed opens")
32parser.add_argument("-p", "--pid",
33 help="trace this PID only")
34args = parser.parse_args()
35debug = 0
36
37# define BPF program
38bpf_text = """
39#include <uapi/linux/ptrace.h>
40
41BPF_HASH(args_filename, u32, const char *);
42
43int kprobe__sys_open(struct pt_regs *ctx, const char __user *filename)
44{
45 u32 pid = bpf_get_current_pid_tgid();
46
47 FILTER
48 args_filename.update(&pid, &filename);
49
50 return 0;
51};
52
53int kretprobe__sys_open(struct pt_regs *ctx)
54{
55 const char **filenamep;
56 int ret = ctx->ax;
57 u32 pid = bpf_get_current_pid_tgid();
58
59 filenamep = args_filename.lookup(&pid);
60 if (filenamep == 0) {
61 // missed entry
62 return 0;
63 }
64
65 bpf_trace_printk("%s %d\\n", *filenamep, ret);
66 args_filename.delete(&pid);
67
68 return 0;
69}
70"""
71if args.pid:
72 bpf_text = bpf_text.replace('FILTER',
73 'if (pid != %s) { return 0; }' % args.pid)
74else:
75 bpf_text = bpf_text.replace('FILTER', '')
76if debug:
77 print(bpf_text)
78
79# initialize BPF
80b = BPF(text=bpf_text)
81
82# header
83if args.timestamp:
84 print("%-14s" % ("TIME(s)"), end="")
85print("%-6s %-16s %4s %3s %s" % ("PID", "COMM", "FD", "ERR", "PATH"))
86
87start_ts = 0
88
89# format output
90while 1:
91 (task, pid, cpu, flags, ts, msg) = b.trace_fields()
Brendan Gregg665c5b02015-09-21 11:55:52 -070092 (filename, ret_s) = msg.split(" ")
Brendan Greggbedd1502015-09-17 21:52:52 -070093
94 ret = int(ret_s)
95 if (args.failed and (ret >= 0)):
96 continue
97
98 # split return value into FD and errno columns
99 if ret >= 0:
100 fd_s = ret; err = 0
101 else:
102 fd_s = "-1"; err = - ret
103
104 # print columns
105 if args.timestamp:
106 if start_ts == 0:
107 start_ts = ts
108 print("%-14.9f" % (ts - start_ts), end="")
Brendan Gregg665c5b02015-09-21 11:55:52 -0700109 print("%-6d %-16s %4s %3s %s" % (pid, task, fd_s, err, filename))