Skip to content

Commit

Permalink
[C++] add BPF::enable_usdt_all() and disble_usdt_all() to handle all …
Browse files Browse the repository at this point in the history
…the USDT at once (#2854)

* add BPF::enable_usdt_all() to enable all the USDT
* add detach_usdt_all() to detach all the USDTs
  • Loading branch information
gfx committed Apr 4, 2020
1 parent ab54de2 commit 689f900
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 56 deletions.
4 changes: 2 additions & 2 deletions examples/cpp/FollyRequestContextSwitch.cc
Expand Up @@ -98,7 +98,7 @@ int main(int argc, char** argv) {
return 1;
}

auto attach_res = bpf->attach_usdt(u);
auto attach_res = bpf->attach_usdt_all();
if (attach_res.code() != 0) {
std::cerr << attach_res.msg() << std::endl;
return 1;
Expand All @@ -114,7 +114,7 @@ int main(int argc, char** argv) {

shutdown_handler = [&](int s) {
std::cerr << "Terminating..." << std::endl;
bpf->detach_usdt(u);
bpf->detach_usdt_all();
delete bpf;
exit(0);
};
Expand Down
138 changes: 84 additions & 54 deletions src/cc/api/BPF.cc
Expand Up @@ -264,46 +264,61 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,
return StatusTuple::OK();
}

StatusTuple BPF::attach_usdt_without_validation(const USDT& u, pid_t pid) {
auto& probe = *static_cast<::USDT::Probe*>(u.probe_.get());
if (!probe.enable(u.probe_func_))
return StatusTuple(-1, "Unable to enable USDT %s" + u.print_name());

bool failed = false;
std::string err_msg;
int cnt = 0;
for (const auto& loc : probe.locations_) {
auto res = attach_uprobe(loc.bin_path_, std::string(), u.probe_func_,
loc.address_, BPF_PROBE_ENTRY, pid);
if (!res.ok()) {
failed = true;
err_msg += "USDT " + u.print_name() + " at " + loc.bin_path_ +
" address " + std::to_string(loc.address_);
err_msg += ": " + res.msg() + "\n";
break;
}
cnt++;
}
if (failed) {
for (int i = 0; i < cnt; i++) {
auto res = detach_uprobe(probe.locations_[i].bin_path_, std::string(),
probe.locations_[i].address_, BPF_PROBE_ENTRY, pid);
if (!res.ok())
err_msg += "During clean up: " + res.msg() + "\n";
}
return StatusTuple(-1, err_msg);
} else {
return StatusTuple::OK();
}
}

StatusTuple BPF::attach_usdt(const USDT& usdt, pid_t pid) {
for (const auto& u : usdt_) {
if (u == usdt) {
auto& probe = *static_cast<::USDT::Probe*>(u.probe_.get());
if (!probe.enable(u.probe_func_))
return StatusTuple(-1, "Unable to enable USDT " + u.print_name());

bool failed = false;
std::string err_msg;
int cnt = 0;
for (const auto& loc : probe.locations_) {
auto res = attach_uprobe(loc.bin_path_, std::string(), u.probe_func_,
loc.address_, BPF_PROBE_ENTRY, pid);
if (res.code() != 0) {
failed = true;
err_msg += "USDT " + u.print_name() + " at " + loc.bin_path_ +
" address " + std::to_string(loc.address_);
err_msg += ": " + res.msg() + "\n";
break;
}
cnt++;
}
if (failed) {
for (int i = 0; i < cnt; i++) {
auto res =
detach_uprobe(probe.locations_[i].bin_path_, std::string(),
probe.locations_[i].address_, BPF_PROBE_ENTRY, pid);
if (res.code() != 0)
err_msg += "During clean up: " + res.msg() + "\n";
}
return StatusTuple(-1, err_msg);
} else {
return StatusTuple::OK();
}
return attach_usdt_without_validation(u, pid);
}
}

return StatusTuple(-1, "USDT %s not found", usdt.print_name().c_str());
}

StatusTuple BPF::attach_usdt_all() {
for (const auto& u : usdt_) {
auto res = attach_usdt_without_validation(u, -1);
if (!res.ok()) {
return res;
}
}

return StatusTuple::OK();
}


StatusTuple BPF::attach_tracepoint(const std::string& tracepoint,
const std::string& probe_func) {
if (tracepoints_.find(tracepoint) != tracepoints_.end())
Expand Down Expand Up @@ -475,38 +490,53 @@ StatusTuple BPF::detach_uprobe(const std::string& binary_path,
return StatusTuple::OK();
}

StatusTuple BPF::detach_usdt_without_validation(const USDT& u, pid_t pid) {
auto& probe = *static_cast<::USDT::Probe*>(u.probe_.get());
bool failed = false;
std::string err_msg;
for (const auto& loc : probe.locations_) {
auto res = detach_uprobe(loc.bin_path_, std::string(), loc.address_,
BPF_PROBE_ENTRY, pid);
if (!res.ok()) {
failed = true;
err_msg += "USDT " + u.print_name() + " at " + loc.bin_path_ +
" address " + std::to_string(loc.address_);
err_msg += ": " + res.msg() + "\n";
}
}

if (!probe.disable()) {
failed = true;
err_msg += "Unable to disable USDT " + u.print_name();
}

if (failed)
return StatusTuple(-1, err_msg);
else
return StatusTuple::OK();
}

StatusTuple BPF::detach_usdt(const USDT& usdt, pid_t pid) {
for (const auto& u : usdt_) {
if (u == usdt) {
auto& probe = *static_cast<::USDT::Probe*>(u.probe_.get());
bool failed = false;
std::string err_msg;
for (const auto& loc : probe.locations_) {
auto res = detach_uprobe(loc.bin_path_, std::string(), loc.address_,
BPF_PROBE_ENTRY, pid);
if (res.code() != 0) {
failed = true;
err_msg += "USDT " + u.print_name() + " at " + loc.bin_path_ +
" address " + std::to_string(loc.address_);
err_msg += ": " + res.msg() + "\n";
}
}

if (!probe.disable()) {
failed = true;
err_msg += "Unable to disable USDT " + u.print_name();
}

if (failed)
return StatusTuple(-1, err_msg);
else
return StatusTuple::OK();
return detach_usdt_without_validation(u, pid);
}
}

return StatusTuple(-1, "USDT %s not found", usdt.print_name().c_str());
}

StatusTuple BPF::detach_usdt_all() {
for (const auto& u : usdt_) {
auto ret = detach_usdt_without_validation(u, -1);
if (!ret.ok()) {
return ret;
}
}

return StatusTuple::OK();
}

StatusTuple BPF::detach_tracepoint(const std::string& tracepoint) {
auto it = tracepoints_.find(tracepoint);
if (it == tracepoints_.end())
Expand Down
5 changes: 5 additions & 0 deletions src/cc/api/BPF.h
Expand Up @@ -85,7 +85,9 @@ class BPF {
pid_t pid = -1,
uint64_t symbol_offset = 0);
StatusTuple attach_usdt(const USDT& usdt, pid_t pid = -1);
StatusTuple attach_usdt_all();
StatusTuple detach_usdt(const USDT& usdt, pid_t pid = -1);
StatusTuple detach_usdt_all();

StatusTuple attach_tracepoint(const std::string& tracepoint,
const std::string& probe_func);
Expand Down Expand Up @@ -248,6 +250,9 @@ class BPF {
std::string get_uprobe_event(const std::string& binary_path, uint64_t offset,
bpf_probe_attach_type type, pid_t pid);

StatusTuple attach_usdt_without_validation(const USDT& usdt, pid_t pid);
StatusTuple detach_usdt_without_validation(const USDT& usdt, pid_t pid);

StatusTuple detach_kprobe_event(const std::string& event, open_probe_t& attr);
StatusTuple detach_uprobe_event(const std::string& event, open_probe_t& attr);
StatusTuple detach_tracepoint_event(const std::string& tracepoint,
Expand Down
14 changes: 14 additions & 0 deletions tests/cc/test_usdt_probes.cc
Expand Up @@ -76,6 +76,20 @@ TEST_CASE("test fine a probe in our own binary with C++ API", "[usdt]") {
REQUIRE(res.code() == 0);
}

TEST_CASE("test fine probes in our own binary with C++ API", "[usdt]") {
ebpf::BPF bpf;
ebpf::USDT u("/proc/self/exe", "libbcc_test", "sample_probe_1", "on_event");

auto res = bpf.init("int on_event() { return 0; }", {}, {u});
REQUIRE(res.ok());

res = bpf.attach_usdt_all();
REQUIRE(res.ok());

res = bpf.detach_usdt_all();
REQUIRE(res.ok());
}

TEST_CASE("test fine a probe in our Process with C++ API", "[usdt]") {
ebpf::BPF bpf;
ebpf::USDT u(::getpid(), "libbcc_test", "sample_probe_1", "on_event");
Expand Down

0 comments on commit 689f900

Please sign in to comment.