Skip to content

Commit

Permalink
runtime: add kernel user perf event array and per cpu array (#68)
Browse files Browse the repository at this point in the history
* Stage commits

* Ignore enabling of non-uprobe attachings

* Re-organize map impls

* Update map implementation of kernel-user perf array

* Update

* Make malloc work

* Update

* Stage changes

* update

* Initial working shared perf event array

* final

* PERF_EVENT_IOC_DISABLE

* Fix

* update DEFAULT_MAX_FD

* Revert some changes

* Update changes
  • Loading branch information
Officeyutong authored Nov 6, 2023
1 parent 34128a1 commit 66b2403
Show file tree
Hide file tree
Showing 45 changed files with 1,099 additions and 168 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ test.txt
test.gdb
index.html*
dump*
test*
### VisualStudioCode ###
.vscode/settings.json
.vscode/runtime.json
Expand Down
16 changes: 8 additions & 8 deletions daemon/kernel/bpf_kernel_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ const volatile bool submit_bpf_events = 0;

static __always_inline bool filter_target(void)
{
u64 pid = bpf_get_current_pid_tgid() >> 32;
u64 pid = bpf_get_current_pid_tgid() & 0xffffffff;
if (target_pid && pid != target_pid) {
// filter target pid
// filter target pid
return false;
}
if (current_pid && pid == current_pid) {
// avoid breaking current process
return false;
}
return true;
if (current_pid && pid == current_pid) {
// avoid breaking current process
return false;
}
return true;
}

#endif // BPFTIME_KERNEL_CONFIG_H
#endif // BPFTIME_KERNEL_CONFIG_H
66 changes: 47 additions & 19 deletions daemon/kernel/bpf_tracer.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ static int process_bpf_prog_load_events(union bpf_attr *attr)
// check whether write is success
bpf_probe_read_user(&new_attr, sizeof(new_attr), attr);
if (new_attr.insn_cnt != 2) {
bpf_printk("write failed\n");
bpf_printk("bpftime: write failed\n");
}
}
return 0;
Expand All @@ -210,6 +210,7 @@ SEC("tracepoint/syscalls/sys_enter_bpf")
int tracepoint__syscalls__sys_enter_bpf(struct trace_event_raw_sys_enter *ctx)
{
if (!filter_target()) {
bpf_printk("bpftime: Skipping sys enter bpf");
return 0;
}

Expand All @@ -226,9 +227,8 @@ int tracepoint__syscalls__sys_enter_bpf(struct trace_event_raw_sys_enter *ctx)
process_bpf_syscall_enter(ctx);
return 0;
}

inline struct event *get_ringbuf_sys_exit_bpf_event(struct bpf_args_t *ap,
int ret)
static __always_inline struct event *
get_ringbuf_sys_exit_bpf_event(struct bpf_args_t *ap, int ret)
{
struct event *event = fill_basic_event_info();
if (!event) {
Expand Down Expand Up @@ -257,47 +257,68 @@ static int process_bpf_syscall_exit(struct bpf_args_t *ap, int ret)
&bpf_progs_new_fd_args_map, &pid_tgid);
if (!id_ptr)
return 0; /* missed entry */
bpf_map_delete_elem(&bpf_progs_new_fd_args_map,
&pid_tgid);
// bpf_map_delete_elem(&bpf_progs_new_fd_args_map,
// &pid_tgid);
struct bpf_fd_data data = { .type = BPF_FD_TYPE_PROG,
.kernel_id = *id_ptr };

set_bpf_fd_data(ret, &data);
bpf_printk("bpf_prog_load exit id: %d fd: %d\n",
*id_ptr, ret);
bpf_printk(
"bpftime: bpf_prog_load exit id: %d fd: %d\n",
*id_ptr, ret);
break;
}

