xref: /aosp_15_r20/external/bcc/tools/bashreadline.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python
2*387f9dfdSAndroid Build Coastguard Worker#
3*387f9dfdSAndroid Build Coastguard Worker# bashreadline  Print entered bash commands from all running shells.
4*387f9dfdSAndroid Build Coastguard Worker#               For Linux, uses BCC, eBPF. Embedded C.
5*387f9dfdSAndroid Build Coastguard Worker#
6*387f9dfdSAndroid Build Coastguard Worker# USAGE: bashreadline [-s SHARED]
7*387f9dfdSAndroid Build Coastguard Worker# This works by tracing the readline() function using a uretprobe (uprobes).
8*387f9dfdSAndroid Build Coastguard Worker# When you failed to run the script directly with error:
9*387f9dfdSAndroid Build Coastguard Worker# `Exception: could not determine address of symbol b'readline'`,
10*387f9dfdSAndroid Build Coastguard Worker# you may need specify the location of libreadline.so library
11*387f9dfdSAndroid Build Coastguard Worker# with `-s` option.
12*387f9dfdSAndroid Build Coastguard Worker#
13*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc.
14*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
15*387f9dfdSAndroid Build Coastguard Worker#
16*387f9dfdSAndroid Build Coastguard Worker# 28-Jan-2016    Brendan Gregg   Created this.
17*387f9dfdSAndroid Build Coastguard Worker# 12-Feb-2016    Allan McAleavy migrated to BPF_PERF_OUTPUT
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
20*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
21*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime
22*387f9dfdSAndroid Build Coastguard Workerimport argparse
23*387f9dfdSAndroid Build Coastguard Worker
24*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
25*387f9dfdSAndroid Build Coastguard Worker        description="Print entered bash commands from all running shells",
26*387f9dfdSAndroid Build Coastguard Worker        formatter_class=argparse.RawDescriptionHelpFormatter)
27*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-s", "--shared", nargs="?",
28*387f9dfdSAndroid Build Coastguard Worker        const="/lib/libreadline.so", type=str,
29*387f9dfdSAndroid Build Coastguard Worker        help="specify the location of libreadline.so library.\
30*387f9dfdSAndroid Build Coastguard Worker              Default is /lib/libreadline.so")
31*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
32*387f9dfdSAndroid Build Coastguard Worker
33*387f9dfdSAndroid Build Coastguard Workername = args.shared if args.shared else "/bin/bash"
34*387f9dfdSAndroid Build Coastguard Worker
35*387f9dfdSAndroid Build Coastguard Worker# load BPF program
36*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
37*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
38*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
39*387f9dfdSAndroid Build Coastguard Worker
40*387f9dfdSAndroid Build Coastguard Workerstruct str_t {
41*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
42*387f9dfdSAndroid Build Coastguard Worker    char str[80];
43*387f9dfdSAndroid Build Coastguard Worker};
44*387f9dfdSAndroid Build Coastguard Worker
45*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events);
46*387f9dfdSAndroid Build Coastguard Worker
47*387f9dfdSAndroid Build Coastguard Workerint printret(struct pt_regs *ctx) {
48*387f9dfdSAndroid Build Coastguard Worker    struct str_t data  = {};
49*387f9dfdSAndroid Build Coastguard Worker    char comm[TASK_COMM_LEN] = {};
50*387f9dfdSAndroid Build Coastguard Worker    if (!PT_REGS_RC(ctx))
51*387f9dfdSAndroid Build Coastguard Worker        return 0;
52*387f9dfdSAndroid Build Coastguard Worker    data.pid = bpf_get_current_pid_tgid() >> 32;
53*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user(&data.str, sizeof(data.str), (void *)PT_REGS_RC(ctx));
54*387f9dfdSAndroid Build Coastguard Worker
55*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&comm, sizeof(comm));
56*387f9dfdSAndroid Build Coastguard Worker    if (comm[0] == 'b' && comm[1] == 'a' && comm[2] == 's' && comm[3] == 'h' && comm[4] == 0 ) {
57*387f9dfdSAndroid Build Coastguard Worker        events.perf_submit(ctx,&data,sizeof(data));
58*387f9dfdSAndroid Build Coastguard Worker    }
59*387f9dfdSAndroid Build Coastguard Worker
60*387f9dfdSAndroid Build Coastguard Worker
61*387f9dfdSAndroid Build Coastguard Worker    return 0;
62*387f9dfdSAndroid Build Coastguard Worker};
63*387f9dfdSAndroid Build Coastguard Worker"""
64*387f9dfdSAndroid Build Coastguard Worker
65*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
66*387f9dfdSAndroid Build Coastguard Workerb.attach_uretprobe(name=name, sym="readline", fn_name="printret")
67*387f9dfdSAndroid Build Coastguard Worker
68*387f9dfdSAndroid Build Coastguard Worker# header
69*387f9dfdSAndroid Build Coastguard Workerprint("%-9s %-7s %s" % ("TIME", "PID", "COMMAND"))
70*387f9dfdSAndroid Build Coastguard Worker
71*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size):
72*387f9dfdSAndroid Build Coastguard Worker    event = b["events"].event(data)
73*387f9dfdSAndroid Build Coastguard Worker    print("%-9s %-7d %s" % (strftime("%H:%M:%S"), event.pid,
74*387f9dfdSAndroid Build Coastguard Worker                            event.str.decode('utf-8', 'replace')))
75*387f9dfdSAndroid Build Coastguard Worker
76*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event)
77*387f9dfdSAndroid Build Coastguard Workerwhile 1:
78*387f9dfdSAndroid Build Coastguard Worker    try:
79*387f9dfdSAndroid Build Coastguard Worker        b.perf_buffer_poll()
80*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
81*387f9dfdSAndroid Build Coastguard Worker        exit()
82