Skip to content

Commit

Permalink
Add support to attach uprobe_multi
Browse files Browse the repository at this point in the history
Signed-off-by: Jiri Olsa <[email protected]>
  • Loading branch information
olsajiri committed Oct 22, 2023
1 parent ff11848 commit d1672f6
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 1 deletion.
109 changes: 108 additions & 1 deletion src/attached_probe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define _GNU_SOURCE
#endif

#include <algorithm>
#include <cstring>
#include <elf.h>
#include <fcntl.h>
Expand All @@ -21,6 +22,7 @@
#include <bcc/bcc_syms.h>
#include <bcc/bcc_usdt.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>

#include "attached_probe.h"
#include "bpftrace.h"
Expand Down Expand Up @@ -761,10 +763,14 @@ void AttachedProbe::load_prog(BPFfeature &feature)
opts.expected_attach_type = static_cast<::bpf_attach_type>(
libbpf::BPF_TRACE_ITER);

if (feature.has_kprobe_multi() && !probe_.funcs.empty())
if (feature.has_kprobe_multi() && !probe_.funcs.empty() && probe_.type == ProbeType::kprobe)
opts.expected_attach_type = static_cast<::bpf_attach_type>(
libbpf::BPF_TRACE_KPROBE_MULTI);

if (feature.has_uprobe_multi() && !probe_.funcs.empty() && probe_.type == ProbeType::uprobe)
opts.expected_attach_type = static_cast<::bpf_attach_type>(
libbpf::BPF_TRACE_UPROBE_MULTI);

if (probe_.type == ProbeType::kfunc ||
probe_.type == ProbeType::kretfunc || probe_.type == ProbeType::iter)
{
Expand Down Expand Up @@ -960,8 +966,109 @@ void AttachedProbe::attach_kprobe(bool safe_mode)
perf_event_fds_.push_back(perf_event_fd);
}

struct bcc_sym_cb_data
{
std::vector<std::string> &syms;
std::set<uint64_t> &offsets;
};

static int bcc_sym_cb(const char *symname, uint64_t start, uint64_t, void *p)
{
struct bcc_sym_cb_data *data = static_cast<struct bcc_sym_cb_data *>(p);
std::vector<std::string> &syms = data->syms;

if (std::binary_search(syms.begin(), syms.end(), symname))
{
data->offsets.insert(start);
}

return 0;
}

void AttachedProbe::attach_multi_uprobe(void)
{
struct bcc_symbol_option option = {};
std::vector<std::string> syms;
unsigned int i;
int err;

for (i = 0; i < probe_.funcs.size(); i++)
{
auto pos = probe_.funcs[i].find(':');

if (pos == std::string::npos)
{
throw std::runtime_error("Error resolving probe: '" + probe_.name + "'");
}

syms.push_back(probe_.funcs[i].c_str() + pos + 1);
}

std::sort(std::begin(syms), std::end(syms));

option.use_debug_file = 1;
option.use_symbol_type = 0xffffffff;

std::vector<uint64_t> offsets;
std::set<uint64_t> set;
struct bcc_sym_cb_data data = {
.syms = syms,
.offsets = set,
};

err = bcc_elf_foreach_sym(probe_.path.c_str(), bcc_sym_cb, &option, &data);
if (err)
{
throw std::runtime_error("Failed to list symbols for probe: '" +
probe_.name + "'");
}

for (auto a : set)
{
offsets.push_back(a);
}

DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);

opts.uprobe_multi.path = probe_.path.c_str();
opts.uprobe_multi.offsets = &offsets[0];
opts.uprobe_multi.cnt = offsets.size();
opts.uprobe_multi.flags = probe_.type == ProbeType::uretprobe
? BPF_F_UPROBE_MULTI_RETURN
: 0;
if (bt_verbose)
{
std::cout << "Attaching to " << probe_.funcs.size() << " functions"
<< std::endl;

if (bt_verbose2)
{
for (i = 0; i < syms.size(); i++)
{
std::cout << probe_.path << ":" << syms[i] << std::endl;
}
}
}

linkfd_ = bpf_link_create(progfd_,
0,
static_cast<enum ::bpf_attach_type>(
libbpf::BPF_TRACE_UPROBE_MULTI),
&opts);
if (linkfd_ < 0)
{
throw std::runtime_error("Error attaching probe: '" + probe_.name + "'");
}
}

void AttachedProbe::attach_uprobe(bool safe_mode)
{
if (!probe_.funcs.empty())
{
attach_multi_uprobe();
return;
}

if (!resolve_offset_uprobe(safe_mode))
return;

Expand Down
1 change: 1 addition & 0 deletions src/attached_probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class AttachedProbe
bool resolve_offset_uprobe(bool safe_mode);
void load_prog(BPFfeature &feature);
void attach_multi_kprobe(void);
void attach_multi_uprobe(void);
void attach_kprobe(bool safe_mode);
void attach_uprobe(bool safe_mode);

Expand Down
20 changes: 20 additions & 0 deletions src/bpftrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,26 @@ int BPFtrace::add_probe(ast::Probe &p)
resources.probes.push_back(probe);
continue;
}

if (feature_->has_uprobe_multi() && has_wildcard(attach_point->func) &&
!p.need_expansion && attach_funcs.size() &&
(probetype(attach_point->provider) == ProbeType::uprobe ||
probetype(attach_point->provider) == ProbeType::uretprobe))
{
Probe probe;
probe.attach_point = attach_point->func;
probe.path = attach_point->target;
probe.type = probetype(attach_point->provider);
probe.log_size = log_size_;
probe.orig_name = p.name();
probe.name = attach_point->name(attach_point->target,
attach_point->func);
probe.index = p.index();
probe.funcs.assign(attach_funcs.begin(), attach_funcs.end());

resources.probes.push_back(probe);
continue;
}
}
else if ((probetype(attach_point->provider) == ProbeType::uprobe ||
probetype(attach_point->provider) == ProbeType::uretprobe ||
Expand Down

0 comments on commit d1672f6

Please sign in to comment.