Commit fdd2389c authored by Derek's avatar Derek

Handling multiple concurrent probe users.

    remove event_desc from front-end, handle it inside libbpf
    Event naming pattern changed to $(eventname)_bcc_$(pid)
parent 1888c167
...@@ -147,22 +147,18 @@ StatusTuple BPF::detach_all() { ...@@ -147,22 +147,18 @@ StatusTuple BPF::detach_all() {
StatusTuple BPF::attach_kprobe(const std::string& kernel_func, StatusTuple BPF::attach_kprobe(const std::string& kernel_func,
const std::string& probe_func, const std::string& probe_func,
bpf_attach_type attach_type, int attach_type,
pid_t pid, int cpu, int group_fd, pid_t pid, int cpu, int group_fd,
perf_reader_cb cb, void* cb_cookie) { perf_reader_cb cb, void* cb_cookie) {
std::string probe_event = get_kprobe_event(kernel_func, attach_type); std::string probe_event = get_kprobe_event(kernel_func, attach_type);
probe_event += "_bcc_" + std::to_string((long)getpid());
if (kprobes_.find(probe_event) != kprobes_.end()) if (kprobes_.find(probe_event) != kprobes_.end())
return StatusTuple(-1, "kprobe %s already attached", probe_event.c_str()); return StatusTuple(-1, "kprobe %s already attached", probe_event.c_str());
int probe_fd; int probe_fd;
TRY2(load_func(probe_func, BPF_PROG_TYPE_KPROBE, probe_fd)); TRY2(load_func(probe_func, BPF_PROG_TYPE_KPROBE, probe_fd));
std::string probe_event_desc = attach_type_prefix(attach_type);
probe_event_desc += ":kprobes/" + probe_event + " " + kernel_func;
void* res = void* res =
bpf_attach_kprobe(probe_fd, probe_event.c_str(), probe_event_desc.c_str(), bpf_attach_kprobe(probe_fd, attach_type, probe_event.c_str(), kernel_func.c_str(),
pid, cpu, group_fd, cb, cb_cookie); pid, cpu, group_fd, cb, cb_cookie);
if (!res) { if (!res) {
...@@ -183,7 +179,7 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path, ...@@ -183,7 +179,7 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,
const std::string& symbol, const std::string& symbol,
const std::string& probe_func, const std::string& probe_func,
uint64_t symbol_addr, uint64_t symbol_addr,
bpf_attach_type attach_type, int attach_type,
pid_t pid, int cpu, int group_fd, pid_t pid, int cpu, int group_fd,
perf_reader_cb cb, void* cb_cookie) { perf_reader_cb cb, void* cb_cookie) {
bcc_symbol sym = bcc_symbol(); bcc_symbol sym = bcc_symbol();
...@@ -197,13 +193,9 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path, ...@@ -197,13 +193,9 @@ StatusTuple BPF::attach_uprobe(const std::string& binary_path,
int probe_fd; int probe_fd;
TRY2(load_func(probe_func, BPF_PROG_TYPE_KPROBE, probe_fd)); TRY2(load_func(probe_func, BPF_PROG_TYPE_KPROBE, probe_fd));
std::string probe_event_desc = attach_type_prefix(attach_type);
probe_event_desc += ":uprobes/" + probe_event + " ";
probe_event_desc += binary_path + ":0x" + uint_to_hex(sym.offset);
void* res = void* res =
bpf_attach_uprobe(probe_fd, probe_event.c_str(), probe_event_desc.c_str(), bpf_attach_uprobe(probe_fd, attach_type, probe_event.c_str(), binary_path.c_str(),
pid, cpu, group_fd, cb, cb_cookie); sym.offset, pid, cpu, group_fd, cb, cb_cookie);
if (!res) { if (!res) {
TRY2(unload_func(probe_func)); TRY2(unload_func(probe_func));
...@@ -326,7 +318,7 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config, ...@@ -326,7 +318,7 @@ StatusTuple BPF::attach_perf_event(uint32_t ev_type, uint32_t ev_config,
} }
StatusTuple BPF::detach_kprobe(const std::string& kernel_func, StatusTuple BPF::detach_kprobe(const std::string& kernel_func,
bpf_attach_type attach_type) { int attach_type) {
std::string event = get_kprobe_event(kernel_func, attach_type); std::string event = get_kprobe_event(kernel_func, attach_type);
auto it = kprobes_.find(event); auto it = kprobes_.find(event);
...@@ -342,7 +334,7 @@ StatusTuple BPF::detach_kprobe(const std::string& kernel_func, ...@@ -342,7 +334,7 @@ StatusTuple BPF::detach_kprobe(const std::string& kernel_func,
StatusTuple BPF::detach_uprobe(const std::string& binary_path, StatusTuple BPF::detach_uprobe(const std::string& binary_path,
const std::string& symbol, uint64_t symbol_addr, const std::string& symbol, uint64_t symbol_addr,
bpf_attach_type attach_type) { int attach_type) {
bcc_symbol sym = bcc_symbol(); bcc_symbol sym = bcc_symbol();
TRY2(check_binary_symbol(binary_path, symbol, symbol_addr, &sym)); TRY2(check_binary_symbol(binary_path, symbol, symbol_addr, &sym));
...@@ -474,14 +466,14 @@ StatusTuple BPF::check_binary_symbol(const std::string& binary_path, ...@@ -474,14 +466,14 @@ StatusTuple BPF::check_binary_symbol(const std::string& binary_path,
} }
std::string BPF::get_kprobe_event(const std::string& kernel_func, std::string BPF::get_kprobe_event(const std::string& kernel_func,
bpf_attach_type type) { int type) {
std::string res = attach_type_prefix(type) + "_"; std::string res = attach_type_prefix(type) + "_";
res += sanitize_str(kernel_func, &BPF::kprobe_event_validator); res += sanitize_str(kernel_func, &BPF::kprobe_event_validator);
return res; return res;
} }
std::string BPF::get_uprobe_event(const std::string& binary_path, std::string BPF::get_uprobe_event(const std::string& binary_path,
uint64_t offset, bpf_attach_type type) { uint64_t offset, int type) {
std::string res = attach_type_prefix(type) + "_"; std::string res = attach_type_prefix(type) + "_";
res += sanitize_str(binary_path, &BPF::uprobe_path_validator); res += sanitize_str(binary_path, &BPF::uprobe_path_validator);
res += "_0x" + uint_to_hex(offset); res += "_0x" + uint_to_hex(offset);
...@@ -495,8 +487,7 @@ StatusTuple BPF::detach_kprobe_event(const std::string& event, ...@@ -495,8 +487,7 @@ StatusTuple BPF::detach_kprobe_event(const std::string& event,
attr.reader_ptr = nullptr; attr.reader_ptr = nullptr;
} }
TRY2(unload_func(attr.func)); TRY2(unload_func(attr.func));
std::string detach_event = "-:kprobes/" + event; if (bpf_detach_kprobe(event.c_str()) < 0)
if (bpf_detach_kprobe(detach_event.c_str(), event.c_str()) < 0)
return StatusTuple(-1, "Unable to detach kprobe %s", event.c_str()); return StatusTuple(-1, "Unable to detach kprobe %s", event.c_str());
return StatusTuple(0); return StatusTuple(0);
} }
...@@ -508,8 +499,7 @@ StatusTuple BPF::detach_uprobe_event(const std::string& event, ...@@ -508,8 +499,7 @@ StatusTuple BPF::detach_uprobe_event(const std::string& event,
attr.reader_ptr = nullptr; attr.reader_ptr = nullptr;
} }
TRY2(unload_func(attr.func)); TRY2(unload_func(attr.func));
std::string detach_event = "-:uprobes/" + event; if (bpf_detach_uprobe(event.c_str()) < 0)
if (bpf_detach_uprobe(detach_event.c_str(), event.c_str()) < 0)
return StatusTuple(-1, "Unable to detach uprobe %s", event.c_str()); return StatusTuple(-1, "Unable to detach uprobe %s", event.c_str());
return StatusTuple(0); return StatusTuple(0);
} }
......
...@@ -29,11 +29,6 @@ ...@@ -29,11 +29,6 @@
namespace ebpf { namespace ebpf {
enum class bpf_attach_type {
probe_entry,
probe_return
};
struct open_probe_t { struct open_probe_t {
void* reader_ptr; void* reader_ptr;
std::string func; std::string func;
...@@ -56,23 +51,23 @@ public: ...@@ -56,23 +51,23 @@ public:
StatusTuple attach_kprobe( StatusTuple attach_kprobe(
const std::string& kernel_func, const std::string& probe_func, const std::string& kernel_func, const std::string& probe_func,
bpf_attach_type attach_type = bpf_attach_type::probe_entry, int attach_type = BPF_PROBE_ENTRY,
pid_t pid = -1, int cpu = 0, int group_fd = -1, pid_t pid = -1, int cpu = 0, int group_fd = -1,
perf_reader_cb cb = nullptr, void* cb_cookie = nullptr); perf_reader_cb cb = nullptr, void* cb_cookie = nullptr);
StatusTuple detach_kprobe( StatusTuple detach_kprobe(
const std::string& kernel_func, const std::string& kernel_func,
bpf_attach_type attach_type = bpf_attach_type::probe_entry); int attach_type = BPF_PROBE_ENTRY);
StatusTuple attach_uprobe( StatusTuple attach_uprobe(
const std::string& binary_path, const std::string& symbol, const std::string& binary_path, const std::string& symbol,
const std::string& probe_func, uint64_t symbol_addr = 0, const std::string& probe_func, uint64_t symbol_addr = 0,
bpf_attach_type attach_type = bpf_attach_type::probe_entry, int attach_type = BPF_PROBE_ENTRY,
pid_t pid = -1, int cpu = 0, int group_fd = -1, pid_t pid = -1, int cpu = 0, int group_fd = -1,
perf_reader_cb cb = nullptr, void* cb_cookie = nullptr); perf_reader_cb cb = nullptr, void* cb_cookie = nullptr);
StatusTuple detach_uprobe( StatusTuple detach_uprobe(
const std::string& binary_path, const std::string& symbol, const std::string& binary_path, const std::string& symbol,
uint64_t symbol_addr = 0, uint64_t symbol_addr = 0,
bpf_attach_type attach_type = bpf_attach_type::probe_entry); int attach_type = BPF_PROBE_ENTRY);
StatusTuple attach_usdt(const USDT& usdt, pid_t pid = -1, int cpu = 0, StatusTuple attach_usdt(const USDT& usdt, pid_t pid = -1, int cpu = 0,
int group_fd = -1); int group_fd = -1);
StatusTuple detach_usdt(const USDT& usdt); StatusTuple detach_usdt(const USDT& usdt);
...@@ -111,9 +106,9 @@ private: ...@@ -111,9 +106,9 @@ private:
StatusTuple unload_func(const std::string& func_name); StatusTuple unload_func(const std::string& func_name);
std::string get_kprobe_event(const std::string& kernel_func, std::string get_kprobe_event(const std::string& kernel_func,
bpf_attach_type type); int attach_type);
std::string get_uprobe_event(const std::string& binary_path, uint64_t offset, std::string get_uprobe_event(const std::string& binary_path, uint64_t offset,
bpf_attach_type type); int attach_type);
StatusTuple detach_kprobe_event(const std::string& event, open_probe_t& attr); 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_uprobe_event(const std::string& event, open_probe_t& attr);
...@@ -121,21 +116,21 @@ private: ...@@ -121,21 +116,21 @@ private:
open_probe_t& attr); open_probe_t& attr);
StatusTuple detach_perf_event_all_cpu(open_probe_t& attr); StatusTuple detach_perf_event_all_cpu(open_probe_t& attr);
std::string attach_type_debug(bpf_attach_type type) { std::string attach_type_debug(int attach_type) {
switch (type) { switch (attach_type) {
case bpf_attach_type::probe_entry: case BPF_PROBE_ENTRY:
return ""; return "";
case bpf_attach_type::probe_return: case BPF_PROBE_RETURN:
return "return "; return "return ";
} }
return "ERROR"; return "ERROR";
} }
std::string attach_type_prefix(bpf_attach_type type) { std::string attach_type_prefix(int attach_type) {
switch (type) { switch (attach_type) {
case bpf_attach_type::probe_entry: case BPF_PROBE_ENTRY:
return "p"; return "p";
case bpf_attach_type::probe_return: case BPF_PROBE_RETURN:
return "r"; return "r";
} }
return "ERROR"; return "ERROR";
......
...@@ -338,14 +338,18 @@ static int bpf_attach_tracing_event(int progfd, const char *event_path, ...@@ -338,14 +338,18 @@ static int bpf_attach_tracing_event(int progfd, const char *event_path,
return 0; return 0;
} }
static void * bpf_attach_probe(int progfd, const char *event, void * bpf_attach_kprobe(int progfd, int attach_type, const char *ev_name,
const char *event_desc, const char *event_type, const char *fn_name,
pid_t pid, int cpu, int group_fd, pid_t pid, int cpu, int group_fd,
perf_reader_cb cb, void *cb_cookie) { perf_reader_cb cb, void *cb_cookie)
{
int kfd; int kfd;
char buf[256]; char buf[strlen(ev_name)+256];
char new_name[strlen(ev_name)+32];
struct perf_reader *reader = NULL; struct perf_reader *reader = NULL;
static char *event_type = "kprobe";
snprintf(new_name, sizeof(new_name), "%s_bcc_%d", ev_name, getpid());
reader = perf_reader_new(cb, NULL, cb_cookie); reader = perf_reader_new(cb, NULL, cb_cookie);
if (!reader) if (!reader)
goto error; goto error;
...@@ -357,8 +361,9 @@ static void * bpf_attach_probe(int progfd, const char *event, ...@@ -357,8 +361,9 @@ static void * bpf_attach_probe(int progfd, const char *event,
goto error; goto error;
} }
if (write(kfd, event_desc, strlen(event_desc)) < 0) { snprintf(buf, sizeof(buf), "%c:%ss/%s %s", attach_type==BPF_PROBE_ENTRY ? 'p' : 'r',
fprintf(stderr, "write(%s, \"%s\") failed: %s\n", buf, event_desc, strerror(errno)); event_type, new_name, fn_name);
if (write(kfd, buf, strlen(buf)) < 0) {
if (errno == EINVAL) if (errno == EINVAL)
fprintf(stderr, "check dmesg output for possible cause\n"); fprintf(stderr, "check dmesg output for possible cause\n");
close(kfd); close(kfd);
...@@ -367,46 +372,78 @@ static void * bpf_attach_probe(int progfd, const char *event, ...@@ -367,46 +372,78 @@ static void * bpf_attach_probe(int progfd, const char *event,
close(kfd); close(kfd);
if (access("/sys/kernel/debug/tracing/instances", F_OK) != -1) { if (access("/sys/kernel/debug/tracing/instances", F_OK) != -1) {
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/instances/%s", event); snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/instances/%s", new_name);
if (mkdir(buf, 0755) == -1) if (mkdir(buf, 0755) == -1)
goto retry; goto retry;
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/instances/%s/events/%ss/%s", event, event_type, event); snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/instances/%s/events/%ss/%s",
if (bpf_attach_tracing_event(progfd, buf, reader, pid, cpu, group_fd) == 0) new_name, event_type, new_name);
if (bpf_attach_tracing_event(progfd, buf, reader, pid, cpu, group_fd) == 0) {
goto out; goto out;
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/instances/%s", event); }
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/instances/%s", new_name);
rmdir(buf); rmdir(buf);
} }
retry: retry:
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%ss/%s", event_type, event); snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%ss/%s", event_type, new_name);
if (bpf_attach_tracing_event(progfd, buf, reader, pid, cpu, group_fd) < 0) if (bpf_attach_tracing_event(progfd, buf, reader, pid, cpu, group_fd) < 0)
goto error; goto error;
out: out:
return reader; return reader;
error: error:
perf_reader_free(reader); perf_reader_free(reader);
return NULL; return NULL;
}
void * bpf_attach_kprobe(int progfd, const char *event,
const char *event_desc,
pid_t pid, int cpu, int group_fd,
perf_reader_cb cb, void *cb_cookie) {
return bpf_attach_probe(progfd, event, event_desc, "kprobe", pid, cpu, group_fd, cb, cb_cookie);
} }
void * bpf_attach_uprobe(int progfd, const char *event, void * bpf_attach_uprobe(int progfd, int attach_type, const char *ev_name,
const char *event_desc, const char *binary_path, uint64_t offset,
pid_t pid, int cpu, int group_fd, pid_t pid, int cpu, int group_fd,
perf_reader_cb cb, void *cb_cookie) { perf_reader_cb cb, void *cb_cookie)
return bpf_attach_probe(progfd, event, event_desc, "uprobe", pid, cpu, group_fd, cb, cb_cookie); {
int kfd;
char buf[strlen(binary_path)+strlen(ev_name)+256];
char new_name[strlen(ev_name)+32];
struct perf_reader *reader = NULL;
static char *event_type = "uprobe";
snprintf(new_name, sizeof(new_name), "%s_bcc_%d", ev_name, getpid());
reader = perf_reader_new(cb, NULL, cb_cookie);
if (!reader)
goto error;
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/%s_events", event_type);
kfd = open(buf, O_WRONLY | O_APPEND, 0);
if (kfd < 0) {
fprintf(stderr, "open(%s): %s\n", buf, strerror(errno));
goto error;
}
snprintf(buf, sizeof(buf), "%c:%ss/%s %s:0x%lx", attach_type==BPF_PROBE_ENTRY ? 'p' : 'r',
event_type, new_name, binary_path, offset);
if (write(kfd, buf, strlen(buf)) < 0) {
if (errno == EINVAL)
fprintf(stderr, "check dmesg output for possible cause\n");
close(kfd);
goto error;
}
close(kfd);
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/events/%ss/%s", event_type, new_name);
if (bpf_attach_tracing_event(progfd, buf, reader, pid, cpu, group_fd) < 0)
goto error;
return reader;
error:
perf_reader_free(reader);
return NULL;
} }
static int bpf_detach_probe(const char *event_desc, const char *event_type, const char *event) { static int bpf_detach_probe(const char *ev_name, const char *event_type)
{
int kfd; int kfd;
char buf[strlen(ev_name)+256];
char buf[256];
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/%s_events", event_type); snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/%s_events", event_type);
kfd = open(buf, O_WRONLY | O_APPEND, 0); kfd = open(buf, O_WRONLY | O_APPEND, 0);
if (kfd < 0) { if (kfd < 0) {
...@@ -414,27 +451,34 @@ static int bpf_detach_probe(const char *event_desc, const char *event_type, cons ...@@ -414,27 +451,34 @@ static int bpf_detach_probe(const char *event_desc, const char *event_type, cons
return -1; return -1;
} }
if (write(kfd, event_desc, strlen(event_desc)) < 0) { snprintf(buf, sizeof(buf), "-:%ss/%s_bcc_%d", event_type, ev_name, getpid());
if (write(kfd, buf, strlen(buf)) < 0) {
fprintf(stderr, "write(%s): %s\n", buf, strerror(errno)); fprintf(stderr, "write(%s): %s\n", buf, strerror(errno));
close(kfd); close(kfd);
return -1; return -1;
} }
close(kfd); close(kfd);
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/instances/%s", event);
return 0;
}
int bpf_detach_kprobe(const char *ev_name)
{
char buf[strlen(ev_name)+256];
int ret = bpf_detach_probe(ev_name, "kprobe");
snprintf(buf, sizeof(buf), "/sys/kernel/debug/tracing/instances/%s_bcc_%d", ev_name, getpid());
if (access(buf, F_OK) != -1) { if (access(buf, F_OK) != -1) {
rmdir(buf); rmdir(buf);
} }
return 0; return ret;
} }
int bpf_detach_kprobe(const char *event_desc, const char *event) { int bpf_detach_uprobe(const char *ev_name)
return bpf_detach_probe(event_desc, "kprobe", event); {
return bpf_detach_probe(ev_name, "uprobe");
} }
int bpf_detach_uprobe(const char *event_desc, const char *event) {
return bpf_detach_probe(event_desc, "uprobe", event);
}
void * bpf_attach_tracepoint(int progfd, const char *tp_category, void * bpf_attach_tracepoint(int progfd, const char *tp_category,
const char *tp_name, int pid, int cpu, const char *tp_name, int pid, int cpu,
......
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
extern "C" { extern "C" {
#endif #endif
#define BPF_PROBE_ENTRY 0
#define BPF_PROBE_RETURN 1
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
int max_entries, int map_flags); int max_entries, int map_flags);
int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags); int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags);
...@@ -44,15 +47,19 @@ typedef void (*perf_reader_cb)(void *cb_cookie, int pid, uint64_t callchain_num, ...@@ -44,15 +47,19 @@ typedef void (*perf_reader_cb)(void *cb_cookie, int pid, uint64_t callchain_num,
void *callchain); void *callchain);
typedef void (*perf_reader_raw_cb)(void *cb_cookie, void *raw, int raw_size); typedef void (*perf_reader_raw_cb)(void *cb_cookie, void *raw, int raw_size);
void * bpf_attach_kprobe(int progfd, const char *event, const char *event_desc, void * bpf_attach_kprobe(int progfd, int attach_type, const char *ev_name,
int pid, int cpu, int group_fd, perf_reader_cb cb, const char *fn_name,
void *cb_cookie); pid_t pid, int cpu, int group_fd,
int bpf_detach_kprobe(const char *event_desc, const char *event); perf_reader_cb cb, void *cb_cookie);
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,
pid_t pid, int cpu, int group_fd,
perf_reader_cb cb, void *cb_cookie);
void * bpf_attach_uprobe(int progfd, const char *event, const char *event_desc, int bpf_detach_uprobe(const char *ev_name);
int pid, int cpu, int group_fd, perf_reader_cb cb,
void *cb_cookie);
int bpf_detach_uprobe(const char *event_desc, const char *event);
void * bpf_attach_tracepoint(int progfd, const char *tp_category, void * bpf_attach_tracepoint(int progfd, const char *tp_category,
const char *tp_name, int pid, int cpu, const char *tp_name, int pid, int cpu,
......
...@@ -14,10 +14,6 @@ See the License for the specific language governing permissions and ...@@ -14,10 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
]] ]]
local ffi = require("ffi") local ffi = require("ffi")
ffi.cdef[[
int getpid(void);
]]
local libbcc = require("bcc.libbcc") local libbcc = require("bcc.libbcc")
local TracerPipe = require("bcc.tracerpipe") local TracerPipe = require("bcc.tracerpipe")
...@@ -47,13 +43,10 @@ function Bpf.static.cleanup() ...@@ -47,13 +43,10 @@ function Bpf.static.cleanup()
libbcc.perf_reader_free(probe) libbcc.perf_reader_free(probe)
-- skip bcc-specific kprobes -- skip bcc-specific kprobes
if not key:starts("bcc:") then if not key:starts("bcc:") then
local desc = string.format("-:%s/%s", probe_type, key)
log.info("detaching %s", desc)
if probe_type == "kprobes" then if probe_type == "kprobes" then
libbcc.bpf_detach_kprobe(desc, key) libbcc.bpf_detach_kprobe(key)
elseif probe_type == "uprobes" then elseif probe_type == "uprobes" then
libbcc.bpf_detach_uprobe(desc, key) libbcc.bpf_detach_uprobe(key)
end end
end end
all_probes[key] = nil all_probes[key] = nil
...@@ -191,11 +184,9 @@ function Bpf:attach_uprobe(args) ...@@ -191,11 +184,9 @@ function Bpf:attach_uprobe(args)
local fn = self:load_func(args.fn_name, 'BPF_PROG_TYPE_KPROBE') local fn = self:load_func(args.fn_name, 'BPF_PROG_TYPE_KPROBE')
local ptype = args.retprobe and "r" or "p" local ptype = args.retprobe and "r" or "p"
local ev_name = string.format("%s_%s_0x%p", ptype, path:gsub("[^%a%d]", "_"), addr) local ev_name = string.format("%s_%s_0x%p", ptype, path:gsub("[^%a%d]", "_"), addr)
local desc = string.format("%s:uprobes/%s %s:0x%p", ptype, ev_name, path, addr) local retprobe = args.retprobe and 1 or 0
log.info(desc) local res = libbcc.bpf_attach_uprobe(fn.fd, retprobe, ev_name, path, addr,
local res = libbcc.bpf_attach_uprobe(fn.fd, ev_name, desc,
args.pid or -1, args.pid or -1,
args.cpu or 0, args.cpu or 0,
args.group_fd or -1, nil, nil) -- TODO; reader callback args.group_fd or -1, nil, nil) -- TODO; reader callback
...@@ -213,12 +204,9 @@ function Bpf:attach_kprobe(args) ...@@ -213,12 +204,9 @@ function Bpf:attach_kprobe(args)
local event = args.event or "" local event = args.event or ""
local ptype = args.retprobe and "r" or "p" local ptype = args.retprobe and "r" or "p"
local ev_name = string.format("%s_%s", ptype, event:gsub("[%+%.]", "_")) local ev_name = string.format("%s_%s", ptype, event:gsub("[%+%.]", "_"))
local ev_name = string.format("%s_bcc_%s", ev_name, ffi.C.getpid()); local retprobe = args.retprobe and 1 or 0
local desc = string.format("%s:kprobes/%s %s", ptype, ev_name, event)
log.info(desc)
local res = libbcc.bpf_attach_kprobe(fn.fd, ev_name, desc, local res = libbcc.bpf_attach_kprobe(fn.fd, retprobe, ev_name, event,
args.pid or -1, args.pid or -1,
args.cpu or 0, args.cpu or 0,
args.group_fd or -1, nil, nil) -- TODO; reader callback args.group_fd or -1, nil, nil) -- TODO; reader callback
......
...@@ -40,13 +40,19 @@ int bpf_open_raw_sock(const char *name); ...@@ -40,13 +40,19 @@ 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_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_raw_cb)(void *cb_cookie, void *raw, int raw_size);
void * bpf_attach_kprobe(int progfd, const char *event, const char *event_desc, void * bpf_attach_kprobe(int progfd, int attach_type, const char *ev_name,
int pid, int cpu, int group_fd, perf_reader_cb cb, void *cb_cookie); const char *fn_name,
int bpf_detach_kprobe(const char *event_desc, const char *event); int pid, int cpu, int group_fd,
perf_reader_cb cb, void *cb_cookie);
void * bpf_attach_uprobe(int progfd, const char *event, const char *event_desc, int bpf_detach_kprobe(const char *ev_name);
int pid, int cpu, int group_fd, perf_reader_cb cb, void *cb_cookie);
int bpf_detach_uprobe(const char *event_desc, const char *event); void * bpf_attach_uprobe(int progfd, int attach_type, const char *ev_name,
const char *binary_path, uint64_t offset,
int pid, int cpu, int group_fd,
perf_reader_cb cb, void *cb_cookie);
int bpf_detach_uprobe(const char *ev_name);
void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, void *cb_cookie, int pid, int cpu); void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, void *cb_cookie, int pid, int cpu);
]] ]]
......
...@@ -455,14 +455,12 @@ class BPF(object): ...@@ -455,14 +455,12 @@ class BPF(object):
pass pass
return return
event = str(event)
self._check_probe_quota(1) self._check_probe_quota(1)
fn = self.load_func(fn_name, BPF.KPROBE) fn = self.load_func(fn_name, BPF.KPROBE)
ev_name = "p_" + event.replace("+", "_").replace(".", "_") event = str(event).replace("+", "_").replace(".", "_")
ev_name += "_bcc_" + str(os.getpid()) ev_name = "p_" + event
desc = "p:kprobes/%s %s" % (ev_name, event) res = lib.bpf_attach_kprobe(fn.fd, 0, ev_name.encode("ascii"),
res = lib.bpf_attach_kprobe(fn.fd, ev_name.encode("ascii"), event.encode("ascii"), pid, cpu, group_fd,
desc.encode("ascii"), pid, cpu, group_fd,
self._reader_cb_impl, ct.cast(id(self), ct.py_object)) self._reader_cb_impl, ct.cast(id(self), ct.py_object))
res = ct.cast(res, ct.c_void_p) res = ct.cast(res, ct.c_void_p)
if not res: if not res:
...@@ -473,12 +471,10 @@ class BPF(object): ...@@ -473,12 +471,10 @@ class BPF(object):
def detach_kprobe(self, event): def detach_kprobe(self, event):
event = str(event) event = str(event)
ev_name = "p_" + event.replace("+", "_").replace(".", "_") ev_name = "p_" + event.replace("+", "_").replace(".", "_")
ev_name += "_bcc_" + str(os.getpid())
if ev_name not in self.open_kprobes: if ev_name not in self.open_kprobes:
raise Exception("Kprobe %s is not attached" % event) raise Exception("Kprobe %s is not attached" % event)
lib.perf_reader_free(self.open_kprobes[ev_name]) lib.perf_reader_free(self.open_kprobes[ev_name])
desc = "-:kprobes/%s" % ev_name res = lib.bpf_detach_kprobe(ev_name.encode("ascii"))
res = lib.bpf_detach_kprobe(desc.encode("ascii"), ev_name.encode("ascii"))
if res < 0: if res < 0:
raise Exception("Failed to detach BPF from kprobe") raise Exception("Failed to detach BPF from kprobe")
self._del_kprobe(ev_name) self._del_kprobe(ev_name)
...@@ -496,14 +492,12 @@ class BPF(object): ...@@ -496,14 +492,12 @@ class BPF(object):
pass pass
return return
event = str(event) event = str(event).replace("+", "_").replace(".", "_")
self._check_probe_quota(1) self._check_probe_quota(1)
fn = self.load_func(fn_name, BPF.KPROBE) fn = self.load_func(fn_name, BPF.KPROBE)
ev_name = "r_" + event.replace("+", "_").replace(".", "_") ev_name = "r_" + event
ev_name += "_bcc_" + str(os.getpid()) res = lib.bpf_attach_kprobe(fn.fd, 1, ev_name.encode("ascii"),
desc = "r:kprobes/%s %s" % (ev_name, event) event.encode("ascii"), pid, cpu, group_fd,
res = lib.bpf_attach_kprobe(fn.fd, ev_name.encode("ascii"),
desc.encode("ascii"), pid, cpu, group_fd,
self._reader_cb_impl, ct.cast(id(self), ct.py_object)) self._reader_cb_impl, ct.cast(id(self), ct.py_object))
res = ct.cast(res, ct.c_void_p) res = ct.cast(res, ct.c_void_p)
if not res: if not res:
...@@ -514,12 +508,10 @@ class BPF(object): ...@@ -514,12 +508,10 @@ class BPF(object):
def detach_kretprobe(self, event): def detach_kretprobe(self, event):
event = str(event) event = str(event)
ev_name = "r_" + event.replace("+", "_").replace(".", "_") ev_name = "r_" + event.replace("+", "_").replace(".", "_")
ev_name += "_bcc_" + str(os.getpid())
if ev_name not in self.open_kprobes: if ev_name not in self.open_kprobes:
raise Exception("Kretprobe %s is not attached" % event) raise Exception("Kretprobe %s is not attached" % event)
lib.perf_reader_free(self.open_kprobes[ev_name]) lib.perf_reader_free(self.open_kprobes[ev_name])
desc = "-:kprobes/%s" % ev_name res = lib.bpf_detach_kprobe(ev_name.encode("ascii"))
res = lib.bpf_detach_kprobe(desc.encode("ascii"), ev_name.encode("ascii"))
if res < 0: if res < 0:
raise Exception("Failed to detach BPF from kprobe") raise Exception("Failed to detach BPF from kprobe")
self._del_kprobe(ev_name) self._del_kprobe(ev_name)
...@@ -771,9 +763,8 @@ class BPF(object): ...@@ -771,9 +763,8 @@ class BPF(object):
self._check_probe_quota(1) self._check_probe_quota(1)
fn = self.load_func(fn_name, BPF.KPROBE) fn = self.load_func(fn_name, BPF.KPROBE)
ev_name = "p_%s_0x%x" % (self._probe_repl.sub("_", path), addr) ev_name = "p_%s_0x%x" % (self._probe_repl.sub("_", path), addr)
desc = "p:uprobes/%s %s:0x%x" % (ev_name, path, addr) res = lib.bpf_attach_uprobe(fn.fd, 0, ev_name.encode("ascii"),
res = lib.bpf_attach_uprobe(fn.fd, ev_name.encode("ascii"), path, addr, pid, cpu, group_fd,
desc.encode("ascii"), pid, cpu, group_fd,
self._reader_cb_impl, ct.cast(id(self), ct.py_object)) self._reader_cb_impl, ct.cast(id(self), ct.py_object))
res = ct.cast(res, ct.c_void_p) res = ct.cast(res, ct.c_void_p)
if not res: if not res:
...@@ -794,8 +785,7 @@ class BPF(object): ...@@ -794,8 +785,7 @@ class BPF(object):
if ev_name not in self.open_uprobes: if ev_name not in self.open_uprobes:
raise Exception("Uprobe %s is not attached" % ev_name) raise Exception("Uprobe %s is not attached" % ev_name)
lib.perf_reader_free(self.open_uprobes[ev_name]) lib.perf_reader_free(self.open_uprobes[ev_name])
desc = "-:uprobes/%s" % ev_name res = lib.bpf_detach_uprobe(ev_name.encode("ascii"))
res = lib.bpf_detach_uprobe(desc.encode("ascii"), ev_name.encode("ascii"))
if res < 0: if res < 0:
raise Exception("Failed to detach BPF from uprobe") raise Exception("Failed to detach BPF from uprobe")
self._del_uprobe(ev_name) self._del_uprobe(ev_name)
...@@ -823,9 +813,8 @@ class BPF(object): ...@@ -823,9 +813,8 @@ class BPF(object):
self._check_probe_quota(1) self._check_probe_quota(1)
fn = self.load_func(fn_name, BPF.KPROBE) fn = self.load_func(fn_name, BPF.KPROBE)
ev_name = "r_%s_0x%x" % (self._probe_repl.sub("_", path), addr) ev_name = "r_%s_0x%x" % (self._probe_repl.sub("_", path), addr)
desc = "r:uprobes/%s %s:0x%x" % (ev_name, path, addr) res = lib.bpf_attach_uprobe(fn.fd, 1, ev_name.encode("ascii"),
res = lib.bpf_attach_uprobe(fn.fd, ev_name.encode("ascii"), path, addr, pid, cpu, group_fd,
desc.encode("ascii"), pid, cpu, group_fd,
self._reader_cb_impl, ct.cast(id(self), ct.py_object)) self._reader_cb_impl, ct.cast(id(self), ct.py_object))
res = ct.cast(res, ct.c_void_p) res = ct.cast(res, ct.c_void_p)
if not res: if not res:
...@@ -846,8 +835,7 @@ class BPF(object): ...@@ -846,8 +835,7 @@ class BPF(object):
if ev_name not in self.open_uprobes: if ev_name not in self.open_uprobes:
raise Exception("Uretprobe %s is not attached" % ev_name) raise Exception("Uretprobe %s is not attached" % ev_name)
lib.perf_reader_free(self.open_uprobes[ev_name]) lib.perf_reader_free(self.open_uprobes[ev_name])
desc = "-:uprobes/%s" % ev_name res = lib.bpf_detach_uprobe(ev_name.encode("ascii"))
res = lib.bpf_detach_uprobe(desc.encode("ascii"), ev_name.encode("ascii"))
if res < 0: if res < 0:
raise Exception("Failed to detach BPF from uprobe") raise Exception("Failed to detach BPF from uprobe")
self._del_uprobe(ev_name) self._del_uprobe(ev_name)
...@@ -1049,13 +1037,11 @@ class BPF(object): ...@@ -1049,13 +1037,11 @@ class BPF(object):
lib.perf_reader_free(v) lib.perf_reader_free(v)
# non-string keys here include the perf_events reader # non-string keys here include the perf_events reader
if isinstance(k, str): if isinstance(k, str):
desc = "-:kprobes/%s" % k lib.bpf_detach_kprobe(str(k).encode("ascii"))
lib.bpf_detach_kprobe(desc.encode("ascii"), str(k).encode("ascii"))
self._del_kprobe(k) self._del_kprobe(k)
for k, v in list(self.open_uprobes.items()): for k, v in list(self.open_uprobes.items()):
lib.perf_reader_free(v) lib.perf_reader_free(v)
desc = "-:uprobes/%s" % k lib.bpf_detach_uprobe(str(k).encode("ascii"))
lib.bpf_detach_uprobe(desc.encode("ascii"), str(k).encode("ascii"))
self._del_uprobe(k) self._del_uprobe(k)
for k, v in self.open_tracepoints.items(): for k, v in self.open_tracepoints.items():
lib.perf_reader_free(v) lib.perf_reader_free(v)
......
...@@ -87,15 +87,15 @@ lib.bpf_attach_kprobe.restype = ct.c_void_p ...@@ -87,15 +87,15 @@ lib.bpf_attach_kprobe.restype = ct.c_void_p
_CB_TYPE = ct.CFUNCTYPE(None, ct.py_object, ct.c_int, _CB_TYPE = ct.CFUNCTYPE(None, ct.py_object, ct.c_int,
ct.c_ulonglong, ct.POINTER(ct.c_ulonglong)) ct.c_ulonglong, ct.POINTER(ct.c_ulonglong))
_RAW_CB_TYPE = ct.CFUNCTYPE(None, ct.py_object, ct.c_void_p, ct.c_int) _RAW_CB_TYPE = ct.CFUNCTYPE(None, ct.py_object, ct.c_void_p, ct.c_int)
lib.bpf_attach_kprobe.argtypes = [ct.c_int, ct.c_char_p, ct.c_char_p, ct.c_int, lib.bpf_attach_kprobe.argtypes = [ct.c_int, ct.c_int, ct.c_char_p, ct.c_char_p, ct.c_int,
ct.c_int, ct.c_int, _CB_TYPE, ct.py_object] ct.c_int, ct.c_int, _CB_TYPE, ct.py_object]
lib.bpf_detach_kprobe.restype = ct.c_int lib.bpf_detach_kprobe.restype = ct.c_int
lib.bpf_detach_kprobe.argtypes = [ct.c_char_p, ct.c_char_p] 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_void_p
lib.bpf_attach_uprobe.argtypes = [ct.c_int, ct.c_char_p, ct.c_char_p, ct.c_int, lib.bpf_attach_uprobe.argtypes = [ct.c_int, ct.c_int, ct.c_char_p, ct.c_char_p,
ct.c_int, ct.c_int, _CB_TYPE, ct.py_object] ct.c_ulonglong, ct.c_int, ct.c_int, ct.c_int, _CB_TYPE, ct.py_object]
lib.bpf_detach_uprobe.restype = ct.c_int lib.bpf_detach_uprobe.restype = ct.c_int
lib.bpf_detach_uprobe.argtypes = [ct.c_char_p, ct.c_char_p] lib.bpf_detach_uprobe.argtypes = [ct.c_char_p]
lib.bpf_attach_tracepoint.restype = ct.c_void_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, ct.c_int, lib.bpf_attach_tracepoint.argtypes = [ct.c_int, ct.c_char_p, ct.c_char_p, ct.c_int,
ct.c_int, ct.c_int, _CB_TYPE, ct.py_object] ct.c_int, ct.c_int, _CB_TYPE, ct.py_object]
......
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