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