Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: add kernel user perf event array and per cpu array #68

Merged
merged 16 commits into from
Nov 6, 2023
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
Loading