1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) 2016 Facebook, Inc.
3*387f9dfdSAndroid Build Coastguard Worker *
4*387f9dfdSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*387f9dfdSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*387f9dfdSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*387f9dfdSAndroid Build Coastguard Worker *
8*387f9dfdSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*387f9dfdSAndroid Build Coastguard Worker *
10*387f9dfdSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*387f9dfdSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*387f9dfdSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*387f9dfdSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*387f9dfdSAndroid Build Coastguard Worker * limitations under the License.
15*387f9dfdSAndroid Build Coastguard Worker */
16*387f9dfdSAndroid Build Coastguard Worker
17*387f9dfdSAndroid Build Coastguard Worker #include <linux/bpf.h>
18*387f9dfdSAndroid Build Coastguard Worker #include <linux/perf_event.h>
19*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
20*387f9dfdSAndroid Build Coastguard Worker #include <cstdio>
21*387f9dfdSAndroid Build Coastguard Worker #include <cstring>
22*387f9dfdSAndroid Build Coastguard Worker #include <exception>
23*387f9dfdSAndroid Build Coastguard Worker #include <fcntl.h>
24*387f9dfdSAndroid Build Coastguard Worker #include <iostream>
25*387f9dfdSAndroid Build Coastguard Worker #include <memory>
26*387f9dfdSAndroid Build Coastguard Worker #include <sstream>
27*387f9dfdSAndroid Build Coastguard Worker #include <sys/stat.h>
28*387f9dfdSAndroid Build Coastguard Worker #include <sys/types.h>
29*387f9dfdSAndroid Build Coastguard Worker #include <utility>
30*387f9dfdSAndroid Build Coastguard Worker #include <vector>
31*387f9dfdSAndroid Build Coastguard Worker
32*387f9dfdSAndroid Build Coastguard Worker #include "bcc_exception.h"
33*387f9dfdSAndroid Build Coastguard Worker #include "bcc_elf.h"
34*387f9dfdSAndroid Build Coastguard Worker #include "bcc_syms.h"
35*387f9dfdSAndroid Build Coastguard Worker #include "bpf_module.h"
36*387f9dfdSAndroid Build Coastguard Worker #include "common.h"
37*387f9dfdSAndroid Build Coastguard Worker #include "libbpf.h"
38*387f9dfdSAndroid Build Coastguard Worker #include "perf_reader.h"
39*387f9dfdSAndroid Build Coastguard Worker #include "syms.h"
40*387f9dfdSAndroid Build Coastguard Worker #include "table_storage.h"
41*387f9dfdSAndroid Build Coastguard Worker #include "usdt.h"
42*387f9dfdSAndroid Build Coastguard Worker
43*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h"
44*387f9dfdSAndroid Build Coastguard Worker
45*387f9dfdSAndroid Build Coastguard Worker namespace {
46*387f9dfdSAndroid Build Coastguard Worker /*
47*387f9dfdSAndroid Build Coastguard Worker * Kernels ~4.20 and later support specifying the ref_ctr_offset as an argument
48*387f9dfdSAndroid Build Coastguard Worker * to attaching a uprobe, which negates the need to seek to this memory offset
49*387f9dfdSAndroid Build Coastguard Worker * in userspace to manage semaphores, as the kernel will do it for us. This
50*387f9dfdSAndroid Build Coastguard Worker * helper function checks if this support is available by reading the uprobe
51*387f9dfdSAndroid Build Coastguard Worker * format for this value, added in a6ca88b241d5e929e6e60b12ad8cd288f0ffa
52*387f9dfdSAndroid Build Coastguard Worker */
uprobe_ref_ctr_supported()53*387f9dfdSAndroid Build Coastguard Worker bool uprobe_ref_ctr_supported() {
54*387f9dfdSAndroid Build Coastguard Worker const char *ref_ctr_pmu_path =
55*387f9dfdSAndroid Build Coastguard Worker "/sys/bus/event_source/devices/uprobe/format/ref_ctr_offset";
56*387f9dfdSAndroid Build Coastguard Worker const char *ref_ctr_pmu_expected = "config:32-63\0";
57*387f9dfdSAndroid Build Coastguard Worker char ref_ctr_pmu_fmt[64]; // in Linux source this buffer is compared vs
58*387f9dfdSAndroid Build Coastguard Worker // PAGE_SIZE, but 64 is probably ample
59*387f9dfdSAndroid Build Coastguard Worker int fd = open(ref_ctr_pmu_path, O_RDONLY);
60*387f9dfdSAndroid Build Coastguard Worker if (fd < 0)
61*387f9dfdSAndroid Build Coastguard Worker return false;
62*387f9dfdSAndroid Build Coastguard Worker
63*387f9dfdSAndroid Build Coastguard Worker int ret = read(fd, ref_ctr_pmu_fmt, sizeof(ref_ctr_pmu_fmt));
64*387f9dfdSAndroid Build Coastguard Worker close(fd);
65*387f9dfdSAndroid Build Coastguard Worker if (ret < 0) {
66*387f9dfdSAndroid Build Coastguard Worker return false;
67*387f9dfdSAndroid Build Coastguard Worker }
68*387f9dfdSAndroid Build Coastguard Worker if (strncmp(ref_ctr_pmu_expected, ref_ctr_pmu_fmt,
69*387f9dfdSAndroid Build Coastguard Worker strlen(ref_ctr_pmu_expected)) == 0) {
70*387f9dfdSAndroid Build Coastguard Worker return true;
71*387f9dfdSAndroid Build Coastguard Worker }
72*387f9dfdSAndroid Build Coastguard Worker return false;
73*387f9dfdSAndroid Build Coastguard Worker }
74*387f9dfdSAndroid Build Coastguard Worker } // namespace
75*387f9dfdSAndroid Build Coastguard Worker
76*387f9dfdSAndroid Build Coastguard Worker namespace ebpf {
77*387f9dfdSAndroid Build Coastguard Worker
uint_to_hex(uint64_t value)78*387f9dfdSAndroid Build Coastguard Worker std::string uint_to_hex(uint64_t value) {
79*387f9dfdSAndroid Build Coastguard Worker std::stringstream ss;
80*387f9dfdSAndroid Build Coastguard Worker ss << std::hex << value;
81*387f9dfdSAndroid Build Coastguard Worker return ss.str();
82*387f9dfdSAndroid Build Coastguard Worker }
83*387f9dfdSAndroid Build Coastguard Worker
sanitize_str(std::string str,bool (* validator)(char),char replacement='_')84*387f9dfdSAndroid Build Coastguard Worker std::string sanitize_str(std::string str, bool (*validator)(char),
85*387f9dfdSAndroid Build Coastguard Worker char replacement = '_') {
86*387f9dfdSAndroid Build Coastguard Worker for (size_t i = 0; i < str.length(); i++)
87*387f9dfdSAndroid Build Coastguard Worker if (!validator(str[i]))
88*387f9dfdSAndroid Build Coastguard Worker str[i] = replacement;
89*387f9dfdSAndroid Build Coastguard Worker return str;
90*387f9dfdSAndroid Build Coastguard Worker }
91*387f9dfdSAndroid Build Coastguard Worker
init_usdt(const USDT & usdt)92*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::init_usdt(const USDT& usdt) {
93*387f9dfdSAndroid Build Coastguard Worker USDT u(usdt);
94*387f9dfdSAndroid Build Coastguard Worker StatusTuple init_stp = u.init();
95*387f9dfdSAndroid Build Coastguard Worker if (!init_stp.ok()) {
96*387f9dfdSAndroid Build Coastguard Worker return init_stp;
97*387f9dfdSAndroid Build Coastguard Worker }
98*387f9dfdSAndroid Build Coastguard Worker
99*387f9dfdSAndroid Build Coastguard Worker usdt_.push_back(std::move(u));
100*387f9dfdSAndroid Build Coastguard Worker all_bpf_program_ += usdt_.back().program_text_;
101*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
102*387f9dfdSAndroid Build Coastguard Worker }
103*387f9dfdSAndroid Build Coastguard Worker
init_fail_reset()104*387f9dfdSAndroid Build Coastguard Worker void BPF::init_fail_reset() {
105*387f9dfdSAndroid Build Coastguard Worker usdt_.clear();
106*387f9dfdSAndroid Build Coastguard Worker all_bpf_program_ = "";
107*387f9dfdSAndroid Build Coastguard Worker }
108*387f9dfdSAndroid Build Coastguard Worker
init(const std::string & bpf_program,const std::vector<std::string> & cflags,const std::vector<USDT> & usdt)109*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::init(const std::string& bpf_program,
110*387f9dfdSAndroid Build Coastguard Worker const std::vector<std::string>& cflags,
111*387f9dfdSAndroid Build Coastguard Worker const std::vector<USDT>& usdt) {
112*387f9dfdSAndroid Build Coastguard Worker usdt_.reserve(usdt.size());
113*387f9dfdSAndroid Build Coastguard Worker for (const auto& u : usdt) {
114*387f9dfdSAndroid Build Coastguard Worker StatusTuple init_stp = init_usdt(u);
115*387f9dfdSAndroid Build Coastguard Worker if (!init_stp.ok()) {
116*387f9dfdSAndroid Build Coastguard Worker init_fail_reset();
117*387f9dfdSAndroid Build Coastguard Worker return init_stp;
118*387f9dfdSAndroid Build Coastguard Worker }
119*387f9dfdSAndroid Build Coastguard Worker }
120*387f9dfdSAndroid Build Coastguard Worker
121*387f9dfdSAndroid Build Coastguard Worker std::vector<const char*> flags;
122*387f9dfdSAndroid Build Coastguard Worker for (const auto& c: cflags)
123*387f9dfdSAndroid Build Coastguard Worker flags.push_back(c.c_str());
124*387f9dfdSAndroid Build Coastguard Worker
125*387f9dfdSAndroid Build Coastguard Worker all_bpf_program_ += bpf_program;
126*387f9dfdSAndroid Build Coastguard Worker if (bpf_module_->load_string(all_bpf_program_,
127*387f9dfdSAndroid Build Coastguard Worker flags.data(),
128*387f9dfdSAndroid Build Coastguard Worker flags.size()) != 0) {
129*387f9dfdSAndroid Build Coastguard Worker init_fail_reset();
130*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to initialize BPF program");
131*387f9dfdSAndroid Build Coastguard Worker }
132*387f9dfdSAndroid Build Coastguard Worker
133*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
134*387f9dfdSAndroid Build Coastguard Worker };
135*387f9dfdSAndroid Build Coastguard Worker
~BPF()136*387f9dfdSAndroid Build Coastguard Worker BPF::~BPF() {
137*387f9dfdSAndroid Build Coastguard Worker auto res = detach_all();
138*387f9dfdSAndroid Build Coastguard Worker if (!res.ok())
139*387f9dfdSAndroid Build Coastguard Worker std::cerr << "Failed to detach all probes on destruction: " << std::endl
140*387f9dfdSAndroid Build Coastguard Worker << res.msg() << std::endl;
141*387f9dfdSAndroid Build Coastguard Worker bcc_free_buildsymcache(bsymcache_);
142*387f9dfdSAndroid Build Coastguard Worker bsymcache_ = NULL;
143*387f9dfdSAndroid Build Coastguard Worker }
144*387f9dfdSAndroid Build Coastguard Worker
detach_all()145*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_all() {
146*387f9dfdSAndroid Build Coastguard Worker bool has_error = false;
147*387f9dfdSAndroid Build Coastguard Worker std::string error_msg;
148*387f9dfdSAndroid Build Coastguard Worker
149*387f9dfdSAndroid Build Coastguard Worker for (auto& it : kprobes_) {
150*387f9dfdSAndroid Build Coastguard Worker auto res = detach_kprobe_event(it.first, it.second);
151*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
152*387f9dfdSAndroid Build Coastguard Worker error_msg += "Failed to detach kprobe event " + it.first + ": ";
153*387f9dfdSAndroid Build Coastguard Worker error_msg += res.msg() + "\n";
154*387f9dfdSAndroid Build Coastguard Worker has_error = true;
155*387f9dfdSAndroid Build Coastguard Worker }
156*387f9dfdSAndroid Build Coastguard Worker }
157*387f9dfdSAndroid Build Coastguard Worker
158*387f9dfdSAndroid Build Coastguard Worker for (auto& it : uprobes_) {
159*387f9dfdSAndroid Build Coastguard Worker auto res = detach_uprobe_event(it.first, it.second);
160*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
161*387f9dfdSAndroid Build Coastguard Worker error_msg += "Failed to detach uprobe event " + it.first + ": ";
162*387f9dfdSAndroid Build Coastguard Worker error_msg += res.msg() + "\n";
163*387f9dfdSAndroid Build Coastguard Worker has_error = true;
164*387f9dfdSAndroid Build Coastguard Worker }
165*387f9dfdSAndroid Build Coastguard Worker }
166*387f9dfdSAndroid Build Coastguard Worker
167*387f9dfdSAndroid Build Coastguard Worker for (auto& it : tracepoints_) {
168*387f9dfdSAndroid Build Coastguard Worker auto res = detach_tracepoint_event(it.first, it.second);
169*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
170*387f9dfdSAndroid Build Coastguard Worker error_msg += "Failed to detach Tracepoint " + it.first + ": ";
171*387f9dfdSAndroid Build Coastguard Worker error_msg += res.msg() + "\n";
172*387f9dfdSAndroid Build Coastguard Worker has_error = true;
173*387f9dfdSAndroid Build Coastguard Worker }
174*387f9dfdSAndroid Build Coastguard Worker }
175*387f9dfdSAndroid Build Coastguard Worker
176*387f9dfdSAndroid Build Coastguard Worker for (auto& it : raw_tracepoints_) {
177*387f9dfdSAndroid Build Coastguard Worker auto res = detach_raw_tracepoint_event(it.first, it.second);
178*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
179*387f9dfdSAndroid Build Coastguard Worker error_msg += "Failed to detach Raw tracepoint " + it.first + ": ";
180*387f9dfdSAndroid Build Coastguard Worker error_msg += res.msg() + "\n";
181*387f9dfdSAndroid Build Coastguard Worker has_error = true;
182*387f9dfdSAndroid Build Coastguard Worker }
183*387f9dfdSAndroid Build Coastguard Worker }
184*387f9dfdSAndroid Build Coastguard Worker
185*387f9dfdSAndroid Build Coastguard Worker for (auto& it : perf_buffers_) {
186*387f9dfdSAndroid Build Coastguard Worker auto res = it.second->close_all_cpu();
187*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
188*387f9dfdSAndroid Build Coastguard Worker error_msg += "Failed to close perf buffer " + it.first + ": ";
189*387f9dfdSAndroid Build Coastguard Worker error_msg += res.msg() + "\n";
190*387f9dfdSAndroid Build Coastguard Worker has_error = true;
191*387f9dfdSAndroid Build Coastguard Worker }
192*387f9dfdSAndroid Build Coastguard Worker delete it.second;
193*387f9dfdSAndroid Build Coastguard Worker }
194*387f9dfdSAndroid Build Coastguard Worker
195*387f9dfdSAndroid Build Coastguard Worker for (auto& it : perf_event_arrays_) {
196*387f9dfdSAndroid Build Coastguard Worker auto res = it.second->close_all_cpu();
197*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
198*387f9dfdSAndroid Build Coastguard Worker error_msg += "Failed to close perf event array " + it.first + ": ";
199*387f9dfdSAndroid Build Coastguard Worker error_msg += res.msg() + "\n";
200*387f9dfdSAndroid Build Coastguard Worker has_error = true;
201*387f9dfdSAndroid Build Coastguard Worker }
202*387f9dfdSAndroid Build Coastguard Worker delete it.second;
203*387f9dfdSAndroid Build Coastguard Worker }
204*387f9dfdSAndroid Build Coastguard Worker
205*387f9dfdSAndroid Build Coastguard Worker for (auto& it : perf_events_) {
206*387f9dfdSAndroid Build Coastguard Worker auto res = detach_perf_event_all_cpu(it.second);
207*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
208*387f9dfdSAndroid Build Coastguard Worker error_msg += res.msg() + "\n";
209*387f9dfdSAndroid Build Coastguard Worker has_error = true;
210*387f9dfdSAndroid Build Coastguard Worker }
211*387f9dfdSAndroid Build Coastguard Worker }
212*387f9dfdSAndroid Build Coastguard Worker
213*387f9dfdSAndroid Build Coastguard Worker for (auto& it : funcs_) {
214*387f9dfdSAndroid Build Coastguard Worker int res = close(it.second);
215*387f9dfdSAndroid Build Coastguard Worker if (res != 0) {
216*387f9dfdSAndroid Build Coastguard Worker error_msg += "Failed to unload BPF program for " + it.first + ": ";
217*387f9dfdSAndroid Build Coastguard Worker error_msg += std::string(std::strerror(errno)) + "\n";
218*387f9dfdSAndroid Build Coastguard Worker has_error = true;
219*387f9dfdSAndroid Build Coastguard Worker }
220*387f9dfdSAndroid Build Coastguard Worker }
221*387f9dfdSAndroid Build Coastguard Worker
222*387f9dfdSAndroid Build Coastguard Worker if (has_error)
223*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, error_msg);
224*387f9dfdSAndroid Build Coastguard Worker else
225*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
226*387f9dfdSAndroid Build Coastguard Worker }
227*387f9dfdSAndroid Build Coastguard Worker
attach_kprobe(const std::string & kernel_func,const std::string & probe_func,uint64_t kernel_func_offset,bpf_probe_attach_type attach_type,int maxactive)228*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_kprobe(const std::string& kernel_func,
229*387f9dfdSAndroid Build Coastguard Worker const std::string& probe_func,
230*387f9dfdSAndroid Build Coastguard Worker uint64_t kernel_func_offset,
231*387f9dfdSAndroid Build Coastguard Worker bpf_probe_attach_type attach_type,
232*387f9dfdSAndroid Build Coastguard Worker int maxactive) {
233*387f9dfdSAndroid Build Coastguard Worker std::string probe_event = get_kprobe_event(kernel_func, attach_type);
234*387f9dfdSAndroid Build Coastguard Worker if (kprobes_.find(probe_event) != kprobes_.end())
235*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "kprobe %s already attached", probe_event.c_str());
236*387f9dfdSAndroid Build Coastguard Worker
237*387f9dfdSAndroid Build Coastguard Worker int probe_fd;
238*387f9dfdSAndroid Build Coastguard Worker TRY2(load_func(probe_func, BPF_PROG_TYPE_KPROBE, probe_fd));
239*387f9dfdSAndroid Build Coastguard Worker
240*387f9dfdSAndroid Build Coastguard Worker int res_fd = bpf_attach_kprobe(probe_fd, attach_type, probe_event.c_str(),
241*387f9dfdSAndroid Build Coastguard Worker kernel_func.c_str(), kernel_func_offset,
242*387f9dfdSAndroid Build Coastguard Worker maxactive);
243*387f9dfdSAndroid Build Coastguard Worker
244*387f9dfdSAndroid Build Coastguard Worker if (res_fd < 0) {
245*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(probe_func));
246*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to attach %skprobe for %s using %s",
247*387f9dfdSAndroid Build Coastguard Worker attach_type_debug(attach_type).c_str(),
248*387f9dfdSAndroid Build Coastguard Worker kernel_func.c_str(), probe_func.c_str());
249*387f9dfdSAndroid Build Coastguard Worker }
250*387f9dfdSAndroid Build Coastguard Worker
251*387f9dfdSAndroid Build Coastguard Worker open_probe_t p = {};
252*387f9dfdSAndroid Build Coastguard Worker p.perf_event_fd = res_fd;
253*387f9dfdSAndroid Build Coastguard Worker p.func = probe_func;
254*387f9dfdSAndroid Build Coastguard Worker kprobes_[probe_event] = std::move(p);
255*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
256*387f9dfdSAndroid Build Coastguard Worker }
257*387f9dfdSAndroid Build Coastguard Worker
attach_uprobe(const std::string & binary_path,const std::string & symbol,const std::string & probe_func,uint64_t symbol_addr,bpf_probe_attach_type attach_type,pid_t pid,uint64_t symbol_offset,uint32_t ref_ctr_offset)258*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_uprobe(const std::string& binary_path,
259*387f9dfdSAndroid Build Coastguard Worker const std::string& symbol,
260*387f9dfdSAndroid Build Coastguard Worker const std::string& probe_func,
261*387f9dfdSAndroid Build Coastguard Worker uint64_t symbol_addr,
262*387f9dfdSAndroid Build Coastguard Worker bpf_probe_attach_type attach_type, pid_t pid,
263*387f9dfdSAndroid Build Coastguard Worker uint64_t symbol_offset,
264*387f9dfdSAndroid Build Coastguard Worker uint32_t ref_ctr_offset) {
265*387f9dfdSAndroid Build Coastguard Worker
266*387f9dfdSAndroid Build Coastguard Worker if (symbol_addr != 0 && symbol_offset != 0)
267*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1,
268*387f9dfdSAndroid Build Coastguard Worker "Attachng uprobe with addr %lx and offset %lx is not supported",
269*387f9dfdSAndroid Build Coastguard Worker symbol_addr, symbol_offset);
270*387f9dfdSAndroid Build Coastguard Worker
271*387f9dfdSAndroid Build Coastguard Worker std::string module;
272*387f9dfdSAndroid Build Coastguard Worker uint64_t offset;
273*387f9dfdSAndroid Build Coastguard Worker TRY2(check_binary_symbol(binary_path, symbol, symbol_addr, module, offset,
274*387f9dfdSAndroid Build Coastguard Worker symbol_offset));
275*387f9dfdSAndroid Build Coastguard Worker
276*387f9dfdSAndroid Build Coastguard Worker std::string probe_event = get_uprobe_event(module, offset, attach_type, pid);
277*387f9dfdSAndroid Build Coastguard Worker if (uprobes_.find(probe_event) != uprobes_.end())
278*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "uprobe %s already attached", probe_event.c_str());
279*387f9dfdSAndroid Build Coastguard Worker
280*387f9dfdSAndroid Build Coastguard Worker int probe_fd;
281*387f9dfdSAndroid Build Coastguard Worker TRY2(load_func(probe_func, BPF_PROG_TYPE_KPROBE, probe_fd));
282*387f9dfdSAndroid Build Coastguard Worker
283*387f9dfdSAndroid Build Coastguard Worker int res_fd = bpf_attach_uprobe(probe_fd, attach_type, probe_event.c_str(),
284*387f9dfdSAndroid Build Coastguard Worker binary_path.c_str(), offset, pid,
285*387f9dfdSAndroid Build Coastguard Worker ref_ctr_offset);
286*387f9dfdSAndroid Build Coastguard Worker
287*387f9dfdSAndroid Build Coastguard Worker if (res_fd < 0) {
288*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(probe_func));
289*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(
290*387f9dfdSAndroid Build Coastguard Worker -1,
291*387f9dfdSAndroid Build Coastguard Worker "Unable to attach %suprobe for binary %s symbol %s addr %lx "
292*387f9dfdSAndroid Build Coastguard Worker "offset %lx using %s\n",
293*387f9dfdSAndroid Build Coastguard Worker attach_type_debug(attach_type).c_str(), binary_path.c_str(),
294*387f9dfdSAndroid Build Coastguard Worker symbol.c_str(), symbol_addr, symbol_offset, probe_func.c_str());
295*387f9dfdSAndroid Build Coastguard Worker }
296*387f9dfdSAndroid Build Coastguard Worker
297*387f9dfdSAndroid Build Coastguard Worker open_probe_t p = {};
298*387f9dfdSAndroid Build Coastguard Worker p.perf_event_fd = res_fd;
299*387f9dfdSAndroid Build Coastguard Worker p.func = probe_func;
300*387f9dfdSAndroid Build Coastguard Worker uprobes_[probe_event] = std::move(p);
301*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
302*387f9dfdSAndroid Build Coastguard Worker }
303*387f9dfdSAndroid Build Coastguard Worker
attach_usdt_without_validation(const USDT & u,pid_t pid)304*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_usdt_without_validation(const USDT& u, pid_t pid) {
305*387f9dfdSAndroid Build Coastguard Worker auto& probe = *static_cast<::USDT::Probe*>(u.probe_.get());
306*387f9dfdSAndroid Build Coastguard Worker if (!uprobe_ref_ctr_supported() && !probe.enable(u.probe_func_))
307*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to enable USDT %s", u.print_name().c_str());
308*387f9dfdSAndroid Build Coastguard Worker
309*387f9dfdSAndroid Build Coastguard Worker bool failed = false;
310*387f9dfdSAndroid Build Coastguard Worker std::string err_msg;
311*387f9dfdSAndroid Build Coastguard Worker int cnt = 0;
312*387f9dfdSAndroid Build Coastguard Worker for (const auto& loc : probe.locations_) {
313*387f9dfdSAndroid Build Coastguard Worker auto res = attach_uprobe(loc.bin_path_, std::string(), u.probe_func_,
314*387f9dfdSAndroid Build Coastguard Worker loc.address_, BPF_PROBE_ENTRY, pid, 0,
315*387f9dfdSAndroid Build Coastguard Worker probe.semaphore_offset());
316*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
317*387f9dfdSAndroid Build Coastguard Worker failed = true;
318*387f9dfdSAndroid Build Coastguard Worker err_msg += "USDT " + u.print_name() + " at " + loc.bin_path_ +
319*387f9dfdSAndroid Build Coastguard Worker " address " + std::to_string(loc.address_);
320*387f9dfdSAndroid Build Coastguard Worker err_msg += ": " + res.msg() + "\n";
321*387f9dfdSAndroid Build Coastguard Worker break;
322*387f9dfdSAndroid Build Coastguard Worker }
323*387f9dfdSAndroid Build Coastguard Worker cnt++;
324*387f9dfdSAndroid Build Coastguard Worker }
325*387f9dfdSAndroid Build Coastguard Worker if (failed) {
326*387f9dfdSAndroid Build Coastguard Worker for (int i = 0; i < cnt; i++) {
327*387f9dfdSAndroid Build Coastguard Worker auto res = detach_uprobe(probe.locations_[i].bin_path_, std::string(),
328*387f9dfdSAndroid Build Coastguard Worker probe.locations_[i].address_, BPF_PROBE_ENTRY, pid);
329*387f9dfdSAndroid Build Coastguard Worker if (!res.ok())
330*387f9dfdSAndroid Build Coastguard Worker err_msg += "During clean up: " + res.msg() + "\n";
331*387f9dfdSAndroid Build Coastguard Worker }
332*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, err_msg);
333*387f9dfdSAndroid Build Coastguard Worker } else {
334*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
335*387f9dfdSAndroid Build Coastguard Worker }
336*387f9dfdSAndroid Build Coastguard Worker }
337*387f9dfdSAndroid Build Coastguard Worker
attach_usdt(const USDT & usdt,pid_t pid)338*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_usdt(const USDT& usdt, pid_t pid) {
339*387f9dfdSAndroid Build Coastguard Worker for (const auto& u : usdt_) {
340*387f9dfdSAndroid Build Coastguard Worker if (u == usdt) {
341*387f9dfdSAndroid Build Coastguard Worker return attach_usdt_without_validation(u, pid);
342*387f9dfdSAndroid Build Coastguard Worker }
343*387f9dfdSAndroid Build Coastguard Worker }
344*387f9dfdSAndroid Build Coastguard Worker
345*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "USDT %s not found", usdt.print_name().c_str());
346*387f9dfdSAndroid Build Coastguard Worker }
347*387f9dfdSAndroid Build Coastguard Worker
attach_usdt_all()348*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_usdt_all() {
349*387f9dfdSAndroid Build Coastguard Worker for (const auto& u : usdt_) {
350*387f9dfdSAndroid Build Coastguard Worker auto res = attach_usdt_without_validation(u, -1);
351*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
352*387f9dfdSAndroid Build Coastguard Worker return res;
353*387f9dfdSAndroid Build Coastguard Worker }
354*387f9dfdSAndroid Build Coastguard Worker }
355*387f9dfdSAndroid Build Coastguard Worker
356*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
357*387f9dfdSAndroid Build Coastguard Worker }
358*387f9dfdSAndroid Build Coastguard Worker
359*387f9dfdSAndroid Build Coastguard Worker
attach_tracepoint(const std::string & tracepoint,const std::string & probe_func)360*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_tracepoint(const std::string& tracepoint,
361*387f9dfdSAndroid Build Coastguard Worker const std::string& probe_func) {
362*387f9dfdSAndroid Build Coastguard Worker if (tracepoints_.find(tracepoint) != tracepoints_.end())
363*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Tracepoint %s already attached",
364*387f9dfdSAndroid Build Coastguard Worker tracepoint.c_str());
365*387f9dfdSAndroid Build Coastguard Worker
366*387f9dfdSAndroid Build Coastguard Worker auto pos = tracepoint.find(":");
367*387f9dfdSAndroid Build Coastguard Worker if ((pos == std::string::npos) || (pos != tracepoint.rfind(":")))
368*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to parse Tracepoint %s", tracepoint.c_str());
369*387f9dfdSAndroid Build Coastguard Worker std::string tp_category = tracepoint.substr(0, pos);
370*387f9dfdSAndroid Build Coastguard Worker std::string tp_name = tracepoint.substr(pos + 1);
371*387f9dfdSAndroid Build Coastguard Worker
372*387f9dfdSAndroid Build Coastguard Worker int probe_fd;
373*387f9dfdSAndroid Build Coastguard Worker TRY2(load_func(probe_func, BPF_PROG_TYPE_TRACEPOINT, probe_fd));
374*387f9dfdSAndroid Build Coastguard Worker
375*387f9dfdSAndroid Build Coastguard Worker int res_fd =
376*387f9dfdSAndroid Build Coastguard Worker bpf_attach_tracepoint(probe_fd, tp_category.c_str(), tp_name.c_str());
377*387f9dfdSAndroid Build Coastguard Worker
378*387f9dfdSAndroid Build Coastguard Worker if (res_fd < 0) {
379*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(probe_func));
380*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to attach Tracepoint %s using %s",
381*387f9dfdSAndroid Build Coastguard Worker tracepoint.c_str(), probe_func.c_str());
382*387f9dfdSAndroid Build Coastguard Worker }
383*387f9dfdSAndroid Build Coastguard Worker
384*387f9dfdSAndroid Build Coastguard Worker open_probe_t p = {};
385*387f9dfdSAndroid Build Coastguard Worker p.perf_event_fd = res_fd;
386*387f9dfdSAndroid Build Coastguard Worker p.func = probe_func;
387*387f9dfdSAndroid Build Coastguard Worker tracepoints_[tracepoint] = std::move(p);
388*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
389*387f9dfdSAndroid Build Coastguard Worker }
390*387f9dfdSAndroid Build Coastguard Worker
attach_raw_tracepoint(const std::string & tracepoint,const std::string & probe_func)391*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_raw_tracepoint(const std::string& tracepoint, const std::string& probe_func) {
392*387f9dfdSAndroid Build Coastguard Worker if (raw_tracepoints_.find(tracepoint) != raw_tracepoints_.end())
393*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Raw tracepoint %s already attached",
394*387f9dfdSAndroid Build Coastguard Worker tracepoint.c_str());
395*387f9dfdSAndroid Build Coastguard Worker
396*387f9dfdSAndroid Build Coastguard Worker int probe_fd;
397*387f9dfdSAndroid Build Coastguard Worker TRY2(load_func(probe_func, BPF_PROG_TYPE_RAW_TRACEPOINT, probe_fd));
398*387f9dfdSAndroid Build Coastguard Worker
399*387f9dfdSAndroid Build Coastguard Worker int res_fd = bpf_attach_raw_tracepoint(probe_fd, tracepoint.c_str());
400*387f9dfdSAndroid Build Coastguard Worker
401*387f9dfdSAndroid Build Coastguard Worker if (res_fd < 0) {
402*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(probe_func));
403*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to attach Raw tracepoint %s using %s",
404*387f9dfdSAndroid Build Coastguard Worker tracepoint.c_str(), probe_func.c_str());
405*387f9dfdSAndroid Build Coastguard Worker }
406*387f9dfdSAndroid Build Coastguard Worker
407*387f9dfdSAndroid Build Coastguard Worker open_probe_t p = {};
408*387f9dfdSAndroid Build Coastguard Worker p.perf_event_fd = res_fd;
409*387f9dfdSAndroid Build Coastguard Worker p.func = probe_func;
410*387f9dfdSAndroid Build Coastguard Worker raw_tracepoints_[tracepoint] = std::move(p);
411*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
412*387f9dfdSAndroid Build Coastguard Worker }
413*387f9dfdSAndroid Build Coastguard Worker
attach_perf_event(uint32_t ev_type,uint32_t ev_config,const std::string & probe_func,uint64_t sample_period,uint64_t sample_freq,pid_t pid,int cpu,int group_fd)414*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config,
415*387f9dfdSAndroid Build Coastguard Worker const std::string& probe_func,
416*387f9dfdSAndroid Build Coastguard Worker uint64_t sample_period, uint64_t sample_freq,
417*387f9dfdSAndroid Build Coastguard Worker pid_t pid, int cpu, int group_fd) {
418*387f9dfdSAndroid Build Coastguard Worker auto ev_pair = std::make_pair(ev_type, ev_config);
419*387f9dfdSAndroid Build Coastguard Worker if (perf_events_.find(ev_pair) != perf_events_.end())
420*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Perf event type %d config %d already attached",
421*387f9dfdSAndroid Build Coastguard Worker ev_type, ev_config);
422*387f9dfdSAndroid Build Coastguard Worker
423*387f9dfdSAndroid Build Coastguard Worker int probe_fd;
424*387f9dfdSAndroid Build Coastguard Worker TRY2(load_func(probe_func, BPF_PROG_TYPE_PERF_EVENT, probe_fd));
425*387f9dfdSAndroid Build Coastguard Worker
426*387f9dfdSAndroid Build Coastguard Worker std::vector<int> cpus;
427*387f9dfdSAndroid Build Coastguard Worker if (cpu >= 0)
428*387f9dfdSAndroid Build Coastguard Worker cpus.push_back(cpu);
429*387f9dfdSAndroid Build Coastguard Worker else
430*387f9dfdSAndroid Build Coastguard Worker cpus = get_online_cpus();
431*387f9dfdSAndroid Build Coastguard Worker auto fds = new std::vector<std::pair<int, int>>();
432*387f9dfdSAndroid Build Coastguard Worker fds->reserve(cpus.size());
433*387f9dfdSAndroid Build Coastguard Worker for (int i : cpus) {
434*387f9dfdSAndroid Build Coastguard Worker int fd = bpf_attach_perf_event(probe_fd, ev_type, ev_config, sample_period,
435*387f9dfdSAndroid Build Coastguard Worker sample_freq, pid, i, group_fd);
436*387f9dfdSAndroid Build Coastguard Worker if (fd < 0) {
437*387f9dfdSAndroid Build Coastguard Worker for (const auto& it : *fds)
438*387f9dfdSAndroid Build Coastguard Worker close(it.second);
439*387f9dfdSAndroid Build Coastguard Worker delete fds;
440*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(probe_func));
441*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Failed to attach perf event type %d config %d",
442*387f9dfdSAndroid Build Coastguard Worker ev_type, ev_config);
443*387f9dfdSAndroid Build Coastguard Worker }
444*387f9dfdSAndroid Build Coastguard Worker fds->emplace_back(i, fd);
445*387f9dfdSAndroid Build Coastguard Worker }
446*387f9dfdSAndroid Build Coastguard Worker
447*387f9dfdSAndroid Build Coastguard Worker open_probe_t p = {};
448*387f9dfdSAndroid Build Coastguard Worker p.func = probe_func;
449*387f9dfdSAndroid Build Coastguard Worker p.per_cpu_fd = fds;
450*387f9dfdSAndroid Build Coastguard Worker perf_events_[ev_pair] = std::move(p);
451*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
452*387f9dfdSAndroid Build Coastguard Worker }
453*387f9dfdSAndroid Build Coastguard Worker
attach_perf_event_raw(void * perf_event_attr,const std::string & probe_func,pid_t pid,int cpu,int group_fd,unsigned long extra_flags)454*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_perf_event_raw(void* perf_event_attr,
455*387f9dfdSAndroid Build Coastguard Worker const std::string& probe_func, pid_t pid,
456*387f9dfdSAndroid Build Coastguard Worker int cpu, int group_fd,
457*387f9dfdSAndroid Build Coastguard Worker unsigned long extra_flags) {
458*387f9dfdSAndroid Build Coastguard Worker auto attr = static_cast<struct perf_event_attr*>(perf_event_attr);
459*387f9dfdSAndroid Build Coastguard Worker auto ev_pair = std::make_pair(attr->type, attr->config);
460*387f9dfdSAndroid Build Coastguard Worker if (perf_events_.find(ev_pair) != perf_events_.end())
461*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Perf event type %d config %d already attached",
462*387f9dfdSAndroid Build Coastguard Worker attr->type, attr->config);
463*387f9dfdSAndroid Build Coastguard Worker
464*387f9dfdSAndroid Build Coastguard Worker int probe_fd;
465*387f9dfdSAndroid Build Coastguard Worker TRY2(load_func(probe_func, BPF_PROG_TYPE_PERF_EVENT, probe_fd));
466*387f9dfdSAndroid Build Coastguard Worker
467*387f9dfdSAndroid Build Coastguard Worker std::vector<int> cpus;
468*387f9dfdSAndroid Build Coastguard Worker if (cpu >= 0)
469*387f9dfdSAndroid Build Coastguard Worker cpus.push_back(cpu);
470*387f9dfdSAndroid Build Coastguard Worker else
471*387f9dfdSAndroid Build Coastguard Worker cpus = get_online_cpus();
472*387f9dfdSAndroid Build Coastguard Worker auto fds = new std::vector<std::pair<int, int>>();
473*387f9dfdSAndroid Build Coastguard Worker fds->reserve(cpus.size());
474*387f9dfdSAndroid Build Coastguard Worker for (int i : cpus) {
475*387f9dfdSAndroid Build Coastguard Worker int fd = bpf_attach_perf_event_raw(probe_fd, attr, pid, i, group_fd,
476*387f9dfdSAndroid Build Coastguard Worker extra_flags);
477*387f9dfdSAndroid Build Coastguard Worker if (fd < 0) {
478*387f9dfdSAndroid Build Coastguard Worker for (const auto& it : *fds)
479*387f9dfdSAndroid Build Coastguard Worker close(it.second);
480*387f9dfdSAndroid Build Coastguard Worker delete fds;
481*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(probe_func));
482*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Failed to attach perf event type %d config %d",
483*387f9dfdSAndroid Build Coastguard Worker attr->type, attr->config);
484*387f9dfdSAndroid Build Coastguard Worker }
485*387f9dfdSAndroid Build Coastguard Worker fds->emplace_back(i, fd);
486*387f9dfdSAndroid Build Coastguard Worker }
487*387f9dfdSAndroid Build Coastguard Worker
488*387f9dfdSAndroid Build Coastguard Worker open_probe_t p = {};
489*387f9dfdSAndroid Build Coastguard Worker p.func = probe_func;
490*387f9dfdSAndroid Build Coastguard Worker p.per_cpu_fd = fds;
491*387f9dfdSAndroid Build Coastguard Worker perf_events_[ev_pair] = std::move(p);
492*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
493*387f9dfdSAndroid Build Coastguard Worker }
494*387f9dfdSAndroid Build Coastguard Worker
detach_kprobe(const std::string & kernel_func,bpf_probe_attach_type attach_type)495*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_kprobe(const std::string& kernel_func,
496*387f9dfdSAndroid Build Coastguard Worker bpf_probe_attach_type attach_type) {
497*387f9dfdSAndroid Build Coastguard Worker std::string event = get_kprobe_event(kernel_func, attach_type);
498*387f9dfdSAndroid Build Coastguard Worker
499*387f9dfdSAndroid Build Coastguard Worker auto it = kprobes_.find(event);
500*387f9dfdSAndroid Build Coastguard Worker if (it == kprobes_.end())
501*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "No open %skprobe for %s",
502*387f9dfdSAndroid Build Coastguard Worker attach_type_debug(attach_type).c_str(),
503*387f9dfdSAndroid Build Coastguard Worker kernel_func.c_str());
504*387f9dfdSAndroid Build Coastguard Worker
505*387f9dfdSAndroid Build Coastguard Worker TRY2(detach_kprobe_event(it->first, it->second));
506*387f9dfdSAndroid Build Coastguard Worker kprobes_.erase(it);
507*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
508*387f9dfdSAndroid Build Coastguard Worker }
509*387f9dfdSAndroid Build Coastguard Worker
detach_uprobe(const std::string & binary_path,const std::string & symbol,uint64_t symbol_addr,bpf_probe_attach_type attach_type,pid_t pid,uint64_t symbol_offset)510*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_uprobe(const std::string& binary_path,
511*387f9dfdSAndroid Build Coastguard Worker const std::string& symbol, uint64_t symbol_addr,
512*387f9dfdSAndroid Build Coastguard Worker bpf_probe_attach_type attach_type, pid_t pid,
513*387f9dfdSAndroid Build Coastguard Worker uint64_t symbol_offset) {
514*387f9dfdSAndroid Build Coastguard Worker std::string module;
515*387f9dfdSAndroid Build Coastguard Worker uint64_t offset;
516*387f9dfdSAndroid Build Coastguard Worker TRY2(check_binary_symbol(binary_path, symbol, symbol_addr, module, offset,
517*387f9dfdSAndroid Build Coastguard Worker symbol_offset));
518*387f9dfdSAndroid Build Coastguard Worker
519*387f9dfdSAndroid Build Coastguard Worker std::string event = get_uprobe_event(module, offset, attach_type, pid);
520*387f9dfdSAndroid Build Coastguard Worker auto it = uprobes_.find(event);
521*387f9dfdSAndroid Build Coastguard Worker if (it == uprobes_.end())
522*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "No open %suprobe for binary %s symbol %s addr %lx",
523*387f9dfdSAndroid Build Coastguard Worker attach_type_debug(attach_type).c_str(),
524*387f9dfdSAndroid Build Coastguard Worker binary_path.c_str(), symbol.c_str(), symbol_addr);
525*387f9dfdSAndroid Build Coastguard Worker
526*387f9dfdSAndroid Build Coastguard Worker TRY2(detach_uprobe_event(it->first, it->second));
527*387f9dfdSAndroid Build Coastguard Worker uprobes_.erase(it);
528*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
529*387f9dfdSAndroid Build Coastguard Worker }
530*387f9dfdSAndroid Build Coastguard Worker
detach_usdt_without_validation(const USDT & u,pid_t pid)531*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_usdt_without_validation(const USDT& u, pid_t pid) {
532*387f9dfdSAndroid Build Coastguard Worker auto& probe = *static_cast<::USDT::Probe*>(u.probe_.get());
533*387f9dfdSAndroid Build Coastguard Worker bool failed = false;
534*387f9dfdSAndroid Build Coastguard Worker std::string err_msg;
535*387f9dfdSAndroid Build Coastguard Worker for (const auto& loc : probe.locations_) {
536*387f9dfdSAndroid Build Coastguard Worker auto res = detach_uprobe(loc.bin_path_, std::string(), loc.address_,
537*387f9dfdSAndroid Build Coastguard Worker BPF_PROBE_ENTRY, pid);
538*387f9dfdSAndroid Build Coastguard Worker if (!res.ok()) {
539*387f9dfdSAndroid Build Coastguard Worker failed = true;
540*387f9dfdSAndroid Build Coastguard Worker err_msg += "USDT " + u.print_name() + " at " + loc.bin_path_ +
541*387f9dfdSAndroid Build Coastguard Worker " address " + std::to_string(loc.address_);
542*387f9dfdSAndroid Build Coastguard Worker err_msg += ": " + res.msg() + "\n";
543*387f9dfdSAndroid Build Coastguard Worker }
544*387f9dfdSAndroid Build Coastguard Worker }
545*387f9dfdSAndroid Build Coastguard Worker
546*387f9dfdSAndroid Build Coastguard Worker if (!uprobe_ref_ctr_supported() && !probe.disable()) {
547*387f9dfdSAndroid Build Coastguard Worker failed = true;
548*387f9dfdSAndroid Build Coastguard Worker err_msg += "Unable to disable USDT " + u.print_name();
549*387f9dfdSAndroid Build Coastguard Worker }
550*387f9dfdSAndroid Build Coastguard Worker
551*387f9dfdSAndroid Build Coastguard Worker if (failed)
552*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, err_msg);
553*387f9dfdSAndroid Build Coastguard Worker else
554*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
555*387f9dfdSAndroid Build Coastguard Worker }
556*387f9dfdSAndroid Build Coastguard Worker
detach_usdt(const USDT & usdt,pid_t pid)557*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_usdt(const USDT& usdt, pid_t pid) {
558*387f9dfdSAndroid Build Coastguard Worker for (const auto& u : usdt_) {
559*387f9dfdSAndroid Build Coastguard Worker if (u == usdt) {
560*387f9dfdSAndroid Build Coastguard Worker return detach_usdt_without_validation(u, pid);
561*387f9dfdSAndroid Build Coastguard Worker }
562*387f9dfdSAndroid Build Coastguard Worker }
563*387f9dfdSAndroid Build Coastguard Worker
564*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "USDT %s not found", usdt.print_name().c_str());
565*387f9dfdSAndroid Build Coastguard Worker }
566*387f9dfdSAndroid Build Coastguard Worker
detach_usdt_all()567*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_usdt_all() {
568*387f9dfdSAndroid Build Coastguard Worker for (const auto& u : usdt_) {
569*387f9dfdSAndroid Build Coastguard Worker auto ret = detach_usdt_without_validation(u, -1);
570*387f9dfdSAndroid Build Coastguard Worker if (!ret.ok()) {
571*387f9dfdSAndroid Build Coastguard Worker return ret;
572*387f9dfdSAndroid Build Coastguard Worker }
573*387f9dfdSAndroid Build Coastguard Worker }
574*387f9dfdSAndroid Build Coastguard Worker
575*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
576*387f9dfdSAndroid Build Coastguard Worker }
577*387f9dfdSAndroid Build Coastguard Worker
detach_tracepoint(const std::string & tracepoint)578*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_tracepoint(const std::string& tracepoint) {
579*387f9dfdSAndroid Build Coastguard Worker auto it = tracepoints_.find(tracepoint);
580*387f9dfdSAndroid Build Coastguard Worker if (it == tracepoints_.end())
581*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "No open Tracepoint %s", tracepoint.c_str());
582*387f9dfdSAndroid Build Coastguard Worker
583*387f9dfdSAndroid Build Coastguard Worker TRY2(detach_tracepoint_event(it->first, it->second));
584*387f9dfdSAndroid Build Coastguard Worker tracepoints_.erase(it);
585*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
586*387f9dfdSAndroid Build Coastguard Worker }
587*387f9dfdSAndroid Build Coastguard Worker
detach_raw_tracepoint(const std::string & tracepoint)588*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_raw_tracepoint(const std::string& tracepoint) {
589*387f9dfdSAndroid Build Coastguard Worker auto it = raw_tracepoints_.find(tracepoint);
590*387f9dfdSAndroid Build Coastguard Worker if (it == raw_tracepoints_.end())
591*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "No open Raw tracepoint %s", tracepoint.c_str());
592*387f9dfdSAndroid Build Coastguard Worker
593*387f9dfdSAndroid Build Coastguard Worker TRY2(detach_raw_tracepoint_event(it->first, it->second));
594*387f9dfdSAndroid Build Coastguard Worker raw_tracepoints_.erase(it);
595*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
596*387f9dfdSAndroid Build Coastguard Worker }
597*387f9dfdSAndroid Build Coastguard Worker
detach_perf_event(uint32_t ev_type,uint32_t ev_config)598*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_perf_event(uint32_t ev_type, uint32_t ev_config) {
599*387f9dfdSAndroid Build Coastguard Worker auto it = perf_events_.find(std::make_pair(ev_type, ev_config));
600*387f9dfdSAndroid Build Coastguard Worker if (it == perf_events_.end())
601*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Perf Event type %d config %d not attached", ev_type,
602*387f9dfdSAndroid Build Coastguard Worker ev_config);
603*387f9dfdSAndroid Build Coastguard Worker TRY2(detach_perf_event_all_cpu(it->second));
604*387f9dfdSAndroid Build Coastguard Worker perf_events_.erase(it);
605*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
606*387f9dfdSAndroid Build Coastguard Worker }
607*387f9dfdSAndroid Build Coastguard Worker
detach_perf_event_raw(void * perf_event_attr)608*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_perf_event_raw(void* perf_event_attr) {
609*387f9dfdSAndroid Build Coastguard Worker auto attr = static_cast<struct perf_event_attr*>(perf_event_attr);
610*387f9dfdSAndroid Build Coastguard Worker return detach_perf_event(attr->type, attr->config);
611*387f9dfdSAndroid Build Coastguard Worker }
612*387f9dfdSAndroid Build Coastguard Worker
open_perf_event(const std::string & name,uint32_t type,uint64_t config,int pid)613*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::open_perf_event(const std::string& name, uint32_t type,
614*387f9dfdSAndroid Build Coastguard Worker uint64_t config, int pid) {
615*387f9dfdSAndroid Build Coastguard Worker if (perf_event_arrays_.find(name) == perf_event_arrays_.end()) {
616*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
617*387f9dfdSAndroid Build Coastguard Worker if (!bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
618*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "open_perf_event: unable to find table_storage %s",
619*387f9dfdSAndroid Build Coastguard Worker name.c_str());
620*387f9dfdSAndroid Build Coastguard Worker perf_event_arrays_[name] = new BPFPerfEventArray(it->second);
621*387f9dfdSAndroid Build Coastguard Worker }
622*387f9dfdSAndroid Build Coastguard Worker auto table = perf_event_arrays_[name];
623*387f9dfdSAndroid Build Coastguard Worker TRY2(table->open_all_cpu(type, config, pid));
624*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
625*387f9dfdSAndroid Build Coastguard Worker }
626*387f9dfdSAndroid Build Coastguard Worker
close_perf_event(const std::string & name)627*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::close_perf_event(const std::string& name) {
628*387f9dfdSAndroid Build Coastguard Worker auto it = perf_event_arrays_.find(name);
629*387f9dfdSAndroid Build Coastguard Worker if (it == perf_event_arrays_.end())
630*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Perf Event for %s not open", name.c_str());
631*387f9dfdSAndroid Build Coastguard Worker TRY2(it->second->close_all_cpu());
632*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
633*387f9dfdSAndroid Build Coastguard Worker }
634*387f9dfdSAndroid Build Coastguard Worker
open_perf_buffer(const std::string & name,perf_reader_raw_cb cb,perf_reader_lost_cb lost_cb,void * cb_cookie,int page_cnt)635*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::open_perf_buffer(const std::string& name,
636*387f9dfdSAndroid Build Coastguard Worker perf_reader_raw_cb cb,
637*387f9dfdSAndroid Build Coastguard Worker perf_reader_lost_cb lost_cb, void* cb_cookie,
638*387f9dfdSAndroid Build Coastguard Worker int page_cnt) {
639*387f9dfdSAndroid Build Coastguard Worker if (perf_buffers_.find(name) == perf_buffers_.end()) {
640*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
641*387f9dfdSAndroid Build Coastguard Worker if (!bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
642*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1,
643*387f9dfdSAndroid Build Coastguard Worker "open_perf_buffer: unable to find table_storage %s",
644*387f9dfdSAndroid Build Coastguard Worker name.c_str());
645*387f9dfdSAndroid Build Coastguard Worker perf_buffers_[name] = new BPFPerfBuffer(it->second);
646*387f9dfdSAndroid Build Coastguard Worker }
647*387f9dfdSAndroid Build Coastguard Worker if ((page_cnt & (page_cnt - 1)) != 0)
648*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "open_perf_buffer page_cnt must be a power of two");
649*387f9dfdSAndroid Build Coastguard Worker auto table = perf_buffers_[name];
650*387f9dfdSAndroid Build Coastguard Worker TRY2(table->open_all_cpu(cb, lost_cb, cb_cookie, page_cnt));
651*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
652*387f9dfdSAndroid Build Coastguard Worker }
653*387f9dfdSAndroid Build Coastguard Worker
close_perf_buffer(const std::string & name)654*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::close_perf_buffer(const std::string& name) {
655*387f9dfdSAndroid Build Coastguard Worker auto it = perf_buffers_.find(name);
656*387f9dfdSAndroid Build Coastguard Worker if (it == perf_buffers_.end())
657*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Perf buffer for %s not open", name.c_str());
658*387f9dfdSAndroid Build Coastguard Worker TRY2(it->second->close_all_cpu());
659*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
660*387f9dfdSAndroid Build Coastguard Worker }
661*387f9dfdSAndroid Build Coastguard Worker
get_perf_buffer(const std::string & name)662*387f9dfdSAndroid Build Coastguard Worker BPFPerfBuffer* BPF::get_perf_buffer(const std::string& name) {
663*387f9dfdSAndroid Build Coastguard Worker auto it = perf_buffers_.find(name);
664*387f9dfdSAndroid Build Coastguard Worker return (it == perf_buffers_.end()) ? nullptr : it->second;
665*387f9dfdSAndroid Build Coastguard Worker }
666*387f9dfdSAndroid Build Coastguard Worker
poll_perf_buffer(const std::string & name,int timeout_ms)667*387f9dfdSAndroid Build Coastguard Worker int BPF::poll_perf_buffer(const std::string& name, int timeout_ms) {
668*387f9dfdSAndroid Build Coastguard Worker auto it = perf_buffers_.find(name);
669*387f9dfdSAndroid Build Coastguard Worker if (it == perf_buffers_.end())
670*387f9dfdSAndroid Build Coastguard Worker return -1;
671*387f9dfdSAndroid Build Coastguard Worker return it->second->poll(timeout_ms);
672*387f9dfdSAndroid Build Coastguard Worker }
673*387f9dfdSAndroid Build Coastguard Worker
load_func(const std::string & func_name,bpf_prog_type type,int & fd,unsigned flags,bpf_attach_type expected_attach_type)674*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::load_func(const std::string& func_name, bpf_prog_type type,
675*387f9dfdSAndroid Build Coastguard Worker int& fd, unsigned flags, bpf_attach_type expected_attach_type) {
676*387f9dfdSAndroid Build Coastguard Worker if (funcs_.find(func_name) != funcs_.end()) {
677*387f9dfdSAndroid Build Coastguard Worker fd = funcs_[func_name];
678*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
679*387f9dfdSAndroid Build Coastguard Worker }
680*387f9dfdSAndroid Build Coastguard Worker
681*387f9dfdSAndroid Build Coastguard Worker uint8_t* func_start = bpf_module_->function_start(func_name);
682*387f9dfdSAndroid Build Coastguard Worker if (!func_start)
683*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Can't find start of function %s",
684*387f9dfdSAndroid Build Coastguard Worker func_name.c_str());
685*387f9dfdSAndroid Build Coastguard Worker size_t func_size = bpf_module_->function_size(func_name);
686*387f9dfdSAndroid Build Coastguard Worker
687*387f9dfdSAndroid Build Coastguard Worker int log_level = 0;
688*387f9dfdSAndroid Build Coastguard Worker if (flag_ & DEBUG_BPF_REGISTER_STATE)
689*387f9dfdSAndroid Build Coastguard Worker log_level = 2;
690*387f9dfdSAndroid Build Coastguard Worker else if (flag_ & DEBUG_BPF)
691*387f9dfdSAndroid Build Coastguard Worker log_level = 1;
692*387f9dfdSAndroid Build Coastguard Worker
693*387f9dfdSAndroid Build Coastguard Worker fd = bpf_module_->bcc_func_load(type, func_name.c_str(),
694*387f9dfdSAndroid Build Coastguard Worker reinterpret_cast<struct bpf_insn*>(func_start), func_size,
695*387f9dfdSAndroid Build Coastguard Worker bpf_module_->license(), bpf_module_->kern_version(),
696*387f9dfdSAndroid Build Coastguard Worker log_level, nullptr, 0, nullptr, flags, expected_attach_type);
697*387f9dfdSAndroid Build Coastguard Worker
698*387f9dfdSAndroid Build Coastguard Worker if (fd < 0)
699*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Failed to load %s: %d", func_name.c_str(), fd);
700*387f9dfdSAndroid Build Coastguard Worker
701*387f9dfdSAndroid Build Coastguard Worker int ret = bpf_module_->annotate_prog_tag(
702*387f9dfdSAndroid Build Coastguard Worker func_name, fd, reinterpret_cast<struct bpf_insn*>(func_start), func_size);
703*387f9dfdSAndroid Build Coastguard Worker if (ret < 0)
704*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "WARNING: cannot get prog tag, ignore saving source with program tag\n");
705*387f9dfdSAndroid Build Coastguard Worker funcs_[func_name] = fd;
706*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
707*387f9dfdSAndroid Build Coastguard Worker }
708*387f9dfdSAndroid Build Coastguard Worker
unload_func(const std::string & func_name)709*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::unload_func(const std::string& func_name) {
710*387f9dfdSAndroid Build Coastguard Worker auto it = funcs_.find(func_name);
711*387f9dfdSAndroid Build Coastguard Worker if (it == funcs_.end())
712*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
713*387f9dfdSAndroid Build Coastguard Worker
714*387f9dfdSAndroid Build Coastguard Worker int res = close(it->second);
715*387f9dfdSAndroid Build Coastguard Worker if (res != 0)
716*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Can't close FD for %s: %d", it->first.c_str(), res);
717*387f9dfdSAndroid Build Coastguard Worker
718*387f9dfdSAndroid Build Coastguard Worker funcs_.erase(it);
719*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
720*387f9dfdSAndroid Build Coastguard Worker }
721*387f9dfdSAndroid Build Coastguard Worker
attach_func(int prog_fd,int attachable_fd,enum bpf_attach_type attach_type,uint64_t flags)722*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::attach_func(int prog_fd, int attachable_fd,
723*387f9dfdSAndroid Build Coastguard Worker enum bpf_attach_type attach_type,
724*387f9dfdSAndroid Build Coastguard Worker uint64_t flags) {
725*387f9dfdSAndroid Build Coastguard Worker int res = bpf_module_->bcc_func_attach(prog_fd, attachable_fd, attach_type, flags);
726*387f9dfdSAndroid Build Coastguard Worker if (res != 0)
727*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Can't attach for prog_fd %d, attachable_fd %d, "
728*387f9dfdSAndroid Build Coastguard Worker "attach_type %d, flags %ld: error %d",
729*387f9dfdSAndroid Build Coastguard Worker prog_fd, attachable_fd, attach_type, flags, res);
730*387f9dfdSAndroid Build Coastguard Worker
731*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
732*387f9dfdSAndroid Build Coastguard Worker }
733*387f9dfdSAndroid Build Coastguard Worker
detach_func(int prog_fd,int attachable_fd,enum bpf_attach_type attach_type)734*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_func(int prog_fd, int attachable_fd,
735*387f9dfdSAndroid Build Coastguard Worker enum bpf_attach_type attach_type) {
736*387f9dfdSAndroid Build Coastguard Worker int res = bpf_module_->bcc_func_detach(prog_fd, attachable_fd, attach_type);
737*387f9dfdSAndroid Build Coastguard Worker if (res != 0)
738*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Can't detach for prog_fd %d, attachable_fd %d, "
739*387f9dfdSAndroid Build Coastguard Worker "attach_type %d: error %d",
740*387f9dfdSAndroid Build Coastguard Worker prog_fd, attachable_fd, attach_type, res);
741*387f9dfdSAndroid Build Coastguard Worker
742*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
743*387f9dfdSAndroid Build Coastguard Worker }
744*387f9dfdSAndroid Build Coastguard Worker
get_syscall_fnname(const std::string & name)745*387f9dfdSAndroid Build Coastguard Worker std::string BPF::get_syscall_fnname(const std::string& name) {
746*387f9dfdSAndroid Build Coastguard Worker if (syscall_prefix_ == nullptr) {
747*387f9dfdSAndroid Build Coastguard Worker KSyms ksym;
748*387f9dfdSAndroid Build Coastguard Worker uint64_t addr;
749*387f9dfdSAndroid Build Coastguard Worker
750*387f9dfdSAndroid Build Coastguard Worker if (ksym.resolve_name(nullptr, "sys_bpf", &addr))
751*387f9dfdSAndroid Build Coastguard Worker syscall_prefix_.reset(new std::string("sys_"));
752*387f9dfdSAndroid Build Coastguard Worker else if (ksym.resolve_name(nullptr, "__x64_sys_bpf", &addr))
753*387f9dfdSAndroid Build Coastguard Worker syscall_prefix_.reset(new std::string("__x64_sys_"));
754*387f9dfdSAndroid Build Coastguard Worker else
755*387f9dfdSAndroid Build Coastguard Worker syscall_prefix_.reset(new std::string());
756*387f9dfdSAndroid Build Coastguard Worker }
757*387f9dfdSAndroid Build Coastguard Worker
758*387f9dfdSAndroid Build Coastguard Worker return *syscall_prefix_ + name;
759*387f9dfdSAndroid Build Coastguard Worker }
760*387f9dfdSAndroid Build Coastguard Worker
check_binary_symbol(const std::string & binary_path,const std::string & symbol,uint64_t symbol_addr,std::string & module_res,uint64_t & offset_res,uint64_t symbol_offset)761*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::check_binary_symbol(const std::string& binary_path,
762*387f9dfdSAndroid Build Coastguard Worker const std::string& symbol,
763*387f9dfdSAndroid Build Coastguard Worker uint64_t symbol_addr,
764*387f9dfdSAndroid Build Coastguard Worker std::string& module_res,
765*387f9dfdSAndroid Build Coastguard Worker uint64_t& offset_res,
766*387f9dfdSAndroid Build Coastguard Worker uint64_t symbol_offset) {
767*387f9dfdSAndroid Build Coastguard Worker bcc_symbol output;
768*387f9dfdSAndroid Build Coastguard Worker int res = bcc_resolve_symname(binary_path.c_str(), symbol.c_str(),
769*387f9dfdSAndroid Build Coastguard Worker symbol_addr, -1, nullptr, &output);
770*387f9dfdSAndroid Build Coastguard Worker if (res < 0)
771*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(
772*387f9dfdSAndroid Build Coastguard Worker -1, "Unable to find offset for binary %s symbol %s address %lx",
773*387f9dfdSAndroid Build Coastguard Worker binary_path.c_str(), symbol.c_str(), symbol_addr);
774*387f9dfdSAndroid Build Coastguard Worker
775*387f9dfdSAndroid Build Coastguard Worker if (output.module) {
776*387f9dfdSAndroid Build Coastguard Worker module_res = output.module;
777*387f9dfdSAndroid Build Coastguard Worker ::free(const_cast<char*>(output.module));
778*387f9dfdSAndroid Build Coastguard Worker } else {
779*387f9dfdSAndroid Build Coastguard Worker module_res = "";
780*387f9dfdSAndroid Build Coastguard Worker }
781*387f9dfdSAndroid Build Coastguard Worker offset_res = output.offset + symbol_offset;
782*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
783*387f9dfdSAndroid Build Coastguard Worker }
784*387f9dfdSAndroid Build Coastguard Worker
get_kprobe_event(const std::string & kernel_func,bpf_probe_attach_type type)785*387f9dfdSAndroid Build Coastguard Worker std::string BPF::get_kprobe_event(const std::string& kernel_func,
786*387f9dfdSAndroid Build Coastguard Worker bpf_probe_attach_type type) {
787*387f9dfdSAndroid Build Coastguard Worker std::string res = attach_type_prefix(type) + "_";
788*387f9dfdSAndroid Build Coastguard Worker res += sanitize_str(kernel_func, &BPF::kprobe_event_validator);
789*387f9dfdSAndroid Build Coastguard Worker return res;
790*387f9dfdSAndroid Build Coastguard Worker }
791*387f9dfdSAndroid Build Coastguard Worker
get_prog_table(const std::string & name)792*387f9dfdSAndroid Build Coastguard Worker BPFProgTable BPF::get_prog_table(const std::string& name) {
793*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
794*387f9dfdSAndroid Build Coastguard Worker if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
795*387f9dfdSAndroid Build Coastguard Worker return BPFProgTable(it->second);
796*387f9dfdSAndroid Build Coastguard Worker return BPFProgTable({});
797*387f9dfdSAndroid Build Coastguard Worker }
798*387f9dfdSAndroid Build Coastguard Worker
get_cgroup_array(const std::string & name)799*387f9dfdSAndroid Build Coastguard Worker BPFCgroupArray BPF::get_cgroup_array(const std::string& name) {
800*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
801*387f9dfdSAndroid Build Coastguard Worker if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
802*387f9dfdSAndroid Build Coastguard Worker return BPFCgroupArray(it->second);
803*387f9dfdSAndroid Build Coastguard Worker return BPFCgroupArray({});
804*387f9dfdSAndroid Build Coastguard Worker }
805*387f9dfdSAndroid Build Coastguard Worker
get_devmap_table(const std::string & name)806*387f9dfdSAndroid Build Coastguard Worker BPFDevmapTable BPF::get_devmap_table(const std::string& name) {
807*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
808*387f9dfdSAndroid Build Coastguard Worker if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
809*387f9dfdSAndroid Build Coastguard Worker return BPFDevmapTable(it->second);
810*387f9dfdSAndroid Build Coastguard Worker return BPFDevmapTable({});
811*387f9dfdSAndroid Build Coastguard Worker }
812*387f9dfdSAndroid Build Coastguard Worker
get_xskmap_table(const std::string & name)813*387f9dfdSAndroid Build Coastguard Worker BPFXskmapTable BPF::get_xskmap_table(const std::string& name) {
814*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
815*387f9dfdSAndroid Build Coastguard Worker if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
816*387f9dfdSAndroid Build Coastguard Worker return BPFXskmapTable(it->second);
817*387f9dfdSAndroid Build Coastguard Worker return BPFXskmapTable({});
818*387f9dfdSAndroid Build Coastguard Worker }
819*387f9dfdSAndroid Build Coastguard Worker
get_stack_table(const std::string & name,bool use_debug_file,bool check_debug_file_crc)820*387f9dfdSAndroid Build Coastguard Worker BPFStackTable BPF::get_stack_table(const std::string& name, bool use_debug_file,
821*387f9dfdSAndroid Build Coastguard Worker bool check_debug_file_crc) {
822*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
823*387f9dfdSAndroid Build Coastguard Worker if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
824*387f9dfdSAndroid Build Coastguard Worker return BPFStackTable(it->second, use_debug_file, check_debug_file_crc);
825*387f9dfdSAndroid Build Coastguard Worker return BPFStackTable({}, use_debug_file, check_debug_file_crc);
826*387f9dfdSAndroid Build Coastguard Worker }
827*387f9dfdSAndroid Build Coastguard Worker
get_stackbuildid_table(const std::string & name,bool use_debug_file,bool check_debug_file_crc)828*387f9dfdSAndroid Build Coastguard Worker BPFStackBuildIdTable BPF::get_stackbuildid_table(const std::string &name, bool use_debug_file,
829*387f9dfdSAndroid Build Coastguard Worker bool check_debug_file_crc) {
830*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
831*387f9dfdSAndroid Build Coastguard Worker
832*387f9dfdSAndroid Build Coastguard Worker if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
833*387f9dfdSAndroid Build Coastguard Worker return BPFStackBuildIdTable(it->second, use_debug_file, check_debug_file_crc, get_bsymcache());
834*387f9dfdSAndroid Build Coastguard Worker return BPFStackBuildIdTable({}, use_debug_file, check_debug_file_crc, get_bsymcache());
835*387f9dfdSAndroid Build Coastguard Worker }
836*387f9dfdSAndroid Build Coastguard Worker
get_sockmap_table(const std::string & name)837*387f9dfdSAndroid Build Coastguard Worker BPFSockmapTable BPF::get_sockmap_table(const std::string& name) {
838*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
839*387f9dfdSAndroid Build Coastguard Worker if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
840*387f9dfdSAndroid Build Coastguard Worker return BPFSockmapTable(it->second);
841*387f9dfdSAndroid Build Coastguard Worker return BPFSockmapTable({});
842*387f9dfdSAndroid Build Coastguard Worker }
843*387f9dfdSAndroid Build Coastguard Worker
get_sockhash_table(const std::string & name)844*387f9dfdSAndroid Build Coastguard Worker BPFSockhashTable BPF::get_sockhash_table(const std::string& name) {
845*387f9dfdSAndroid Build Coastguard Worker TableStorage::iterator it;
846*387f9dfdSAndroid Build Coastguard Worker if (bpf_module_->table_storage().Find(Path({bpf_module_->id(), name}), it))
847*387f9dfdSAndroid Build Coastguard Worker return BPFSockhashTable(it->second);
848*387f9dfdSAndroid Build Coastguard Worker return BPFSockhashTable({});
849*387f9dfdSAndroid Build Coastguard Worker }
850*387f9dfdSAndroid Build Coastguard Worker
add_module(std::string module)851*387f9dfdSAndroid Build Coastguard Worker bool BPF::add_module(std::string module)
852*387f9dfdSAndroid Build Coastguard Worker {
853*387f9dfdSAndroid Build Coastguard Worker return bcc_buildsymcache_add_module(get_bsymcache(), module.c_str()) != 0 ?
854*387f9dfdSAndroid Build Coastguard Worker false : true;
855*387f9dfdSAndroid Build Coastguard Worker }
856*387f9dfdSAndroid Build Coastguard Worker
857*387f9dfdSAndroid Build Coastguard Worker namespace {
858*387f9dfdSAndroid Build Coastguard Worker
859*387f9dfdSAndroid Build Coastguard Worker constexpr size_t kEventNameSizeLimit = 224;
860*387f9dfdSAndroid Build Coastguard Worker
shorten_event_name(const std::string & name)861*387f9dfdSAndroid Build Coastguard Worker std::string shorten_event_name(const std::string& name) {
862*387f9dfdSAndroid Build Coastguard Worker std::string hash = uint_to_hex(std::hash<std::string>{}(name));
863*387f9dfdSAndroid Build Coastguard Worker return name.substr(0, kEventNameSizeLimit - hash.size()) + hash;
864*387f9dfdSAndroid Build Coastguard Worker }
865*387f9dfdSAndroid Build Coastguard Worker
866*387f9dfdSAndroid Build Coastguard Worker } // namespace
867*387f9dfdSAndroid Build Coastguard Worker
get_uprobe_event(const std::string & binary_path,uint64_t offset,bpf_probe_attach_type type,pid_t pid)868*387f9dfdSAndroid Build Coastguard Worker std::string BPF::get_uprobe_event(const std::string& binary_path,
869*387f9dfdSAndroid Build Coastguard Worker uint64_t offset, bpf_probe_attach_type type,
870*387f9dfdSAndroid Build Coastguard Worker pid_t pid) {
871*387f9dfdSAndroid Build Coastguard Worker std::string res = attach_type_prefix(type) + "_";
872*387f9dfdSAndroid Build Coastguard Worker res += sanitize_str(binary_path, &BPF::uprobe_path_validator);
873*387f9dfdSAndroid Build Coastguard Worker res += "_0x" + uint_to_hex(offset);
874*387f9dfdSAndroid Build Coastguard Worker if (pid != -1)
875*387f9dfdSAndroid Build Coastguard Worker res += "_" + std::to_string(pid);
876*387f9dfdSAndroid Build Coastguard Worker if (res.size() > kEventNameSizeLimit) {
877*387f9dfdSAndroid Build Coastguard Worker return shorten_event_name(res);
878*387f9dfdSAndroid Build Coastguard Worker }
879*387f9dfdSAndroid Build Coastguard Worker return res;
880*387f9dfdSAndroid Build Coastguard Worker }
881*387f9dfdSAndroid Build Coastguard Worker
detach_kprobe_event(const std::string & event,open_probe_t & attr)882*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_kprobe_event(const std::string& event,
883*387f9dfdSAndroid Build Coastguard Worker open_probe_t& attr) {
884*387f9dfdSAndroid Build Coastguard Worker bpf_close_perf_event_fd(attr.perf_event_fd);
885*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(attr.func));
886*387f9dfdSAndroid Build Coastguard Worker if (bpf_detach_kprobe(event.c_str()) < 0)
887*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to detach kprobe %s", event.c_str());
888*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
889*387f9dfdSAndroid Build Coastguard Worker }
890*387f9dfdSAndroid Build Coastguard Worker
detach_uprobe_event(const std::string & event,open_probe_t & attr)891*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_uprobe_event(const std::string& event,
892*387f9dfdSAndroid Build Coastguard Worker open_probe_t& attr) {
893*387f9dfdSAndroid Build Coastguard Worker bpf_close_perf_event_fd(attr.perf_event_fd);
894*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(attr.func));
895*387f9dfdSAndroid Build Coastguard Worker if (bpf_detach_uprobe(event.c_str()) < 0)
896*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to detach uprobe %s", event.c_str());
897*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
898*387f9dfdSAndroid Build Coastguard Worker }
899*387f9dfdSAndroid Build Coastguard Worker
detach_tracepoint_event(const std::string & tracepoint,open_probe_t & attr)900*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_tracepoint_event(const std::string& tracepoint,
901*387f9dfdSAndroid Build Coastguard Worker open_probe_t& attr) {
902*387f9dfdSAndroid Build Coastguard Worker bpf_close_perf_event_fd(attr.perf_event_fd);
903*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(attr.func));
904*387f9dfdSAndroid Build Coastguard Worker
905*387f9dfdSAndroid Build Coastguard Worker // TODO: bpf_detach_tracepoint currently does nothing.
906*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
907*387f9dfdSAndroid Build Coastguard Worker }
908*387f9dfdSAndroid Build Coastguard Worker
detach_raw_tracepoint_event(const std::string & tracepoint,open_probe_t & attr)909*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_raw_tracepoint_event(const std::string& tracepoint,
910*387f9dfdSAndroid Build Coastguard Worker open_probe_t& attr) {
911*387f9dfdSAndroid Build Coastguard Worker TRY2(close(attr.perf_event_fd));
912*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(attr.func));
913*387f9dfdSAndroid Build Coastguard Worker
914*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
915*387f9dfdSAndroid Build Coastguard Worker }
916*387f9dfdSAndroid Build Coastguard Worker
detach_perf_event_all_cpu(open_probe_t & attr)917*387f9dfdSAndroid Build Coastguard Worker StatusTuple BPF::detach_perf_event_all_cpu(open_probe_t& attr) {
918*387f9dfdSAndroid Build Coastguard Worker bool has_error = false;
919*387f9dfdSAndroid Build Coastguard Worker std::string err_msg;
920*387f9dfdSAndroid Build Coastguard Worker for (const auto& it : *attr.per_cpu_fd) {
921*387f9dfdSAndroid Build Coastguard Worker int res = bpf_close_perf_event_fd(it.second);
922*387f9dfdSAndroid Build Coastguard Worker if (res != 0) {
923*387f9dfdSAndroid Build Coastguard Worker has_error = true;
924*387f9dfdSAndroid Build Coastguard Worker err_msg += "Failed to close perf event FD " + std::to_string(it.second) +
925*387f9dfdSAndroid Build Coastguard Worker " For CPU " + std::to_string(it.first) + ": ";
926*387f9dfdSAndroid Build Coastguard Worker err_msg += std::string(std::strerror(errno)) + "\n";
927*387f9dfdSAndroid Build Coastguard Worker }
928*387f9dfdSAndroid Build Coastguard Worker }
929*387f9dfdSAndroid Build Coastguard Worker delete attr.per_cpu_fd;
930*387f9dfdSAndroid Build Coastguard Worker TRY2(unload_func(attr.func));
931*387f9dfdSAndroid Build Coastguard Worker
932*387f9dfdSAndroid Build Coastguard Worker if (has_error)
933*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, err_msg);
934*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
935*387f9dfdSAndroid Build Coastguard Worker }
936*387f9dfdSAndroid Build Coastguard Worker
free_bcc_memory()937*387f9dfdSAndroid Build Coastguard Worker int BPF::free_bcc_memory() {
938*387f9dfdSAndroid Build Coastguard Worker return bcc_free_memory();
939*387f9dfdSAndroid Build Coastguard Worker }
940*387f9dfdSAndroid Build Coastguard Worker
USDT(const std::string & binary_path,const std::string & provider,const std::string & name,const std::string & probe_func)941*387f9dfdSAndroid Build Coastguard Worker USDT::USDT(const std::string& binary_path, const std::string& provider,
942*387f9dfdSAndroid Build Coastguard Worker const std::string& name, const std::string& probe_func)
943*387f9dfdSAndroid Build Coastguard Worker : initialized_(false),
944*387f9dfdSAndroid Build Coastguard Worker binary_path_(binary_path),
945*387f9dfdSAndroid Build Coastguard Worker pid_(-1),
946*387f9dfdSAndroid Build Coastguard Worker provider_(provider),
947*387f9dfdSAndroid Build Coastguard Worker name_(name),
948*387f9dfdSAndroid Build Coastguard Worker probe_func_(probe_func),
949*387f9dfdSAndroid Build Coastguard Worker mod_match_inode_only_(1) {}
950*387f9dfdSAndroid Build Coastguard Worker
USDT(pid_t pid,const std::string & provider,const std::string & name,const std::string & probe_func)951*387f9dfdSAndroid Build Coastguard Worker USDT::USDT(pid_t pid, const std::string& provider, const std::string& name,
952*387f9dfdSAndroid Build Coastguard Worker const std::string& probe_func)
953*387f9dfdSAndroid Build Coastguard Worker : initialized_(false),
954*387f9dfdSAndroid Build Coastguard Worker binary_path_(),
955*387f9dfdSAndroid Build Coastguard Worker pid_(pid),
956*387f9dfdSAndroid Build Coastguard Worker provider_(provider),
957*387f9dfdSAndroid Build Coastguard Worker name_(name),
958*387f9dfdSAndroid Build Coastguard Worker probe_func_(probe_func),
959*387f9dfdSAndroid Build Coastguard Worker mod_match_inode_only_(1) {}
960*387f9dfdSAndroid Build Coastguard Worker
USDT(const std::string & binary_path,pid_t pid,const std::string & provider,const std::string & name,const std::string & probe_func)961*387f9dfdSAndroid Build Coastguard Worker USDT::USDT(const std::string& binary_path, pid_t pid,
962*387f9dfdSAndroid Build Coastguard Worker const std::string& provider, const std::string& name,
963*387f9dfdSAndroid Build Coastguard Worker const std::string& probe_func)
964*387f9dfdSAndroid Build Coastguard Worker : initialized_(false),
965*387f9dfdSAndroid Build Coastguard Worker binary_path_(binary_path),
966*387f9dfdSAndroid Build Coastguard Worker pid_(pid),
967*387f9dfdSAndroid Build Coastguard Worker provider_(provider),
968*387f9dfdSAndroid Build Coastguard Worker name_(name),
969*387f9dfdSAndroid Build Coastguard Worker probe_func_(probe_func),
970*387f9dfdSAndroid Build Coastguard Worker mod_match_inode_only_(1) {}
971*387f9dfdSAndroid Build Coastguard Worker
USDT(const USDT & usdt)972*387f9dfdSAndroid Build Coastguard Worker USDT::USDT(const USDT& usdt)
973*387f9dfdSAndroid Build Coastguard Worker : initialized_(false),
974*387f9dfdSAndroid Build Coastguard Worker binary_path_(usdt.binary_path_),
975*387f9dfdSAndroid Build Coastguard Worker pid_(usdt.pid_),
976*387f9dfdSAndroid Build Coastguard Worker provider_(usdt.provider_),
977*387f9dfdSAndroid Build Coastguard Worker name_(usdt.name_),
978*387f9dfdSAndroid Build Coastguard Worker probe_func_(usdt.probe_func_),
979*387f9dfdSAndroid Build Coastguard Worker mod_match_inode_only_(usdt.mod_match_inode_only_) {}
980*387f9dfdSAndroid Build Coastguard Worker
USDT(USDT && usdt)981*387f9dfdSAndroid Build Coastguard Worker USDT::USDT(USDT&& usdt) noexcept
982*387f9dfdSAndroid Build Coastguard Worker : initialized_(usdt.initialized_),
983*387f9dfdSAndroid Build Coastguard Worker binary_path_(std::move(usdt.binary_path_)),
984*387f9dfdSAndroid Build Coastguard Worker pid_(usdt.pid_),
985*387f9dfdSAndroid Build Coastguard Worker provider_(std::move(usdt.provider_)),
986*387f9dfdSAndroid Build Coastguard Worker name_(std::move(usdt.name_)),
987*387f9dfdSAndroid Build Coastguard Worker probe_func_(std::move(usdt.probe_func_)),
988*387f9dfdSAndroid Build Coastguard Worker probe_(std::move(usdt.probe_)),
989*387f9dfdSAndroid Build Coastguard Worker program_text_(std::move(usdt.program_text_)),
990*387f9dfdSAndroid Build Coastguard Worker mod_match_inode_only_(usdt.mod_match_inode_only_) {
991*387f9dfdSAndroid Build Coastguard Worker usdt.initialized_ = false;
992*387f9dfdSAndroid Build Coastguard Worker }
993*387f9dfdSAndroid Build Coastguard Worker
operator ==(const USDT & other) const994*387f9dfdSAndroid Build Coastguard Worker bool USDT::operator==(const USDT& other) const {
995*387f9dfdSAndroid Build Coastguard Worker return (provider_ == other.provider_) && (name_ == other.name_) &&
996*387f9dfdSAndroid Build Coastguard Worker (binary_path_ == other.binary_path_) && (pid_ == other.pid_) &&
997*387f9dfdSAndroid Build Coastguard Worker (probe_func_ == other.probe_func_);
998*387f9dfdSAndroid Build Coastguard Worker }
999*387f9dfdSAndroid Build Coastguard Worker
set_probe_matching_kludge(uint8_t kludge)1000*387f9dfdSAndroid Build Coastguard Worker int USDT::set_probe_matching_kludge(uint8_t kludge) {
1001*387f9dfdSAndroid Build Coastguard Worker if (kludge != 0 && kludge != 1)
1002*387f9dfdSAndroid Build Coastguard Worker return -1;
1003*387f9dfdSAndroid Build Coastguard Worker
1004*387f9dfdSAndroid Build Coastguard Worker mod_match_inode_only_ = kludge;
1005*387f9dfdSAndroid Build Coastguard Worker return 0;
1006*387f9dfdSAndroid Build Coastguard Worker }
1007*387f9dfdSAndroid Build Coastguard Worker
init()1008*387f9dfdSAndroid Build Coastguard Worker StatusTuple USDT::init() {
1009*387f9dfdSAndroid Build Coastguard Worker std::unique_ptr<::USDT::Context> ctx;
1010*387f9dfdSAndroid Build Coastguard Worker if (!binary_path_.empty() && pid_ > 0)
1011*387f9dfdSAndroid Build Coastguard Worker ctx.reset(new ::USDT::Context(pid_, binary_path_, mod_match_inode_only_));
1012*387f9dfdSAndroid Build Coastguard Worker else if (!binary_path_.empty())
1013*387f9dfdSAndroid Build Coastguard Worker ctx.reset(new ::USDT::Context(binary_path_, mod_match_inode_only_));
1014*387f9dfdSAndroid Build Coastguard Worker else if (pid_ > 0)
1015*387f9dfdSAndroid Build Coastguard Worker ctx.reset(new ::USDT::Context(pid_, mod_match_inode_only_));
1016*387f9dfdSAndroid Build Coastguard Worker else
1017*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "No valid Binary Path or PID provided");
1018*387f9dfdSAndroid Build Coastguard Worker
1019*387f9dfdSAndroid Build Coastguard Worker if (!ctx->loaded())
1020*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to load USDT " + print_name());
1021*387f9dfdSAndroid Build Coastguard Worker
1022*387f9dfdSAndroid Build Coastguard Worker auto deleter = [](void* probe) { delete static_cast<::USDT::Probe*>(probe); };
1023*387f9dfdSAndroid Build Coastguard Worker for (auto& p : ctx->probes_) {
1024*387f9dfdSAndroid Build Coastguard Worker if (p->provider_ == provider_ && p->name_ == name_) {
1025*387f9dfdSAndroid Build Coastguard Worker // Take ownership of the probe that we are interested in, and avoid it
1026*387f9dfdSAndroid Build Coastguard Worker // being destructed when we destruct the USDT::Context instance
1027*387f9dfdSAndroid Build Coastguard Worker probe_ = std::unique_ptr<void, std::function<void(void*)>>(p.release(),
1028*387f9dfdSAndroid Build Coastguard Worker deleter);
1029*387f9dfdSAndroid Build Coastguard Worker p.swap(ctx->probes_.back());
1030*387f9dfdSAndroid Build Coastguard Worker ctx->probes_.pop_back();
1031*387f9dfdSAndroid Build Coastguard Worker break;
1032*387f9dfdSAndroid Build Coastguard Worker }
1033*387f9dfdSAndroid Build Coastguard Worker }
1034*387f9dfdSAndroid Build Coastguard Worker if (!probe_)
1035*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(-1, "Unable to find USDT " + print_name());
1036*387f9dfdSAndroid Build Coastguard Worker ctx.reset(nullptr);
1037*387f9dfdSAndroid Build Coastguard Worker auto& probe = *static_cast<::USDT::Probe*>(probe_.get());
1038*387f9dfdSAndroid Build Coastguard Worker
1039*387f9dfdSAndroid Build Coastguard Worker std::ostringstream stream;
1040*387f9dfdSAndroid Build Coastguard Worker if (!probe.usdt_getarg(stream, probe_func_))
1041*387f9dfdSAndroid Build Coastguard Worker return StatusTuple(
1042*387f9dfdSAndroid Build Coastguard Worker -1, "Unable to generate program text for USDT " + print_name());
1043*387f9dfdSAndroid Build Coastguard Worker program_text_ = ::USDT::USDT_PROGRAM_HEADER + stream.str();
1044*387f9dfdSAndroid Build Coastguard Worker
1045*387f9dfdSAndroid Build Coastguard Worker initialized_ = true;
1046*387f9dfdSAndroid Build Coastguard Worker return StatusTuple::OK();
1047*387f9dfdSAndroid Build Coastguard Worker }
1048*387f9dfdSAndroid Build Coastguard Worker
1049*387f9dfdSAndroid Build Coastguard Worker } // namespace ebpf
1050