xref: /aosp_15_r20/external/bcc/tools/opensnoop.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports
3*387f9dfdSAndroid Build Coastguard Worker#
4*387f9dfdSAndroid Build Coastguard Worker# opensnoop Trace open() syscalls.
5*387f9dfdSAndroid Build Coastguard Worker#           For Linux, uses BCC, eBPF. Embedded C.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: opensnoop [-h] [-T] [-U] [-x] [-p PID] [-t TID]
8*387f9dfdSAndroid Build Coastguard Worker#                  [--cgroupmap CGROUPMAP] [--mntnsmap MNTNSMAP] [-u UID]
9*387f9dfdSAndroid Build Coastguard Worker#                  [-d DURATION] [-n NAME] [-F] [-e] [-f FLAG_FILTER]
10*387f9dfdSAndroid Build Coastguard Worker#                  [-b BUFFER_PAGES]
11*387f9dfdSAndroid Build Coastguard Worker#
12*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg.
13*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
14*387f9dfdSAndroid Build Coastguard Worker#
15*387f9dfdSAndroid Build Coastguard Worker# 17-Sep-2015   Brendan Gregg   Created this.
16*387f9dfdSAndroid Build Coastguard Worker# 29-Apr-2016   Allan McAleavy  Updated for BPF_PERF_OUTPUT.
17*387f9dfdSAndroid Build Coastguard Worker# 08-Oct-2016   Dina Goldshtein Support filtering by PID and TID.
18*387f9dfdSAndroid Build Coastguard Worker# 28-Dec-2018   Tim Douglas     Print flags argument, enable filtering
19*387f9dfdSAndroid Build Coastguard Worker# 06-Jan-2019   Takuma Kume     Support filtering by UID
20*387f9dfdSAndroid Build Coastguard Worker# 21-Aug-2022   Rocky Xing      Support showing full path for an open file.
21*387f9dfdSAndroid Build Coastguard Worker# 06-Sep-2022   Rocky Xing      Support setting size of the perf ring buffer.
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
24*387f9dfdSAndroid Build Coastguard Workerfrom bcc import ArgString, BPF
25*387f9dfdSAndroid Build Coastguard Workerfrom bcc.containers import filter_by_containers
26*387f9dfdSAndroid Build Coastguard Workerfrom bcc.utils import printb
27*387f9dfdSAndroid Build Coastguard Workerimport argparse
28*387f9dfdSAndroid Build Coastguard Workerfrom collections import defaultdict
29*387f9dfdSAndroid Build Coastguard Workerfrom datetime import datetime, timedelta
30*387f9dfdSAndroid Build Coastguard Workerimport os
31*387f9dfdSAndroid Build Coastguard Worker
32*387f9dfdSAndroid Build Coastguard Worker# arguments
33*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
34*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop                        # trace all open() syscalls
35*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -T                     # include timestamps
36*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -U                     # include UID
37*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -x                     # only show failed opens
38*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -p 181                 # only trace PID 181
39*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -t 123                 # only trace TID 123
40*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -u 1000                # only trace UID 1000
41*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -d 10                  # trace for 10 seconds only
42*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -n main                # only print process names containing "main"
43*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -e                     # show extended fields
44*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -f O_WRONLY -f O_RDWR  # only print calls for writing
45*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop -F                     # show full path for an open file with relative path
46*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop --cgroupmap mappath    # only trace cgroups in this BPF map
47*387f9dfdSAndroid Build Coastguard Worker    ./opensnoop --mntnsmap mappath     # only trace mount namespaces in the map
48*387f9dfdSAndroid Build Coastguard Worker"""
49*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
50*387f9dfdSAndroid Build Coastguard Worker    description="Trace open() syscalls",
51*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
52*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
53*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--timestamp", action="store_true",
54*387f9dfdSAndroid Build Coastguard Worker    help="include timestamp on output")
55*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-U", "--print-uid", action="store_true",
56*387f9dfdSAndroid Build Coastguard Worker    help="print UID column")
57*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-x", "--failed", action="store_true",
58*387f9dfdSAndroid Build Coastguard Worker    help="only show failed opens")
59*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid",
60*387f9dfdSAndroid Build Coastguard Worker    help="trace this PID only")
61*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-t", "--tid",
62*387f9dfdSAndroid Build Coastguard Worker    help="trace this TID only")
63*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--cgroupmap",
64*387f9dfdSAndroid Build Coastguard Worker    help="trace cgroups in this BPF map only")
65*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--mntnsmap",
66*387f9dfdSAndroid Build Coastguard Worker    help="trace mount namespaces in this BPF map only")
67*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-u", "--uid",
68*387f9dfdSAndroid Build Coastguard Worker    help="trace this UID only")
69*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-d", "--duration",
70*387f9dfdSAndroid Build Coastguard Worker    help="total duration of trace in seconds")
71*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-n", "--name",
72*387f9dfdSAndroid Build Coastguard Worker    type=ArgString,
73*387f9dfdSAndroid Build Coastguard Worker    help="only print process names containing this name")
74*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
75*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
76*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-e", "--extended_fields", action="store_true",
77*387f9dfdSAndroid Build Coastguard Worker    help="show extended fields")
78*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-f", "--flag_filter", action="append",
79*387f9dfdSAndroid Build Coastguard Worker    help="filter on flags argument (e.g., O_WRONLY)")
80*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-F", "--full-path", action="store_true",
81*387f9dfdSAndroid Build Coastguard Worker    help="show full path for an open file with relative path")
82*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-b", "--buffer-pages", type=int, default=64,
83*387f9dfdSAndroid Build Coastguard Worker    help="size of the perf ring buffer "
84*387f9dfdSAndroid Build Coastguard Worker        "(must be a power of two number of pages and defaults to 64)")
85*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
86*387f9dfdSAndroid Build Coastguard Workerdebug = 0
87*387f9dfdSAndroid Build Coastguard Workerif args.duration:
88*387f9dfdSAndroid Build Coastguard Worker    args.duration = timedelta(seconds=int(args.duration))
89*387f9dfdSAndroid Build Coastguard Workerflag_filter_mask = 0
90*387f9dfdSAndroid Build Coastguard Workerfor flag in args.flag_filter or []:
91*387f9dfdSAndroid Build Coastguard Worker    if not flag.startswith('O_'):
92*387f9dfdSAndroid Build Coastguard Worker        exit("Bad flag: %s" % flag)
93*387f9dfdSAndroid Build Coastguard Worker    try:
94*387f9dfdSAndroid Build Coastguard Worker        flag_filter_mask |= getattr(os, flag)
95*387f9dfdSAndroid Build Coastguard Worker    except AttributeError:
96*387f9dfdSAndroid Build Coastguard Worker        exit("Bad flag: %s" % flag)
97*387f9dfdSAndroid Build Coastguard Worker
98*387f9dfdSAndroid Build Coastguard Worker# define BPF program
99*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
100*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
101*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/limits.h>
102*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
103*387f9dfdSAndroid Build Coastguard Worker#ifdef FULLPATH
104*387f9dfdSAndroid Build Coastguard Worker#include <linux/fs_struct.h>
105*387f9dfdSAndroid Build Coastguard Worker#include <linux/dcache.h>
106*387f9dfdSAndroid Build Coastguard Worker
107*387f9dfdSAndroid Build Coastguard Worker#define MAX_ENTRIES 32
108*387f9dfdSAndroid Build Coastguard Worker
109*387f9dfdSAndroid Build Coastguard Workerenum event_type {
110*387f9dfdSAndroid Build Coastguard Worker    EVENT_ENTRY,
111*387f9dfdSAndroid Build Coastguard Worker    EVENT_END,
112*387f9dfdSAndroid Build Coastguard Worker};
113*387f9dfdSAndroid Build Coastguard Worker#endif
114*387f9dfdSAndroid Build Coastguard Worker
115*387f9dfdSAndroid Build Coastguard Workerstruct val_t {
116*387f9dfdSAndroid Build Coastguard Worker    u64 id;
117*387f9dfdSAndroid Build Coastguard Worker    char comm[TASK_COMM_LEN];
118*387f9dfdSAndroid Build Coastguard Worker    const char *fname;
119*387f9dfdSAndroid Build Coastguard Worker    int flags; // EXTENDED_STRUCT_MEMBER
120*387f9dfdSAndroid Build Coastguard Worker};
121*387f9dfdSAndroid Build Coastguard Worker
122*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
123*387f9dfdSAndroid Build Coastguard Worker    u64 id;
124*387f9dfdSAndroid Build Coastguard Worker    u64 ts;
125*387f9dfdSAndroid Build Coastguard Worker    u32 uid;
126*387f9dfdSAndroid Build Coastguard Worker    int ret;
127*387f9dfdSAndroid Build Coastguard Worker    char comm[TASK_COMM_LEN];
128*387f9dfdSAndroid Build Coastguard Worker#ifdef FULLPATH
129*387f9dfdSAndroid Build Coastguard Worker    enum event_type type;
130*387f9dfdSAndroid Build Coastguard Worker#endif
131*387f9dfdSAndroid Build Coastguard Worker    char name[NAME_MAX];
132*387f9dfdSAndroid Build Coastguard Worker    int flags; // EXTENDED_STRUCT_MEMBER
133*387f9dfdSAndroid Build Coastguard Worker};
134*387f9dfdSAndroid Build Coastguard Worker
135*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
136*387f9dfdSAndroid Build Coastguard Worker"""
137*387f9dfdSAndroid Build Coastguard Worker
138*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe = """
139*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(infotmp, u64, struct val_t);
140*387f9dfdSAndroid Build Coastguard Worker
141*387f9dfdSAndroid Build Coastguard Workerint trace_return(struct pt_regs *ctx)
142*387f9dfdSAndroid Build Coastguard Worker{
143*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
144*387f9dfdSAndroid Build Coastguard Worker    struct val_t *valp;
145*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {};
146*387f9dfdSAndroid Build Coastguard Worker
147*387f9dfdSAndroid Build Coastguard Worker    u64 tsp = bpf_ktime_get_ns();
148*387f9dfdSAndroid Build Coastguard Worker
149*387f9dfdSAndroid Build Coastguard Worker    valp = infotmp.lookup(&id);
150*387f9dfdSAndroid Build Coastguard Worker    if (valp == 0) {
151*387f9dfdSAndroid Build Coastguard Worker        // missed entry
152*387f9dfdSAndroid Build Coastguard Worker        return 0;
153*387f9dfdSAndroid Build Coastguard Worker    }
154*387f9dfdSAndroid Build Coastguard Worker
155*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_kernel(&data.comm, sizeof(data.comm), valp->comm);
156*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user_str(&data.name, sizeof(data.name), (void *)valp->fname);
157*387f9dfdSAndroid Build Coastguard Worker    data.id = valp->id;
158*387f9dfdSAndroid Build Coastguard Worker    data.ts = tsp / 1000;
159*387f9dfdSAndroid Build Coastguard Worker    data.uid = bpf_get_current_uid_gid();
160*387f9dfdSAndroid Build Coastguard Worker    data.flags = valp->flags; // EXTENDED_STRUCT_MEMBER
161*387f9dfdSAndroid Build Coastguard Worker    data.ret = PT_REGS_RC(ctx);
162*387f9dfdSAndroid Build Coastguard Worker
163*387f9dfdSAndroid Build Coastguard Worker    SUBMIT_DATA
164*387f9dfdSAndroid Build Coastguard Worker
165*387f9dfdSAndroid Build Coastguard Worker    infotmp.delete(&id);
166*387f9dfdSAndroid Build Coastguard Worker
167*387f9dfdSAndroid Build Coastguard Worker    return 0;
168*387f9dfdSAndroid Build Coastguard Worker}
169*387f9dfdSAndroid Build Coastguard Worker"""
170*387f9dfdSAndroid Build Coastguard Worker
171*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_header_open = """
172*387f9dfdSAndroid Build Coastguard Workerint syscall__trace_entry_open(struct pt_regs *ctx, const char __user *filename, int flags)
173*387f9dfdSAndroid Build Coastguard Worker{
174*387f9dfdSAndroid Build Coastguard Worker"""
175*387f9dfdSAndroid Build Coastguard Worker
176*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_header_openat = """
177*387f9dfdSAndroid Build Coastguard Workerint syscall__trace_entry_openat(struct pt_regs *ctx, int dfd, const char __user *filename, int flags)
178*387f9dfdSAndroid Build Coastguard Worker{
179*387f9dfdSAndroid Build Coastguard Worker"""
180*387f9dfdSAndroid Build Coastguard Worker
181*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_header_openat2 = """
182*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/openat2.h>
183*387f9dfdSAndroid Build Coastguard Workerint syscall__trace_entry_openat2(struct pt_regs *ctx, int dfd, const char __user *filename, struct open_how *how)
184*387f9dfdSAndroid Build Coastguard Worker{
185*387f9dfdSAndroid Build Coastguard Worker    int flags = how->flags;
186*387f9dfdSAndroid Build Coastguard Worker"""
187*387f9dfdSAndroid Build Coastguard Worker
188*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_body = """
189*387f9dfdSAndroid Build Coastguard Worker    struct val_t val = {};
190*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
191*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
192*387f9dfdSAndroid Build Coastguard Worker    u32 tid = id;       // Cast and get the lower part
193*387f9dfdSAndroid Build Coastguard Worker    u32 uid = bpf_get_current_uid_gid();
194*387f9dfdSAndroid Build Coastguard Worker
195*387f9dfdSAndroid Build Coastguard Worker    PID_TID_FILTER
196*387f9dfdSAndroid Build Coastguard Worker    UID_FILTER
197*387f9dfdSAndroid Build Coastguard Worker    FLAGS_FILTER
198*387f9dfdSAndroid Build Coastguard Worker
199*387f9dfdSAndroid Build Coastguard Worker    if (container_should_be_filtered()) {
200*387f9dfdSAndroid Build Coastguard Worker        return 0;
201*387f9dfdSAndroid Build Coastguard Worker    }
202*387f9dfdSAndroid Build Coastguard Worker
203*387f9dfdSAndroid Build Coastguard Worker    if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
204*387f9dfdSAndroid Build Coastguard Worker        val.id = id;
205*387f9dfdSAndroid Build Coastguard Worker        val.fname = filename;
206*387f9dfdSAndroid Build Coastguard Worker        val.flags = flags; // EXTENDED_STRUCT_MEMBER
207*387f9dfdSAndroid Build Coastguard Worker        infotmp.update(&id, &val);
208*387f9dfdSAndroid Build Coastguard Worker    }
209*387f9dfdSAndroid Build Coastguard Worker
210*387f9dfdSAndroid Build Coastguard Worker    return 0;
211*387f9dfdSAndroid Build Coastguard Worker};
212*387f9dfdSAndroid Build Coastguard Worker"""
213*387f9dfdSAndroid Build Coastguard Worker
214*387f9dfdSAndroid Build Coastguard Workerbpf_text_kfunc_header_open = """
215*387f9dfdSAndroid Build Coastguard Worker#if defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER) && !defined(__s390x__)
216*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, struct pt_regs *regs, int ret)
217*387f9dfdSAndroid Build Coastguard Worker{
218*387f9dfdSAndroid Build Coastguard Worker    const char __user *filename = (char *)PT_REGS_PARM1(regs);
219*387f9dfdSAndroid Build Coastguard Worker    int flags = PT_REGS_PARM2(regs);
220*387f9dfdSAndroid Build Coastguard Worker#else
221*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, const char __user *filename, int flags, int ret)
222*387f9dfdSAndroid Build Coastguard Worker{
223*387f9dfdSAndroid Build Coastguard Worker#endif
224*387f9dfdSAndroid Build Coastguard Worker"""
225*387f9dfdSAndroid Build Coastguard Worker
226*387f9dfdSAndroid Build Coastguard Workerbpf_text_kfunc_header_openat = """
227*387f9dfdSAndroid Build Coastguard Worker#if defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER) && !defined(__s390x__)
228*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, struct pt_regs *regs, int ret)
229*387f9dfdSAndroid Build Coastguard Worker{
230*387f9dfdSAndroid Build Coastguard Worker    int dfd = PT_REGS_PARM1(regs);
231*387f9dfdSAndroid Build Coastguard Worker    const char __user *filename = (char *)PT_REGS_PARM2(regs);
232*387f9dfdSAndroid Build Coastguard Worker    int flags = PT_REGS_PARM3(regs);
233*387f9dfdSAndroid Build Coastguard Worker#else
234*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, int dfd, const char __user *filename, int flags, int ret)
235*387f9dfdSAndroid Build Coastguard Worker{
236*387f9dfdSAndroid Build Coastguard Worker#endif
237*387f9dfdSAndroid Build Coastguard Worker"""
238*387f9dfdSAndroid Build Coastguard Worker
239*387f9dfdSAndroid Build Coastguard Workerbpf_text_kfunc_header_openat2 = """
240*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/openat2.h>
241*387f9dfdSAndroid Build Coastguard Worker#if defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER) && !defined(__s390x__)
242*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, struct pt_regs *regs, int ret)
243*387f9dfdSAndroid Build Coastguard Worker{
244*387f9dfdSAndroid Build Coastguard Worker    int dfd = PT_REGS_PARM1(regs);
245*387f9dfdSAndroid Build Coastguard Worker    const char __user *filename = (char *)PT_REGS_PARM2(regs);
246*387f9dfdSAndroid Build Coastguard Worker    struct open_how __user how;
247*387f9dfdSAndroid Build Coastguard Worker    int flags;
248*387f9dfdSAndroid Build Coastguard Worker
249*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user(&how, sizeof(struct open_how), (struct open_how*)PT_REGS_PARM3(regs));
250*387f9dfdSAndroid Build Coastguard Worker    flags = how.flags;
251*387f9dfdSAndroid Build Coastguard Worker#else
252*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, int dfd, const char __user *filename, struct open_how __user *how, int ret)
253*387f9dfdSAndroid Build Coastguard Worker{
254*387f9dfdSAndroid Build Coastguard Worker    int flags = how->flags;
255*387f9dfdSAndroid Build Coastguard Worker#endif
256*387f9dfdSAndroid Build Coastguard Worker"""
257*387f9dfdSAndroid Build Coastguard Worker
258*387f9dfdSAndroid Build Coastguard Workerbpf_text_kfunc_body = """
259*387f9dfdSAndroid Build Coastguard Worker    u64 id = bpf_get_current_pid_tgid();
260*387f9dfdSAndroid Build Coastguard Worker    u32 pid = id >> 32; // PID is higher part
261*387f9dfdSAndroid Build Coastguard Worker    u32 tid = id;       // Cast and get the lower part
262*387f9dfdSAndroid Build Coastguard Worker    u32 uid = bpf_get_current_uid_gid();
263*387f9dfdSAndroid Build Coastguard Worker
264*387f9dfdSAndroid Build Coastguard Worker    PID_TID_FILTER
265*387f9dfdSAndroid Build Coastguard Worker    UID_FILTER
266*387f9dfdSAndroid Build Coastguard Worker    FLAGS_FILTER
267*387f9dfdSAndroid Build Coastguard Worker    if (container_should_be_filtered()) {
268*387f9dfdSAndroid Build Coastguard Worker        return 0;
269*387f9dfdSAndroid Build Coastguard Worker    }
270*387f9dfdSAndroid Build Coastguard Worker
271*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {};
272*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&data.comm, sizeof(data.comm));
273*387f9dfdSAndroid Build Coastguard Worker
274*387f9dfdSAndroid Build Coastguard Worker    u64 tsp = bpf_ktime_get_ns();
275*387f9dfdSAndroid Build Coastguard Worker
276*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user_str(&data.name, sizeof(data.name), (void *)filename);
277*387f9dfdSAndroid Build Coastguard Worker    data.id    = id;
278*387f9dfdSAndroid Build Coastguard Worker    data.ts    = tsp / 1000;
279*387f9dfdSAndroid Build Coastguard Worker    data.uid   = bpf_get_current_uid_gid();
280*387f9dfdSAndroid Build Coastguard Worker    data.flags = flags; // EXTENDED_STRUCT_MEMBER
281*387f9dfdSAndroid Build Coastguard Worker    data.ret   = ret;
282*387f9dfdSAndroid Build Coastguard Worker
283*387f9dfdSAndroid Build Coastguard Worker    SUBMIT_DATA
284*387f9dfdSAndroid Build Coastguard Worker
285*387f9dfdSAndroid Build Coastguard Worker    return 0;
286*387f9dfdSAndroid Build Coastguard Worker}
287*387f9dfdSAndroid Build Coastguard Worker"""
288*387f9dfdSAndroid Build Coastguard Worker
289*387f9dfdSAndroid Build Coastguard Workerb = BPF(text='')
290*387f9dfdSAndroid Build Coastguard Worker# open and openat are always in place since 2.6.16
291*387f9dfdSAndroid Build Coastguard Workerfnname_open = b.get_syscall_prefix().decode() + 'open'
292*387f9dfdSAndroid Build Coastguard Workerfnname_openat = b.get_syscall_prefix().decode() + 'openat'
293*387f9dfdSAndroid Build Coastguard Workerfnname_openat2 = b.get_syscall_prefix().decode() + 'openat2'
294*387f9dfdSAndroid Build Coastguard Workerif b.ksymname(fnname_openat2) == -1:
295*387f9dfdSAndroid Build Coastguard Worker    fnname_openat2 = None
296*387f9dfdSAndroid Build Coastguard Worker
297*387f9dfdSAndroid Build Coastguard Workerif args.full_path:
298*387f9dfdSAndroid Build Coastguard Worker    bpf_text = "#define FULLPATH\n" + bpf_text
299*387f9dfdSAndroid Build Coastguard Worker
300*387f9dfdSAndroid Build Coastguard Workeris_support_kfunc = BPF.support_kfunc()
301*387f9dfdSAndroid Build Coastguard Workerif is_support_kfunc:
302*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kfunc_header_open.replace('FNNAME', fnname_open)
303*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kfunc_body
304*387f9dfdSAndroid Build Coastguard Worker
305*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kfunc_header_openat.replace('FNNAME', fnname_openat)
306*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kfunc_body
307*387f9dfdSAndroid Build Coastguard Worker
308*387f9dfdSAndroid Build Coastguard Worker    if fnname_openat2:
309*387f9dfdSAndroid Build Coastguard Worker        bpf_text += bpf_text_kfunc_header_openat2.replace('FNNAME', fnname_openat2)
310*387f9dfdSAndroid Build Coastguard Worker        bpf_text += bpf_text_kfunc_body
311*387f9dfdSAndroid Build Coastguard Workerelse:
312*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kprobe
313*387f9dfdSAndroid Build Coastguard Worker
314*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kprobe_header_open
315*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kprobe_body
316*387f9dfdSAndroid Build Coastguard Worker
317*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kprobe_header_openat
318*387f9dfdSAndroid Build Coastguard Worker    bpf_text += bpf_text_kprobe_body
319*387f9dfdSAndroid Build Coastguard Worker
320*387f9dfdSAndroid Build Coastguard Worker    if fnname_openat2:
321*387f9dfdSAndroid Build Coastguard Worker        bpf_text += bpf_text_kprobe_header_openat2
322*387f9dfdSAndroid Build Coastguard Worker        bpf_text += bpf_text_kprobe_body
323*387f9dfdSAndroid Build Coastguard Worker
324*387f9dfdSAndroid Build Coastguard Workerif args.tid:  # TID trumps PID
325*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('PID_TID_FILTER',
326*387f9dfdSAndroid Build Coastguard Worker        'if (tid != %s) { return 0; }' % args.tid)
327*387f9dfdSAndroid Build Coastguard Workerelif args.pid:
328*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('PID_TID_FILTER',
329*387f9dfdSAndroid Build Coastguard Worker        'if (pid != %s) { return 0; }' % args.pid)
330*387f9dfdSAndroid Build Coastguard Workerelse:
331*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('PID_TID_FILTER', '')
332*387f9dfdSAndroid Build Coastguard Workerif args.uid:
333*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('UID_FILTER',
334*387f9dfdSAndroid Build Coastguard Worker        'if (uid != %s) { return 0; }' % args.uid)
335*387f9dfdSAndroid Build Coastguard Workerelse:
336*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('UID_FILTER', '')
337*387f9dfdSAndroid Build Coastguard Workerbpf_text = filter_by_containers(args) + bpf_text
338*387f9dfdSAndroid Build Coastguard Workerif args.flag_filter:
339*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FLAGS_FILTER',
340*387f9dfdSAndroid Build Coastguard Worker        'if (!(flags & %d)) { return 0; }' % flag_filter_mask)
341*387f9dfdSAndroid Build Coastguard Workerelse:
342*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('FLAGS_FILTER', '')
343*387f9dfdSAndroid Build Coastguard Workerif not (args.extended_fields or args.flag_filter):
344*387f9dfdSAndroid Build Coastguard Worker    bpf_text = '\n'.join(x for x in bpf_text.split('\n')
345*387f9dfdSAndroid Build Coastguard Worker        if 'EXTENDED_STRUCT_MEMBER' not in x)
346*387f9dfdSAndroid Build Coastguard Worker
347*387f9dfdSAndroid Build Coastguard Workerif args.full_path:
348*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('SUBMIT_DATA', """
349*387f9dfdSAndroid Build Coastguard Worker    data.type = EVENT_ENTRY;
350*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
351*387f9dfdSAndroid Build Coastguard Worker
352*387f9dfdSAndroid Build Coastguard Worker    if (data.name[0] != '/') { // relative path
353*387f9dfdSAndroid Build Coastguard Worker        struct task_struct *task;
354*387f9dfdSAndroid Build Coastguard Worker        struct dentry *dentry;
355*387f9dfdSAndroid Build Coastguard Worker        int i;
356*387f9dfdSAndroid Build Coastguard Worker
357*387f9dfdSAndroid Build Coastguard Worker        task = (struct task_struct *)bpf_get_current_task_btf();
358*387f9dfdSAndroid Build Coastguard Worker        dentry = task->fs->pwd.dentry;
359*387f9dfdSAndroid Build Coastguard Worker
360*387f9dfdSAndroid Build Coastguard Worker        for (i = 1; i < MAX_ENTRIES; i++) {
361*387f9dfdSAndroid Build Coastguard Worker            bpf_probe_read_kernel(&data.name, sizeof(data.name), (void *)dentry->d_name.name);
362*387f9dfdSAndroid Build Coastguard Worker            data.type = EVENT_ENTRY;
363*387f9dfdSAndroid Build Coastguard Worker            events.perf_submit(ctx, &data, sizeof(data));
364*387f9dfdSAndroid Build Coastguard Worker
365*387f9dfdSAndroid Build Coastguard Worker            if (dentry == dentry->d_parent) { // root directory
366*387f9dfdSAndroid Build Coastguard Worker                break;
367*387f9dfdSAndroid Build Coastguard Worker            }
368*387f9dfdSAndroid Build Coastguard Worker
369*387f9dfdSAndroid Build Coastguard Worker            dentry = dentry->d_parent;
370*387f9dfdSAndroid Build Coastguard Worker        }
371*387f9dfdSAndroid Build Coastguard Worker    }
372*387f9dfdSAndroid Build Coastguard Worker
373*387f9dfdSAndroid Build Coastguard Worker    data.type = EVENT_END;
374*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
375*387f9dfdSAndroid Build Coastguard Worker    """)
376*387f9dfdSAndroid Build Coastguard Workerelse:
377*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('SUBMIT_DATA', """
378*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
379*387f9dfdSAndroid Build Coastguard Worker    """)
380*387f9dfdSAndroid Build Coastguard Worker
381*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf:
382*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
383*387f9dfdSAndroid Build Coastguard Worker    if args.ebpf:
384*387f9dfdSAndroid Build Coastguard Worker        exit()
385*387f9dfdSAndroid Build Coastguard Worker
386*387f9dfdSAndroid Build Coastguard Worker# initialize BPF
387*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
388*387f9dfdSAndroid Build Coastguard Workerif not is_support_kfunc:
389*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event=fnname_open, fn_name="syscall__trace_entry_open")
390*387f9dfdSAndroid Build Coastguard Worker    b.attach_kretprobe(event=fnname_open, fn_name="trace_return")
391*387f9dfdSAndroid Build Coastguard Worker
392*387f9dfdSAndroid Build Coastguard Worker    b.attach_kprobe(event=fnname_openat, fn_name="syscall__trace_entry_openat")
393*387f9dfdSAndroid Build Coastguard Worker    b.attach_kretprobe(event=fnname_openat, fn_name="trace_return")
394*387f9dfdSAndroid Build Coastguard Worker
395*387f9dfdSAndroid Build Coastguard Worker    if fnname_openat2:
396*387f9dfdSAndroid Build Coastguard Worker        b.attach_kprobe(event=fnname_openat2, fn_name="syscall__trace_entry_openat2")
397*387f9dfdSAndroid Build Coastguard Worker        b.attach_kretprobe(event=fnname_openat2, fn_name="trace_return")
398*387f9dfdSAndroid Build Coastguard Worker
399*387f9dfdSAndroid Build Coastguard Workerinitial_ts = 0
400*387f9dfdSAndroid Build Coastguard Worker
401*387f9dfdSAndroid Build Coastguard Worker# header
402*387f9dfdSAndroid Build Coastguard Workerif args.timestamp:
403*387f9dfdSAndroid Build Coastguard Worker    print("%-14s" % ("TIME(s)"), end="")
404*387f9dfdSAndroid Build Coastguard Workerif args.print_uid:
405*387f9dfdSAndroid Build Coastguard Worker    print("%-6s" % ("UID"), end="")
406*387f9dfdSAndroid Build Coastguard Workerprint("%-6s %-16s %4s %3s " %
407*387f9dfdSAndroid Build Coastguard Worker      ("TID" if args.tid else "PID", "COMM", "FD", "ERR"), end="")
408*387f9dfdSAndroid Build Coastguard Workerif args.extended_fields:
409*387f9dfdSAndroid Build Coastguard Worker    print("%-9s" % ("FLAGS"), end="")
410*387f9dfdSAndroid Build Coastguard Workerprint("PATH")
411*387f9dfdSAndroid Build Coastguard Worker
412*387f9dfdSAndroid Build Coastguard Workerclass EventType(object):
413*387f9dfdSAndroid Build Coastguard Worker    EVENT_ENTRY = 0
414*387f9dfdSAndroid Build Coastguard Worker    EVENT_END = 1
415*387f9dfdSAndroid Build Coastguard Worker
416*387f9dfdSAndroid Build Coastguard Workerentries = defaultdict(list)
417*387f9dfdSAndroid Build Coastguard Worker
418*387f9dfdSAndroid Build Coastguard Worker# process event
419*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
420*387f9dfdSAndroid Build Coastguard Worker    event = b["events"].event(data)
421*387f9dfdSAndroid Build Coastguard Worker    global initial_ts
422*387f9dfdSAndroid Build Coastguard Worker
423*387f9dfdSAndroid Build Coastguard Worker    if not args.full_path or event.type == EventType.EVENT_END:
424*387f9dfdSAndroid Build Coastguard Worker        skip = False
425*387f9dfdSAndroid Build Coastguard Worker
426*387f9dfdSAndroid Build Coastguard Worker        # split return value into FD and errno columns
427*387f9dfdSAndroid Build Coastguard Worker        if event.ret >= 0:
428*387f9dfdSAndroid Build Coastguard Worker            fd_s = event.ret
429*387f9dfdSAndroid Build Coastguard Worker            err = 0
430*387f9dfdSAndroid Build Coastguard Worker        else:
431*387f9dfdSAndroid Build Coastguard Worker            fd_s = -1
432*387f9dfdSAndroid Build Coastguard Worker            err = - event.ret
433*387f9dfdSAndroid Build Coastguard Worker
434*387f9dfdSAndroid Build Coastguard Worker        if not initial_ts:
435*387f9dfdSAndroid Build Coastguard Worker            initial_ts = event.ts
436*387f9dfdSAndroid Build Coastguard Worker
437*387f9dfdSAndroid Build Coastguard Worker        if args.failed and (event.ret >= 0):
438*387f9dfdSAndroid Build Coastguard Worker            skip = True
439*387f9dfdSAndroid Build Coastguard Worker
440*387f9dfdSAndroid Build Coastguard Worker        if args.name and bytes(args.name) not in event.comm:
441*387f9dfdSAndroid Build Coastguard Worker            skip = True
442*387f9dfdSAndroid Build Coastguard Worker
443*387f9dfdSAndroid Build Coastguard Worker        if not skip:
444*387f9dfdSAndroid Build Coastguard Worker            if args.timestamp:
445*387f9dfdSAndroid Build Coastguard Worker                delta = event.ts - initial_ts
446*387f9dfdSAndroid Build Coastguard Worker                printb(b"%-14.9f" % (float(delta) / 1000000), nl="")
447*387f9dfdSAndroid Build Coastguard Worker
448*387f9dfdSAndroid Build Coastguard Worker            if args.print_uid:
449*387f9dfdSAndroid Build Coastguard Worker                printb(b"%-6d" % event.uid, nl="")
450*387f9dfdSAndroid Build Coastguard Worker
451*387f9dfdSAndroid Build Coastguard Worker            printb(b"%-6d %-16s %4d %3d " %
452*387f9dfdSAndroid Build Coastguard Worker                   (event.id & 0xffffffff if args.tid else event.id >> 32,
453*387f9dfdSAndroid Build Coastguard Worker                    event.comm, fd_s, err), nl="")
454*387f9dfdSAndroid Build Coastguard Worker
455*387f9dfdSAndroid Build Coastguard Worker            if args.extended_fields:
456*387f9dfdSAndroid Build Coastguard Worker                printb(b"%08o " % event.flags, nl="")
457*387f9dfdSAndroid Build Coastguard Worker
458*387f9dfdSAndroid Build Coastguard Worker            if not args.full_path:
459*387f9dfdSAndroid Build Coastguard Worker                printb(b"%s" % event.name)
460*387f9dfdSAndroid Build Coastguard Worker            else:
461*387f9dfdSAndroid Build Coastguard Worker                paths = entries[event.id]
462*387f9dfdSAndroid Build Coastguard Worker                paths.reverse()
463*387f9dfdSAndroid Build Coastguard Worker                printb(b"%s" % os.path.join(*paths))
464*387f9dfdSAndroid Build Coastguard Worker
465*387f9dfdSAndroid Build Coastguard Worker        if args.full_path:
466*387f9dfdSAndroid Build Coastguard Worker            try:
467*387f9dfdSAndroid Build Coastguard Worker                del(entries[event.id])
468*387f9dfdSAndroid Build Coastguard Worker            except Exception:
469*387f9dfdSAndroid Build Coastguard Worker                pass
470*387f9dfdSAndroid Build Coastguard Worker    elif event.type == EventType.EVENT_ENTRY:
471*387f9dfdSAndroid Build Coastguard Worker        entries[event.id].append(event.name)
472*387f9dfdSAndroid Build Coastguard Worker
473*387f9dfdSAndroid Build Coastguard Worker# loop with callback to print_event
474*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event, page_cnt=args.buffer_pages)
475*387f9dfdSAndroid Build Coastguard Workerstart_time = datetime.now()
476*387f9dfdSAndroid Build Coastguard Workerwhile not args.duration or datetime.now() - start_time < args.duration:
477*387f9dfdSAndroid Build Coastguard Worker    try:
478*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll()
479*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
480*387f9dfdSAndroid Build Coastguard Worker        exit()
481