Skip to content

Commit

Permalink
tranche 3
Browse files Browse the repository at this point in the history
  • Loading branch information
khuey committed May 30, 2024
1 parent ee997ff commit e272850
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 47 deletions.
14 changes: 11 additions & 3 deletions src/PerfCounters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1131,13 +1131,13 @@ class BpfAccelerator {
static std::shared_ptr<BpfAccelerator> get_or_create();

ScopedFd create_counter(pid_t tid);
void match_regs_and_open_counter(Registers regs, ScopedFd& counter);
void match_regs_and_open_counter(const Registers& regs, ScopedFd& counter);
uint64_t skips() const {
return *bpf_skips;
}

// Can't be private because of make_shared.
BpfAccelerator(ScopedFd&& bpf_prog_fd, user_regs_struct* bpf_regs, uint64_t* bpf_skips)
BpfAccelerator(ScopedFd bpf_prog_fd, user_regs_struct* bpf_regs, uint64_t* bpf_skips)
: bpf_prog_fd(std::move(bpf_prog_fd)), bpf_regs(bpf_regs), bpf_skips(bpf_skips)
{}

Expand Down Expand Up @@ -1166,40 +1166,48 @@ std::shared_ptr<BpfAccelerator> BpfAccelerator::singleton;
string path = resource_path() + "share/rr/async_event_filter.o";
struct bpf_object* obj = bpf_object__open(path.c_str());
if ((intptr_t)obj <= 0) {
LOG(error) << "Failed to find bpf at " << path;
return nullptr;
}
if (bpf_object__load(obj) < 0) {
LOG(error) << "Failed to load bpf at " << path << " into the kernel. Do we have permissions?";
return nullptr;
}
int bpf_map_fd = bpf_object__find_map_fd_by_name(obj, "registers");
if (bpf_map_fd < 0) {
CLEAN_FATAL() << "rr's bpf at " << path << " is corrupt";
return nullptr;
}
struct bpf_program* prog = bpf_program__next(NULL, obj);
if (!prog) {
CLEAN_FATAL() << "rr's bpf at " << path << " is corrupt";
return nullptr;
}
ScopedFd bpf_prog_fd = ScopedFd(bpf_program__fd(prog));
if (bpf_prog_fd < 0) {
CLEAN_FATAL() << "rr's bpf at " << path << " is corrupt";
return nullptr;
}

auto bpf_regs = (struct user_regs_struct*)
mmap(NULL, 4096, PROT_READ | PROT_WRITE,
MAP_SHARED, bpf_map_fd, 0);
if (bpf_regs == MAP_FAILED) {
CLEAN_FATAL() << "Failed to mmap bpf maps";
return nullptr;
}

bpf_map_fd = bpf_object__find_map_fd_by_name(obj, "skips");
if (bpf_map_fd < 0) {
CLEAN_FATAL() << "rr's bpf at " << path << " is corrupt";
return nullptr;
}

auto bpf_skips = (uint64_t*)
mmap(NULL, 4096, PROT_READ | PROT_WRITE,
MAP_SHARED, bpf_map_fd, 0);
if (bpf_regs == MAP_FAILED) {
CLEAN_FATAL() << "Failed to mmap bpf maps";
return nullptr;
}

Expand Down Expand Up @@ -1244,7 +1252,7 @@ ScopedFd BpfAccelerator::create_counter(pid_t tid) {
return fd;
}

void BpfAccelerator::match_regs_and_open_counter(Registers regs, ScopedFd& fd) {
void BpfAccelerator::match_regs_and_open_counter(const Registers& regs, ScopedFd& fd) {
attr.bp_addr = regs.ip().register_value();
if (ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr)) {
FATAL() << "Failed PERF_EVENT_IOC_MODIFY_ATTRIBUTES";
Expand Down
90 changes: 46 additions & 44 deletions src/bpf/async_event_filter.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */

#include <linux/bpf.h>
#include <linux/bpf_perf_event.h>
#include <bpf/bpf_helpers.h>
Expand All @@ -6,58 +8,58 @@
const uint32_t REGISTER_COUNT = sizeof(struct pt_regs)/sizeof(uint64_t);

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, REGISTER_COUNT);
__uint(map_flags, BPF_F_MMAPABLE);
__type(key, uint32_t);
__type(value, uint64_t);
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, REGISTER_COUNT);
__uint(map_flags, BPF_F_MMAPABLE);
__type(key, uint32_t);
__type(value, uint64_t);
} registers SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__uint(map_flags, BPF_F_MMAPABLE);
__type(key, uint32_t);
__type(value, uint64_t);
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__uint(map_flags, BPF_F_MMAPABLE);
__type(key, uint32_t);
__type(value, uint64_t);
} skips SEC(".maps");

SEC("perf_event")
int match_registers(struct bpf_perf_event_data* event) {
#define CHECK_REG(name) \
{ \
const uint32_t i = offsetof(struct pt_regs, name) / sizeof(uint64_t); \
uint64_t* reg = bpf_map_lookup_elem(&registers, &i); \
if (!reg) { \
return 1; \
} \
if (event->regs.name != *reg) { \
const uint32_t j = 0; \
uint64_t* s = bpf_map_lookup_elem(&skips, &j); \
if (s) { \
*s += 1; \
} \
return 0; \
} \
}

CHECK_REG(r15)
CHECK_REG(r14)
CHECK_REG(r13)
CHECK_REG(r12)
CHECK_REG(rbp)
CHECK_REG(rbx)
CHECK_REG(r11)
CHECK_REG(r10)
CHECK_REG(r9)
CHECK_REG(r8)
CHECK_REG(rax)
CHECK_REG(rcx)
CHECK_REG(rdx)
CHECK_REG(rsi)
CHECK_REG(rdi)
CHECK_REG(rsp)

return 1;
do { \
const uint32_t i = offsetof(struct pt_regs, name) / sizeof(uint64_t); \
uint64_t* reg = bpf_map_lookup_elem(&registers, &i); \
if (!reg) { \
return 1; \
} \
if (event->regs.name != *reg) { \
const uint32_t j = 0; \
uint64_t* s = bpf_map_lookup_elem(&skips, &j); \
if (s) { \
*s += 1; \
} \
return 0; \
} \
} while(0)

CHECK_REG(r15);
CHECK_REG(r14);
CHECK_REG(r13);
CHECK_REG(r12);
CHECK_REG(rbp);
CHECK_REG(rbx);
CHECK_REG(r11);
CHECK_REG(r10);
CHECK_REG(r9);
CHECK_REG(r8);
CHECK_REG(rax);
CHECK_REG(rcx);
CHECK_REG(rdx);
CHECK_REG(rsi);
CHECK_REG(rdi);
CHECK_REG(rsp);

return 1;
}

char _license[] SEC("license") = "Dual MIT/GPL";

0 comments on commit e272850

Please sign in to comment.