Skip to content

Commit

Permalink
usdt: Use uprobe refcnt if available in usdt C++ API
Browse files Browse the repository at this point in the history
  • Loading branch information
danobi committed Oct 19, 2020
1 parent 3f0c5f0 commit 28a5cef
Showing 1 changed file with 38 additions and 3 deletions.
41 changes: 38 additions & 3 deletions src/cc/api/BPF.cc
Expand Up @@ -20,9 +20,12 @@
#include <cstdio>
#include <cstring>
#include <exception>
#include <fcntl.h>
#include <iostream>
#include <memory>
#include <sstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <utility>
#include <vector>

Expand All @@ -39,6 +42,37 @@

#include "BPF.h"

namespace {
/*
* Kernels ~4.20 and later support specifying the ref_ctr_offset as an argument
* to attaching a uprobe, which negates the need to seek to this memory offset
* in userspace to manage semaphores, as the kernel will do it for us. This
* helper function checks if this support is available by reading the uprobe
* format for this value, added in a6ca88b241d5e929e6e60b12ad8cd288f0ffa
*/
bool uprobe_ref_ctr_supported() {
const char *ref_ctr_pmu_path =
"/sys/bus/event_source/devices/uprobe/format/ref_ctr_offset";
const char *ref_ctr_pmu_expected = "config:32-63\0";
char ref_ctr_pmu_fmt[64]; // in Linux source this buffer is compared vs
// PAGE_SIZE, but 64 is probably ample
int fd = open(ref_ctr_pmu_path, O_RDONLY);
if (fd < 0)
return false;

int ret = read(fd, ref_ctr_pmu_fmt, sizeof(ref_ctr_pmu_fmt));
close(fd);
if (ret < 0) {
return false;
}
if (strncmp(ref_ctr_pmu_expected, ref_ctr_pmu_fmt,
strlen(ref_ctr_pmu_expected)) == 0) {
return true;
}
return false;
}
} // namespace

namespace ebpf {

std::string uint_to_hex(uint64_t value) {
Expand Down Expand Up @@ -268,15 +302,16 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,

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_))
if (!uprobe_ref_ctr_supported() && !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);
loc.address_, BPF_PROBE_ENTRY, pid, 0,
probe.semaphore_offset());
if (!res.ok()) {
failed = true;
err_msg += "USDT " + u.print_name() + " at " + loc.bin_path_ +
Expand Down Expand Up @@ -507,7 +542,7 @@ StatusTuple BPF::detach_usdt_without_validation(const USDT& u, pid_t pid) {
}
}

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

0 comments on commit 28a5cef

Please sign in to comment.