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