case BPF_MAP_CREATE: {
u64 pid_tgid = bpf_get_current_pid_tgid();
u32 *id_ptr = (u32 *)bpf_map_lookup_elem(
&bpf_map_new_fd_args_map, &pid_tgid);
if (!id_ptr)
return 0; /* missed entry */
bpf_map_delete_elem(&bpf_map_new_fd_args_map,
&pid_tgid);
u32 id = *id_ptr;
// bpf_map_delete_elem(&bpf_map_new_fd_args_map,
// &pid_tgid);
struct bpf_fd_data data = { .type = BPF_FD_TYPE_MAP,
.kernel_id = *id_ptr };
.kernel_id = id };
// record map fd and id
set_bpf_fd_data(ret, &data);
bpf_printk("bpf_map_create exit id: %d fd: %d\n",
*id_ptr, ret);
bpf_printk(
"bpftime: bpf_map_create exit id: %d fd: %d\n",
id, ret);
if (submit_bpf_events) {
// submit event to user for record
struct event *event =
get_ringbuf_sys_exit_bpf_event(ap, ret);
event->bpf_data.map_id = *id_ptr;
// Make verifier happy
if (!event)
return 0;
event->bpf_data.map_id = (int)id;
bpf_ringbuf_submit(event, 0);
}
break;
}
case BPF_LINK_CREATE: {
u64 pid_tgid = bpf_get_current_pid_tgid();
u32 *id_ptr = (u32 *)bpf_map_lookup_elem(
&bpf_progs_new_fd_args_map, &pid_tgid);
if (!id_ptr) {
bpf_printk(
"bpftime: Unable to get prog id when creating link");
return 0; /* missed entry */
}
u32 id = *id_ptr;
// bpf_map_delete_elem(&bpf_map_new_fd_args_map,
// &pid_tgid);
struct bpf_fd_data data = { .type = BPF_FD_TYPE_OTHERS,
.kernel_id = 0 };
.kernel_id = id };
set_bpf_fd_data(ret, &data);
bpf_printk("bpftime: bpf_link_create");
if (submit_bpf_events) {
bpf_printk("bpftime: Submitting link creation");
struct event *event =
get_ringbuf_sys_exit_bpf_event(ap, ret);
if (!event)
return 0;
bpf_ringbuf_submit(event, 0);
}
break;
Expand All @@ -309,6 +330,8 @@ static int process_bpf_syscall_exit(struct bpf_args_t *ap, int ret)
if (submit_bpf_events) {
struct event *event =
get_ringbuf_sys_exit_bpf_event(ap, ret);
if (!event)
return 0;
bpf_ringbuf_submit(event, 0);
}
break;
Expand Down Expand Up @@ -356,7 +379,7 @@ process_perf_event_open_enter(struct trace_event_raw_sys_enter *ctx)
// found uprobe
if (enable_replace_uprobe) {
new_attr.probe_offset = 0;
int size = bpf_probe_read_user_str(
long size = bpf_probe_read_user_str(
old_uprobe_path, sizeof(old_uprobe_path),
(void *)new_attr.uprobe_path);
if (size <= 0) {
Expand All @@ -367,8 +390,13 @@ process_perf_event_open_enter(struct trace_event_raw_sys_enter *ctx)
size = PATH_LENTH;
}
bpf_probe_write_user((void *)new_attr.uprobe_path,
new_uprobe_path, size);
&new_uprobe_path, (size_t)size);
bpf_probe_write_user(attr, &new_attr, sizeof(new_attr));

char buf[64];
bpf_probe_read_user_str(buf, sizeof(buf),
(void *)new_attr.uprobe_path);
bpf_printk("Writting new uprobe path: %s", buf);
}
return 0;
}
Expand Down Expand Up @@ -408,7 +436,7 @@ int tracepoint__syscalls__sys_enter_perf_event_open(
args.cpu = (int)ctx->args[2];
bpf_probe_read_user_str(args.name_or_path, PATH_LENTH,
(const void *)args.attr.uprobe_path);

bpf_printk("Received path: %s", args.name_or_path);
u64 pid_tgid = bpf_get_current_pid_tgid();
bpf_map_update_elem(&perf_event_open_param_start, &pid_tgid, &args, 0);

Expand Down
11 changes: 9 additions & 2 deletions daemon/user/bpf_tracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ static int libbpf_print_fn(enum libbpf_print_level level, const char *format,
{
if (level == LIBBPF_DEBUG && !verbose)
return 0;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
return vfprintf(stderr, format, args);
#pragma GCC diagnostic pop
}

static void sig_int(int signo)
Expand Down Expand Up @@ -75,12 +78,16 @@ int bpftime::start_daemon(struct daemon_config env)
/* initialize global data (filtering options) */
obj->rodata->target_pid = env.pid;
obj->rodata->enable_replace_prog = env.enable_replace_prog;
strncpy(obj->rodata->new_uprobe_path, env.new_uprobe_path, PATH_LENTH);
// strncpy(obj->rodata->new_uprobe_path, env.new_uprobe_path,
// PATH_LENTH);
#warning FIXME: currently using `/a` as the replacing executable path to uprobe perf event in the kernel, since long strings (such as bpftime_daemon it self) may break userspace memory. Find a better way to solve this in the future
strncpy(obj->rodata->new_uprobe_path, "/a", PATH_LENTH);

obj->rodata->enable_replace_uprobe = env.enable_replace_uprobe;
obj->rodata->uprobe_perf_type = determine_uprobe_perf_type();
obj->rodata->kprobe_perf_type = determine_kprobe_perf_type();
obj->rodata->submit_bpf_events = env.submit_bpf_events;

obj->rodata->current_pid = getpid();
if (!env.show_open) {
bpf_program__set_autoload(
obj->progs.tracepoint__syscalls__sys_exit_open, false);
Expand Down
51 changes: 34 additions & 17 deletions daemon/user/bpftime_driver.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "bpftime_driver.hpp"
#include <linux/bpf.h>
#include <bpf/bpf.h>
#include "ebpf-vm.h"
#include "ebpf_inst.h"
#include <spdlog/spdlog.h>
#include "bpftime_shm.hpp"
Expand Down Expand Up @@ -42,7 +41,7 @@ static int get_kernel_bpf_prog_insns(int fd, const bpf_prog_info *info,

struct bpf_insn_data insn_data;

static int get_bpf_map_id_from_pid_fd(bpf_tracer_bpf *obj, int pid, int fd)
static int get_bpf_obj_id_from_pid_fd(bpf_tracer_bpf *obj, int pid, int fd)
{
unsigned long long key = MAKE_PFD(pid, fd);
int map_id = -1;
Expand All @@ -55,10 +54,10 @@ static int get_bpf_map_id_from_pid_fd(bpf_tracer_bpf *obj, int pid, int fd)
pid, fd);
return -1;
}
if (data.type != BPF_FD_TYPE_MAP) {
spdlog::error("Invalid bpf fd type {} for pid {} fd {}",
data.type, pid, fd);
}
// if (data.type != BPF_FD_TYPE_MAP) {
// spdlog::error("Invalid bpf fd type {} for pid {} fd {}",
// (int)data.type, pid, fd);
// }
map_id = data.kernel_id;
return map_id;
}
Expand Down Expand Up @@ -90,7 +89,7 @@ static int relocate_bpf_prog_insns(std::vector<ebpf_inst> &insns,
switch (inst.code) {
case EBPF_OP_LDDW:
if (inst.src_reg == 1 || inst.src_reg == 2) {
int map_id = get_bpf_map_id_from_pid_fd(
int map_id = get_bpf_obj_id_from_pid_fd(
obj, pid, inst.imm);
if (map_id < 0) {
return -1;
Expand Down Expand Up @@ -154,7 +153,8 @@ int bpftime_driver::bpftime_progs_create_server(int kernel_id, int server_pid)
{
int fd = bpf_prog_get_fd_by_id(kernel_id);
if (fd < 0) {
spdlog::error("Failed to get prog fd for id {}", kernel_id);
spdlog::error("Failed to get prog fd by prog id {}, err={}",
kernel_id, errno);
return -1;
}
spdlog::debug("get prog fd {} for id {}", fd, kernel_id);
Expand All @@ -177,13 +177,14 @@ int bpftime_driver::bpftime_progs_create_server(int kernel_id, int server_pid)
kernel_id);
return -1;
}
res = bpftime_progs_create(kernel_id, buffer.data(), buffer.size(),
info.name, info.type);
res = bpftime_progs_create(kernel_id,
buffer.data(), buffer.size(), info.name,
info.type);
if (res < 0) {
spdlog::error("Failed to create prog for id {}", kernel_id);
return -1;
}
spdlog::info("create prog {} in shm success", kernel_id);
spdlog::info("create prog {}, fd {} in shm success", kernel_id, fd);
// check and created related maps
res = check_and_create_prog_related_maps(fd, &info);
if (res < 0) {
Expand Down Expand Up @@ -237,7 +238,20 @@ int bpftime_driver::bpftime_maps_create_server(int kernel_id)
spdlog::info("create map in kernel id {}", kernel_id);
return kernel_id;
}

int bpftime_driver::bpftime_attach_perf_to_bpf_fd_server(int server_pid,
int perf_fd,
int bpf_prog_fd)
{
int prog_id =
get_bpf_obj_id_from_pid_fd(object, server_pid, bpf_prog_fd);
if (prog_id < 0) {
spdlog::error(
"Failed to lookup bpf prog id from bpf prog fd {}",
bpf_prog_fd);
return -1;
}
return bpftime_attach_perf_to_bpf_server(server_pid, perf_fd, prog_id);
}
int bpftime_driver::bpftime_attach_perf_to_bpf_server(int server_pid,
int perf_fd,
int kernel_bpf_id)
Expand All @@ -254,13 +268,15 @@ int bpftime_driver::bpftime_attach_perf_to_bpf_server(int server_pid,
int res =
bpftime_progs_create_server(kernel_bpf_id, server_pid);
if (res < 0) {
spdlog::error("Failed to create bpf for id {}",
kernel_bpf_id);
spdlog::error(
"Failed to create bpf program (userspace side) for kernel program id {}",
kernel_bpf_id);
return -1;
}
}

int res = bpftime_attach_perf_to_bpf(perf_id, kernel_bpf_id);
int res = bpftime_attach_perf_to_bpf(
perf_id, kernel_bpf_id);
if (res < 0) {
spdlog::error("Failed to attach perf to bpf");
return -1;
Expand Down Expand Up @@ -297,8 +313,9 @@ int bpftime_driver::bpftime_perf_event_enable_server(int server_pid, int fd)
{
int fd_id = check_and_get_pid_fd(server_pid, fd);
if (fd_id < 0) {
spdlog::error("fd {} for pid {} not exists", fd, server_pid);
return -1;
spdlog::warn("Unrecorded uprobe fd: {} for pid {}", fd,
server_pid);
return 0;
}
int res = bpftime_perf_event_enable(fd_id);
if (res < 0) {
Expand Down
7 changes: 4 additions & 3 deletions daemon/user/bpftime_driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
#define BPFTIME_DRIVER_HPP

#include "daemon_config.hpp"
#include "bpftime_shm.hpp"
#include <string>
#include <ebpf-vm.h>
#include <map>

Expand Down Expand Up @@ -34,7 +32,8 @@ class bpftime_driver {
daemon_config config;
struct bpf_tracer_bpf *object = NULL;

int check_and_create_prog_related_maps(int fd, const bpf_prog_info* info);
int check_and_create_prog_related_maps(int fd,
const bpf_prog_info *info);

public:
// create a bpf prog in the global shared memory
Expand All @@ -51,6 +50,8 @@ class bpftime_driver {

int bpftime_attach_perf_to_bpf_server(int server_pid, int perf_fd,
int kernel_bpf_id);
int bpftime_attach_perf_to_bpf_fd_server(int server_pid, int perf_fd,
int bpf_prog_fd);

// create uprobe in the global shared memory
//
Expand Down
2 changes: 1 addition & 1 deletion daemon/user/daemon_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct daemon_config {
// should bpftime be involve
bool is_driving_bpftime = true;

bool submit_bpf_events = false;
bool submit_bpf_events = true;
};

#endif // BPFTIME_DAEMON_CONFIG_HPP
Loading

0 comments on commit 66b2403

Please sign in to comment.