Commit 8e8d6467 authored by Alastair Robertson's avatar Alastair Robertson

Support for attaching probes to kernel tracepoints

parent 02d6031a
......@@ -138,11 +138,14 @@ public:
using AttachPointList = std::vector<std::string>;
class Probe : public Node {
public:
// BEGIN/END
Probe(const std::string &type, Predicate *pred, StatementList *stmts)
: type(type), attach_points(new AttachPointList), pred(pred), stmts(stmts) { }
// kprobe
Probe(const std::string &type, AttachPointList *attach_points,
Predicate *pred, StatementList *stmts)
: type(type), attach_points(attach_points), pred(pred), stmts(stmts) { }
// uprobe, tracepoint
Probe(const std::string &type, const std::string &path,
AttachPointList *attach_points, Predicate *pred, StatementList *stmts)
: type(type), path(path), attach_points(attach_points), pred(pred), stmts(stmts) { }
......
......@@ -27,10 +27,11 @@ bpf_prog_type progtype(ProbeType t)
{
switch (t)
{
case ProbeType::kprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::kretprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::uprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::uretprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::kprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::kretprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::uprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::uretprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::tracepoint: return BPF_PROG_TYPE_TRACEPOINT; break;
default: abort();
}
}
......@@ -50,6 +51,9 @@ AttachedProbe::AttachedProbe(Probe &probe, std::tuple<uint8_t *, uintptr_t> &fun
case ProbeType::uretprobe:
attach_uprobe();
break;
case ProbeType::tracepoint:
attach_tracepoint();
break;
default:
abort();
}
......@@ -70,6 +74,9 @@ AttachedProbe::~AttachedProbe()
case ProbeType::uretprobe:
err = bpf_detach_uprobe(eventname().c_str());
break;
case ProbeType::tracepoint:
err = bpf_detach_tracepoint(probe_.path.c_str(), eventname().c_str());
break;
default:
abort();
}
......@@ -102,6 +109,8 @@ std::string AttachedProbe::eventname() const
case ProbeType::uretprobe:
offset_str << std::hex << offset();
return eventprefix() + sanitise(probe_.path) + "_" + offset_str.str();
case ProbeType::tracepoint:
return probe_.attach_point;
default:
abort();
}
......@@ -182,4 +191,19 @@ void AttachedProbe::attach_uprobe()
throw std::runtime_error("Error attaching probe: " + probe_.name);
}
void AttachedProbe::attach_tracepoint()
{
int pid = -1;
int cpu = 0;
int group_fd = -1;
perf_reader_cb cb = nullptr;
void *cb_cookie = nullptr;
perf_reader_ = bpf_attach_tracepoint(progfd_, probe_.path.c_str(),
eventname().c_str(), pid, cpu, group_fd, cb, cb_cookie);
if (perf_reader_ == nullptr)
throw std::runtime_error("Error attaching probe: " + probe_.name);
}
} // namespace bpftrace
......@@ -25,6 +25,7 @@ private:
void load_prog();
void attach_kprobe();
void attach_uprobe();
void attach_tracepoint();
Probe &probe_;
std::tuple<uint8_t *, uintptr_t> &func_;
......
......@@ -48,7 +48,9 @@ void SemanticAnalyser::visit(Builtin &builtin)
}
else if (builtin.ident == "func") {
ProbeType type = probetype(probe_->type);
if (type == ProbeType::kprobe || type == ProbeType::kretprobe)
if (type == ProbeType::kprobe ||
type == ProbeType::kretprobe ||
type == ProbeType::tracepoint)
builtin.type = SizedType(Type::sym, 8);
else if (type == ProbeType::uprobe || type == ProbeType::uretprobe)
builtin.type = SizedType(Type::usym, 8);
......@@ -333,6 +335,12 @@ void SemanticAnalyser::visit(Probe &probe)
if (probe.path == "")
err_ << "uprobes must have a path" << std::endl;
}
else if (probe.type == "tracepoint") {
if (probe.attach_points->size() == 0)
err_ << "tracepoint probe must have an event" << std::endl;
if (probe.path == "")
err_ << "tracepoint probe must have a category" << std::endl;
}
else if (probe.type == "BEGIN" || probe.type == "END") {
if (probe.attach_points->size() != 0)
err_ << "BEGIN/END probes should not have an attachment point" << std::endl;
......
......@@ -52,6 +52,8 @@ ProbeType probetype(const std::string &type)
return ProbeType::uprobe;
else if (type == "END")
return ProbeType::uprobe;
else if (type == "tracepoint")
return ProbeType::tracepoint;
return ProbeType::invalid;
}
......
......@@ -47,6 +47,7 @@ enum class ProbeType
kretprobe,
uprobe,
uretprobe,
tracepoint,
};
std::string typestr(Type t);
......
......@@ -172,6 +172,30 @@ TEST(bpftrace, add_probes_uprobe_wildcard)
EXPECT_EQ(bpftrace.get_special_probes().size(), 0);
}
TEST(bpftrace, add_probes_tracepoint)
{
ast::AttachPointList attach_points = {"sched_switch"};
ast::Probe probe("tracepoint", "sched", &attach_points, nullptr, nullptr);
StrictMock<MockBPFtrace> bpftrace;
EXPECT_EQ(bpftrace.add_probe(probe), 0);
EXPECT_EQ(bpftrace.get_probes().size(), 1);
EXPECT_EQ(bpftrace.get_special_probes().size(), 0);
}
TEST(bpftrace, add_probes_tracepoint_wildcard)
{
ast::AttachPointList attach_points = {"sched_*"};
ast::Probe probe("tracepoint", "sched", &attach_points, nullptr, nullptr);
StrictMock<MockBPFtrace> bpftrace;
EXPECT_NE(bpftrace.add_probe(probe), 0);
EXPECT_EQ(bpftrace.get_probes().size(), 0);
EXPECT_EQ(bpftrace.get_special_probes().size(), 0);
}
} // namespace bpftrace
} // namespace test
} // namespace bpftrace
......@@ -220,7 +220,7 @@ TEST(Parser, begin_probe)
" int: 1\n");
}
TEST(Parser, multiple_attach_points)
TEST(Parser, multiple_attach_points_kprobe)
{
test("kprobe:sys_open,sys_close { 1 }",
"Program\n"
......@@ -228,6 +228,22 @@ TEST(Parser, multiple_attach_points)
" int: 1\n");
}
TEST(Parser, multiple_attach_points_uprobe)
{
test("uprobe:/bin/sh:foo,bar { 1 }",
"Program\n"
" uprobe:/bin/sh:foo,bar\n"
" int: 1\n");
}
TEST(Parser, multiple_attach_points_tracepoint)
{
test("tracepoint:syscalls:sys_enter_* { 1 }",
"Program\n"
" tracepoint:syscalls:sys_enter_*\n"
" int: 1\n");
}
TEST(Parser, wildcard_attach_points)
{
test("kprobe:sys_* { 1 }",
......
......@@ -222,6 +222,13 @@ TEST(semantic_analyser, begin_end_probes)
test("END { 1 } END { 2 }", 10);
}
TEST(semantic_analyser, tracepoint)
{
test("tracepoint:category:event { 1 }", 0);
test("tracepoint:f { 1 }", 1);
test("tracepoint { 1 }", 1);
}
} // namespace semantic_analyser
} // namespace test
} // namespace bpftrace
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment