xref: /aosp_15_r20/external/bcc/examples/cpp/RandomRead.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
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