Commit fafbf3ca authored by Teng Qin's avatar Teng Qin

Do not use perf reader for TRACEPOINT events

parent abef8350
......@@ -159,8 +159,7 @@ StatusTuple BPF::detach_all() {
StatusTuple BPF::attach_kprobe(const std::string& kernel_func,
const std::string& probe_func,
bpf_probe_attach_type attach_type,
perf_reader_cb cb, void* cb_cookie) {
bpf_probe_attach_type attach_type) {
std::string probe_event = get_kprobe_event(kernel_func, attach_type);
if (kprobes_.find(probe_event) != kprobes_.end())
return StatusTuple(-1, "kprobe %s already attached", probe_event.c_str());
......@@ -168,10 +167,10 @@ StatusTuple BPF::attach_kprobe(const std::string& kernel_func,
int probe_fd;
TRY2(load_func(probe_func, BPF_PROG_TYPE_KPROBE, probe_fd));
void* res = bpf_attach_kprobe(probe_fd, attach_type, probe_event.c_str(),
kernel_func.c_str(), cb, cb_cookie);
int res_fd = bpf_attach_kprobe(probe_fd, attach_type, probe_event.c_str(),
kernel_func.c_str());
if (!res) {
if (res_fd < 0) {
TRY2(unload_func(probe_func));
return StatusTuple(-1, "Unable to attach %skprobe for %s using %s",
attach_type_debug(attach_type).c_str(),
......@@ -179,7 +178,7 @@ StatusTuple BPF::attach_kprobe(const std::string& kernel_func,
}
open_probe_t p = {};
p.reader_ptr = res;
p.perf_event_fd = res_fd;
p.func = probe_func;
kprobes_[probe_event] = std::move(p);
return StatusTuple(0);
......@@ -189,8 +188,7 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,
const std::string& symbol,
const std::string& probe_func,
uint64_t symbol_addr,
bpf_probe_attach_type attach_type, pid_t pid,
perf_reader_cb cb, void* cb_cookie) {
bpf_probe_attach_type attach_type, pid_t pid) {
std::string module;
uint64_t offset;
TRY2(check_binary_symbol(binary_path, symbol, symbol_addr, module, offset));
......@@ -202,11 +200,10 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,
int probe_fd;
TRY2(load_func(probe_func, BPF_PROG_TYPE_KPROBE, probe_fd));
void* res =
bpf_attach_uprobe(probe_fd, attach_type, probe_event.c_str(),
binary_path.c_str(), offset, pid, cb, cb_cookie);
int res_fd = bpf_attach_uprobe(probe_fd, attach_type, probe_event.c_str(),
binary_path.c_str(), offset, pid);
if (!res) {
if (res_fd < 0) {
TRY2(unload_func(probe_func));
return StatusTuple(
-1,
......@@ -216,7 +213,7 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,
}
open_probe_t p = {};
p.reader_ptr = res;
p.perf_event_fd = res_fd;
p.func = probe_func;
uprobes_[probe_event] = std::move(p);
return StatusTuple(0);
......@@ -253,8 +250,7 @@ StatusTuple BPF::attach_usdt(const USDT& usdt, pid_t pid) {
}
StatusTuple BPF::attach_tracepoint(const std::string& tracepoint,
const std::string& probe_func,
perf_reader_cb cb, void* cb_cookie) {
const std::string& probe_func) {
if (tracepoints_.find(tracepoint) != tracepoints_.end())
return StatusTuple(-1, "Tracepoint %s already attached",
tracepoint.c_str());
......@@ -268,17 +264,17 @@ StatusTuple BPF::attach_tracepoint(const std::string& tracepoint,
int probe_fd;
TRY2(load_func(probe_func, BPF_PROG_TYPE_TRACEPOINT, probe_fd));
void* res = bpf_attach_tracepoint(probe_fd, tp_category.c_str(),
tp_name.c_str(), cb, cb_cookie);
int res_fd = bpf_attach_tracepoint(probe_fd, tp_category.c_str(),
tp_name.c_str());
if (!res) {
if (res_fd < 0) {
TRY2(unload_func(probe_func));
return StatusTuple(-1, "Unable to attach Tracepoint %s using %s",
tracepoint.c_str(), probe_func.c_str());
}
open_probe_t p = {};
p.reader_ptr = res;
p.perf_event_fd = res_fd;
p.func = probe_func;
tracepoints_[tracepoint] = std::move(p);
return StatusTuple(0);
......@@ -558,10 +554,7 @@ std::string BPF::get_uprobe_event(const std::string& binary_path,
StatusTuple BPF::detach_kprobe_event(const std::string& event,
open_probe_t& attr) {
if (attr.reader_ptr) {
perf_reader_free(attr.reader_ptr);
attr.reader_ptr = nullptr;
}
bpf_close_perf_event_fd(attr.perf_event_fd);
TRY2(unload_func(attr.func));
if (bpf_detach_kprobe(event.c_str()) < 0)
return StatusTuple(-1, "Unable to detach kprobe %s", event.c_str());
......@@ -570,10 +563,7 @@ StatusTuple BPF::detach_kprobe_event(const std::string& event,
StatusTuple BPF::detach_uprobe_event(const std::string& event,
open_probe_t& attr) {
if (attr.reader_ptr) {
perf_reader_free(attr.reader_ptr);
attr.reader_ptr = nullptr;
}
bpf_close_perf_event_fd(attr.perf_event_fd);
TRY2(unload_func(attr.func));
if (bpf_detach_uprobe(event.c_str()) < 0)
return StatusTuple(-1, "Unable to detach uprobe %s", event.c_str());
......@@ -582,10 +572,7 @@ StatusTuple BPF::detach_uprobe_event(const std::string& event,
StatusTuple BPF::detach_tracepoint_event(const std::string& tracepoint,
open_probe_t& attr) {
if (attr.reader_ptr) {
perf_reader_free(attr.reader_ptr);
attr.reader_ptr = nullptr;
}
bpf_close_perf_event_fd(attr.perf_event_fd);
TRY2(unload_func(attr.func));
// TODO: bpf_detach_tracepoint currently does nothing.
......
......@@ -34,7 +34,7 @@ static const int DEFAULT_PERF_BUFFER_PAGE_CNT = 8;
namespace ebpf {
struct open_probe_t {
void* reader_ptr;
int perf_event_fd;
std::string func;
std::map<int, int>* per_cpu_fd;
};
......@@ -57,9 +57,7 @@ class BPF {
StatusTuple attach_kprobe(const std::string& kernel_func,
const std::string& probe_func,
bpf_probe_attach_type = BPF_PROBE_ENTRY,
perf_reader_cb cb = nullptr,
void* cb_cookie = nullptr);
bpf_probe_attach_type = BPF_PROBE_ENTRY);
StatusTuple detach_kprobe(
const std::string& kernel_func,
bpf_probe_attach_type attach_type = BPF_PROBE_ENTRY);
......@@ -69,8 +67,7 @@ class BPF {
const std::string& probe_func,
uint64_t symbol_addr = 0,
bpf_probe_attach_type attach_type = BPF_PROBE_ENTRY,
pid_t pid = -1, perf_reader_cb cb = nullptr,
void* cb_cookie = nullptr);
pid_t pid = -1);
StatusTuple detach_uprobe(const std::string& binary_path,
const std::string& symbol, uint64_t symbol_addr = 0,
bpf_probe_attach_type attach_type = BPF_PROBE_ENTRY,
......@@ -79,9 +76,7 @@ class BPF {
StatusTuple detach_usdt(const USDT& usdt);
StatusTuple attach_tracepoint(const std::string& tracepoint,
const std::string& probe_func,
perf_reader_cb cb = nullptr,
void* cb_cookie = nullptr);
const std::string& probe_func);
StatusTuple detach_tracepoint(const std::string& tracepoint);
StatusTuple attach_perf_event(uint32_t ev_type, uint32_t ev_config,
......
......@@ -151,8 +151,6 @@ static struct bpf_helper helpers[] = {
{"sock_ops_cb_flags_set", "4.16"},
};
static int probe_perf_reader_page_cnt = 8;
static uint64_t ptr_to_u64(void *ptr)
{
return (uint64_t) (unsigned long) ptr;
......@@ -682,7 +680,6 @@ static int bpf_try_perf_event_open_with_probe(const char *name, uint64_t offs,
if (type < 0 || is_return_bit < 0)
return -1;
attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
attr.sample_period = 1;
attr.wakeup_events = 1;
if (is_return)
......@@ -724,16 +721,23 @@ static int bpf_try_perf_event_open_with_probe(const char *name, uint64_t offs,
PERF_FLAG_FD_CLOEXEC);
}
static int bpf_attach_tracing_event(int progfd, const char *event_path,
struct perf_reader *reader, int pid,
int pfd)
// When a valid Perf Event FD provided through pfd, it will be used to enable
// and attach BPF program to the event, and event_path will be ignored.
// Otherwise, event_path is expected to contain the path to the event in debugfs
// and it will be used to open the Perf Event FD.
// In either case, if the attach partially failed (such as issue with the
// ioctl operations), the **caller** need to clean up the Perf Event FD, either
// provided by the caller or opened here.
static int bpf_attach_tracing_event(int progfd, const char *event_path, int pid,
int *pfd)
{
int efd, cpu = 0;
ssize_t bytes;
char buf[PATH_MAX];
struct perf_event_attr attr = {};
if (pfd < 0) {
// Caller did not provided a valid Perf Event FD. Create one with the debugfs
// event path provided.
if (*pfd < 0) {
snprintf(buf, sizeof(buf), "%s/id", event_path);
efd = open(buf, O_RDONLY, 0);
if (efd < 0) {
......@@ -751,7 +755,6 @@ static int bpf_attach_tracing_event(int progfd, const char *event_path,
buf[bytes] = '\0';
attr.config = strtol(buf, NULL, 0);
attr.type = PERF_TYPE_TRACEPOINT;
attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN;
attr.sample_period = 1;
attr.wakeup_events = 1;
// PID filter is only possible for uprobe events.
......@@ -762,22 +765,18 @@ static int bpf_attach_tracing_event(int progfd, const char *event_path,
// Tracing events do not do CPU filtering in any cases.
if (pid != -1)
cpu = -1;
pfd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC);
if (pfd < 0) {
*pfd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC);
if (*pfd < 0) {
fprintf(stderr, "perf_event_open(%s/id): %s\n", event_path, strerror(errno));
return -1;
}
}
perf_reader_set_fd(reader, pfd);
if (perf_reader_mmap(reader, attr.type, attr.sample_type) < 0)
return -1;
if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, progfd) < 0) {
if (ioctl(*pfd, PERF_EVENT_IOC_SET_BPF, progfd) < 0) {
perror("ioctl(PERF_EVENT_IOC_SET_BPF)");
return -1;
}
if (ioctl(pfd, PERF_EVENT_IOC_ENABLE, 0) < 0) {
if (ioctl(*pfd, PERF_EVENT_IOC_ENABLE, 0) < 0) {
perror("ioctl(PERF_EVENT_IOC_ENABLE)");
return -1;
}
......@@ -785,24 +784,19 @@ static int bpf_attach_tracing_event(int progfd, const char *event_path,
return 0;
}
void *bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
const char *ev_name, const char *fn_name,
perf_reader_cb cb, void *cb_cookie)
int bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
const char *ev_name, const char *fn_name)
{
int kfd;
int pfd;
int kfd, pfd = -1;
char buf[256];
char event_alias[128];
struct perf_reader *reader = NULL;
static char *event_type = "kprobe";
reader = perf_reader_new(cb, NULL, NULL, cb_cookie, probe_perf_reader_page_cnt);
if (!reader)
goto error;
// Try create the kprobe Perf Event with perf_event_open API.
pfd = bpf_try_perf_event_open_with_probe(fn_name, 0, -1, event_type,
attach_type != BPF_PROBE_ENTRY);
// If failed, most likely Kernel doesn't support the new perf_event_open API
// yet. Try create the event using debugfs.
if (pfd < 0) {
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/%s_events", event_type);
kfd = open(buf, O_WRONLY | O_APPEND, 0);
......@@ -823,15 +817,16 @@ void *bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
close(kfd);
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%ss/%s", event_type, event_alias);
}
if (bpf_attach_tracing_event(progfd, buf, reader, -1 /* PID */, pfd) < 0)
goto error;
return reader;
// If perf_event_open succeeded, bpf_attach_tracing_event will use the created
// Perf Event FD directly and buf would be empty and unused.
// Otherwise it will read the event ID from the path in buf, create the
// Perf Event event using that ID, and updated value of pfd.
if (bpf_attach_tracing_event(progfd, buf, -1 /* PID */, &pfd) == 0)
return pfd;
error:
perf_reader_free(reader);
return NULL;
bpf_close_perf_event_fd(pfd);
return -1;
}
static int enter_mount_ns(int pid) {
......@@ -895,24 +890,19 @@ static void exit_mount_ns(int fd) {
perror("setns");
}
void *bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type,
const char *ev_name, const char *binary_path,
uint64_t offset, pid_t pid, perf_reader_cb cb,
void *cb_cookie)
int bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type,
const char *ev_name, const char *binary_path,
uint64_t offset, pid_t pid)
{
char buf[PATH_MAX];
char event_alias[PATH_MAX];
struct perf_reader *reader = NULL;
static char *event_type = "uprobe";
int res, kfd = -1, ns_fd = -1;
int pfd;
reader = perf_reader_new(cb, NULL, NULL, cb_cookie, probe_perf_reader_page_cnt);
if (!reader)
goto error;
int res, kfd = -1, pfd = -1, ns_fd = -1;
// Try create the uprobe Perf Event with perf_event_open API.
pfd = bpf_try_perf_event_open_with_probe(binary_path, offset, pid, event_type,
attach_type != BPF_PROBE_ENTRY);
// If failed, most likely Kernel doesn't support the new perf_event_open API
// yet. Try create the event using debugfs.
if (pfd < 0) {
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/%s_events", event_type);
kfd = open(buf, O_WRONLY | O_APPEND, 0);
......@@ -940,22 +930,25 @@ void *bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type,
goto error;
}
close(kfd);
kfd = -1;
exit_mount_ns(ns_fd);
ns_fd = -1;
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%ss/%s", event_type, event_alias);
}
if (bpf_attach_tracing_event(progfd, buf, reader, pid, pfd) < 0)
goto error;
return reader;
// If perf_event_open succeeded, bpf_attach_tracing_event will use the created
// Perf Event FD directly and buf would be empty and unused.
// Otherwise it will read the event ID from the path in buf, create the
// Perf Event event using that ID, and updated value of pfd.
if (bpf_attach_tracing_event(progfd, buf, pid, &pfd) == 0)
return pfd;
error:
if (kfd >= 0)
close(kfd);
exit_mount_ns(ns_fd);
perf_reader_free(reader);
return NULL;
bpf_close_perf_event_fd(pfd);
return -1;
}
static int bpf_detach_probe(const char *ev_name, const char *event_type)
......@@ -1036,26 +1029,19 @@ int bpf_detach_uprobe(const char *ev_name)
}
void *bpf_attach_tracepoint(int progfd, const char *tp_category,
const char *tp_name, perf_reader_cb cb,
void *cb_cookie) {
int bpf_attach_tracepoint(int progfd, const char *tp_category,
const char *tp_name)
{
char buf[256];
struct perf_reader *reader = NULL;
reader = perf_reader_new(cb, NULL, NULL, cb_cookie, probe_perf_reader_page_cnt);
if (!reader)
goto error;
int pfd = -1;
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%s/%s",
tp_category, tp_name);
if (bpf_attach_tracing_event(progfd, buf, reader, -1 /* PID */, -1 /* pfd */) < 0)
goto error;
if (bpf_attach_tracing_event(progfd, buf, -1 /* PID */, &pfd) == 0)
return pfd;
return reader;
error:
perf_reader_free(reader);
return NULL;
bpf_close_perf_event_fd(pfd);
return -1;
}
int bpf_detach_tracepoint(const char *tp_category, const char *tp_name) {
......
......@@ -70,22 +70,17 @@ typedef void (*perf_reader_cb)(void *cb_cookie, int pid, uint64_t callchain_num,
typedef void (*perf_reader_raw_cb)(void *cb_cookie, void *raw, int raw_size);
typedef void (*perf_reader_lost_cb)(void *cb_cookie, uint64_t lost);
void *bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
const char *ev_name, const char *fn_name,
perf_reader_cb cb, void *cb_cookie);
int bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
const char *ev_name, const char *fn_name);
int bpf_detach_kprobe(const char *ev_name);
void *bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type,
const char *ev_name, const char *binary_path,
uint64_t offset, pid_t pid, perf_reader_cb cb,
void *cb_cookie);
int bpf_attach_uprobe(int progfd, enum bpf_probe_attach_type attach_type,
const char *ev_name, const char *binary_path,
uint64_t offset, pid_t pid);
int bpf_detach_uprobe(const char *ev_name);
void *bpf_attach_tracepoint(int progfd, const char *tp_category,
const char *tp_name, perf_reader_cb cb,
void *cb_cookie);
int bpf_attach_tracepoint(int progfd, const char *tp_category,
const char *tp_name);
int bpf_detach_tracepoint(const char *tp_category, const char *tp_name);
void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb,
......
......@@ -24,6 +24,7 @@ local Bpf = class("BPF")
Bpf.static.open_kprobes = {}
Bpf.static.open_uprobes = {}
Bpf.static.perf_buffers = {}
Bpf.static.KPROBE_LIMIT = 1000
Bpf.static.tracer_pipe = nil
Bpf.static.DEFAULT_CFLAGS = {
......@@ -39,8 +40,8 @@ end
function Bpf.static.cleanup()
local function detach_all(probe_type, all_probes)
for key, probe in pairs(all_probes) do
libbcc.perf_reader_free(probe)
for key, fd in pairs(all_probes) do
libbcc.bpf_close_perf_event_fd(fd)
-- skip bcc-specific kprobes
if not key:starts("bcc:") then
if probe_type == "kprobes" then
......@@ -55,6 +56,12 @@ function Bpf.static.cleanup()
detach_all("kprobes", Bpf.static.open_kprobes)
detach_all("uprobes", Bpf.static.open_uprobes)
for key, perf_buffer in pairs(Bpf.static.perf_buffers) do
libbcc.perf_reader_free(perf_buffer)
Bpf.static.perf_buffers[key] = nil
end
if Bpf.static.tracer_pipe ~= nil then
Bpf.static.tracer_pipe:close()
end
......@@ -189,9 +196,9 @@ function Bpf:attach_uprobe(args)
local retprobe = args.retprobe and 1 or 0
local res = libbcc.bpf_attach_uprobe(fn.fd, retprobe, ev_name, path, addr,
args.pid or -1, nil, nil) -- TODO; reader callback
args.pid or -1)
assert(res ~= nil, "failed to attach BPF to uprobe")
assert(res >= 0, "failed to attach BPF to uprobe")
self:probe_store("uprobe", ev_name, res)
return self
end
......@@ -206,10 +213,9 @@ function Bpf:attach_kprobe(args)
local ev_name = string.format("%s_%s", ptype, event:gsub("[%+%.]", "_"))
local retprobe = args.retprobe and 1 or 0
local res = libbcc.bpf_attach_kprobe(fn.fd, retprobe, ev_name, event,
nil, nil) -- TODO; reader callback
local res = libbcc.bpf_attach_kprobe(fn.fd, retprobe, ev_name, event)
assert(res ~= nil, "failed to attach BPF to kprobe")
assert(res >= 0, "failed to attach BPF to kprobe")
self:probe_store("kprobe", ev_name, res)
return self
end
......@@ -228,16 +234,22 @@ function Bpf:get_table(name, key_type, leaf_type)
return self.tables[name]
end
function Bpf:probe_store(t, id, reader)
function Bpf:probe_store(t, id, fd)
if t == "kprobe" then
Bpf.open_kprobes[id] = reader
Bpf.open_kprobes[id] = fd
elseif t == "uprobe" then
Bpf.open_uprobes[id] = reader
Bpf.open_uprobes[id] = fd
else
error("unknown probe type '%s'" % t)
end
log.info("%s -> %s", id, reader)
log.info("%s -> %s", id, fd)
end
function Bpf:perf_buffer_store(t, id, reader)
Bpf.perf_buffers[id] = reader
log.info("%s -> %s", id, fd)
end
function Bpf:probe_lookup(t, id)
......@@ -250,32 +262,32 @@ function Bpf:probe_lookup(t, id)
end
end
function Bpf:_kprobe_array()
local kprobe_count = table.count(Bpf.open_kprobes)
local readers = ffi.new("struct perf_reader*[?]", kprobe_count)
function Bpf:_perf_buffer_array()
local perf_buffer_count = table.count(Bpf.perf_buffers)
local readers = ffi.new("struct perf_reader*[?]", perf_buffer_count)
local n = 0
for _, r in pairs(Bpf.open_kprobes) do
for _, r in pairs(Bpf.perf_buffers) do
readers[n] = r
n = n + 1
end
assert(n == kprobe_count)
assert(n == perf_buffer_count)
return readers, n
end
function Bpf:kprobe_poll_loop()
local probes, probe_count = self:_kprobe_array()
local perf_buffer, perf_buffer_count = self:_perf_buffer_array()
return pcall(function()
while true do
libbcc.perf_reader_poll(probe_count, probes, -1)
libbcc.perf_reader_poll(perf_buffer_count, perf_buffers, -1)
end
end)
end
function Bpf:kprobe_poll(timeout)
local probes, probe_count = self:_kprobe_array()
libbcc.perf_reader_poll(probe_count, probes, timeout or -1)
local perf_buffer, perf_buffer_count = self:_perf_buffer_array()
libbcc.perf_reader_poll(perf_buffer_count, perf_buffers, timeout or -1)
end
return Bpf
......@@ -39,23 +39,22 @@ int bpf_attach_socket(int sockfd, int progfd);
/* create RAW socket and bind to interface 'name' */
int bpf_open_raw_sock(const char *name);
typedef void (*perf_reader_cb)(void *cb_cookie, int pid, uint64_t callchain_num, void *callchain);
typedef void (*perf_reader_raw_cb)(void *cb_cookie, void *raw, int raw_size);
typedef void (*perf_reader_lost_cb)(void *cb_cookie, uint64_t lost);
void *bpf_attach_kprobe(int progfd, int attach_type, const char *ev_name,
const char *fn_name, perf_reader_cb cb,
void *cb_cookie);
int bpf_attach_kprobe(int progfd, int attach_type, const char *ev_name,
const char *fn_name);
int bpf_detach_kprobe(const char *ev_name);
void *bpf_attach_uprobe(int progfd, int attach_type, const char *ev_name,
const char *binary_path, uint64_t offset, int pid,
perf_reader_cb cb, void *cb_cookie);
int bpf_attach_uprobe(int progfd, int attach_type, const char *ev_name,
const char *binary_path, uint64_t offset, int pid);
int bpf_detach_uprobe(const char *ev_name);
void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, perf_reader_lost_cb lost_cb, void *cb_cookie, int pid, int cpu, int page_cnt);
int bpf_close_perf_event_fd(int fd);
]]
ffi.cdef[[
......
......@@ -263,7 +263,7 @@ function PerfEventArray:_open_perf_buffer(cpu, callback, ctype, page_cnt, lost_c
local fd = libbcc.perf_reader_fd(reader)
self:set(cpu, fd)
self.bpf:probe_store("kprobe", _perf_id(self.map_id, cpu), reader)
self.bpf:perf_buffer_store(_perf_id(self.map_id, cpu), reader)
self._callbacks[cpu] = _cb
end
......
This diff is collapsed.
......@@ -85,23 +85,19 @@ lib.bpf_attach_socket.argtypes = [ct.c_int, ct.c_int]
lib.bpf_prog_load.restype = ct.c_int
lib.bpf_prog_load.argtypes = [ct.c_int, ct.c_char_p, ct.c_void_p,
ct.c_size_t, ct.c_char_p, ct.c_uint, ct.c_int, ct.c_char_p, ct.c_uint]
lib.bpf_attach_kprobe.restype = ct.c_void_p
_CB_TYPE = ct.CFUNCTYPE(None, ct.py_object, ct.c_int,
ct.c_ulonglong, ct.POINTER(ct.c_ulonglong))
_RAW_CB_TYPE = ct.CFUNCTYPE(None, ct.py_object, ct.c_void_p, ct.c_int)
_LOST_CB_TYPE = ct.CFUNCTYPE(None, ct.py_object, ct.c_ulonglong)
lib.bpf_attach_kprobe.argtypes = [ct.c_int, ct.c_int, ct.c_char_p, ct.c_char_p,
_CB_TYPE, ct.py_object]
lib.bpf_attach_kprobe.restype = ct.c_int
lib.bpf_attach_kprobe.argtypes = [ct.c_int, ct.c_int, ct.c_char_p, ct.c_char_p]
lib.bpf_detach_kprobe.restype = ct.c_int
lib.bpf_detach_kprobe.argtypes = [ct.c_char_p]
lib.bpf_attach_uprobe.restype = ct.c_void_p
lib.bpf_attach_uprobe.restype = ct.c_int
lib.bpf_attach_uprobe.argtypes = [ct.c_int, ct.c_int, ct.c_char_p, ct.c_char_p,
ct.c_ulonglong, ct.c_int, _CB_TYPE, ct.py_object]
ct.c_ulonglong, ct.c_int]
lib.bpf_detach_uprobe.restype = ct.c_int
lib.bpf_detach_uprobe.argtypes = [ct.c_char_p]
lib.bpf_attach_tracepoint.restype = ct.c_void_p
lib.bpf_attach_tracepoint.argtypes = [ct.c_int, ct.c_char_p, ct.c_char_p,
_CB_TYPE, ct.py_object]
lib.bpf_attach_tracepoint.restype = ct.c_int
lib.bpf_attach_tracepoint.argtypes = [ct.c_int, ct.c_char_p, ct.c_char_p]
lib.bpf_detach_tracepoint.restype = ct.c_int
lib.bpf_detach_tracepoint.argtypes = [ct.c_char_p, ct.c_char_p]
lib.bpf_open_perf_buffer.restype = ct.c_void_p
......
......@@ -494,10 +494,10 @@ class PerfEventArray(ArrayBase):
# Delete entry from the array
super(PerfEventArray, self).__delitem__(key)
key_id = (id(self), key)
if key_id in self.bpf.open_kprobes:
if key_id in self.bpf.perf_buffers:
# The key is opened for perf ring buffer
lib.perf_reader_free(self.bpf.open_kprobes[key_id])
self.bpf._del_kprobe(key_id)
lib.perf_reader_free(self.bpf.perf_buffers[key_id])
del self.bpf.perf_buffers[key_id]
del self._cbs[key]
else:
# The key is opened for perf event read
......@@ -544,7 +544,7 @@ class PerfEventArray(ArrayBase):
raise Exception("Could not open perf buffer")
fd = lib.perf_reader_fd(reader)
self[self.Key(cpu)] = self.Leaf(fd)
self.bpf._add_kprobe((id(self), cpu), reader)
self.bpf.perf_buffers[(id(self), cpu)] = reader
# keep a refcnt
self._cbs[cpu] = (fn, lost_fn)
# The actual fd is held by the perf reader, add to track opened keys
......
......@@ -46,8 +46,6 @@ add_test(NAME py_test_clang WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${TEST_WRAPPER} py_clang sudo ${CMAKE_CURRENT_SOURCE_DIR}/test_clang.py)
add_test(NAME py_test_histogram WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${TEST_WRAPPER} py_histogram sudo ${CMAKE_CURRENT_SOURCE_DIR}/test_histogram.py)
add_test(NAME py_test_callchain WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${TEST_WRAPPER} py_callchain sudo ${CMAKE_CURRENT_SOURCE_DIR}/test_callchain.py)
add_test(NAME py_array WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${TEST_WRAPPER} py_array sudo ${CMAKE_CURRENT_SOURCE_DIR}/test_array.py)
add_test(NAME py_uprobes WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
......
#!/usr/bin/env python
# Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")
from bcc import BPF
import time
from unittest import main, TestCase
class TestCallchain(TestCase):
def test_callchain1(self):
hist = {}
def cb(pid, callchain):
counter = hist.get(callchain, 0)
counter += 1
hist[callchain] = counter
b = BPF(text="""
#include <linux/ptrace.h>
int kprobe__finish_task_switch(struct pt_regs *ctx) {
return 1;
}
""", cb=cb)
start = time.time()
while time.time() < start + 1:
b.kprobe_poll()
for k, v in hist.items():
syms = [b.ksym(addr) for addr in k]
print("%-08d:" % v, syms)
if __name__ == "__main__":
main()
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