#include
#include
#include
#include
#include "attached_probe.h"
#include "bpfprogram.h"
#include "log.h"
#include "util/exceptions.h"
#include "util/fd.h"
namespace bpftrace {
BpfProgram::BpfProgram(struct bpf_program *bpf_prog) : bpf_prog_(bpf_prog)
{
}
int BpfProgram::fd() const
{
return bpf_program__fd(bpf_prog_);
}
void BpfProgram::set_prog_type(const Probe &probe)
{
auto prog_type = progtype(probe.type);
bpf_program__set_type(bpf_prog_, prog_type);
}
void BpfProgram::set_expected_attach_type(const Probe &probe,
BPFfeature &feature)
{
auto attach_type = static_cast(0);
if (probe.type == ProbeType::fentry)
attach_type = BPF_TRACE_FENTRY;
else if (probe.type == ProbeType::fexit)
attach_type = BPF_TRACE_FEXIT;
else if (probe.type == ProbeType::iter)
attach_type = BPF_TRACE_ITER;
else if (probe.type == ProbeType::rawtracepoint)
attach_type = BPF_TRACE_RAW_TP;
// We want to avoid kprobe_multi when a module is specified
// because the BPF_TRACE_KPROBE_MULTI link type does not
// currently support the `module:function` syntax.
if ((probe.type == ProbeType::kprobe || probe.type == ProbeType::kretprobe) &&
!probe.funcs.empty() && probe.path.empty()) {
if (probe.is_session && feature.has_kprobe_session())
attach_type = BPF_TRACE_KPROBE_SESSION;
else if (feature.has_kprobe_multi())
attach_type = BPF_TRACE_KPROBE_MULTI;
}
if (feature.has_uprobe_multi() && (((probe.type == ProbeType::uprobe ||
probe.type == ProbeType::uretprobe) &&
!probe.funcs.empty()) ||
probe.type == ProbeType::usdt)) {
attach_type = BPF_TRACE_UPROBE_MULTI;
}
bpf_program__set_expected_attach_type(bpf_prog_, attach_type);
}
void BpfProgram::set_attach_target(const Probe &probe,
const BTF &btf,
const Config &config)
{
if (probe.type != ProbeType::fentry && probe.type != ProbeType::fexit &&
probe.type != ProbeType::iter && probe.type != ProbeType::rawtracepoint)
return;
const std::string &mod = probe.path;
const std::string &fun = probe.attach_point;
std::string attach_target = !mod.empty() ? mod + ":" + fun : fun;
std::string btf_fun;
__u32 btf_kind = BTF_KIND_FUNC;
if (probe.type == ProbeType::iter) {
btf_fun = "bpf_iter_" + fun;
} else if (probe.type == ProbeType::rawtracepoint) {
btf_fun = "btf_trace_" + fun;
btf_kind = BTF_KIND_TYPEDEF;
} else {
btf_fun = fun;
}
std::string err_msg;
if ((probe.type == ProbeType::fentry || probe.type == ProbeType::fexit) &&
mod == "bpf") {
int raw_fd = bpf_prog_get_fd_by_id(static_cast<__u32>(probe.bpf_prog_id));
if (raw_fd < 0) {
err_msg = "No valid BPF program found with name: " + fun +
" and id: " + std::to_string(probe.bpf_prog_id) + ".";
} else {
bpf_prog_fd_ = util::FD(raw_fd);
attach_target = fun;
}
} else if (btf.get_btf_id(btf_fun, mod, btf_kind) < 0) {
err_msg = "No BTF found for " + attach_target + ".";
}
if (!err_msg.empty()) {
if (config.missing_probes == ConfigMissingProbes::error) {
LOG(ERROR) << err_msg;
} else if (config.missing_probes == ConfigMissingProbes::warn) {
LOG(WARNING) << err_msg;
}
bpf_program__set_autoload(bpf_prog_, false);
}
bpf_program__set_attach_target(bpf_prog_,
bpf_prog_fd_ ? *bpf_prog_fd_ : 0,
attach_target.c_str());
}
void BpfProgram::set_no_autoattach()
{
bpf_program__set_autoattach(bpf_prog_, false);
}
void BpfProgram::set_no_autoload()
{
bpf_program__set_autoload(bpf_prog_, false);
}
struct bpf_program *BpfProgram::bpf_prog() const
{
return bpf_prog_;
}
} // namespace bpftrace