xref: /aosp_15_r20/external/bcc/tools/execsnoop.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# execsnoop Trace new processes via exec() syscalls.
5*387f9dfdSAndroid Build Coastguard Worker#           For Linux, uses BCC, eBPF. Embedded C.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: execsnoop [-h] [-T] [-t] [-x] [--cgroupmap CGROUPMAP]
8*387f9dfdSAndroid Build Coastguard Worker#                  [--mntnsmap MNTNSMAP] [-u USER] [-q] [-n NAME] [-l LINE]
9*387f9dfdSAndroid Build Coastguard Worker#                  [-U] [--max-args MAX_ARGS] [-P PPID]
10*387f9dfdSAndroid Build Coastguard Worker#
11*387f9dfdSAndroid Build Coastguard Worker# This currently will print up to a maximum of 19 arguments, plus the process
12*387f9dfdSAndroid Build Coastguard Worker# name, so 20 fields in total (MAXARG).
13*387f9dfdSAndroid Build Coastguard Worker#
14*387f9dfdSAndroid Build Coastguard Worker# This won't catch all new processes: an application may fork() but not exec().
15*387f9dfdSAndroid Build Coastguard Worker#
16*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc.
17*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
18*387f9dfdSAndroid Build Coastguard Worker#
19*387f9dfdSAndroid Build Coastguard Worker# 07-Feb-2016   Brendan Gregg   Created this.
20*387f9dfdSAndroid Build Coastguard Worker# 11-Aug-2022   Rocky Xing      Added PPID filter support.
21*387f9dfdSAndroid Build Coastguard Worker
22*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
23*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
24*387f9dfdSAndroid Build Coastguard Workerfrom bcc.containers import filter_by_containers
25*387f9dfdSAndroid Build Coastguard Workerfrom bcc.utils import ArgString, printb
26*387f9dfdSAndroid Build Coastguard Workerimport bcc.utils as utils
27*387f9dfdSAndroid Build Coastguard Workerimport argparse
28*387f9dfdSAndroid Build Coastguard Workerimport re
29*387f9dfdSAndroid Build Coastguard Workerimport time
30*387f9dfdSAndroid Build Coastguard Workerimport pwd
31*387f9dfdSAndroid Build Coastguard Workerfrom collections import defaultdict
32*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime
33*387f9dfdSAndroid Build Coastguard Worker
34*387f9dfdSAndroid Build Coastguard Worker
35*387f9dfdSAndroid Build Coastguard Workerdef parse_uid(user):
36*387f9dfdSAndroid Build Coastguard Worker    try:
37*387f9dfdSAndroid Build Coastguard Worker        result = int(user)
38*387f9dfdSAndroid Build Coastguard Worker    except ValueError:
39*387f9dfdSAndroid Build Coastguard Worker        try:
40*387f9dfdSAndroid Build Coastguard Worker            user_info = pwd.getpwnam(user)
41*387f9dfdSAndroid Build Coastguard Worker        except KeyError:
42*387f9dfdSAndroid Build Coastguard Worker            raise argparse.ArgumentTypeError(
43*387f9dfdSAndroid Build Coastguard Worker                "{0!r} is not valid UID or user entry".format(user))
44*387f9dfdSAndroid Build Coastguard Worker        else:
45*387f9dfdSAndroid Build Coastguard Worker            return user_info.pw_uid
46*387f9dfdSAndroid Build Coastguard Worker    else:
47*387f9dfdSAndroid Build Coastguard Worker        # Maybe validate if UID < 0 ?
48*387f9dfdSAndroid Build Coastguard Worker        return result
49*387f9dfdSAndroid Build Coastguard Worker
50*387f9dfdSAndroid Build Coastguard Worker
51*387f9dfdSAndroid Build Coastguard Worker# arguments
52*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
53*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop                      # trace all exec() syscalls
54*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -x                   # include failed exec()s
55*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -T                   # include time (HH:MM:SS)
56*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -P 181               # only trace new processes whose parent PID is 181
57*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -U                   # include UID
58*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -u 1000              # only trace UID 1000
59*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -u user              # get user UID and trace only them
60*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -t                   # include timestamps
61*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -q                   # add "quotemarks" around arguments
62*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -n main              # only print command lines containing "main"
63*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop -l tpkg              # only print command where arguments contains "tpkg"
64*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop --cgroupmap mappath  # only trace cgroups in this BPF map
65*387f9dfdSAndroid Build Coastguard Worker    ./execsnoop --mntnsmap mappath   # only trace mount namespaces in the map
66*387f9dfdSAndroid Build Coastguard Worker"""
67*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
68*387f9dfdSAndroid Build Coastguard Worker    description="Trace exec() syscalls",
69*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
70*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
71*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--time", action="store_true",
72*387f9dfdSAndroid Build Coastguard Worker    help="include time column on output (HH:MM:SS)")
73*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-t", "--timestamp", action="store_true",
74*387f9dfdSAndroid Build Coastguard Worker    help="include timestamp on output")
75*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-x", "--fails", action="store_true",
76*387f9dfdSAndroid Build Coastguard Worker    help="include failed exec()s")
77*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--cgroupmap",
78*387f9dfdSAndroid Build Coastguard Worker    help="trace cgroups in this BPF map only")
79*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--mntnsmap",
80*387f9dfdSAndroid Build Coastguard Worker    help="trace mount namespaces in this BPF map only")
81*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-u", "--uid", type=parse_uid, metavar='USER',
82*387f9dfdSAndroid Build Coastguard Worker    help="trace this UID only")
83*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-q", "--quote", action="store_true",
84*387f9dfdSAndroid Build Coastguard Worker    help="Add quotemarks (\") around arguments."
85*387f9dfdSAndroid Build Coastguard Worker    )
86*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-n", "--name",
87*387f9dfdSAndroid Build Coastguard Worker    type=ArgString,
88*387f9dfdSAndroid Build Coastguard Worker    help="only print commands matching this name (regex), any arg")
89*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-l", "--line",
90*387f9dfdSAndroid Build Coastguard Worker    type=ArgString,
91*387f9dfdSAndroid Build Coastguard Worker    help="only print commands where arg contains this line (regex)")
92*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-U", "--print-uid", action="store_true",
93*387f9dfdSAndroid Build Coastguard Worker    help="print UID column")
94*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--max-args", default="20",
95*387f9dfdSAndroid Build Coastguard Worker    help="maximum number of arguments parsed and displayed, defaults to 20")
96*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-P", "--ppid",
97*387f9dfdSAndroid Build Coastguard Worker    help="trace this parent PID only")
98*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
99*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
100*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
101*387f9dfdSAndroid Build Coastguard Worker
102*387f9dfdSAndroid Build Coastguard Worker# define BPF program
103*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
104*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
105*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
106*387f9dfdSAndroid Build Coastguard Worker#include <linux/fs.h>
107*387f9dfdSAndroid Build Coastguard Worker
108*387f9dfdSAndroid Build Coastguard Worker#define ARGSIZE  128
109*387f9dfdSAndroid Build Coastguard Worker
110*387f9dfdSAndroid Build Coastguard Workerenum event_type {
111*387f9dfdSAndroid Build Coastguard Worker    EVENT_ARG,
112*387f9dfdSAndroid Build Coastguard Worker    EVENT_RET,
113*387f9dfdSAndroid Build Coastguard Worker};
114*387f9dfdSAndroid Build Coastguard Worker
115*387f9dfdSAndroid Build Coastguard Workerstruct data_t {
116*387f9dfdSAndroid Build Coastguard Worker    u32 pid;  // PID as in the userspace term (i.e. task->tgid in kernel)
117*387f9dfdSAndroid Build Coastguard Worker    u32 ppid; // Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel)
118*387f9dfdSAndroid Build Coastguard Worker    u32 uid;
119*387f9dfdSAndroid Build Coastguard Worker    char comm[TASK_COMM_LEN];
120*387f9dfdSAndroid Build Coastguard Worker    enum event_type type;
121*387f9dfdSAndroid Build Coastguard Worker    char argv[ARGSIZE];
122*387f9dfdSAndroid Build Coastguard Worker    int retval;
123*387f9dfdSAndroid Build Coastguard Worker};
124*387f9dfdSAndroid Build Coastguard Worker
125*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
126*387f9dfdSAndroid Build Coastguard Worker
127*387f9dfdSAndroid Build Coastguard Workerstatic int __submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data)
128*387f9dfdSAndroid Build Coastguard Worker{
129*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user(data->argv, sizeof(data->argv), ptr);
130*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, data, sizeof(struct data_t));
131*387f9dfdSAndroid Build Coastguard Worker    return 1;
132*387f9dfdSAndroid Build Coastguard Worker}
133*387f9dfdSAndroid Build Coastguard Worker
134*387f9dfdSAndroid Build Coastguard Workerstatic int submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data)
135*387f9dfdSAndroid Build Coastguard Worker{
136*387f9dfdSAndroid Build Coastguard Worker    const char *argp = NULL;
137*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user(&argp, sizeof(argp), ptr);
138*387f9dfdSAndroid Build Coastguard Worker    if (argp) {
139*387f9dfdSAndroid Build Coastguard Worker        return __submit_arg(ctx, (void *)(argp), data);
140*387f9dfdSAndroid Build Coastguard Worker    }
141*387f9dfdSAndroid Build Coastguard Worker    return 0;
142*387f9dfdSAndroid Build Coastguard Worker}
143*387f9dfdSAndroid Build Coastguard Worker
144*387f9dfdSAndroid Build Coastguard Workerint syscall__execve(struct pt_regs *ctx,
145*387f9dfdSAndroid Build Coastguard Worker    const char __user *filename,
146*387f9dfdSAndroid Build Coastguard Worker    const char __user *const __user *__argv,
147*387f9dfdSAndroid Build Coastguard Worker    const char __user *const __user *__envp)
148*387f9dfdSAndroid Build Coastguard Worker{
149*387f9dfdSAndroid Build Coastguard Worker
150*387f9dfdSAndroid Build Coastguard Worker    u32 uid = bpf_get_current_uid_gid() & 0xffffffff;
151*387f9dfdSAndroid Build Coastguard Worker
152*387f9dfdSAndroid Build Coastguard Worker    UID_FILTER
153*387f9dfdSAndroid Build Coastguard Worker
154*387f9dfdSAndroid Build Coastguard Worker    if (container_should_be_filtered()) {
155*387f9dfdSAndroid Build Coastguard Worker        return 0;
156*387f9dfdSAndroid Build Coastguard Worker    }
157*387f9dfdSAndroid Build Coastguard Worker
158*387f9dfdSAndroid Build Coastguard Worker    // create data here and pass to submit_arg to save stack space (#555)
159*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {};
160*387f9dfdSAndroid Build Coastguard Worker    struct task_struct *task;
161*387f9dfdSAndroid Build Coastguard Worker
162*387f9dfdSAndroid Build Coastguard Worker    data.pid = bpf_get_current_pid_tgid() >> 32;
163*387f9dfdSAndroid Build Coastguard Worker
164*387f9dfdSAndroid Build Coastguard Worker    task = (struct task_struct *)bpf_get_current_task();
165*387f9dfdSAndroid Build Coastguard Worker    // Some kernels, like Ubuntu 4.13.0-generic, return 0
166*387f9dfdSAndroid Build Coastguard Worker    // as the real_parent->tgid.
167*387f9dfdSAndroid Build Coastguard Worker    // We use the get_ppid function as a fallback in those cases. (#1883)
168*387f9dfdSAndroid Build Coastguard Worker    data.ppid = task->real_parent->tgid;
169*387f9dfdSAndroid Build Coastguard Worker
170*387f9dfdSAndroid Build Coastguard Worker    PPID_FILTER
171*387f9dfdSAndroid Build Coastguard Worker
172*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&data.comm, sizeof(data.comm));
173*387f9dfdSAndroid Build Coastguard Worker    data.type = EVENT_ARG;
174*387f9dfdSAndroid Build Coastguard Worker
175*387f9dfdSAndroid Build Coastguard Worker    __submit_arg(ctx, (void *)filename, &data);
176*387f9dfdSAndroid Build Coastguard Worker
177*387f9dfdSAndroid Build Coastguard Worker    // skip first arg, as we submitted filename
178*387f9dfdSAndroid Build Coastguard Worker    #pragma unroll
179*387f9dfdSAndroid Build Coastguard Worker    for (int i = 1; i < MAXARG; i++) {
180*387f9dfdSAndroid Build Coastguard Worker        if (submit_arg(ctx, (void *)&__argv[i], &data) == 0)
181*387f9dfdSAndroid Build Coastguard Worker             goto out;
182*387f9dfdSAndroid Build Coastguard Worker    }
183*387f9dfdSAndroid Build Coastguard Worker
184*387f9dfdSAndroid Build Coastguard Worker    // handle truncated argument list
185*387f9dfdSAndroid Build Coastguard Worker    char ellipsis[] = "...";
186*387f9dfdSAndroid Build Coastguard Worker    __submit_arg(ctx, (void *)ellipsis, &data);
187*387f9dfdSAndroid Build Coastguard Workerout:
188*387f9dfdSAndroid Build Coastguard Worker    return 0;
189*387f9dfdSAndroid Build Coastguard Worker}
190*387f9dfdSAndroid Build Coastguard Worker
191*387f9dfdSAndroid Build Coastguard Workerint do_ret_sys_execve(struct pt_regs *ctx)
192*387f9dfdSAndroid Build Coastguard Worker{
193*387f9dfdSAndroid Build Coastguard Worker    if (container_should_be_filtered()) {
194*387f9dfdSAndroid Build Coastguard Worker        return 0;
195*387f9dfdSAndroid Build Coastguard Worker    }
196*387f9dfdSAndroid Build Coastguard Worker
197*387f9dfdSAndroid Build Coastguard Worker    struct data_t data = {};
198*387f9dfdSAndroid Build Coastguard Worker    struct task_struct *task;
199*387f9dfdSAndroid Build Coastguard Worker
200*387f9dfdSAndroid Build Coastguard Worker    u32 uid = bpf_get_current_uid_gid() & 0xffffffff;
201*387f9dfdSAndroid Build Coastguard Worker    UID_FILTER
202*387f9dfdSAndroid Build Coastguard Worker
203*387f9dfdSAndroid Build Coastguard Worker    data.pid = bpf_get_current_pid_tgid() >> 32;
204*387f9dfdSAndroid Build Coastguard Worker    data.uid = uid;
205*387f9dfdSAndroid Build Coastguard Worker
206*387f9dfdSAndroid Build Coastguard Worker    task = (struct task_struct *)bpf_get_current_task();
207*387f9dfdSAndroid Build Coastguard Worker    // Some kernels, like Ubuntu 4.13.0-generic, return 0
208*387f9dfdSAndroid Build Coastguard Worker    // as the real_parent->tgid.
209*387f9dfdSAndroid Build Coastguard Worker    // We use the get_ppid function as a fallback in those cases. (#1883)
210*387f9dfdSAndroid Build Coastguard Worker    data.ppid = task->real_parent->tgid;
211*387f9dfdSAndroid Build Coastguard Worker
212*387f9dfdSAndroid Build Coastguard Worker    PPID_FILTER
213*387f9dfdSAndroid Build Coastguard Worker
214*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&data.comm, sizeof(data.comm));
215*387f9dfdSAndroid Build Coastguard Worker    data.type = EVENT_RET;
216*387f9dfdSAndroid Build Coastguard Worker    data.retval = PT_REGS_RC(ctx);
217*387f9dfdSAndroid Build Coastguard Worker    events.perf_submit(ctx, &data, sizeof(data));
218*387f9dfdSAndroid Build Coastguard Worker
219*387f9dfdSAndroid Build Coastguard Worker    return 0;
220*387f9dfdSAndroid Build Coastguard Worker}
221*387f9dfdSAndroid Build Coastguard Worker"""
222*387f9dfdSAndroid Build Coastguard Worker
223*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace("MAXARG", args.max_args)
224*387f9dfdSAndroid Build Coastguard Worker
225*387f9dfdSAndroid Build Coastguard Workerif args.uid:
226*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('UID_FILTER',
227*387f9dfdSAndroid Build Coastguard Worker        'if (uid != %s) { return 0; }' % args.uid)
228*387f9dfdSAndroid Build Coastguard Workerelse:
229*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('UID_FILTER', '')
230*387f9dfdSAndroid Build Coastguard Worker
231*387f9dfdSAndroid Build Coastguard Workerif args.ppid:
232*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('PPID_FILTER',
233*387f9dfdSAndroid Build Coastguard Worker        'if (data.ppid != %s) { return 0; }' % args.ppid)
234*387f9dfdSAndroid Build Coastguard Workerelse:
235*387f9dfdSAndroid Build Coastguard Worker    bpf_text = bpf_text.replace('PPID_FILTER', '')
236*387f9dfdSAndroid Build Coastguard Worker
237*387f9dfdSAndroid Build Coastguard Workerbpf_text = filter_by_containers(args) + bpf_text
238*387f9dfdSAndroid Build Coastguard Workerif args.ebpf:
239*387f9dfdSAndroid Build Coastguard Worker    print(bpf_text)
240*387f9dfdSAndroid Build Coastguard Worker    exit()
241*387f9dfdSAndroid Build Coastguard Worker
242*387f9dfdSAndroid Build Coastguard Worker# initialize BPF
243*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
244*387f9dfdSAndroid Build Coastguard Workerexecve_fnname = b.get_syscall_fnname("execve")
245*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event=execve_fnname, fn_name="syscall__execve")
246*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event=execve_fnname, fn_name="do_ret_sys_execve")
247*387f9dfdSAndroid Build Coastguard Worker
248*387f9dfdSAndroid Build Coastguard Worker# header
249*387f9dfdSAndroid Build Coastguard Workerif args.time:
250*387f9dfdSAndroid Build Coastguard Worker    print("%-9s" % ("TIME"), end="")
251*387f9dfdSAndroid Build Coastguard Workerif args.timestamp:
252*387f9dfdSAndroid Build Coastguard Worker    print("%-8s" % ("TIME(s)"), end="")
253*387f9dfdSAndroid Build Coastguard Workerif args.print_uid:
254*387f9dfdSAndroid Build Coastguard Worker    print("%-6s" % ("UID"), end="")
255*387f9dfdSAndroid Build Coastguard Workerprint("%-16s %-7s %-7s %3s %s" % ("PCOMM", "PID", "PPID", "RET", "ARGS"))
256*387f9dfdSAndroid Build Coastguard Worker
257*387f9dfdSAndroid Build Coastguard Workerclass EventType(object):
258*387f9dfdSAndroid Build Coastguard Worker    EVENT_ARG = 0
259*387f9dfdSAndroid Build Coastguard Worker    EVENT_RET = 1
260*387f9dfdSAndroid Build Coastguard Worker
261*387f9dfdSAndroid Build Coastguard Workerstart_ts = time.time()
262*387f9dfdSAndroid Build Coastguard Workerargv = defaultdict(list)
263*387f9dfdSAndroid Build Coastguard Worker
264*387f9dfdSAndroid Build Coastguard Worker# This is best-effort PPID matching. Short-lived processes may exit
265*387f9dfdSAndroid Build Coastguard Worker# before we get a chance to read the PPID.
266*387f9dfdSAndroid Build Coastguard Worker# This is a fallback for when fetching the PPID from task->real_parent->tgip
267*387f9dfdSAndroid Build Coastguard Worker# returns 0, which happens in some kernel versions.
268*387f9dfdSAndroid Build Coastguard Workerdef get_ppid(pid):
269*387f9dfdSAndroid Build Coastguard Worker    try:
270*387f9dfdSAndroid Build Coastguard Worker        with open("/proc/%d/status" % pid) as status:
271*387f9dfdSAndroid Build Coastguard Worker            for line in status:
272*387f9dfdSAndroid Build Coastguard Worker                if line.startswith("PPid:"):
273*387f9dfdSAndroid Build Coastguard Worker                    return int(line.split()[1])
274*387f9dfdSAndroid Build Coastguard Worker    except IOError:
275*387f9dfdSAndroid Build Coastguard Worker        pass
276*387f9dfdSAndroid Build Coastguard Worker    return 0
277*387f9dfdSAndroid Build Coastguard Worker
278*387f9dfdSAndroid Build Coastguard Worker# process event
279*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
280*387f9dfdSAndroid Build Coastguard Worker    event = b["events"].event(data)
281*387f9dfdSAndroid Build Coastguard Worker    skip = False
282*387f9dfdSAndroid Build Coastguard Worker
283*387f9dfdSAndroid Build Coastguard Worker    if event.type == EventType.EVENT_ARG:
284*387f9dfdSAndroid Build Coastguard Worker        argv[event.pid].append(event.argv)
285*387f9dfdSAndroid Build Coastguard Worker    elif event.type == EventType.EVENT_RET:
286*387f9dfdSAndroid Build Coastguard Worker        if event.retval != 0 and not args.fails:
287*387f9dfdSAndroid Build Coastguard Worker            skip = True
288*387f9dfdSAndroid Build Coastguard Worker        if args.name and not re.search(bytes(args.name), event.comm):
289*387f9dfdSAndroid Build Coastguard Worker            skip = True
290*387f9dfdSAndroid Build Coastguard Worker        if args.line and not re.search(bytes(args.line),
291*387f9dfdSAndroid Build Coastguard Worker                                       b' '.join(argv[event.pid])):
292*387f9dfdSAndroid Build Coastguard Worker            skip = True
293*387f9dfdSAndroid Build Coastguard Worker        if args.quote:
294*387f9dfdSAndroid Build Coastguard Worker            argv[event.pid] = [
295*387f9dfdSAndroid Build Coastguard Worker                b"\"" + arg.replace(b"\"", b"\\\"") + b"\""
296*387f9dfdSAndroid Build Coastguard Worker                for arg in argv[event.pid]
297*387f9dfdSAndroid Build Coastguard Worker            ]
298*387f9dfdSAndroid Build Coastguard Worker
299*387f9dfdSAndroid Build Coastguard Worker        if not skip:
300*387f9dfdSAndroid Build Coastguard Worker            if args.time:
301*387f9dfdSAndroid Build Coastguard Worker                printb(b"%-9s" % strftime("%H:%M:%S").encode('ascii'), nl="")
302*387f9dfdSAndroid Build Coastguard Worker            if args.timestamp:
303*387f9dfdSAndroid Build Coastguard Worker                printb(b"%-8.3f" % (time.time() - start_ts), nl="")
304*387f9dfdSAndroid Build Coastguard Worker            if args.print_uid:
305*387f9dfdSAndroid Build Coastguard Worker                printb(b"%-6d" % event.uid, nl="")
306*387f9dfdSAndroid Build Coastguard Worker            ppid = event.ppid if event.ppid > 0 else get_ppid(event.pid)
307*387f9dfdSAndroid Build Coastguard Worker            ppid = b"%d" % ppid if ppid > 0 else b"?"
308*387f9dfdSAndroid Build Coastguard Worker            argv_text = b' '.join(argv[event.pid]).replace(b'\n', b'\\n')
309*387f9dfdSAndroid Build Coastguard Worker            printb(b"%-16s %-7d %-7s %3d %s" % (event.comm, event.pid,
310*387f9dfdSAndroid Build Coastguard Worker                   ppid, event.retval, argv_text))
311*387f9dfdSAndroid Build Coastguard Worker        try:
312*387f9dfdSAndroid Build Coastguard Worker            del(argv[event.pid])
313*387f9dfdSAndroid Build Coastguard Worker        except Exception:
314*387f9dfdSAndroid Build Coastguard Worker            pass
315*387f9dfdSAndroid Build Coastguard Worker
316*387f9dfdSAndroid Build Coastguard Worker
317*387f9dfdSAndroid Build Coastguard Worker# loop with callback to print_event
318*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event)
319*387f9dfdSAndroid Build Coastguard Workerwhile 1:
320*387f9dfdSAndroid Build Coastguard Worker    try:
321*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll()
322*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
323*387f9dfdSAndroid Build Coastguard Worker        exit()
324