Commit b67f5598 authored by Alastair Robertson's avatar Alastair Robertson

Allow wildcard tracepoints and multiple attach points from different providers on a single probe

tracepoint:random:*_read { ... }
kprobe:sys_read, uprobe:/bin/bash:readline { ... }
parent 1c3a29d7
...@@ -113,7 +113,7 @@ Tracepoints are guaranteed to be stable between kernel versions, unlike kprobes. ...@@ -113,7 +113,7 @@ Tracepoints are guaranteed to be stable between kernel versions, unlike kprobes.
### Multiple attachment points ### Multiple attachment points
More than one function/tracepoint can be specified for a single probe: More than one function/tracepoint can be specified for a single probe:
`kprobe:sys_read,sys_write { ... }` `kprobe:sys_read,kprobe:sys_write { ... }`
### Wildcards ### Wildcards
Some probe types allow wildcards to be used when attaching a probe: Some probe types allow wildcards to be used when attaching a probe:
......
...@@ -52,6 +52,10 @@ void Predicate::accept(Visitor &v) { ...@@ -52,6 +52,10 @@ void Predicate::accept(Visitor &v) {
v.visit(*this); v.visit(*this);
} }
void AttachPoint::accept(Visitor &v) {
v.visit(*this);
}
void Probe::accept(Visitor &v) { void Probe::accept(Visitor &v) {
v.visit(*this); v.visit(*this);
} }
...@@ -93,27 +97,30 @@ std::string opstr(Unop &unop) ...@@ -93,27 +97,30 @@ std::string opstr(Unop &unop)
} }
} }
std::string AttachPoint::name(const std::string &attach_point) const
{
std::string n = provider;
if (target != "")
n += ":" + target;
if (attach_point != "")
n += ":" + attach_point;
return n;
}
std::string Probe::name() const std::string Probe::name() const
{ {
std::string n = type; std::string n = "";
if (path != "") for (auto attach_point : *attach_points)
n += ":" + path;
n += ":";
for (std::string attach_point : *attach_points)
{ {
n += attach_point + ","; n += attach_point->provider;
if (attach_point->target != "")
n += ":" + attach_point->target;
if (attach_point->func != "")
n += ":" + attach_point->func;
n += ",";
} }
return n.substr(0, n.size()-1); return n.substr(0, n.size()-1);
} }
std::string Probe::name(const std::string &attach_point) const
{
std::string n = type;
if (path != "")
n += ":" + path;
n += ":" + attach_point;
return n;
}
} // namespace ast } // namespace ast
} // namespace bpftrace } // namespace bpftrace
...@@ -136,30 +136,38 @@ public: ...@@ -136,30 +136,38 @@ public:
void accept(Visitor &v) override; void accept(Visitor &v) override;
}; };
using AttachPointList = std::vector<std::string>; class AttachPoint : public Node {
public:
explicit AttachPoint(const std::string &provider)
: provider(provider) { }
AttachPoint(const std::string &provider,
const std::string &func)
: provider(provider), func(func) { }
AttachPoint(const std::string &provider,
const std::string &target,
const std::string &func)
: provider(provider), target(target), func(func) { }
std::string provider;
std::string target;
std::string func;
void accept(Visitor &v) override;
std::string name(const std::string &attach_point) const;
};
using AttachPointList = std::vector<AttachPoint *>;
class Probe : public Node { class Probe : public Node {
public: public:
// BEGIN/END Probe(AttachPointList *attach_points, Predicate *pred, StatementList *stmts)
Probe(const std::string &type, Predicate *pred, StatementList *stmts) : attach_points(attach_points), pred(pred), stmts(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) { }
std::string type;
std::string path;
AttachPointList *attach_points; AttachPointList *attach_points;
Predicate *pred; Predicate *pred;
StatementList *stmts; StatementList *stmts;
void accept(Visitor &v) override; void accept(Visitor &v) override;
std::string name() const; std::string name() const;
std::string name(const std::string &attach_point) const;
}; };
using ProbeList = std::vector<Probe *>; using ProbeList = std::vector<Probe *>;
...@@ -186,6 +194,7 @@ public: ...@@ -186,6 +194,7 @@ public:
virtual void visit(AssignMapStatement &assignment) = 0; virtual void visit(AssignMapStatement &assignment) = 0;
virtual void visit(AssignVarStatement &assignment) = 0; virtual void visit(AssignVarStatement &assignment) = 0;
virtual void visit(Predicate &pred) = 0; virtual void visit(Predicate &pred) = 0;
virtual void visit(AttachPoint &ap) = 0;
virtual void visit(Probe &probe) = 0; virtual void visit(Probe &probe) = 0;
virtual void visit(Program &program) = 0; virtual void visit(Program &program) = 0;
}; };
......
#include <assert.h>
#include <fstream> #include <fstream>
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
...@@ -16,73 +17,82 @@ namespace bpftrace { ...@@ -16,73 +17,82 @@ namespace bpftrace {
int BPFtrace::add_probe(ast::Probe &p) int BPFtrace::add_probe(ast::Probe &p)
{ {
if (p.type == "BEGIN") for (auto attach_point : *p.attach_points)
{
Probe probe;
probe.path = "/proc/self/exe";
probe.attach_point = "BEGIN_trigger";
probe.type = probetype(p.type);
probe.prog_name = p.name();
probe.name = p.name();
special_probes_.push_back(probe);
return 0;
}
else if (p.type == "END")
{ {
Probe probe; if (attach_point->provider == "BEGIN")
probe.path = "/proc/self/exe"; {
probe.attach_point = "END_trigger"; Probe probe;
probe.type = probetype(p.type); probe.path = "/proc/self/exe";
probe.prog_name = p.name(); probe.attach_point = "BEGIN_trigger";
probe.name = p.name(); probe.type = probetype(attach_point->provider);
special_probes_.push_back(probe); probe.prog_name = p.name();
return 0; probe.name = p.name();
} special_probes_.push_back(probe);
continue;
}
else if (attach_point->provider == "END")
{
Probe probe;
probe.path = "/proc/self/exe";
probe.attach_point = "END_trigger";
probe.type = probetype(attach_point->provider);
probe.prog_name = p.name();
probe.name = p.name();
special_probes_.push_back(probe);
continue;
}
ast::AttachPointList expanded_attach_points; std::vector<std::string> attach_funcs;
for (std::string attach_point : *p.attach_points) if (attach_point->func.find("*") != std::string::npos)
{
if (attach_point.find("*") != std::string::npos)
{ {
std::string file_name; std::string file_name;
switch (probetype(p.type)) switch (probetype(attach_point->provider))
{ {
case ProbeType::kprobe: case ProbeType::kprobe:
case ProbeType::kretprobe: case ProbeType::kretprobe:
file_name = "/sys/kernel/debug/tracing/available_filter_functions"; file_name = "/sys/kernel/debug/tracing/available_filter_functions";
break; break;
case ProbeType::tracepoint:
file_name = "/sys/kernel/debug/tracing/available_events";
break;
default: default:
std::cerr << "Wildcard matches aren't available on probe type '" std::cerr << "Wildcard matches aren't available on probe type '"
<< p.type << "'" << std::endl; << attach_point->provider << "'" << std::endl;
return 1; return 1;
} }
auto matches = find_wildcard_matches(attach_point, file_name); auto matches = find_wildcard_matches(attach_point->target,
expanded_attach_points.insert(expanded_attach_points.end(), attach_point->func,
matches.begin(), matches.end()); file_name);
continue; attach_funcs.insert(attach_funcs.end(), matches.begin(), matches.end());
}
else
{
attach_funcs.push_back(attach_point->func);
} }
expanded_attach_points.push_back(attach_point); for (auto func : attach_funcs)
{
Probe probe;
probe.path = attach_point->target;
probe.attach_point = func;
probe.type = probetype(attach_point->provider);
probe.prog_name = p.name();
probe.name = attach_point->name(func);
probes_.push_back(probe);
}
} }
for (std::string attach_point : expanded_attach_points)
{
Probe probe;
probe.path = p.path;
probe.attach_point = attach_point;
probe.type = probetype(p.type);
probe.prog_name = p.name();
probe.name = p.name(attach_point);
probes_.push_back(probe);
}
return 0; return 0;
} }
std::set<std::string> BPFtrace::find_wildcard_matches(std::string attach_point, std::string file_name) std::set<std::string> BPFtrace::find_wildcard_matches(const std::string &prefix, const std::string &func, const std::string &file_name)
{ {
// Turn glob into a regex // Turn glob into a regex
attach_point = "^" + std::regex_replace(attach_point, std::regex("\\*"), "[^\\s]*"); auto regex_str = "(" + std::regex_replace(func, std::regex("\\*"), "[^\\s]*") + ")";
std::regex attach_point_regex(attach_point); if (prefix != "")
regex_str = prefix + ":" + regex_str;
regex_str = "^" + regex_str;
std::regex func_regex(regex_str);
std::smatch match; std::smatch match;
std::ifstream file(file_name); std::ifstream file(file_name);
...@@ -90,9 +100,10 @@ std::set<std::string> BPFtrace::find_wildcard_matches(std::string attach_point, ...@@ -90,9 +100,10 @@ std::set<std::string> BPFtrace::find_wildcard_matches(std::string attach_point,
std::set<std::string> matches; std::set<std::string> matches;
while (std::getline(file, line)) while (std::getline(file, line))
{ {
if (std::regex_search(line, match, attach_point_regex)) if (std::regex_search(line, match, func_regex))
{ {
matches.insert(match[0]); assert(match.size() == 2);
matches.insert(match[1]);
} }
} }
return matches; return matches;
......
...@@ -38,7 +38,7 @@ public: ...@@ -38,7 +38,7 @@ public:
std::vector<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> &values_by_key); std::vector<std::pair<std::vector<uint8_t>, std::vector<uint8_t>>> &values_by_key);
protected: protected:
virtual std::set<std::string> find_wildcard_matches(std::string attach_point, std::string file_name); virtual std::set<std::string> find_wildcard_matches(const std::string &prefix, const std::string &attach_point, const std::string &file_name);
std::vector<Probe> probes_; std::vector<Probe> probes_;
std::vector<Probe> special_probes_; std::vector<Probe> special_probes_;
......
...@@ -370,6 +370,11 @@ void CodegenLLVM::visit(Predicate &pred) ...@@ -370,6 +370,11 @@ void CodegenLLVM::visit(Predicate &pred)
b_.SetInsertPoint(pred_true_block); b_.SetInsertPoint(pred_true_block);
} }
void CodegenLLVM::visit(AttachPoint &)
{
// Empty
}
void CodegenLLVM::visit(Probe &probe) void CodegenLLVM::visit(Probe &probe)
{ {
FunctionType *func_type = FunctionType::get( FunctionType *func_type = FunctionType::get(
......
...@@ -39,6 +39,7 @@ public: ...@@ -39,6 +39,7 @@ public:
void visit(AssignMapStatement &assignment) override; void visit(AssignMapStatement &assignment) override;
void visit(AssignVarStatement &assignment) override; void visit(AssignVarStatement &assignment) override;
void visit(Predicate &pred) override; void visit(Predicate &pred) override;
void visit(AttachPoint &ap) override;
void visit(Probe &probe) override; void visit(Probe &probe) override;
void visit(Program &program) override; void visit(Program &program) override;
AllocaInst *getMapKey(Map &map); AllocaInst *getMapKey(Map &map);
......
...@@ -85,7 +85,8 @@ void yyerror(bpftrace::Driver &driver, const char *s); ...@@ -85,7 +85,8 @@ void yyerror(bpftrace::Driver &driver, const char *s);
%type <ast::Variable *> var %type <ast::Variable *> var
%type <ast::ExpressionList *> vargs %type <ast::ExpressionList *> vargs
%type <ast::AttachPointList *> attach_points %type <ast::AttachPointList *> attach_points
%type <std::string> attach_point %type <ast::AttachPoint *> attach_point
%type <std::string> wildcard
%right ASSIGN %right ASSIGN
%left LOR %left LOR
...@@ -110,21 +111,23 @@ probes : probes probe { $$ = $1; $1->push_back($2); } ...@@ -110,21 +111,23 @@ probes : probes probe { $$ = $1; $1->push_back($2); }
| probe { $$ = new ast::ProbeList; $$->push_back($1); } | probe { $$ = new ast::ProbeList; $$->push_back($1); }
; ;
probe : IDENT pred block { $$ = new ast::Probe($1, $2, $3); } probe : attach_points pred block { $$ = new ast::Probe($1, $2, $3); }
| IDENT ":" attach_points pred block { $$ = new ast::Probe($1, $3, $4, $5); }
| IDENT PATH attach_points pred block { $$ = new ast::Probe($1, $2.substr(1, $2.size()-2), $3, $4, $5); }
; ;
attach_points : attach_points "," attach_point { $$ = $1; $1->push_back($3); } attach_points : attach_points "," attach_point { $$ = $1; $1->push_back($3); }
| attach_point { $$ = new ast::AttachPointList; $$->push_back($1); } | attach_point { $$ = new ast::AttachPointList; $$->push_back($1); }
; ;
attach_point : attach_point IDENT { $$ = $1 + $2; } attach_point : IDENT { $$ = new ast::AttachPoint($1); }
| attach_point MUL { $$ = $1 + "*"; } | IDENT ":" wildcard { $$ = new ast::AttachPoint($1, $3); }
| IDENT { $$ = $1; } | IDENT PATH wildcard { $$ = new ast::AttachPoint($1, $2.substr(1, $2.size()-2), $3); }
| MUL { $$ = "*"; }
; ;
wildcard : wildcard IDENT { $$ = $1 + $2; }
| wildcard MUL { $$ = $1 + "*"; }
| { $$ = ""; }
;
pred : DIV expr ENDPRED { $$ = new ast::Predicate($2); } pred : DIV expr ENDPRED { $$ = new ast::Predicate($2); }
| { $$ = nullptr; } | { $$ = nullptr; }
; ;
......
...@@ -123,10 +123,19 @@ void Printer::visit(Predicate &pred) ...@@ -123,10 +123,19 @@ void Printer::visit(Predicate &pred)
--depth_; --depth_;
} }
void Printer::visit(AttachPoint &ap)
{
std::string indent(depth_, ' ');
out_ << indent << ap.name(ap.func) << std::endl;
}
void Printer::visit(Probe &probe) void Printer::visit(Probe &probe)
{ {
std::string indent(depth_, ' '); std::string indent(depth_, ' ');
out_ << indent << probe.name() << std::endl;
for (AttachPoint *ap : *probe.attach_points) {
ap->accept(*this);
}
++depth_; ++depth_;
if (probe.pred) { if (probe.pred) {
......
...@@ -22,6 +22,7 @@ public: ...@@ -22,6 +22,7 @@ public:
void visit(AssignMapStatement &assignment) override; void visit(AssignMapStatement &assignment) override;
void visit(AssignVarStatement &assignment) override; void visit(AssignVarStatement &assignment) override;
void visit(Predicate &pred) override; void visit(Predicate &pred) override;
void visit(AttachPoint &ap) override;
void visit(Probe &probe) override; void visit(Probe &probe) override;
void visit(Program &program) override; void visit(Program &program) override;
......
...@@ -48,16 +48,19 @@ void SemanticAnalyser::visit(Builtin &builtin) ...@@ -48,16 +48,19 @@ void SemanticAnalyser::visit(Builtin &builtin)
builtin.type = SizedType(Type::string, STRING_SIZE); builtin.type = SizedType(Type::string, STRING_SIZE);
} }
else if (builtin.ident == "func") { else if (builtin.ident == "func") {
ProbeType type = probetype(probe_->type); for (auto &attach_point : *probe_->attach_points)
if (type == ProbeType::kprobe || {
type == ProbeType::kretprobe || ProbeType type = probetype(attach_point->provider);
type == ProbeType::tracepoint) if (type == ProbeType::kprobe ||
builtin.type = SizedType(Type::sym, 8); type == ProbeType::kretprobe ||
else if (type == ProbeType::uprobe || type == ProbeType::uretprobe) type == ProbeType::tracepoint)
builtin.type = SizedType(Type::usym, 8); builtin.type = SizedType(Type::sym, 8);
else else if (type == ProbeType::uprobe || type == ProbeType::uretprobe)
err_ << "The func builtin can not be used with '" << probe_->type builtin.type = SizedType(Type::usym, 8);
<< "' probes" << std::endl; else
err_ << "The func builtin can not be used with '" << attach_point->provider
<< "' probes" << std::endl;
}
} }
else if (!builtin.ident.compare(0, 3, "arg") && builtin.ident.size() == 4 && else if (!builtin.ident.compare(0, 3, "arg") && builtin.ident.size() == 4 &&
builtin.ident.at(3) >= '0' && builtin.ident.at(3) <= '9') { builtin.ident.at(3) >= '0' && builtin.ident.at(3) <= '9') {
...@@ -318,42 +321,34 @@ void SemanticAnalyser::visit(Predicate &pred) ...@@ -318,42 +321,34 @@ void SemanticAnalyser::visit(Predicate &pred)
} }
} }
void SemanticAnalyser::visit(Probe &probe) void SemanticAnalyser::visit(AttachPoint &ap)
{ {
// Clear out map of variable names - variables should be probe-local if (ap.provider == "kprobe" || ap.provider == "kretprobe") {
variable_val_.clear(); if (ap.target != "")
probe_ = &probe; err_ << "kprobes should not have a target" << std::endl;
if (ap.func == "")
if (probe.type == "kprobe" || probe.type == "kretprobe") { err_ << "kprobes should be attached to a function" << std::endl;
if (probe.attach_points->size() == 0) }
err_ << "kprobes must have an attachment point" << std::endl; else if (ap.provider == "uprobe" || ap.provider == "uretprobe") {
if (probe.path != "") if (ap.target == "")
err_ << "kprobes should not have a path" << std::endl; err_ << "uprobes should have a target" << std::endl;
} if (ap.func == "")
else if (probe.type == "uprobe" || probe.type == "uretprobe") { err_ << "uprobes should be attached to a function" << std::endl;
if (probe.attach_points->size() == 0) }
err_ << "uprobes must have an attachment point" << std::endl; else if (ap.provider == "tracepoint") {
if (probe.path == "") if (ap.target == "" || ap.func == "")
err_ << "uprobes must have a path" << std::endl; err_ << "tracepoint probe must have a target" << std::endl;
} }
else if (probe.type == "tracepoint") { else if (ap.provider == "BEGIN" || ap.provider == "END") {
if (probe.attach_points->size() == 0) if (ap.target != "" || ap.func != "")
err_ << "tracepoint probe must have an event" << std::endl; err_ << "BEGIN/END probes should not have a target" << 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;
if (probe.path != "")
err_ << "BEGIN/END probes should not have a path" << std::endl;
if (is_final_pass()) { if (is_final_pass()) {
if (probe.type == "BEGIN") { if (ap.provider == "BEGIN") {
if (has_begin_probe_) if (has_begin_probe_)
err_ << "More than one BEGIN probe defined" << std::endl; err_ << "More than one BEGIN probe defined" << std::endl;
has_begin_probe_ = true; has_begin_probe_ = true;
} }
if (probe.type == "END") { if (ap.provider == "END") {
if (has_end_probe_) if (has_end_probe_)
err_ << "More than one END probe defined" << std::endl; err_ << "More than one END probe defined" << std::endl;
has_end_probe_ = true; has_end_probe_ = true;
...@@ -361,9 +356,19 @@ void SemanticAnalyser::visit(Probe &probe) ...@@ -361,9 +356,19 @@ void SemanticAnalyser::visit(Probe &probe)
} }
} }
else { else {
err_ << "Invalid probe type: '" << probe.type << "'" << std::endl; err_ << "Invalid provider: '" << ap.provider << "'" << std::endl;
} }
}
void SemanticAnalyser::visit(Probe &probe)
{
// Clear out map of variable names - variables should be probe-local
variable_val_.clear();
probe_ = &probe;
for (AttachPoint *ap : *probe.attach_points) {
ap->accept(*this);
}
if (probe.pred) { if (probe.pred) {
probe.pred->accept(*this); probe.pred->accept(*this);
} }
......
...@@ -29,6 +29,7 @@ public: ...@@ -29,6 +29,7 @@ public:
void visit(AssignMapStatement &assignment) override; void visit(AssignMapStatement &assignment) override;
void visit(AssignVarStatement &assignment) override; void visit(AssignVarStatement &assignment) override;
void visit(Predicate &pred) override; void visit(Predicate &pred) override;
void visit(AttachPoint &ap) override;
void visit(Probe &probe) override; void visit(Probe &probe) override;
void visit(Program &program) override; void visit(Program &program) override;
......
...@@ -5,48 +5,60 @@ namespace bpftrace { ...@@ -5,48 +5,60 @@ namespace bpftrace {
namespace test { namespace test {
namespace ast { namespace ast {
using bpftrace::ast::AttachPoint;
using bpftrace::ast::AttachPointList; using bpftrace::ast::AttachPointList;
using bpftrace::ast::Probe; using bpftrace::ast::Probe;
TEST(ast, probe_name_special) TEST(ast, probe_name_special)
{ {
Probe begin("BEGIN", nullptr, nullptr); AttachPoint ap1("BEGIN");
AttachPointList attach_points1 = { &ap1 };
Probe begin(&attach_points1, nullptr, nullptr);
EXPECT_EQ(begin.name(), "BEGIN"); EXPECT_EQ(begin.name(), "BEGIN");
Probe end("END", nullptr, nullptr); AttachPoint ap2("END");
AttachPointList attach_points2 = { &ap2 };
Probe end(&attach_points2, nullptr, nullptr);
EXPECT_EQ(end.name(), "END"); EXPECT_EQ(end.name(), "END");
} }
TEST(ast, probe_name_kprobe) TEST(ast, probe_name_kprobe)
{ {
AttachPointList attach_points1 = { "sys_read" }; AttachPoint ap1("kprobe", "sys_read");
Probe kprobe1("kprobe", &attach_points1, nullptr, nullptr); AttachPointList attach_points1 = { &ap1 };
Probe kprobe1(&attach_points1, nullptr, nullptr);
EXPECT_EQ(kprobe1.name(), "kprobe:sys_read"); EXPECT_EQ(kprobe1.name(), "kprobe:sys_read");
AttachPointList attach_points2 = { "sys_read", "sys_write" }; AttachPoint ap2("kprobe", "sys_write");
Probe kprobe2("kprobe", &attach_points2, nullptr, nullptr); AttachPointList attach_points2 = { &ap1, &ap2 };
EXPECT_EQ(kprobe2.name(), "kprobe:sys_read,sys_write"); Probe kprobe2(&attach_points2, nullptr, nullptr);
EXPECT_EQ(kprobe2.name(), "kprobe:sys_read,kprobe:sys_write");
} }
TEST(ast, probe_name_uprobe) TEST(ast, probe_name_uprobe)
{ {
AttachPointList attach_points1 = { "readline" }; AttachPoint ap1("uprobe", "/bin/sh", "readline");
Probe uprobe1("uprobe", "/bin/sh", &attach_points1, nullptr, nullptr); AttachPointList attach_points1 = { &ap1 };
Probe uprobe1(&attach_points1, nullptr, nullptr);
EXPECT_EQ(uprobe1.name(), "uprobe:/bin/sh:readline"); EXPECT_EQ(uprobe1.name(), "uprobe:/bin/sh:readline");
AttachPointList attach_points2 = { "readline", "somefunc" }; AttachPoint ap2("uprobe", "/bin/sh", "somefunc");
Probe uprobe2("uprobe", "/bin/sh", &attach_points2, nullptr, nullptr); AttachPointList attach_points2 = { &ap1, &ap2 };
EXPECT_EQ(uprobe2.name(), "uprobe:/bin/sh:readline,somefunc"); Probe uprobe2(&attach_points2, nullptr, nullptr);
EXPECT_EQ(uprobe2.name(), "uprobe:/bin/sh:readline,uprobe:/bin/sh:somefunc");
} }
TEST(ast, probe_name_singular) TEST(ast, attach_point_name)
{ {
AttachPointList attach_points = { "sys_read", "sys_thisone", "readline" }; AttachPoint ap1("kprobe", "sys_read");
Probe kprobe("kprobe", &attach_points, nullptr, nullptr); AttachPoint ap2("kprobe", "sys_thisone");
EXPECT_EQ(kprobe.name("sys_thisone"), "kprobe:sys_thisone"); AttachPoint ap3("uprobe", "/bin/sh", "readline");
AttachPointList attach_points = { &ap1, &ap2, &ap3 };
Probe kprobe(&attach_points, nullptr, nullptr);
EXPECT_EQ(ap2.name("sys_thisone"), "kprobe:sys_thisone");
Probe uprobe("uprobe", "/bin/sh", &attach_points, nullptr, nullptr); Probe uprobe(&attach_points, nullptr, nullptr);
EXPECT_EQ(uprobe.name("readline"), "uprobe:/bin/sh:readline"); EXPECT_EQ(ap3.name("readline"), "uprobe:/bin/sh:readline");
} }
} // namespace ast } // namespace ast
......
This diff is collapsed.
...@@ -222,24 +222,11 @@ TEST(Parser, begin_probe) ...@@ -222,24 +222,11 @@ TEST(Parser, begin_probe)
TEST(Parser, multiple_attach_points_kprobe) TEST(Parser, multiple_attach_points_kprobe)
{ {
test("kprobe:sys_open,sys_close { 1 }", test("BEGIN,kprobe:sys_open,uprobe:/bin/sh:foo,tracepoint:syscalls:sys_enter_* { 1 }",
"Program\n"
" kprobe:sys_open,sys_close\n"
" 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" "Program\n"
" BEGIN\n"
" kprobe:sys_open\n"
" uprobe:/bin/sh:foo\n"
" tracepoint:syscalls:sys_enter_*\n" " tracepoint:syscalls:sys_enter_*\n"
" int: 1\n"); " int: 1\n");
} }
......
...@@ -23,7 +23,7 @@ void test(BPFtrace &bpftrace, Driver &driver, const std::string &input, int expe ...@@ -23,7 +23,7 @@ void test(BPFtrace &bpftrace, Driver &driver, const std::string &input, int expe
ast::SemanticAnalyser semantics(driver.root_, bpftrace, out); ast::SemanticAnalyser semantics(driver.root_, bpftrace, out);
std::stringstream msg; std::stringstream msg;
msg << "\nInput:\n" << input << "\n\nOutput:\n"; msg << "\nInput:\n" << input << "\n\nOutput:\n";
EXPECT_EQ(semantics.analyse(), expected_result) << msg.str() + out.str(); EXPECT_EQ(expected_result, semantics.analyse()) << msg.str() + out.str();
} }
void test(BPFtrace &bpftrace, const std::string &input, int expected_result=0) void test(BPFtrace &bpftrace, const std::string &input, int expected_result=0)
......
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