1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker * RandomRead Monitor random number read events.
3*387f9dfdSAndroid Build Coastguard Worker * For Linux, uses BCC, eBPF. Embedded C.
4*387f9dfdSAndroid Build Coastguard Worker *
5*387f9dfdSAndroid Build Coastguard Worker * Basic example of BCC Tracepoint and perf buffer.
6*387f9dfdSAndroid Build Coastguard Worker *
7*387f9dfdSAndroid Build Coastguard Worker * USAGE: RandomRead
8*387f9dfdSAndroid Build Coastguard Worker *
9*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) Facebook, Inc.
10*387f9dfdSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License")
11*387f9dfdSAndroid Build Coastguard Worker */
12*387f9dfdSAndroid Build Coastguard Worker
13*387f9dfdSAndroid Build Coastguard Worker #include <signal.h>
14*387f9dfdSAndroid Build Coastguard Worker #include <sys/resource.h>
15*387f9dfdSAndroid Build Coastguard Worker #include <iostream>
16*387f9dfdSAndroid Build Coastguard Worker
17*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h"
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
20*387f9dfdSAndroid Build Coastguard Worker #include <linux/sched.h>
21*387f9dfdSAndroid Build Coastguard Worker #include <uapi/linux/ptrace.h>
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard Worker #ifndef CGROUP_FILTER
24*387f9dfdSAndroid Build Coastguard Worker #define CGROUP_FILTER 0
25*387f9dfdSAndroid Build Coastguard Worker #endif
26*387f9dfdSAndroid Build Coastguard Worker
27*387f9dfdSAndroid Build Coastguard Worker struct event_t {
28*387f9dfdSAndroid Build Coastguard Worker int pid;
29*387f9dfdSAndroid Build Coastguard Worker char comm[16];
30*387f9dfdSAndroid Build Coastguard Worker int cpu;
31*387f9dfdSAndroid Build Coastguard Worker int got_bits;
32*387f9dfdSAndroid Build Coastguard Worker };
33*387f9dfdSAndroid Build Coastguard Worker
34*387f9dfdSAndroid Build Coastguard Worker BPF_PERF_OUTPUT(events);
35*387f9dfdSAndroid Build Coastguard Worker BPF_CGROUP_ARRAY(cgroup, 1);
36*387f9dfdSAndroid Build Coastguard Worker
37*387f9dfdSAndroid Build Coastguard Worker int on_urandom_read(struct bpf_raw_tracepoint_args *ctx) {
38*387f9dfdSAndroid Build Coastguard Worker if (CGROUP_FILTER && (cgroup.check_current_task(0) != 1))
39*387f9dfdSAndroid Build Coastguard Worker return 0;
40*387f9dfdSAndroid Build Coastguard Worker
41*387f9dfdSAndroid Build Coastguard Worker struct event_t event = {};
42*387f9dfdSAndroid Build Coastguard Worker event.pid = bpf_get_current_pid_tgid();
43*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&event.comm, sizeof(event.comm));
44*387f9dfdSAndroid Build Coastguard Worker event.cpu = bpf_get_smp_processor_id();
45*387f9dfdSAndroid Build Coastguard Worker // from include/trace/events/random.h:
46*387f9dfdSAndroid Build Coastguard Worker // TP_PROTO(int got_bits, int pool_left, int input_left)
47*387f9dfdSAndroid Build Coastguard Worker event.got_bits = ctx->args[0];
48*387f9dfdSAndroid Build Coastguard Worker
49*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event));
50*387f9dfdSAndroid Build Coastguard Worker return 0;
51*387f9dfdSAndroid Build Coastguard Worker }
52*387f9dfdSAndroid Build Coastguard Worker )";
53*387f9dfdSAndroid Build Coastguard Worker
54*387f9dfdSAndroid Build Coastguard Worker // Define the same struct to use in user space.
55*387f9dfdSAndroid Build Coastguard Worker struct event_t {
56*387f9dfdSAndroid Build Coastguard Worker int pid;
57*387f9dfdSAndroid Build Coastguard Worker char comm[16];
58*387f9dfdSAndroid Build Coastguard Worker int cpu;
59*387f9dfdSAndroid Build Coastguard Worker int got_bits;
60*387f9dfdSAndroid Build Coastguard Worker };
61*387f9dfdSAndroid Build Coastguard Worker
handle_output(void * cb_cookie,void * data,int data_size)62*387f9dfdSAndroid Build Coastguard Worker void handle_output(void* cb_cookie, void* data, int data_size) {
63*387f9dfdSAndroid Build Coastguard Worker auto event = static_cast<event_t*>(data);
64*387f9dfdSAndroid Build Coastguard Worker std::cout << "PID: " << event->pid << " (" << event->comm << ") on CPU "
65*387f9dfdSAndroid Build Coastguard Worker << event->cpu << " read " << event->got_bits << " bits"
66*387f9dfdSAndroid Build Coastguard Worker << std::endl;
67*387f9dfdSAndroid Build Coastguard Worker }
68*387f9dfdSAndroid Build Coastguard Worker
69*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF* bpf;
70*387f9dfdSAndroid Build Coastguard Worker
signal_handler(int s)71*387f9dfdSAndroid Build Coastguard Worker void signal_handler(int s) {
72*387f9dfdSAndroid Build Coastguard Worker std::cerr << "Terminating..." << std::endl;
73*387f9dfdSAndroid Build Coastguard Worker delete bpf;
74*387f9dfdSAndroid Build Coastguard Worker exit(0);
75*387f9dfdSAndroid Build Coastguard Worker }
76*387f9dfdSAndroid Build Coastguard Worker
usage(void)77*387f9dfdSAndroid Build Coastguard Worker void usage(void) {
78*387f9dfdSAndroid Build Coastguard Worker std::cerr << "USAGE: RandomRead [{-r|-u} [cgroup2_path]]" << std::endl;
79*387f9dfdSAndroid Build Coastguard Worker }
80*387f9dfdSAndroid Build Coastguard Worker
main(int argc,char ** argv)81*387f9dfdSAndroid Build Coastguard Worker int main(int argc, char** argv) {
82*387f9dfdSAndroid Build Coastguard Worker if (argc > 3) {
83*387f9dfdSAndroid Build Coastguard Worker usage();
84*387f9dfdSAndroid Build Coastguard Worker return 1;
85*387f9dfdSAndroid Build Coastguard Worker }
86*387f9dfdSAndroid Build Coastguard Worker
87*387f9dfdSAndroid Build Coastguard Worker bool allow_rlimit = true;
88*387f9dfdSAndroid Build Coastguard Worker if (argc >= 2) {
89*387f9dfdSAndroid Build Coastguard Worker // Set a small rlimit for MEMLOCK
90*387f9dfdSAndroid Build Coastguard Worker struct rlimit rlim_new = {4096, 4096};
91*387f9dfdSAndroid Build Coastguard Worker setrlimit(RLIMIT_MEMLOCK, &rlim_new);
92*387f9dfdSAndroid Build Coastguard Worker
93*387f9dfdSAndroid Build Coastguard Worker if (strcmp(argv[1], "-r") == 0) {
94*387f9dfdSAndroid Build Coastguard Worker allow_rlimit = false;
95*387f9dfdSAndroid Build Coastguard Worker } else if (strcmp(argv[1], "-u") == 0) {
96*387f9dfdSAndroid Build Coastguard Worker allow_rlimit = true;
97*387f9dfdSAndroid Build Coastguard Worker } else {
98*387f9dfdSAndroid Build Coastguard Worker usage();
99*387f9dfdSAndroid Build Coastguard Worker return 1;
100*387f9dfdSAndroid Build Coastguard Worker }
101*387f9dfdSAndroid Build Coastguard Worker }
102*387f9dfdSAndroid Build Coastguard Worker
103*387f9dfdSAndroid Build Coastguard Worker std::vector<std::string> cflags = {};
104*387f9dfdSAndroid Build Coastguard Worker if (argc == 3)
105*387f9dfdSAndroid Build Coastguard Worker cflags.emplace_back("-DCGROUP_FILTER=1");
106*387f9dfdSAndroid Build Coastguard Worker
107*387f9dfdSAndroid Build Coastguard Worker bpf = new ebpf::BPF(0, nullptr, true, "", allow_rlimit);
108*387f9dfdSAndroid Build Coastguard Worker auto init_res = bpf->init(BPF_PROGRAM, cflags, {});
109*387f9dfdSAndroid Build Coastguard Worker if (!init_res.ok()) {
110*387f9dfdSAndroid Build Coastguard Worker std::cerr << init_res.msg() << std::endl;
111*387f9dfdSAndroid Build Coastguard Worker return 1;
112*387f9dfdSAndroid Build Coastguard Worker }
113*387f9dfdSAndroid Build Coastguard Worker if (argc == 3) {
114*387f9dfdSAndroid Build Coastguard Worker auto cgroup_array = bpf->get_cgroup_array("cgroup");
115*387f9dfdSAndroid Build Coastguard Worker auto update_res = cgroup_array.update_value(0, argv[2]);
116*387f9dfdSAndroid Build Coastguard Worker if (!update_res.ok()) {
117*387f9dfdSAndroid Build Coastguard Worker std::cerr << update_res.msg() << std::endl;
118*387f9dfdSAndroid Build Coastguard Worker return 1;
119*387f9dfdSAndroid Build Coastguard Worker }
120*387f9dfdSAndroid Build Coastguard Worker }
121*387f9dfdSAndroid Build Coastguard Worker
122*387f9dfdSAndroid Build Coastguard Worker auto attach_res =
123*387f9dfdSAndroid Build Coastguard Worker bpf->attach_raw_tracepoint("urandom_read", "on_urandom_read");
124*387f9dfdSAndroid Build Coastguard Worker if (!attach_res.ok()) {
125*387f9dfdSAndroid Build Coastguard Worker std::cerr << attach_res.msg() << std::endl;
126*387f9dfdSAndroid Build Coastguard Worker return 1;
127*387f9dfdSAndroid Build Coastguard Worker }
128*387f9dfdSAndroid Build Coastguard Worker
129*387f9dfdSAndroid Build Coastguard Worker auto open_res = bpf->open_perf_buffer("events", &handle_output);
130*387f9dfdSAndroid Build Coastguard Worker if (!open_res.ok()) {
131*387f9dfdSAndroid Build Coastguard Worker std::cerr << open_res.msg() << std::endl;
132*387f9dfdSAndroid Build Coastguard Worker return 1;
133*387f9dfdSAndroid Build Coastguard Worker }
134*387f9dfdSAndroid Build Coastguard Worker
135*387f9dfdSAndroid Build Coastguard Worker // done with all initial work, free bcc memory
136*387f9dfdSAndroid Build Coastguard Worker if (bpf->free_bcc_memory()) {
137*387f9dfdSAndroid Build Coastguard Worker std::cerr << "Failed to free llvm/clang memory" << std::endl;
138*387f9dfdSAndroid Build Coastguard Worker return 1;
139*387f9dfdSAndroid Build Coastguard Worker }
140*387f9dfdSAndroid Build Coastguard Worker
141*387f9dfdSAndroid Build Coastguard Worker signal(SIGINT, signal_handler);
142*387f9dfdSAndroid Build Coastguard Worker std::cout << "Started tracing, hit Ctrl-C to terminate." << std::endl;
143*387f9dfdSAndroid Build Coastguard Worker while (true)
144*387f9dfdSAndroid Build Coastguard Worker bpf->poll_perf_buffer("events");
145*387f9dfdSAndroid Build Coastguard Worker
146*387f9dfdSAndroid Build Coastguard Worker return 0;
147*387f9dfdSAndroid Build Coastguard Worker }
148