xref: /aosp_15_r20/external/bcc/examples/cpp/KFuncExample.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) Facebook, Inc.
3*387f9dfdSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License")
4*387f9dfdSAndroid Build Coastguard Worker  *
5*387f9dfdSAndroid Build Coastguard Worker  * Usage:
6*387f9dfdSAndroid Build Coastguard Worker  *   ./KFunc
7*387f9dfdSAndroid Build Coastguard Worker  * A sample output:
8*387f9dfdSAndroid Build Coastguard Worker  *   Started tracing, hit Ctrl-C to terminate.
9*387f9dfdSAndroid Build Coastguard Worker  *      FD  FNAME
10*387f9dfdSAndroid Build Coastguard Worker  *    NONE  /proc/stat
11*387f9dfdSAndroid Build Coastguard Worker  *      87  /proc/stat
12*387f9dfdSAndroid Build Coastguard Worker  *    NONE  /proc/8208/status
13*387f9dfdSAndroid Build Coastguard Worker  *      36  /proc/8208/status
14*387f9dfdSAndroid Build Coastguard Worker  *    NONE  /proc/8208/status
15*387f9dfdSAndroid Build Coastguard Worker  *      36  /proc/8208/status
16*387f9dfdSAndroid Build Coastguard Worker  *    ...
17*387f9dfdSAndroid Build Coastguard Worker  *
18*387f9dfdSAndroid Build Coastguard Worker  * KFunc support is only available at kernel version 5.5 and later.
19*387f9dfdSAndroid Build Coastguard Worker  * This example only works for x64.
20*387f9dfdSAndroid Build Coastguard Worker  */
21*387f9dfdSAndroid Build Coastguard Worker 
22*387f9dfdSAndroid Build Coastguard Worker #include <fstream>
23*387f9dfdSAndroid Build Coastguard Worker #include <iostream>
24*387f9dfdSAndroid Build Coastguard Worker #include <iomanip>
25*387f9dfdSAndroid Build Coastguard Worker #include <string>
26*387f9dfdSAndroid Build Coastguard Worker 
27*387f9dfdSAndroid Build Coastguard Worker #include "bcc_version.h"
28*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h"
29*387f9dfdSAndroid Build Coastguard Worker 
30*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
31*387f9dfdSAndroid Build Coastguard Worker #include <linux/ptrace.h>
32*387f9dfdSAndroid Build Coastguard Worker 
33*387f9dfdSAndroid Build Coastguard Worker struct info_t {
34*387f9dfdSAndroid Build Coastguard Worker   char name[64];
35*387f9dfdSAndroid Build Coastguard Worker   int fd;
36*387f9dfdSAndroid Build Coastguard Worker   int is_ret;
37*387f9dfdSAndroid Build Coastguard Worker };
38*387f9dfdSAndroid Build Coastguard Worker BPF_PERF_OUTPUT(events);
39*387f9dfdSAndroid Build Coastguard Worker 
40*387f9dfdSAndroid Build Coastguard Worker KFUNC_PROBE(__x64_sys_openat, struct pt_regs *regs)
41*387f9dfdSAndroid Build Coastguard Worker {
42*387f9dfdSAndroid Build Coastguard Worker   const char __user *filename = (char *)PT_REGS_PARM2(regs);
43*387f9dfdSAndroid Build Coastguard Worker   struct info_t info = {};
44*387f9dfdSAndroid Build Coastguard Worker 
45*387f9dfdSAndroid Build Coastguard Worker   bpf_probe_read_user_str(info.name, sizeof(info.name), filename);
46*387f9dfdSAndroid Build Coastguard Worker   info.is_ret = 0;
47*387f9dfdSAndroid Build Coastguard Worker   events.perf_submit(ctx, &info, sizeof(info));
48*387f9dfdSAndroid Build Coastguard Worker   return 0;
49*387f9dfdSAndroid Build Coastguard Worker }
50*387f9dfdSAndroid Build Coastguard Worker 
51*387f9dfdSAndroid Build Coastguard Worker KRETFUNC_PROBE(__x64_sys_openat, struct pt_regs *regs, int ret)
52*387f9dfdSAndroid Build Coastguard Worker {
53*387f9dfdSAndroid Build Coastguard Worker   const char __user *filename = (char *)PT_REGS_PARM2(regs);
54*387f9dfdSAndroid Build Coastguard Worker   struct info_t info = {};
55*387f9dfdSAndroid Build Coastguard Worker 
56*387f9dfdSAndroid Build Coastguard Worker   bpf_probe_read_user_str(info.name, sizeof(info.name), filename);
57*387f9dfdSAndroid Build Coastguard Worker   info.fd = ret;
58*387f9dfdSAndroid Build Coastguard Worker   info.is_ret = 1;
59*387f9dfdSAndroid Build Coastguard Worker   events.perf_submit(ctx, &info, sizeof(info));
60*387f9dfdSAndroid Build Coastguard Worker   return 0;
61*387f9dfdSAndroid Build Coastguard Worker }
62*387f9dfdSAndroid Build Coastguard Worker )";
63*387f9dfdSAndroid Build Coastguard Worker 
64*387f9dfdSAndroid Build Coastguard Worker struct info_t {
65*387f9dfdSAndroid Build Coastguard Worker   char name[64];
66*387f9dfdSAndroid Build Coastguard Worker   int fd;
67*387f9dfdSAndroid Build Coastguard Worker   int is_ret;
68*387f9dfdSAndroid Build Coastguard Worker };
69*387f9dfdSAndroid Build Coastguard Worker 
handle_output(void * cb_cookie,void * data,int data_size)70*387f9dfdSAndroid Build Coastguard Worker void handle_output(void *cb_cookie, void *data, int data_size) {
71*387f9dfdSAndroid Build Coastguard Worker   auto info = static_cast<info_t *>(data);
72*387f9dfdSAndroid Build Coastguard Worker   if (info->is_ret)
73*387f9dfdSAndroid Build Coastguard Worker     std::cout << std::setw(5) << info->fd << "  " << info->name << std::endl;
74*387f9dfdSAndroid Build Coastguard Worker   else
75*387f9dfdSAndroid Build Coastguard Worker     std::cout << " NONE  " << info->name << std::endl;
76*387f9dfdSAndroid Build Coastguard Worker }
77*387f9dfdSAndroid Build Coastguard Worker 
main()78*387f9dfdSAndroid Build Coastguard Worker int main() {
79*387f9dfdSAndroid Build Coastguard Worker   ebpf::BPF bpf;
80*387f9dfdSAndroid Build Coastguard Worker   auto res = bpf.init(BPF_PROGRAM);
81*387f9dfdSAndroid Build Coastguard Worker   if (!res.ok()) {
82*387f9dfdSAndroid Build Coastguard Worker     std::cerr << res.msg() << std::endl;
83*387f9dfdSAndroid Build Coastguard Worker     return 1;
84*387f9dfdSAndroid Build Coastguard Worker   }
85*387f9dfdSAndroid Build Coastguard Worker 
86*387f9dfdSAndroid Build Coastguard Worker   int prog_fd;
87*387f9dfdSAndroid Build Coastguard Worker   res = bpf.load_func("kfunc____x64_sys_openat", BPF_PROG_TYPE_TRACING, prog_fd);
88*387f9dfdSAndroid Build Coastguard Worker   if (!res.ok()) {
89*387f9dfdSAndroid Build Coastguard Worker     std::cerr << res.msg() << std::endl;
90*387f9dfdSAndroid Build Coastguard Worker     return 1;
91*387f9dfdSAndroid Build Coastguard Worker   }
92*387f9dfdSAndroid Build Coastguard Worker 
93*387f9dfdSAndroid Build Coastguard Worker   int ret = bpf_attach_kfunc(prog_fd);
94*387f9dfdSAndroid Build Coastguard Worker   if (ret < 0) {
95*387f9dfdSAndroid Build Coastguard Worker     std::cerr << "bpf_attach_kfunc failed: " << ret << std::endl;
96*387f9dfdSAndroid Build Coastguard Worker     return 1;
97*387f9dfdSAndroid Build Coastguard Worker   }
98*387f9dfdSAndroid Build Coastguard Worker 
99*387f9dfdSAndroid Build Coastguard Worker   res = bpf.load_func("kretfunc____x64_sys_openat", BPF_PROG_TYPE_TRACING, prog_fd);
100*387f9dfdSAndroid Build Coastguard Worker   if (!res.ok()) {
101*387f9dfdSAndroid Build Coastguard Worker     std::cerr << res.msg() << std::endl;
102*387f9dfdSAndroid Build Coastguard Worker     return 1;
103*387f9dfdSAndroid Build Coastguard Worker   }
104*387f9dfdSAndroid Build Coastguard Worker 
105*387f9dfdSAndroid Build Coastguard Worker   ret = bpf_attach_kfunc(prog_fd);
106*387f9dfdSAndroid Build Coastguard Worker   if (ret < 0) {
107*387f9dfdSAndroid Build Coastguard Worker     std::cerr << "bpf_attach_kfunc failed: " << ret << std::endl;
108*387f9dfdSAndroid Build Coastguard Worker     return 1;
109*387f9dfdSAndroid Build Coastguard Worker   }
110*387f9dfdSAndroid Build Coastguard Worker 
111*387f9dfdSAndroid Build Coastguard Worker   auto open_res = bpf.open_perf_buffer("events", &handle_output);
112*387f9dfdSAndroid Build Coastguard Worker   if (!open_res.ok()) {
113*387f9dfdSAndroid Build Coastguard Worker     std::cerr << open_res.msg() << std::endl;
114*387f9dfdSAndroid Build Coastguard Worker     return 1;
115*387f9dfdSAndroid Build Coastguard Worker   }
116*387f9dfdSAndroid Build Coastguard Worker 
117*387f9dfdSAndroid Build Coastguard Worker   std::cout << "Started tracing, hit Ctrl-C to terminate." << std::endl;
118*387f9dfdSAndroid Build Coastguard Worker   std::cout << "   FD  FNAME" << std::endl;
119*387f9dfdSAndroid Build Coastguard Worker   auto perf_buffer = bpf.get_perf_buffer("events");
120*387f9dfdSAndroid Build Coastguard Worker   if (perf_buffer) {
121*387f9dfdSAndroid Build Coastguard Worker     while (true)
122*387f9dfdSAndroid Build Coastguard Worker       // 100ms timeout
123*387f9dfdSAndroid Build Coastguard Worker       perf_buffer->poll(100);
124*387f9dfdSAndroid Build Coastguard Worker   }
125*387f9dfdSAndroid Build Coastguard Worker 
126*387f9dfdSAndroid Build Coastguard Worker   return 0;
127*387f9dfdSAndroid Build Coastguard Worker }
128