From cd104bed94f2edb073960bf7784e0b0970d232a0 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Tue, 19 Mar 2024 19:06:28 +0800 Subject: [PATCH 01/14] Basic update for uprobe_multi --- example/uprobe_multi/.gitignore | 11 ++ example/uprobe_multi/Makefile | 141 ++++++++++++++++++++++++ example/uprobe_multi/README.md | 3 + example/uprobe_multi/uprobe_multi.bpf.c | 13 +++ example/uprobe_multi/uprobe_multi.c | 4 + example/uprobe_multi/victim.c | 36 ++++++ 6 files changed, 208 insertions(+) create mode 100644 example/uprobe_multi/.gitignore create mode 100644 example/uprobe_multi/Makefile create mode 100644 example/uprobe_multi/README.md create mode 100644 example/uprobe_multi/uprobe_multi.bpf.c create mode 100644 example/uprobe_multi/uprobe_multi.c create mode 100644 example/uprobe_multi/victim.c diff --git a/example/uprobe_multi/.gitignore b/example/uprobe_multi/.gitignore new file mode 100644 index 000000000..37b722818 --- /dev/null +++ b/example/uprobe_multi/.gitignore @@ -0,0 +1,11 @@ +.vscode +package.json +*.o +*.skel.json +*.skel.yaml +package.yaml +ecli +uprobe_multi +.output +test +victim diff --git a/example/uprobe_multi/Makefile b/example/uprobe_multi/Makefile new file mode 100644 index 000000000..f29e0466d --- /dev/null +++ b/example/uprobe_multi/Makefile @@ -0,0 +1,141 @@ +# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +OUTPUT := .output +CLANG ?= clang +LIBBPF_SRC := $(abspath ../../third_party/libbpf/src) +BPFTOOL_SRC := $(abspath ../../third_party/bpftool/src) +LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a) +BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool) +BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool +ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \ + | sed 's/arm.*/arm/' \ + | sed 's/aarch64/arm64/' \ + | sed 's/ppc64le/powerpc/' \ + | sed 's/mips.*/mips/' \ + | sed 's/riscv64/riscv/' \ + | sed 's/loongarch64/loongarch/') +VMLINUX := ../../third_party/vmlinux/$(ARCH)/vmlinux.h +# Use our own libbpf API headers and Linux UAPI headers distributed with +# libbpf to avoid dependency on system-wide headers, which could be missing or +# outdated +INCLUDES := -I$(OUTPUT) -I../../third_party/libbpf/include/uapi -I$(dir $(VMLINUX)) +CFLAGS := -g -Wall +ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS) + +APPS = uprobe_multi # minimal minimal_legacy uprobe kprobe fentry usdt sockfilter tc ksyscall + +CARGO ?= $(shell which cargo) +ifeq ($(strip $(CARGO)),) +BZS_APPS := +else +BZS_APPS := # profile +APPS += $(BZS_APPS) +# Required by libblazesym +ALL_LDFLAGS += -lrt -ldl -lpthread -lm +endif + +# Get Clang's default includes on this system. We'll explicitly add these dirs +# to the includes list when compiling with `-target bpf` because otherwise some +# architecture-specific dirs will be "missing" on some architectures/distros - +# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h, +# sys/cdefs.h etc. might be missing. +# +# Use '-idirafter': Don't interfere with include mechanics except where the +# build would have failed anyways. +CLANG_BPF_SYS_INCLUDES ?= $(shell $(CLANG) -v -E - &1 \ + | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') + +ifeq ($(V),1) + Q = + msg = +else + Q = @ + msg = @printf ' %-8s %s%s\n' \ + "$(1)" \ + "$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \ + "$(if $(3), $(3))"; + MAKEFLAGS += --no-print-directory +endif + +define allow-override + $(if $(or $(findstring environment,$(origin $(1))),\ + $(findstring command line,$(origin $(1)))),,\ + $(eval $(1) = $(2))) +endef + +$(call allow-override,CC,$(CROSS_COMPILE)cc) +$(call allow-override,LD,$(CROSS_COMPILE)ld) + +.PHONY: all +all: $(APPS) victim + +victim: victim.c + gcc victim.c -o victim -Wall -g + +.PHONY: clean +clean: + $(call msg,CLEAN) + $(Q)rm -rf $(OUTPUT) $(APPS) + +$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT): + $(call msg,MKDIR,$@) + $(Q)mkdir -p $@ + +# Build libbpf +$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf + $(call msg,LIB,$@) + $(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \ + OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \ + INCLUDEDIR= LIBDIR= UAPIDIR= \ + install + +# Build bpftool +$(BPFTOOL): | $(BPFTOOL_OUTPUT) + $(call msg,BPFTOOL,$@) + $(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap + + +$(LIBBLAZESYM_SRC)/target/release/libblazesym.a:: + $(Q)cd $(LIBBLAZESYM_SRC) && $(CARGO) build --features=cheader,dont-generate-test-files --release + +$(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) + $(call msg,LIB, $@) + $(Q)cp $(LIBBLAZESYM_SRC)/target/release/libblazesym.a $@ + +$(LIBBLAZESYM_HEADER): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT) + $(call msg,LIB,$@) + $(Q)cp $(LIBBLAZESYM_SRC)/target/release/blazesym.h $@ + +# Build BPF code +$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL) + $(call msg,BPF,$@) + $(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \ + $(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \ + -c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@) + $(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@) + +# Generate BPF skeletons +$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) + $(call msg,GEN-SKEL,$@) + $(Q)$(BPFTOOL) gen skeleton $< > $@ + +# Build user-space code +$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h + +$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT) + $(call msg,CC,$@) + $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ + +$(patsubst %,$(OUTPUT)/%.o,$(BZS_APPS)): $(LIBBLAZESYM_HEADER) + +$(BZS_APPS): $(LIBBLAZESYM_OBJ) + +# Build application binary +$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT) + $(call msg,BINARY,$@) + $(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@ + +# delete failed targets +.DELETE_ON_ERROR: + +# keep intermediate (.skel.h, .bpf.o, etc) targets +.SECONDARY: diff --git a/example/uprobe_multi/README.md b/example/uprobe_multi/README.md new file mode 100644 index 000000000..efe9465fa --- /dev/null +++ b/example/uprobe_multi/README.md @@ -0,0 +1,3 @@ +# uprobe_multi example + +This is a simple uprobe_multi example diff --git a/example/uprobe_multi/uprobe_multi.bpf.c b/example/uprobe_multi/uprobe_multi.bpf.c new file mode 100644 index 000000000..97006ac44 --- /dev/null +++ b/example/uprobe_multi/uprobe_multi.bpf.c @@ -0,0 +1,13 @@ +#define BPF_NO_GLOBAL_DATA +#include +#include +#include + +SEC("uprobe.multi/./victim:uprobe_multi_func_*") +int uprobe_multi_test(struct pt_regs* ctx){ + bpf_printk("Triggered: %ld", ctx->si); + return 0; +} + + +char _license[] SEC("license") = "GPL"; diff --git a/example/uprobe_multi/uprobe_multi.c b/example/uprobe_multi/uprobe_multi.c new file mode 100644 index 000000000..a3a68f2e6 --- /dev/null +++ b/example/uprobe_multi/uprobe_multi.c @@ -0,0 +1,4 @@ +int main(){ + + return 0; +} diff --git a/example/uprobe_multi/victim.c b/example/uprobe_multi/victim.c new file mode 100644 index 000000000..e5f5e027a --- /dev/null +++ b/example/uprobe_multi/victim.c @@ -0,0 +1,36 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +int uprobe_multi_func_add(int a, int b) +{ + return a + b; +} +int uprobe_multi_func_sub(int a, int b) +{ + return a - b; +} +int uprobe_multi_func_mul(int a, int b) +{ + return a * b; +} + +int main() +{ + srand(time(NULL)); + while (true) { + int a = rand() & 0xff; + int b = rand() & 0xff; + + int r1 = uprobe_multi_func_add(a, b); + int r2 = uprobe_multi_func_sub(a, b); + int r3 = uprobe_multi_func_mul(a, b); + + printf("%d+%d=%d, %d-%d=%d, %d*%d=%d\n", a, b, r1, a, b, r2, a, + b, r3); + usleep(1000 * 1000); + } + return 0; +} From 70b831d9dbc25acca9680d87a1b8f5f5dfb1e461 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Tue, 19 Mar 2024 20:54:44 +0800 Subject: [PATCH 02/14] Update --- example/uprobe_multi/.gitignore | 1 + example/uprobe_multi/uprobe_multi.bpf.c | 13 +++-- example/uprobe_multi/uprobe_multi.c | 51 +++++++++++++++++- runtime/CMakeLists.txt | 3 +- runtime/include/bpftime_shm.hpp | 9 ++++ runtime/src/attach/bpf_attach_ctx.cpp | 41 ++++++++------ runtime/src/bpftime_shm_internal.cpp | 8 ++- runtime/src/handler/link_handler.cpp | 63 ++++++++++++++++++++++ runtime/src/handler/link_handler.hpp | 63 ++++++++++++++++------ runtime/syscall-server/syscall_context.cpp | 12 +---- 10 files changed, 214 insertions(+), 50 deletions(-) create mode 100644 runtime/src/handler/link_handler.cpp diff --git a/example/uprobe_multi/.gitignore b/example/uprobe_multi/.gitignore index 37b722818..6ce66ade2 100644 --- a/example/uprobe_multi/.gitignore +++ b/example/uprobe_multi/.gitignore @@ -9,3 +9,4 @@ uprobe_multi .output test victim +dump* diff --git a/example/uprobe_multi/uprobe_multi.bpf.c b/example/uprobe_multi/uprobe_multi.bpf.c index 97006ac44..76df4e2b6 100644 --- a/example/uprobe_multi/uprobe_multi.bpf.c +++ b/example/uprobe_multi/uprobe_multi.bpf.c @@ -4,10 +4,17 @@ #include SEC("uprobe.multi/./victim:uprobe_multi_func_*") -int uprobe_multi_test(struct pt_regs* ctx){ - bpf_printk("Triggered: %ld", ctx->si); - return 0; +int uprobe_multi_test(struct pt_regs *ctx) +{ + bpf_printk("Entry triggered: %d, %d", ctx->di, ctx->si); + return 0; } +SEC("uretprobe.multi/./victim:uprobe_multi_func_*") +int uretprobe_multi_test(struct pt_regs *ctx) +{ + bpf_printk("Return triggered: %d", ctx->ax); + return 0; +} char _license[] SEC("license") = "GPL"; diff --git a/example/uprobe_multi/uprobe_multi.c b/example/uprobe_multi/uprobe_multi.c index a3a68f2e6..c0b777ae5 100644 --- a/example/uprobe_multi/uprobe_multi.c +++ b/example/uprobe_multi/uprobe_multi.c @@ -1,4 +1,51 @@ -int main(){ +#include ".output/uprobe_multi.skel.h" +#include "bpf/libbpf.h" +#include +#include +#include +static int libbpf_print_fn(enum libbpf_print_level level, const char *format, + va_list args) +{ + return vfprintf(stderr, format, args); +} + +static volatile bool exiting = false; + +static void sig_handler(int sig) +{ + exiting = true; +} + +int main() +{ + // libbpf_set_print(libbpf_print_fn); + int err; + signal(SIGINT, sig_handler); + signal(SIGTERM, sig_handler); + struct uprobe_multi_bpf *skel = uprobe_multi_bpf__open(); + if (!skel) { + fprintf(stderr, "Failed to open and load BPF skeleton\n"); + return 1; + } + err = uprobe_multi_bpf__load(skel); + if (err) { + fprintf(stderr, "Failed to load and verify BPF skeleton\n"); + goto cleanup; + } + err = uprobe_multi_bpf__attach(skel); + if (err < 0) { + fprintf(stderr, "Unable to attach %d", err); + goto cleanup; + } + while (!exiting) { + sleep(1); + puts("See /sys/kernel/tracing/trace_pipe"); + } + // bpf_program__attach_uprobe_multi(const struct bpf_program *prog, + // pid_t pid, const char *binary_path, const char *func_pattern, const + // struct bpf_uprobe_multi_opts *opts) +cleanup: + uprobe_multi_bpf__destroy(skel); - return 0; + return err < 0 ? -err : 0; } diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index e6f770db6..babf3bd5c 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -55,7 +55,8 @@ set(sources src/handler/perf_event_handler.cpp src/handler/prog_handler.cpp src/handler/epoll_handler.cpp - + src/handler/link_handler.cpp + src/bpftime_shm.cpp src/bpftime_shm_internal.cpp src/bpftime_shm_json.cpp diff --git a/runtime/include/bpftime_shm.hpp b/runtime/include/bpftime_shm.hpp index 9f76c9ecb..ad24c084c 100644 --- a/runtime/include/bpftime_shm.hpp +++ b/runtime/include/bpftime_shm.hpp @@ -238,6 +238,15 @@ struct bpf_link_create_args { __aligned_u64 addrs; __aligned_u64 cookies; } kprobe_multi; + struct { + __u32 flags; + __u32 cnt; + const char *path; + const unsigned long *offsets; + const unsigned long *ref_ctr_offsets; + const __u64 *cookies; + __u32 pid; + } uprobe_multi; struct { /* this is overlaid with the target_btf_id above. */ __u32 target_btf_id; diff --git a/runtime/src/attach/bpf_attach_ctx.cpp b/runtime/src/attach/bpf_attach_ctx.cpp index b58f90808..f7d3db581 100644 --- a/runtime/src/attach/bpf_attach_ctx.cpp +++ b/runtime/src/attach/bpf_attach_ctx.cpp @@ -208,9 +208,9 @@ int bpf_attach_ctx::instantiate_bpf_link_handler_at( int id, const bpf_link_handler &handler) { SPDLOG_DEBUG( - "Instantiating link handler: prog {} -> perf event {}, cookie {}", + "Instantiating link handler: prog {} -> perf event {}, link_attach_type {}", handler.prog_id, handler.attach_target_id, - handler.attach_cookie.value_or(0)); + handler.link_attach_type); auto &[priv_data, attach_type] = instantiated_perf_events[handler.attach_target_id]; attach::base_attach_impl *attach_impl; @@ -222,21 +222,30 @@ int bpf_attach_ctx::instantiate_bpf_link_handler_at( return -ENOTSUP; } auto prog = instantiated_progs.at(handler.prog_id).get(); - auto cookie = handler.attach_cookie; - int attach_id = attach_impl->create_attach_with_ebpf_callback( - [=](void *mem, size_t mem_size, uint64_t *ret) -> int { - current_thread_bpf_cookie = cookie; - int err = prog->bpftime_prog_exec((void *)mem, mem_size, - ret); - return err; - }, - *priv_data, attach_type); - if (attach_id < 0) { - SPDLOG_ERROR("Unable to instantiate bpf link handler {}: {}", - id, attach_id); - return attach_id; + if (handler.link_attach_type == BPF_PERF_EVENT) { + auto cookie = std::get(handler.data) + .attach_cookie; + int attach_id = attach_impl->create_attach_with_ebpf_callback( + [=](void *mem, size_t mem_size, uint64_t *ret) -> int { + current_thread_bpf_cookie = cookie; + int err = prog->bpftime_prog_exec( + (void *)mem, mem_size, ret); + return err; + }, + *priv_data, attach_type); + if (attach_id < 0) { + SPDLOG_ERROR( + "Unable to instantiate bpf link handler {}: {}", + id, attach_id); + return attach_id; + } + instantiated_attach_ids[id] = + std::make_pair(attach_id, attach_impl); + } else { + SPDLOG_ERROR("We does not support link with attach type {} yet", + handler.link_attach_type); + return -ENOTSUP; } - instantiated_attach_ids[id] = std::make_pair(attach_id, attach_impl); return 0; } int bpf_attach_ctx::instantiate_perf_event_handler_at( diff --git a/runtime/src/bpftime_shm_internal.cpp b/runtime/src/bpftime_shm_internal.cpp index 5540e333f..a8423896b 100644 --- a/runtime/src/bpftime_shm_internal.cpp +++ b/runtime/src/bpftime_shm_internal.cpp @@ -484,8 +484,12 @@ int bpftime_shm::add_bpf_link(int fd, struct bpf_link_create_args *args) errno = EBADF; return -1; } - return manager->set_handler(fd, bpftime::bpf_link_handler(*args), - segment); + int result = manager->set_handler( + fd, bpftime::bpf_link_handler(*args, segment), segment); + // TODO: We should create corresponding perf_event handles for the link, + // if the attach type is uprobe_multi + + return result; } void bpftime_shm::close_fd(int fd) diff --git a/runtime/src/handler/link_handler.cpp b/runtime/src/handler/link_handler.cpp new file mode 100644 index 000000000..65b037f29 --- /dev/null +++ b/runtime/src/handler/link_handler.cpp @@ -0,0 +1,63 @@ +#include "link_handler.hpp" +#include "handler/perf_event_handler.hpp" +#include "spdlog/spdlog.h" +using namespace bpftime; +bpf_link_handler::bpf_link_handler(struct bpf_link_create_args args, + managed_shared_memory &mem) + : args(args), prog_id(args.prog_fd), attach_target_id(args.target_fd), + link_attach_type(args.attach_type) +{ + if (args.attach_type == BPF_PERF_EVENT) { + SPDLOG_DEBUG( + "Initializing bpf link of type perf event, using link create args"); + if (args.perf_event.bpf_cookie != 0) { + data = perf_event_link_data{ + .attach_cookie = args.perf_event.bpf_cookie + }; + SPDLOG_DEBUG("Set attach cookie to {}", + args.perf_event.bpf_cookie); + } else { + data = perf_event_link_data{}; + } + } else if (args.attach_type == BPF_TRACE_UPROBE_MULTI) { + SPDLOG_DEBUG( + "Initializing bpf link of type uprobe_multi, using link create args"); + const auto &opts = args.uprobe_multi; + uprobe_multi_entry_vector entries(uprobe_multi_entry_allocator( + mem.get_segment_manager())); + for (size_t i = 0; i < opts.cnt; i++) { + entries.push_back(uprobe_multi_entry{ + .offset = opts.offsets[i], + .ref_ctr_offset = opts.offsets[i], + .cookie = (opts.cookies == nullptr || + opts.cookies[i] == 0) ? + 0 : + opts.cookies[i], + .attach_target = {} }); + } + data = uprobe_multi_link_data{ + .path = boost_shm_string( + opts.path, + char_allocator(mem.get_segment_manager())), + .entries = entries, + .flags = opts.flags + }; + } else { + SPDLOG_ERROR("Unsupport bpf_link attach type: {}", + link_attach_type); + throw std::runtime_error("Unsupported bpf_link attach type"); + } +} +bpf_link_handler::bpf_link_handler(int prog_id, int attach_target_id) + : prog_id(prog_id), attach_target_id(attach_target_id), + link_attach_type(BPF_PERF_EVENT), + data(perf_event_link_data{ .attach_cookie = {} }) +{ +} +bpf_link_handler::bpf_link_handler(int prog_id, int attach_target_id, + std::optional cookie) + : prog_id(prog_id), attach_target_id(attach_target_id), + link_attach_type(BPF_PERF_EVENT), + data(perf_event_link_data{ .attach_cookie = cookie }) +{ +} diff --git a/runtime/src/handler/link_handler.hpp b/runtime/src/handler/link_handler.hpp index 057a4deee..3d57a71c7 100644 --- a/runtime/src/handler/link_handler.hpp +++ b/runtime/src/handler/link_handler.hpp @@ -6,33 +6,66 @@ #ifndef _LINK_HANDLER_HPP #define _LINK_HANDLER_HPP +#include "handler/perf_event_handler.hpp" +#include "handler/prog_handler.hpp" +#include +#include #include #include #include +#include +#include namespace bpftime { +constexpr static int BPF_PERF_EVENT = 41; +constexpr static int BPF_TRACE_UPROBE_MULTI = 48; + +struct perf_event_link_data { + std::optional attach_cookie; +}; + +struct uprobe_multi_entry { + uint64_t offset; + uint64_t ref_ctr_offset; + std::optional cookie; + // Out attach implementation requires that each attach has a + // perf event handler, so we also need it if we attach a uprobe + // multi link + std::optional attach_target; +}; +using uprobe_multi_entry_allocator = + boost::interprocess::allocator; +using uprobe_multi_entry_vector = + boost::interprocess::vector; +struct uprobe_multi_link_data { + boost_shm_string path; + uprobe_multi_entry_vector entries; + uint64_t flags; +}; + +using bpf_link_data = + std::variant; + // handle the bpf link fd struct bpf_link_handler { struct bpf_link_create_args args; int prog_id; int attach_target_id; - std::optional attach_cookie; - bpf_link_handler(struct bpf_link_create_args args) - : args(args), prog_id(args.prog_fd), - attach_target_id(args.target_fd) - { - } - bpf_link_handler(int prog_id, int attach_target_id) - : prog_id(prog_id), attach_target_id(attach_target_id) - { - } + int link_attach_type; + bpf_link_data data; + // Create a customized bpf_link + bpf_link_handler(struct bpf_link_create_args args, + managed_shared_memory &mem); + // Create a bpf_link of type BPF_PERF_EVENT, with provided prog_id and + // attach_target_id + bpf_link_handler(int prog_id, int attach_target_id); + // Create a bpf_link of type BPF_PERF_EVENT, with provided prog_id and + // attach_target_id, and cookie bpf_link_handler(int prog_id, int attach_target_id, - std::optional cookie) - : prog_id(prog_id), attach_target_id(attach_target_id), - attach_cookie(cookie) - { - } + std::optional cookie); }; } // namespace bpftime diff --git a/runtime/syscall-server/syscall_context.cpp b/runtime/syscall-server/syscall_context.cpp index 620e7843a..a3455b9d8 100644 --- a/runtime/syscall-server/syscall_context.cpp +++ b/runtime/syscall-server/syscall_context.cpp @@ -357,17 +357,7 @@ long syscall_context::handle_sysbpf(int cmd, union bpf_attr *attr, size_t size) int id = bpftime_link_create( -1 /* let the shm alloc fd for us */, (bpf_link_create_args *)&attr->link_create); - SPDLOG_DEBUG("Created link {}", id); - if (bpftime_is_prog_fd(prog_fd) && - bpftime_is_perf_event_fd(target_fd) && - attach_type == BPF_PERF_EVENT) { - auto cookie = attr->link_create.perf_event.bpf_cookie; - SPDLOG_DEBUG( - "Attaching perf event {} to prog {}, with bpf cookie {:x}", - target_fd, prog_fd, cookie); - bpftime_attach_perf_to_bpf_with_cookie(target_fd, - prog_fd, cookie); - } + SPDLOG_DEBUG("syscall-server: Created link {}", id); return id; } case BPF_MAP_FREEZE: { From 6b013367c2ae6ad3805f3c6a0fe7bd4e36020f30 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Tue, 19 Mar 2024 21:29:57 +0800 Subject: [PATCH 03/14] Fix CI --- runtime/src/bpftime_shm_json.cpp | 19 ++++++++++++++----- runtime/unit-test/maps/test_shm_hash_maps.cpp | 2 +- runtime/unit-test/test_bpftime_shm_json.cpp | 2 ++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/runtime/src/bpftime_shm_json.cpp b/runtime/src/bpftime_shm_json.cpp index db445a6a3..8fb28e0c8 100644 --- a/runtime/src/bpftime_shm_json.cpp +++ b/runtime/src/bpftime_shm_json.cpp @@ -5,6 +5,7 @@ */ #include "bpftime_shm.hpp" #include "handler/epoll_handler.hpp" +#include "handler/link_handler.hpp" #include "handler/perf_event_handler.hpp" #include "spdlog/spdlog.h" #include @@ -174,10 +175,11 @@ static int import_shm_handler_from_json(bpftime_shm &shm, json value, int fd) } else if (handler_type == "bpf_link_handler") { unsigned int prog_fd = value["attr"]["prog_fd"]; unsigned int target_fd = value["attr"]["target_fd"]; - bpf_link_create_args args = { - .prog_fd = prog_fd, - .target_fd = target_fd, - }; + unsigned int link_attach_type = + value["attr"]["link_attach_type"]; + bpf_link_create_args args = { .prog_fd = prog_fd, + .target_fd = target_fd, + .attach_type = link_attach_type }; shm.add_bpf_link(fd, &args); } else { SPDLOG_ERROR("Unsupported handler type {}", handler_type); @@ -291,11 +293,18 @@ int bpftime::bpftime_export_shm_to_json(const bpftime_shm &shm, SPDLOG_INFO("epoll_handler found at {}", i); } else if (std::holds_alternative(handler)) { auto &h = std::get(handler); + if (h.link_attach_type != bpftime::BPF_PERF_EVENT) { + SPDLOG_ERROR( + "We only support exporting links with attach type BPF_PERF_EVENT now"); + return -ENOTSUP; + } j[std::to_string(i)] = { { "type", "bpf_link_handler" }, { "attr", { { "prog_fd", h.prog_id }, - { "target_fd", h.attach_target_id } } } + { "target_fd", h.attach_target_id }, + { "link_attach_type", + h.link_attach_type } } } }; SPDLOG_INFO( "bpf_link_handler found at {},link {} -> {}", diff --git a/runtime/unit-test/maps/test_shm_hash_maps.cpp b/runtime/unit-test/maps/test_shm_hash_maps.cpp index ea5c66f2c..3f1e3b00a 100644 --- a/runtime/unit-test/maps/test_shm_hash_maps.cpp +++ b/runtime/unit-test/maps/test_shm_hash_maps.cpp @@ -89,7 +89,7 @@ TEST_CASE("Test shm hash maps with sub process") struct shm_remove remover(SHM_NAME); // The side that creates the mapping - managed_shared_memory segment(create_only, SHM_NAME, 1 << 20); + managed_shared_memory segment(create_only, SHM_NAME, 1 << 21); auto manager = segment.construct(HANDLER_NAME)(segment); auto &manager_ref = *manager; diff --git a/runtime/unit-test/test_bpftime_shm_json.cpp b/runtime/unit-test/test_bpftime_shm_json.cpp index 531177792..c2dec4401 100644 --- a/runtime/unit-test/test_bpftime_shm_json.cpp +++ b/runtime/unit-test/test_bpftime_shm_json.cpp @@ -1,4 +1,5 @@ #include "catch2/catch_message.hpp" +#include "handler/link_handler.hpp" #include #include #include @@ -72,6 +73,7 @@ TEST_CASE("Test bpftime shm json import/export") bpf_link_create_args args = { .prog_fd = 4, .target_fd = 5, + .attach_type = bpftime::BPF_PERF_EVENT }; shm.add_bpf_link(7, &args); shm.add_bpf_map(8, "test_map1", From 60321b33460d66be1a487fd5cc5a4f5ecf883c13 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Fri, 22 Mar 2024 01:06:21 +0800 Subject: [PATCH 04/14] update --- runtime/include/bpftime_shm.hpp | 37 ++++++--- runtime/src/attach/bpf_attach_ctx.cpp | 78 ++++++++++++++----- runtime/src/bpftime_shm_internal.cpp | 29 ++++++- runtime/src/bpftime_shm_json.cpp | 5 +- runtime/src/handler/handler_manager.cpp | 2 +- runtime/src/handler/link_handler.cpp | 39 +++++++--- runtime/src/handler/link_handler.hpp | 17 ++-- runtime/syscall-server/syscall_context.cpp | 8 ++ .../test_shm_progs_attach.cpp | 8 +- 9 files changed, 167 insertions(+), 56 deletions(-) diff --git a/runtime/include/bpftime_shm.hpp b/runtime/include/bpftime_shm.hpp index ad24c084c..566333956 100644 --- a/runtime/include/bpftime_shm.hpp +++ b/runtime/include/bpftime_shm.hpp @@ -206,14 +206,14 @@ int bpftime_export_global_shm_to_json(const char *filename); // import a hander to global shared memory from json string int bpftime_import_shm_handler_from_json(int fd, const char *json_string); -/* struct used by BPF_LINK_CREATE command */ +/* struct type of kernel bpf_attr::link_create */ struct bpf_link_create_args { union { __u32 prog_fd; /* eBPF program to attach */ __u32 map_fd; /* struct_ops to attach */ }; union { - __u32 target_fd; /* object to attach to */ + __u32 target_fd; /* target object to attach to or ... */ __u32 target_ifindex; /* target ifindex */ }; __u32 attach_type; /* attach type */ @@ -238,15 +238,6 @@ struct bpf_link_create_args { __aligned_u64 addrs; __aligned_u64 cookies; } kprobe_multi; - struct { - __u32 flags; - __u32 cnt; - const char *path; - const unsigned long *offsets; - const unsigned long *ref_ctr_offsets; - const __u64 *cookies; - __u32 pid; - } uprobe_multi; struct { /* this is overlaid with the target_btf_id above. */ __u32 target_btf_id; @@ -262,9 +253,31 @@ struct bpf_link_create_args { __s32 priority; __u32 flags; } netfilter; + struct { + union { + __u32 relative_fd; + __u32 relative_id; + }; + __u64 expected_revision; + } tcx; + struct { + __aligned_u64 path; + __aligned_u64 offsets; + __aligned_u64 ref_ctr_offsets; + __aligned_u64 cookies; + __u32 cnt; + __u32 flags; + __u32 pid; + } uprobe_multi; + struct { + union { + __u32 relative_fd; + __u32 relative_id; + }; + __u64 expected_revision; + } netkit; }; }; - // create a bpf link in the global shared memory // // @param[fd]: fd is the fd allocated by the kernel. if fd is -1, then the diff --git a/runtime/src/attach/bpf_attach_ctx.cpp b/runtime/src/attach/bpf_attach_ctx.cpp index f7d3db581..e2f8a93b3 100644 --- a/runtime/src/attach/bpf_attach_ctx.cpp +++ b/runtime/src/attach/bpf_attach_ctx.cpp @@ -133,14 +133,18 @@ int bpf_attach_ctx::instantiate_handler_at(const handler_manager *manager, link_handler.prog_id, id, err); return err; } - if (int err = instantiate_handler_at( - manager, link_handler.attach_target_id, stk, - config); - err < 0) { - SPDLOG_ERROR( - "Unable to instantiate perf event handler {} when instantiating link handler {}: {}", - link_handler.attach_target_id, id, err); - return err; + for (auto attach_target_id : link_handler.attach_target_ids) { + SPDLOG_DEBUG( + "Instantiating attach target id {} for link handler {}", + attach_target_id, id); + if (int err = instantiate_handler_at( + manager, attach_target_id, stk, config); + err < 0) { + SPDLOG_ERROR( + "Unable to instantiate perf event handler {} when instantiating link handler {}: {}", + attach_target_id, id, err); + return err; + } } if (int err = instantiate_bpf_link_handler_at(id, link_handler); err < 0) { @@ -149,6 +153,9 @@ int bpf_attach_ctx::instantiate_handler_at(const handler_manager *manager, id, err); return err; } + } else if (std::holds_alternative(handler)) { + SPDLOG_ERROR("Instantiating a unused handler at {}", id); + return -EINVAL; } else { SPDLOG_DEBUG("Instantiating type {}", handler.index()); } @@ -211,18 +218,20 @@ int bpf_attach_ctx::instantiate_bpf_link_handler_at( "Instantiating link handler: prog {} -> perf event {}, link_attach_type {}", handler.prog_id, handler.attach_target_id, handler.link_attach_type); - auto &[priv_data, attach_type] = - instantiated_perf_events[handler.attach_target_id]; - attach::base_attach_impl *attach_impl; - if (auto itr = attach_impls.find(attach_type); - itr != attach_impls.end()) { - attach_impl = itr->second.first; - } else { - SPDLOG_ERROR("Attach type {} is not registered", attach_type); - return -ENOTSUP; - } + auto prog = instantiated_progs.at(handler.prog_id).get(); if (handler.link_attach_type == BPF_PERF_EVENT) { + auto &[priv_data, attach_type] = + instantiated_perf_events[handler.attach_target_id]; + attach::base_attach_impl *attach_impl; + if (auto itr = attach_impls.find(attach_type); + itr != attach_impls.end()) { + attach_impl = itr->second.first; + } else { + SPDLOG_ERROR("Attach type {} is not registered", + attach_type); + return -ENOTSUP; + } auto cookie = std::get(handler.data) .attach_cookie; int attach_id = attach_impl->create_attach_with_ebpf_callback( @@ -241,6 +250,39 @@ int bpf_attach_ctx::instantiate_bpf_link_handler_at( } instantiated_attach_ids[id] = std::make_pair(attach_id, attach_impl); + } else if (handler.link_attach_type == BPF_TRACE_UPROBE_MULTI) { + auto link_data = std::get(handler.data); + for (const auto &entry : link_data.entries) { + auto &[priv_data, attach_type] = + instantiated_perf_events[entry.attach_target + .value()]; + attach::base_attach_impl *attach_impl; + if (auto itr = attach_impls.find(attach_type); + itr != attach_impls.end()) { + attach_impl = itr->second.first; + } else { + SPDLOG_ERROR("Attach type {} is not registered", + attach_type); + return -ENOTSUP; + } + auto cookie = + std::get(handler.data) + .attach_cookie; + int attach_id = + attach_impl->create_attach_with_ebpf_callback( + [=](void *mem, size_t mem_size, + uint64_t *ret) -> int { + current_thread_bpf_cookie = + cookie; + int err = + prog->bpftime_prog_exec( + (void *)mem, + mem_size, ret); + return err; + }, + *priv_data, attach_type); + } + SPDLOG_WARN("TODO: Record attach ids of uprobe multi"); } else { SPDLOG_ERROR("We does not support link with attach type {} yet", handler.link_attach_type); diff --git a/runtime/src/bpftime_shm_internal.cpp b/runtime/src/bpftime_shm_internal.cpp index a8423896b..4e7a35aac 100644 --- a/runtime/src/bpftime_shm_internal.cpp +++ b/runtime/src/bpftime_shm_internal.cpp @@ -238,7 +238,9 @@ int bpftime_shm::add_bpf_prog_attach_target(int perf_fd, int bpf_fd, SPDLOG_ERROR("Unable to find an available id: {}", next_id); return -ENOSPC; } - manager->set_handler(next_id, bpf_link_handler(bpf_fd, perf_fd, cookie), + manager->set_handler(next_id, + bpf_link_handler(bpf_fd, perf_fd, cookie, + segment), segment); return next_id; } @@ -486,8 +488,29 @@ int bpftime_shm::add_bpf_link(int fd, struct bpf_link_create_args *args) } int result = manager->set_handler( fd, bpftime::bpf_link_handler(*args, segment), segment); - // TODO: We should create corresponding perf_event handles for the link, - // if the attach type is uprobe_multi + auto &link = + std::get(manager->get_handler(fd)); + if (link.link_attach_type == BPF_TRACE_UPROBE_MULTI) { + auto &link_data = std::get(link.data); + int i = 0; + for (auto &entry : link_data.entries) { + std::string uprobe_name("sub_uprobe_"); + uprobe_name += std::to_string(fd); + uprobe_name += "_"; + uprobe_name += std::to_string(i); + entry.attach_target = + add_uprobe(-1, link_data.pid, + uprobe_name.c_str(), entry.offset, + (link_data.flags & + BPF_F_UPROBE_MULTI_RETURN) != 0, + entry.ref_ctr_offset); + i++; + SPDLOG_DEBUG( + "Created sub uprobe perf event for uprobe_multi {}: sub id {}, sub name {}, sub offset {:x}", + fd, entry.attach_target.value(), uprobe_name, + entry.offset); + } + } return result; } diff --git a/runtime/src/bpftime_shm_json.cpp b/runtime/src/bpftime_shm_json.cpp index 8fb28e0c8..f4ca3c8bf 100644 --- a/runtime/src/bpftime_shm_json.cpp +++ b/runtime/src/bpftime_shm_json.cpp @@ -298,11 +298,14 @@ int bpftime::bpftime_export_shm_to_json(const bpftime_shm &shm, "We only support exporting links with attach type BPF_PERF_EVENT now"); return -ENOTSUP; } + json attach_target_ids; + for (auto x : h.attach_target_ids) + attach_target_ids.push_back(x); j[std::to_string(i)] = { { "type", "bpf_link_handler" }, { "attr", { { "prog_fd", h.prog_id }, - { "target_fd", h.attach_target_id }, + { "target_fd", attach_target_ids }, { "link_attach_type", h.link_attach_type } } } }; diff --git a/runtime/src/handler/handler_manager.cpp b/runtime/src/handler/handler_manager.cpp index 0511f9cad..a9d6af694 100644 --- a/runtime/src/handler/handler_manager.cpp +++ b/runtime/src/handler/handler_manager.cpp @@ -95,7 +95,7 @@ void handler_manager::clear_id_at(int fd, managed_shared_memory &memory) if (std::holds_alternative(handler)) { auto &link_handler = std::get(handler); - if (link_handler.attach_target_id == fd) { + if (link_handler.attach_target_ids == fd) { SPDLOG_DEBUG( "Remove link handler with id {}, prog id {}, due to the removal of perf event {}", i, link_handler.prog_id, fd); diff --git a/runtime/src/handler/link_handler.cpp b/runtime/src/handler/link_handler.cpp index 65b037f29..c047514b0 100644 --- a/runtime/src/handler/link_handler.cpp +++ b/runtime/src/handler/link_handler.cpp @@ -2,9 +2,11 @@ #include "handler/perf_event_handler.hpp" #include "spdlog/spdlog.h" using namespace bpftime; + bpf_link_handler::bpf_link_handler(struct bpf_link_create_args args, managed_shared_memory &mem) - : args(args), prog_id(args.prog_fd), attach_target_id(args.target_fd), + : args(args), prog_id(args.prog_fd), + attach_target_ids(mem.get_segment_manager()), link_attach_type(args.attach_type) { if (args.attach_type == BPF_PERF_EVENT) { @@ -19,6 +21,7 @@ bpf_link_handler::bpf_link_handler(struct bpf_link_create_args args, } else { data = perf_event_link_data{}; } + attach_target_ids.push_back(args.target_fd); } else if (args.attach_type == BPF_TRACE_UPROBE_MULTI) { SPDLOG_DEBUG( "Initializing bpf link of type uprobe_multi, using link create args"); @@ -27,20 +30,28 @@ bpf_link_handler::bpf_link_handler(struct bpf_link_create_args args, mem.get_segment_manager())); for (size_t i = 0; i < opts.cnt; i++) { entries.push_back(uprobe_multi_entry{ - .offset = opts.offsets[i], - .ref_ctr_offset = opts.offsets[i], - .cookie = (opts.cookies == nullptr || - opts.cookies[i] == 0) ? + .offset = ((unsigned long *)(uintptr_t) + opts.offsets)[i], + .ref_ctr_offset = + opts.ref_ctr_offsets != 0 ? + ((unsigned long *)(uintptr_t)opts + .ref_ctr_offsets)[i] : + 0, + .cookie = (opts.cookies == 0 || + ((uint64_t *)(uintptr_t) + opts.cookies)[i] == 0) ? 0 : - opts.cookies[i], + ((uint64_t *)(uintptr_t) + opts.cookies)[i], .attach_target = {} }); } data = uprobe_multi_link_data{ .path = boost_shm_string( - opts.path, + (const char *)(uintptr_t)opts.path, char_allocator(mem.get_segment_manager())), .entries = entries, - .flags = opts.flags + .flags = opts.flags, + .pid = static_cast(opts.pid) }; } else { SPDLOG_ERROR("Unsupport bpf_link attach type: {}", @@ -48,16 +59,20 @@ bpf_link_handler::bpf_link_handler(struct bpf_link_create_args args, throw std::runtime_error("Unsupported bpf_link attach type"); } } -bpf_link_handler::bpf_link_handler(int prog_id, int attach_target_id) - : prog_id(prog_id), attach_target_id(attach_target_id), +bpf_link_handler::bpf_link_handler(int prog_id, int attach_target_id, + managed_shared_memory &mem) + : prog_id(prog_id), attach_target_ids(mem.get_segment_manager()), link_attach_type(BPF_PERF_EVENT), data(perf_event_link_data{ .attach_cookie = {} }) { + attach_target_ids.push_back(attach_target_id); } bpf_link_handler::bpf_link_handler(int prog_id, int attach_target_id, - std::optional cookie) - : prog_id(prog_id), attach_target_id(attach_target_id), + std::optional cookie, + managed_shared_memory &mem) + : prog_id(prog_id), attach_target_ids(mem.get_segment_manager()), link_attach_type(BPF_PERF_EVENT), data(perf_event_link_data{ .attach_cookie = cookie }) { + attach_target_ids.push_back(attach_target_id); } diff --git a/runtime/src/handler/link_handler.hpp b/runtime/src/handler/link_handler.hpp index 3d57a71c7..0e447c92c 100644 --- a/runtime/src/handler/link_handler.hpp +++ b/runtime/src/handler/link_handler.hpp @@ -20,7 +20,7 @@ namespace bpftime { constexpr static int BPF_PERF_EVENT = 41; constexpr static int BPF_TRACE_UPROBE_MULTI = 48; - +constexpr static int BPF_F_UPROBE_MULTI_RETURN = 1; struct perf_event_link_data { std::optional attach_cookie; }; @@ -32,7 +32,7 @@ struct uprobe_multi_entry { // Out attach implementation requires that each attach has a // perf event handler, so we also need it if we attach a uprobe // multi link - std::optional attach_target; + mutable std::optional attach_target; }; using uprobe_multi_entry_allocator = boost::interprocess::allocator; +using i32_vec_allocator = boost::interprocess::allocator< + int32_t, boost::interprocess::managed_shared_memory::segment_manager>; +using i32_vec = boost::interprocess::vector; + // handle the bpf link fd struct bpf_link_handler { struct bpf_link_create_args args; int prog_id; - int attach_target_id; + i32_vec attach_target_ids; int link_attach_type; bpf_link_data data; // Create a customized bpf_link @@ -61,11 +66,13 @@ struct bpf_link_handler { managed_shared_memory &mem); // Create a bpf_link of type BPF_PERF_EVENT, with provided prog_id and // attach_target_id - bpf_link_handler(int prog_id, int attach_target_id); + bpf_link_handler(int prog_id, int attach_target_id, + managed_shared_memory &mem); // Create a bpf_link of type BPF_PERF_EVENT, with provided prog_id and // attach_target_id, and cookie bpf_link_handler(int prog_id, int attach_target_id, - std::optional cookie); + std::optional cookie, + managed_shared_memory &mem); }; } // namespace bpftime diff --git a/runtime/syscall-server/syscall_context.cpp b/runtime/syscall-server/syscall_context.cpp index a3455b9d8..2e6c120db 100644 --- a/runtime/syscall-server/syscall_context.cpp +++ b/runtime/syscall-server/syscall_context.cpp @@ -354,6 +354,14 @@ long syscall_context::handle_sysbpf(int cmd, union bpf_attr *attr, size_t size) (long)(uintptr_t)attr, (long)size); } + // auto &kargs = attr->link_create; + // bpf_link_create_args args{ .prog_fd = kargs.prog_fd, + // .target_fd = kargs.target_fd, + // .attach_type = kargs.attach_type, + // .flags = kargs.flags, + // .uprobe_multi = { + + // } }; int id = bpftime_link_create( -1 /* let the shm alloc fd for us */, (bpf_link_create_args *)&attr->link_create); diff --git a/runtime/unit-test/attach_with_ebpf/test_shm_progs_attach.cpp b/runtime/unit-test/attach_with_ebpf/test_shm_progs_attach.cpp index 0b0257586..727eb7c5e 100644 --- a/runtime/unit-test/attach_with_ebpf/test_shm_progs_attach.cpp +++ b/runtime/unit-test/attach_with_ebpf/test_shm_progs_attach.cpp @@ -109,8 +109,8 @@ static int attach_uprobe(bpftime::handler_manager &manager_ref, manager_ref.set_handler(4, hd, segment); auto &prog_handler = std::get(manager_ref[0]); // the attach fd is 3 - return manager_ref.set_handler_at_empty_slot(bpf_link_handler(0, 4), - segment); + return manager_ref.set_handler_at_empty_slot( + bpf_link_handler(0, 4, segment), segment); } static int attach_replace(bpftime::handler_manager &manager_ref, @@ -139,8 +139,8 @@ static int attach_replace(bpftime::handler_manager &manager_ref, segment); // the attach fd is 3 - return manager_ref.set_handler_at_empty_slot(bpf_link_handler(0, 3), - segment); + return manager_ref.set_handler_at_empty_slot( + bpf_link_handler(0, 3, segment), segment); } static void handle_sub_process() From fb7f2fe421341de5a80a44848a079a35f728d8b5 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Fri, 22 Mar 2024 20:21:43 +0800 Subject: [PATCH 05/14] Update --- .github/workflows/test-examples.yml | 6 +- attach/CMakeLists.txt | 2 +- .../base_attach_impl/attach_private_data.hpp | 5 + .../include/frida_attach_entry.hpp | 5 +- .../include/frida_attach_private_data.hpp | 8 +- .../src/frida_attach_private_data.cpp | 6 + .../src/frida_attach_utils.cpp | 13 ++- .../src/frida_internal_attach_entry.cpp | 2 + example/uprobe_multi/uprobe_multi.bpf.c | 23 +++- example/uprobe_multi/uprobe_multi.c | 36 +++++- example/uprobe_multi/uprobe_multi.h | 17 +++ example/uprobe_multi/victim.c | 20 ++-- runtime/include/bpf_attach_ctx.hpp | 4 +- runtime/src/attach/bpf_attach_ctx.cpp | 108 ++++++++++-------- runtime/src/bpftime_shm_internal.cpp | 35 +++--- runtime/src/bpftime_shm_internal.hpp | 4 +- runtime/src/handler/handler_manager.cpp | 32 ++++-- runtime/src/handler/link_handler.cpp | 3 +- runtime/src/handler/link_handler.hpp | 7 +- 19 files changed, 224 insertions(+), 112 deletions(-) create mode 100644 example/uprobe_multi/uprobe_multi.h diff --git a/.github/workflows/test-examples.yml b/.github/workflows/test-examples.yml index b77fa2798..b8dad905e 100644 --- a/.github/workflows/test-examples.yml +++ b/.github/workflows/test-examples.yml @@ -133,7 +133,11 @@ jobs: victim: ./victim syscall_trace: false expected_str: "bpf:" - + - path: uprobe_multi + executable: ./uprobe_multi + victim: ./victim + syscall_trace: false + expected_str: "Uretprobe triggered:" steps: - name: Download prebuilt runtime (with jit) if: ${{matrix.enable_jit}} diff --git a/attach/CMakeLists.txt b/attach/CMakeLists.txt index 70654644e..4cd029654 100644 --- a/attach/CMakeLists.txt +++ b/attach/CMakeLists.txt @@ -1,5 +1,5 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") - add_definitions(-DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_DEBUG) + add_definitions(-DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE) else() add_definitions(-DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_INFO) endif() diff --git a/attach/base_attach_impl/attach_private_data.hpp b/attach/base_attach_impl/attach_private_data.hpp index 1310519a3..0a714f07c 100644 --- a/attach/base_attach_impl/attach_private_data.hpp +++ b/attach/base_attach_impl/attach_private_data.hpp @@ -1,6 +1,7 @@ #ifndef _BPFTIME_ATTACH_PRIVATE_DATA_HPP #define _BPFTIME_ATTACH_PRIVATE_DATA_HPP +#include #include #include "spdlog/spdlog.h" #include @@ -23,6 +24,10 @@ struct attach_private_data { throw std::runtime_error( "attach_private_data::initialize_from_string"); } + virtual std::string to_string() + { + return ""; + } }; } // namespace attach } // namespace bpftime diff --git a/attach/frida_uprobe_attach_impl/include/frida_attach_entry.hpp b/attach/frida_uprobe_attach_impl/include/frida_attach_entry.hpp index 3005c8a5a..1803875f0 100644 --- a/attach/frida_uprobe_attach_impl/include/frida_attach_entry.hpp +++ b/attach/frida_uprobe_attach_impl/include/frida_attach_entry.hpp @@ -54,9 +54,12 @@ class frida_attach_entry { frida_attach_entry &operator=(const frida_attach_entry &) = delete; // Create this attach entry with its id, callback function, and function // address to hook - frida_attach_entry(int id, frida_attach_entry_callback &&cb, void *function) + frida_attach_entry(int id, frida_attach_entry_callback &&cb, + void *function) : self_id(id), callback(cb), function(function) { + SPDLOG_DEBUG("Creating frida attach entry at addr 0x{:x}", + (uintptr_t)function); } frida_attach_entry(frida_attach_entry &&) = default; }; diff --git a/attach/frida_uprobe_attach_impl/include/frida_attach_private_data.hpp b/attach/frida_uprobe_attach_impl/include/frida_attach_private_data.hpp index 47b7dca70..a8af97682 100644 --- a/attach/frida_uprobe_attach_impl/include/frida_attach_private_data.hpp +++ b/attach/frida_uprobe_attach_impl/include/frida_attach_private_data.hpp @@ -8,10 +8,14 @@ namespace attach { // Private data for frida uprobe attach struct frida_attach_private_data final : public attach_private_data { - // The address to hook + // The address to hook uint64_t addr; - // The input string should be: Either an decimal integer in string format, indicating the function address to hook. Or in format of NAME:OFFSET, where NAME is the module name (empty is ok), OFFSET is the module offset + // The input string should be: Either an decimal integer in string + // format, indicating the function address to hook. Or in format of + // NAME:OFFSET, where NAME is the module name (empty is ok), OFFSET is + // the module offset int initialize_from_string(const std::string_view &sv) override; + std::string to_string() override; }; } // namespace attach } // namespace bpftime diff --git a/attach/frida_uprobe_attach_impl/src/frida_attach_private_data.cpp b/attach/frida_uprobe_attach_impl/src/frida_attach_private_data.cpp index 952250ace..f7e3ea633 100644 --- a/attach/frida_uprobe_attach_impl/src/frida_attach_private_data.cpp +++ b/attach/frida_uprobe_attach_impl/src/frida_attach_private_data.cpp @@ -32,3 +32,9 @@ int frida_attach_private_data::initialize_from_string(const std::string_view &sv return 0; } + +std::string frida_attach_private_data::to_string() +{ + return std::string("interceptor = gum_object_ref(interceptor); + SPDLOG_DEBUG("Initialized frida internal attach entry at {:x}", + (uintptr_t)function); } frida_internal_attach_entry::~frida_internal_attach_entry() diff --git a/example/uprobe_multi/uprobe_multi.bpf.c b/example/uprobe_multi/uprobe_multi.bpf.c index 76df4e2b6..7c32f390d 100644 --- a/example/uprobe_multi/uprobe_multi.bpf.c +++ b/example/uprobe_multi/uprobe_multi.bpf.c @@ -2,18 +2,37 @@ #include #include #include +#include "uprobe_multi.h" + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 256 * 1024); +} rb SEC(".maps"); SEC("uprobe.multi/./victim:uprobe_multi_func_*") int uprobe_multi_test(struct pt_regs *ctx) { - bpf_printk("Entry triggered: %d, %d", ctx->di, ctx->si); + struct uprobe_multi_event *event; + event = bpf_ringbuf_reserve(&rb, sizeof(*event), 0); + if (!event) + return 0; + event->is_ret = 0; + event->uprobe.arg1 = (long)ctx->di; + event->uprobe.arg2 = (long)ctx->si; + bpf_ringbuf_submit(event, 0); return 0; } SEC("uretprobe.multi/./victim:uprobe_multi_func_*") int uretprobe_multi_test(struct pt_regs *ctx) { - bpf_printk("Return triggered: %d", ctx->ax); + struct uprobe_multi_event *event; + event = bpf_ringbuf_reserve(&rb, sizeof(*event), 0); + if (!event) + return 0; + event->is_ret = 1; + event->uretprobe.ret_val = (long)ctx->ax; + bpf_ringbuf_submit(event, 0); return 0; } diff --git a/example/uprobe_multi/uprobe_multi.c b/example/uprobe_multi/uprobe_multi.c index c0b777ae5..7e6571ede 100644 --- a/example/uprobe_multi/uprobe_multi.c +++ b/example/uprobe_multi/uprobe_multi.c @@ -3,6 +3,7 @@ #include #include #include +#include "uprobe_multi.h" static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) { @@ -16,9 +17,22 @@ static void sig_handler(int sig) exiting = true; } +static int handle_event_rb(void *ctx, void *data, size_t data_sz) +{ + const struct uprobe_multi_event *e = data; + if (!e->is_ret) { + printf("Uprobe triggered: %ld , %ld\n", e->uprobe.arg1, + e->uprobe.arg2); + } else { + printf("Uretprobe triggered: %ld \n", e->uretprobe.ret_val); + } + fflush(stdout); + return 0; +} + int main() { - // libbpf_set_print(libbpf_print_fn); + libbpf_set_print(libbpf_print_fn); int err; signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); @@ -37,13 +51,23 @@ int main() fprintf(stderr, "Unable to attach %d", err); goto cleanup; } + struct ring_buffer *rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), + handle_event_rb, NULL, NULL); + if (!rb) { + err = -1; + fprintf(stderr, "Failed to create ring buffer\n"); + goto cleanup; + } + while (!exiting) { - sleep(1); - puts("See /sys/kernel/tracing/trace_pipe"); + err = ring_buffer__poll(rb, 100); + if (err < 0 && err != -EINTR) { + fprintf(stderr, "error polling perf buffer: %s\n", + strerror(-err)); + goto cleanup; + } + err = 0; } - // bpf_program__attach_uprobe_multi(const struct bpf_program *prog, - // pid_t pid, const char *binary_path, const char *func_pattern, const - // struct bpf_uprobe_multi_opts *opts) cleanup: uprobe_multi_bpf__destroy(skel); diff --git a/example/uprobe_multi/uprobe_multi.h b/example/uprobe_multi/uprobe_multi.h new file mode 100644 index 000000000..1b93e930d --- /dev/null +++ b/example/uprobe_multi/uprobe_multi.h @@ -0,0 +1,17 @@ +#ifndef _UPROBE_MULTI_H +#define _UPROBE_MULTI_H + +struct uprobe_multi_event { + int is_ret; + union { + struct { + long arg1; + long arg2; + } uprobe; + struct { + long ret_val; + } uretprobe; + }; +}; + +#endif diff --git a/example/uprobe_multi/victim.c b/example/uprobe_multi/victim.c index e5f5e027a..a3af87a8d 100644 --- a/example/uprobe_multi/victim.c +++ b/example/uprobe_multi/victim.c @@ -4,15 +4,15 @@ #include #include #include -int uprobe_multi_func_add(int a, int b) +long uprobe_multi_func_add(long a, long b) { return a + b; } -int uprobe_multi_func_sub(int a, int b) +long uprobe_multi_func_sub(long a, long b) { return a - b; } -int uprobe_multi_func_mul(int a, int b) +long uprobe_multi_func_mul(long a, long b) { return a * b; } @@ -21,15 +21,15 @@ int main() { srand(time(NULL)); while (true) { - int a = rand() & 0xff; - int b = rand() & 0xff; + long a = rand() & 0xff; + long b = rand() & 0xff; - int r1 = uprobe_multi_func_add(a, b); - int r2 = uprobe_multi_func_sub(a, b); - int r3 = uprobe_multi_func_mul(a, b); + long r1 = uprobe_multi_func_add(a, b); + long r2 = uprobe_multi_func_sub(a, b); + long r3 = uprobe_multi_func_mul(a, b); - printf("%d+%d=%d, %d-%d=%d, %d*%d=%d\n", a, b, r1, a, b, r2, a, - b, r3); + printf("%ld+%ld=%ld, %ld-%ld=%ld, %ld*%ld=%ld\n", a, b, r1, a, + b, r2, a, b, r3); usleep(1000 * 1000); } return 0; diff --git a/runtime/include/bpf_attach_ctx.hpp b/runtime/include/bpf_attach_ctx.hpp index 0439f7e97..7ef6b1d62 100644 --- a/runtime/include/bpf_attach_ctx.hpp +++ b/runtime/include/bpf_attach_ctx.hpp @@ -62,8 +62,8 @@ class bpf_attach_ctx { // handler_id -> instantiated programs std::map > instantiated_progs; - // handler_id -> (instantiated attaches id, attach_impl*) - std::map > + // handler_id -> (instantiated attaches id, attach_impl*)[] + std::map > > instantiated_attach_ids; // handler_id -> instantiated attach private data & attach type std::map #include #include #include @@ -27,6 +28,13 @@ #include #include #include +#include "spdlog/fmt/ostr.h" +std::ostream &operator<<(std::ostream &os, const bpftime::i32_vec &vec) +{ + for (auto x : vec) + os << x << ","; + return os; +} extern "C" uint64_t bpftime_set_retval(uint64_t value); namespace bpftime { @@ -215,47 +223,25 @@ int bpf_attach_ctx::instantiate_bpf_link_handler_at( int id, const bpf_link_handler &handler) { SPDLOG_DEBUG( - "Instantiating link handler: prog {} -> perf event {}, link_attach_type {}", - handler.prog_id, handler.attach_target_id, + "Instantiating link handler ({}): prog {} -> perf event count ({}), link_attach_type {}", + id, handler.prog_id, handler.attach_target_ids.size(), handler.link_attach_type); auto prog = instantiated_progs.at(handler.prog_id).get(); - if (handler.link_attach_type == BPF_PERF_EVENT) { - auto &[priv_data, attach_type] = - instantiated_perf_events[handler.attach_target_id]; - attach::base_attach_impl *attach_impl; - if (auto itr = attach_impls.find(attach_type); - itr != attach_impls.end()) { - attach_impl = itr->second.first; - } else { - SPDLOG_ERROR("Attach type {} is not registered", - attach_type); - return -ENOTSUP; - } - auto cookie = std::get(handler.data) - .attach_cookie; - int attach_id = attach_impl->create_attach_with_ebpf_callback( - [=](void *mem, size_t mem_size, uint64_t *ret) -> int { - current_thread_bpf_cookie = cookie; - int err = prog->bpftime_prog_exec( - (void *)mem, mem_size, ret); - return err; - }, - *priv_data, attach_type); - if (attach_id < 0) { - SPDLOG_ERROR( - "Unable to instantiate bpf link handler {}: {}", - id, attach_id); - return attach_id; - } - instantiated_attach_ids[id] = - std::make_pair(attach_id, attach_impl); - } else if (handler.link_attach_type == BPF_TRACE_UPROBE_MULTI) { - auto link_data = std::get(handler.data); - for (const auto &entry : link_data.entries) { + if (handler.link_attach_type == BPF_PERF_EVENT || + handler.link_attach_type == BPF_TRACE_UPROBE_MULTI) { + std::vector > + internal_attach_records; + int i = 0; + for (auto target_id : handler.attach_target_ids) { + SPDLOG_DEBUG( + "Handling sub attach target with target id {}, index {}", + target_id, i); auto &[priv_data, attach_type] = - instantiated_perf_events[entry.attach_target - .value()]; + instantiated_perf_events[target_id]; + SPDLOG_DEBUG( + "Attach private data is {}, attach type is ", + priv_data->to_string(), attach_type); attach::base_attach_impl *attach_impl; if (auto itr = attach_impls.find(attach_type); itr != attach_impls.end()) { @@ -265,9 +251,25 @@ int bpf_attach_ctx::instantiate_bpf_link_handler_at( attach_type); return -ENOTSUP; } - auto cookie = - std::get(handler.data) - .attach_cookie; + + std::optional cookie; + if (std::holds_alternative( + handler.data)) { + cookie = std::get( + handler.data) + .attach_cookie; + + } else if (std::holds_alternative( + handler.data)) { + cookie = std::get( + handler.data) + .entries[i] + .cookie; + } + if (cookie.has_value()) { + SPDLOG_DEBUG("Attach cookie is {}", + cookie.value()); + } int attach_id = attach_impl->create_attach_with_ebpf_callback( [=](void *mem, size_t mem_size, @@ -281,8 +283,18 @@ int bpf_attach_ctx::instantiate_bpf_link_handler_at( return err; }, *priv_data, attach_type); + if (attach_id < 0) { + SPDLOG_ERROR( + "Unable to instantiate bpf link handler {} (sub perf id {}): {}", + id, target_id, attach_id); + return attach_id; + } + internal_attach_records.emplace_back(attach_id, + attach_impl); + i++; } - SPDLOG_WARN("TODO: Record attach ids of uprobe multi"); + instantiated_attach_ids[id] = internal_attach_records; + } else { SPDLOG_ERROR("We does not support link with attach type {} yet", handler.link_attach_type); @@ -368,12 +380,14 @@ int bpf_attach_ctx::destroy_instantiated_attach_link(int link_id) SPDLOG_DEBUG("Destroy attach link {}", link_id); if (auto itr = instantiated_attach_ids.find(link_id); itr != instantiated_attach_ids.end()) { - auto [attach_id, impl] = itr->second; - if (int err = impl->detach_by_id(attach_id); err < 0) { - SPDLOG_ERROR( - "Failed to detach attach link id {}, attach-specified id {}: {}", - link_id, attach_id, err); - return err; + for (const auto &[attach_id, impl] : itr->second) { + SPDLOG_DEBUG("Destroy sub attach {}", attach_id); + if (int err = impl->detach_by_id(attach_id); err < 0) { + SPDLOG_ERROR( + "Failed to detach attach link id {}, attach-specified id {}: {}", + link_id, attach_id, err); + return err; + } } instantiated_attach_ids.erase(itr); return 0; diff --git a/runtime/src/bpftime_shm_internal.cpp b/runtime/src/bpftime_shm_internal.cpp index 4e7a35aac..509294f88 100644 --- a/runtime/src/bpftime_shm_internal.cpp +++ b/runtime/src/bpftime_shm_internal.cpp @@ -137,20 +137,20 @@ int bpftime_shm::bpf_map_get_next_key(int fd, const void *key, void *next_key, return handler.bpf_map_get_next_key(key, next_key, from_syscall); } -int bpftime_shm::add_uprobe(int fd, int pid, const char *name, uint64_t offset, - bool retprobe, size_t ref_ctr_off) +int bpftime_shm::add_uprobe(int fd, int pid, const char *module_name, + uint64_t offset, bool retprobe, size_t ref_ctr_off) { if (fd < 0) { // if fd is negative, we need to create a new fd for allocating fd = open_fake_fd(); } SPDLOG_DEBUG("Set fd {} to uprobe, pid={}, name={}, offset={}", fd, pid, - name, offset); - return manager->set_handler( - fd, - bpftime::bpf_perf_event_handler{ retprobe, offset, pid, name, - ref_ctr_off, segment }, - segment); + module_name, offset); + return manager->set_handler(fd, + bpftime::bpf_perf_event_handler{ + retprobe, offset, pid, module_name, + ref_ctr_off, segment }, + segment); } int bpftime_shm::add_uprobe_override(int fd, int pid, const char *name, @@ -239,8 +239,7 @@ int bpftime_shm::add_bpf_prog_attach_target(int perf_fd, int bpf_fd, return -ENOSPC; } manager->set_handler(next_id, - bpf_link_handler(bpf_fd, perf_fd, cookie, - segment), + bpf_link_handler(bpf_fd, perf_fd, cookie, segment), segment); return next_id; } @@ -492,23 +491,17 @@ int bpftime_shm::add_bpf_link(int fd, struct bpf_link_create_args *args) std::get(manager->get_handler(fd)); if (link.link_attach_type == BPF_TRACE_UPROBE_MULTI) { auto &link_data = std::get(link.data); - int i = 0; for (auto &entry : link_data.entries) { - std::string uprobe_name("sub_uprobe_"); - uprobe_name += std::to_string(fd); - uprobe_name += "_"; - uprobe_name += std::to_string(i); - entry.attach_target = + int id = add_uprobe(-1, link_data.pid, - uprobe_name.c_str(), entry.offset, + link_data.path.c_str(), entry.offset, (link_data.flags & BPF_F_UPROBE_MULTI_RETURN) != 0, entry.ref_ctr_offset); - i++; + link.attach_target_ids.push_back(id); SPDLOG_DEBUG( - "Created sub uprobe perf event for uprobe_multi {}: sub id {}, sub name {}, sub offset {:x}", - fd, entry.attach_target.value(), uprobe_name, - entry.offset); + "Created sub uprobe perf event for uprobe_multi {}: sub id {}, sub offset {:x}", + fd, id, entry.offset); } } diff --git a/runtime/src/bpftime_shm_internal.hpp b/runtime/src/bpftime_shm_internal.hpp index f4599eb0d..71aa5f9cb 100644 --- a/runtime/src/bpftime_shm_internal.hpp +++ b/runtime/src/bpftime_shm_internal.hpp @@ -108,8 +108,8 @@ class bpftime_shm { bool from_syscall) const; // create an uprobe fd - int add_uprobe(int fd, int pid, const char *name, uint64_t offset, - bool retprobe, size_t ref_ctr_off); + int add_uprobe(int fd, int pid, const char *module_name, + uint64_t offset, bool retprobe, size_t ref_ctr_off); // create a tracepoint fd int add_tracepoint(int fd, int pid, int32_t tracepoint_id); // create a software perf event fd, typically for a perf event diff --git a/runtime/src/handler/handler_manager.cpp b/runtime/src/handler/handler_manager.cpp index a9d6af694..045506871 100644 --- a/runtime/src/handler/handler_manager.cpp +++ b/runtime/src/handler/handler_manager.cpp @@ -95,11 +95,29 @@ void handler_manager::clear_id_at(int fd, managed_shared_memory &memory) if (std::holds_alternative(handler)) { auto &link_handler = std::get(handler); - if (link_handler.attach_target_ids == fd) { + size_t new_len = + std::remove( + link_handler.attach_target_ids + .begin(), + link_handler.attach_target_ids + .end(), + fd) - + link_handler.attach_target_ids.begin(); + if (link_handler.attach_target_ids.size() != + new_len) { SPDLOG_DEBUG( - "Remove link handler with id {}, prog id {}, due to the removal of perf event {}", - i, link_handler.prog_id, fd); - clear_id_at(i, memory); + "Remove perf event id {} from the attach target list of link {}", + fd, i); + link_handler.attach_target_ids.resize( + new_len); + if (link_handler.attach_target_ids + .empty()) { + SPDLOG_DEBUG( + "Attach link {} has no attach target now, removing it..", + i); + + clear_id_at(i, memory); + } } } } @@ -112,10 +130,8 @@ void handler_manager::clear_id_at(int fd, managed_shared_memory &memory) std::get(handler); if (link_handler.prog_id == fd) { SPDLOG_DEBUG( - "Remove link handler with id {}, perf event id {}, due to the removal of perf event {}", - i, - link_handler.attach_target_id, - fd); + "Remove link handler with id {}, due to the removal of perf event {}", + i, fd); clear_id_at(i, memory); } } diff --git a/runtime/src/handler/link_handler.cpp b/runtime/src/handler/link_handler.cpp index c047514b0..7ebaa1a23 100644 --- a/runtime/src/handler/link_handler.cpp +++ b/runtime/src/handler/link_handler.cpp @@ -42,8 +42,7 @@ bpf_link_handler::bpf_link_handler(struct bpf_link_create_args args, opts.cookies)[i] == 0) ? 0 : ((uint64_t *)(uintptr_t) - opts.cookies)[i], - .attach_target = {} }); + opts.cookies)[i] }); } data = uprobe_multi_link_data{ .path = boost_shm_string( diff --git a/runtime/src/handler/link_handler.hpp b/runtime/src/handler/link_handler.hpp index 0e447c92c..13e05b28e 100644 --- a/runtime/src/handler/link_handler.hpp +++ b/runtime/src/handler/link_handler.hpp @@ -29,10 +29,6 @@ struct uprobe_multi_entry { uint64_t offset; uint64_t ref_ctr_offset; std::optional cookie; - // Out attach implementation requires that each attach has a - // perf event handler, so we also need it if we attach a uprobe - // multi link - mutable std::optional attach_target; }; using uprobe_multi_entry_allocator = boost::interprocess::allocator; struct bpf_link_handler { struct bpf_link_create_args args; int prog_id; - i32_vec attach_target_ids; + // Now we support multiple attach targets + mutable i32_vec attach_target_ids; int link_attach_type; bpf_link_data data; // Create a customized bpf_link From 851fc7249940a66cc7ecc11537b78758d53eb580 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Fri, 22 Mar 2024 20:48:10 +0800 Subject: [PATCH 06/14] update --- runtime/src/bpftime_shm_json.cpp | 12 +++++++++--- .../attach_with_ebpf/test_shm_progs_attach.cpp | 2 +- runtime/unit-test/maps/test_external_map_ops.cpp | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/runtime/src/bpftime_shm_json.cpp b/runtime/src/bpftime_shm_json.cpp index f4ca3c8bf..643e1aee7 100644 --- a/runtime/src/bpftime_shm_json.cpp +++ b/runtime/src/bpftime_shm_json.cpp @@ -9,6 +9,7 @@ #include "handler/perf_event_handler.hpp" #include "spdlog/spdlog.h" #include +#include #include #include #include @@ -174,11 +175,16 @@ static int import_shm_handler_from_json(bpftime_shm &shm, json value, int fd) } } else if (handler_type == "bpf_link_handler") { unsigned int prog_fd = value["attr"]["prog_fd"]; - unsigned int target_fd = value["attr"]["target_fd"]; + json target_ids = value["attr"]["attach_target_ids"]; unsigned int link_attach_type = value["attr"]["link_attach_type"]; + if (link_attach_type != BPF_PERF_EVENT) { + SPDLOG_ERROR( + "We only support loading links of type BPF_PERF_EVENT"); + return -ENOTSUP; + } bpf_link_create_args args = { .prog_fd = prog_fd, - .target_fd = target_fd, + .target_fd = target_ids[0], .attach_type = link_attach_type }; shm.add_bpf_link(fd, &args); } else { @@ -305,7 +311,7 @@ int bpftime::bpftime_export_shm_to_json(const bpftime_shm &shm, { "type", "bpf_link_handler" }, { "attr", { { "prog_fd", h.prog_id }, - { "target_fd", attach_target_ids }, + { "attach_target_ids", attach_target_ids }, { "link_attach_type", h.link_attach_type } } } }; diff --git a/runtime/unit-test/attach_with_ebpf/test_shm_progs_attach.cpp b/runtime/unit-test/attach_with_ebpf/test_shm_progs_attach.cpp index 727eb7c5e..5c774f5ac 100644 --- a/runtime/unit-test/attach_with_ebpf/test_shm_progs_attach.cpp +++ b/runtime/unit-test/attach_with_ebpf/test_shm_progs_attach.cpp @@ -198,7 +198,7 @@ __attribute__((optnone)) TEST_CASE("Test shm progs attach") bpftime::shm_remove remover(SHM_NAME); // The side that creates the mapping - managed_shared_memory segment(create_only, SHM_NAME, 1 << 20); + managed_shared_memory segment(create_only, SHM_NAME, 1 << 22); auto manager = segment.construct(HANDLER_NAME)(segment); auto &manager_ref = *manager; diff --git a/runtime/unit-test/maps/test_external_map_ops.cpp b/runtime/unit-test/maps/test_external_map_ops.cpp index b05abdf45..049dab560 100644 --- a/runtime/unit-test/maps/test_external_map_ops.cpp +++ b/runtime/unit-test/maps/test_external_map_ops.cpp @@ -49,7 +49,7 @@ TEST_CASE("Test basic operations of external hash map ops") { struct bpftime::shm_remove remover(SHM_NAME); // The side that creates the mapping - managed_shared_memory segment(create_only, SHM_NAME, 1 << 20); + managed_shared_memory segment(create_only, SHM_NAME, 1 << 22); auto manager = segment.construct(HANDLER_NAME)(segment); auto &manager_ref = *manager; From 8b99a7871b148dd90d02da40d80a80484128e818 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Fri, 22 Mar 2024 20:56:42 +0800 Subject: [PATCH 07/14] update --- runtime/unit-test/maps/test_shm_hash_maps.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/unit-test/maps/test_shm_hash_maps.cpp b/runtime/unit-test/maps/test_shm_hash_maps.cpp index 3f1e3b00a..bb6a0017d 100644 --- a/runtime/unit-test/maps/test_shm_hash_maps.cpp +++ b/runtime/unit-test/maps/test_shm_hash_maps.cpp @@ -58,10 +58,10 @@ static void test_get_next_element(int fd, bpftime::handler_manager &manager_ref, uint32_t key = 0; uint32_t next_key = 0; while (map_handler.bpf_map_get_next_key(&key, &next_key) == 0) { - spdlog::info("key = {}, next_key = {}", key, next_key); + spdlog::debug("key = {}, next_key = {}", key, next_key); key = next_key; } - spdlog::info("key = {}, next_key = {}", key, next_key); + spdlog::debug("key = {}, next_key = {}", key, next_key); } static void handle_sub_process() From 7133b58149fbd85c79b7043c76540e9615a41a0e Mon Sep 17 00:00:00 2001 From: officeyutong Date: Fri, 22 Mar 2024 21:33:35 +0800 Subject: [PATCH 08/14] update --- .github/workflows/test-runtime.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-runtime.yml b/.github/workflows/test-runtime.yml index eafcf6a1c..4ad5afc92 100644 --- a/.github/workflows/test-runtime.yml +++ b/.github/workflows/test-runtime.yml @@ -34,8 +34,8 @@ jobs: - name: build runtime with mpk enable run: | rm -rf build - cmake -Bbuild -DBPFTIME_LLVM_JIT=YES -DBPFTIME_ENABLE_UNIT_TESTING=YES -DBPFTIME_ENABLE_MPK=YES -DCMAKE_BUILD_TYPE=Debug - cmake --build build --config Debug --target bpftime_runtime_tests -j$(nproc) + cmake -Bbuild -DBPFTIME_LLVM_JIT=YES -DBPFTIME_ENABLE_UNIT_TESTING=YES -DBPFTIME_ENABLE_MPK=YES -DCMAKE_BUILD_TYPE=MinSizeRel + cmake --build build --config MinSizeRel --target bpftime_runtime_tests -j$(nproc) - name: test runtime with mpk From 6f4e0c40a7f79ff48b77403c324b0ac1ef82f045 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Fri, 22 Mar 2024 21:45:09 +0800 Subject: [PATCH 09/14] Update --- runtime/unit-test/maps/test_per_cpu_hash.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/unit-test/maps/test_per_cpu_hash.cpp b/runtime/unit-test/maps/test_per_cpu_hash.cpp index e709a0425..d1d087539 100644 --- a/runtime/unit-test/maps/test_per_cpu_hash.cpp +++ b/runtime/unit-test/maps/test_per_cpu_hash.cpp @@ -22,7 +22,7 @@ static const char *SHM_NAME = "BPFTIME_PER_CPU_HASH_SHM"; TEST_CASE("Test basic operations of hash map") { shm_remove remover(SHM_NAME); - managed_shared_memory mem(create_only, SHM_NAME, 20 << 20); + managed_shared_memory mem(create_only, SHM_NAME, 1 << 22); uint32_t ncpu = sysconf(_SC_NPROCESSORS_ONLN); std::mt19937 gen; gen.seed(Catch::rngSeed()); From e26f5724482eaa6239224a26129c98c063be9b1e Mon Sep 17 00:00:00 2001 From: officeyutong Date: Fri, 22 Mar 2024 21:52:13 +0800 Subject: [PATCH 10/14] update --- runtime/unit-test/maps/test_external_map_ops.cpp | 2 +- runtime/unit-test/maps/test_shm_hash_maps.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/unit-test/maps/test_external_map_ops.cpp b/runtime/unit-test/maps/test_external_map_ops.cpp index 049dab560..d65d79715 100644 --- a/runtime/unit-test/maps/test_external_map_ops.cpp +++ b/runtime/unit-test/maps/test_external_map_ops.cpp @@ -87,6 +87,6 @@ TEST_CASE("Test basic operations of external hash map ops") uint32_t key = i; auto val = *(uint64_t *)(map_handler.map_lookup_elem(&key)); REQUIRE(val == i); - spdlog::info("val for {} = {:x}", i, val); + spdlog::debug("val for {} = {:x}", i, val); } } diff --git a/runtime/unit-test/maps/test_shm_hash_maps.cpp b/runtime/unit-test/maps/test_shm_hash_maps.cpp index bb6a0017d..6a0e64c39 100644 --- a/runtime/unit-test/maps/test_shm_hash_maps.cpp +++ b/runtime/unit-test/maps/test_shm_hash_maps.cpp @@ -37,7 +37,7 @@ static void test_lookup_map(int fd, bpftime::handler_manager &manager_ref, uint32_t key = i; auto val = *(uint64_t *)(map_handler.map_lookup_elem(&key)); REQUIRE(val == ((((uint64_t)key) << 32) | 0xffffffff)); - spdlog::info("val for {} = {:x}", i, val); + spdlog::debug("val for {} = {:x}", i, val); } } From 8bd227c80dea3d438ba05cf7c49858369c441426 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Fri, 22 Mar 2024 22:10:56 +0800 Subject: [PATCH 11/14] Update --- .github/workflows/test-runtime.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test-runtime.yml b/.github/workflows/test-runtime.yml index 4ad5afc92..b58b70a34 100644 --- a/.github/workflows/test-runtime.yml +++ b/.github/workflows/test-runtime.yml @@ -39,4 +39,6 @@ jobs: - name: test runtime with mpk + # We don't have enough disk space to run this + if: ${{matrix.container != 'fedora-39'}} run: ./build/runtime/unit-test/bpftime_runtime_tests From f08f4930e26e206736d63c78280dbb183bfc5ece Mon Sep 17 00:00:00 2001 From: officeyutong Date: Sun, 24 Mar 2024 23:18:26 +0800 Subject: [PATCH 12/14] Update --- runtime/include/bpf_attach_ctx.hpp | 42 ++- runtime/src/attach/bpf_attach_ctx.cpp | 327 +++++++++++++++++------- runtime/src/bpftime_shm_internal.cpp | 20 +- runtime/src/bpftime_shm_json.cpp | 12 +- runtime/src/handler/handler_manager.cpp | 26 +- runtime/src/handler/link_handler.cpp | 14 +- runtime/src/handler/link_handler.hpp | 9 +- 7 files changed, 289 insertions(+), 161 deletions(-) diff --git a/runtime/include/bpf_attach_ctx.hpp b/runtime/include/bpf_attach_ctx.hpp index 7ef6b1d62..38550c4b8 100644 --- a/runtime/include/bpf_attach_ctx.hpp +++ b/runtime/include/bpf_attach_ctx.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,22 @@ using syscall_hooker_func_t = int64_t (*)(int64_t sys_nr, int64_t arg1, int64_t arg4, int64_t arg5, int64_t arg6); +/** + * @brief Represent a series of native attach entries instantiated by a certain + * bpf link + * + */ +using instantiated_link_record = + std::vector >; +/** + * @brief Callback type for create a private data instance for a certain attach + * type + * + */ +using private_data_creator = + std::function( + const std::string_view &, int &)>; + class bpf_attach_ctx { public: bpf_attach_ctx(); @@ -63,17 +80,13 @@ class bpf_attach_ctx { // handler_id -> instantiated programs std::map > instantiated_progs; // handler_id -> (instantiated attaches id, attach_impl*)[] - std::map > > - instantiated_attach_ids; + std::map instantiated_attach_ids; // handler_id -> instantiated attach private data & attach type std::map, int> > instantiated_perf_events; // attach_type -> attach impl - std::map( - const std::string_view &, int &)> > > + std::map > attach_impls; // Holds the ownership of all attach impls std::vector > @@ -81,15 +94,28 @@ class bpf_attach_ctx { // Record which handlers were already instantiated std::set instantiated_handlers; + // Handlers for different link attach type + std::map( + const bpf_link_handler &link, int id, + const handler_manager *man)> > + link_attach_handlers; + int instantiate_handler_at(const handler_manager *manager, int id, std::set &stk, const agent_config &config); int instantiate_prog_handler_at(int id, const bpf_prog_handler &handler, const agent_config &config); - int instantiate_bpf_link_handler_at(int id, - const bpf_link_handler &handler); int instantiate_perf_event_handler_at( int id, const bpf_perf_event_handler &perf_handler); + + std::optional + instantiate_perf_event_bpf_link_handler_at( + int id, const bpf_link_handler &handler, + const handler_manager *manager); + + std::optional + instantiate_uprobe_multi_handler_at(int id, + const bpf_link_handler &handler); }; } // namespace bpftime diff --git a/runtime/src/attach/bpf_attach_ctx.cpp b/runtime/src/attach/bpf_attach_ctx.cpp index 2e6a4e472..4d3d89877 100644 --- a/runtime/src/attach/bpf_attach_ctx.cpp +++ b/runtime/src/attach/bpf_attach_ctx.cpp @@ -8,6 +8,7 @@ #include "bpftime_shm.hpp" #include "handler/link_handler.hpp" #include "handler/prog_handler.hpp" +#include #include #include #include @@ -29,12 +30,7 @@ #include #include #include "spdlog/fmt/ostr.h" -std::ostream &operator<<(std::ostream &os, const bpftime::i32_vec &vec) -{ - for (auto x : vec) - os << x << ","; - return os; -} + extern "C" uint64_t bpftime_set_retval(uint64_t value); namespace bpftime { @@ -95,6 +91,33 @@ bpf_attach_ctx::bpf_attach_ctx(void) { current_id = CURRENT_ID_OFFSET; + // Register handlers for different link attach type + link_attach_handlers[BPF_PERF_EVENT] = + [this](const bpf_link_handler &link, int id, + const handler_manager *manager) + -> std::optional { + // Need to instantiate the corresponding perf event first + if (int err = instantiate_perf_event_handler_at( + link.target_id, + (std::get( + manager->get_handler(link.target_id)))); + err < 0) { + SPDLOG_ERROR( + "Unable to instantiate perf event handler {} when instantiating link handler {}: {}", + link.target_id, id, err); + return {}; + } + // For normal perf events, we instantiate by calling + // instantiate_perf_event_bpf_link_handler_at + return instantiate_perf_event_bpf_link_handler_at(id, link, + manager); + }; + link_attach_handlers[BPF_TRACE_UPROBE_MULTI] = + [this](const bpf_link_handler &link, int id, + const handler_manager *manager) + -> std::optional { + return this->instantiate_uprobe_multi_handler_at(id, link); + }; } int bpf_attach_ctx::instantiate_handler_at(const handler_manager *manager, @@ -133,6 +156,7 @@ int bpf_attach_ctx::instantiate_handler_at(const handler_manager *manager, } } else if (std::holds_alternative(handler)) { auto &link_handler = std::get(handler); + // Instantiate program of the current bpf link if (int err = instantiate_handler_at( manager, link_handler.prog_id, stk, config); err < 0) { @@ -141,25 +165,24 @@ int bpf_attach_ctx::instantiate_handler_at(const handler_manager *manager, link_handler.prog_id, id, err); return err; } - for (auto attach_target_id : link_handler.attach_target_ids) { - SPDLOG_DEBUG( - "Instantiating attach target id {} for link handler {}", - attach_target_id, id); - if (int err = instantiate_handler_at( - manager, attach_target_id, stk, config); - err < 0) { + // Call the related handler to handler the instantiation of the + // link. Handler might instantiate other handlers. + if (auto itr = link_attach_handlers.find( + link_handler.link_attach_type); + itr != link_attach_handlers.end()) { + if (auto ret = itr->second(link_handler, id, manager); + ret.has_value()) { + instantiated_attach_ids[id] = ret.value(); + } else { SPDLOG_ERROR( - "Unable to instantiate perf event handler {} when instantiating link handler {}: {}", - attach_target_id, id, err); - return err; + "Unable to instantiate link handler {}", + id); + return -EINVAL; } - } - if (int err = instantiate_bpf_link_handler_at(id, link_handler); - err < 0) { - SPDLOG_ERROR( - "Unable to instantiate bpf link handler {}: {}", - id, err); - return err; + } else { + SPDLOG_ERROR("Unsupported link attach type: {}", + link_handler.link_attach_type); + return -ENOTSUP; } } else if (std::holds_alternative(handler)) { SPDLOG_ERROR("Instantiating a unused handler at {}", id); @@ -219,89 +242,203 @@ int bpf_attach_ctx::instantiate_prog_handler_at(int id, } return 0; } -int bpf_attach_ctx::instantiate_bpf_link_handler_at( +std::optional +bpf_attach_ctx::instantiate_uprobe_multi_handler_at( int id, const bpf_link_handler &handler) { SPDLOG_DEBUG( - "Instantiating link handler ({}): prog {} -> perf event count ({}), link_attach_type {}", - id, handler.prog_id, handler.attach_target_ids.size(), - handler.link_attach_type); - + "Instantiating bpf link handler of type uprobe multi at {}", + id); auto prog = instantiated_progs.at(handler.prog_id).get(); - if (handler.link_attach_type == BPF_PERF_EVENT || - handler.link_attach_type == BPF_TRACE_UPROBE_MULTI) { - std::vector > - internal_attach_records; - int i = 0; - for (auto target_id : handler.attach_target_ids) { - SPDLOG_DEBUG( - "Handling sub attach target with target id {}, index {}", - target_id, i); - auto &[priv_data, attach_type] = - instantiated_perf_events[target_id]; - SPDLOG_DEBUG( - "Attach private data is {}, attach type is ", - priv_data->to_string(), attach_type); - attach::base_attach_impl *attach_impl; - if (auto itr = attach_impls.find(attach_type); - itr != attach_impls.end()) { - attach_impl = itr->second.first; - } else { - SPDLOG_ERROR("Attach type {} is not registered", - attach_type); - return -ENOTSUP; - } + // Instantiate uprobe multi link handler + // Such type doesn't have an attach target, so we direct create uprobes + const auto &link_data = std::get(handler.data); - std::optional cookie; - if (std::holds_alternative( - handler.data)) { - cookie = std::get( - handler.data) - .attach_cookie; + attach::base_attach_impl *attach_impl = nullptr; + private_data_creator priv_creator; + int attach_type; + if (link_data.flags & BPF_F_UPROBE_MULTI_RETURN) { + // Here we should ensure that attach impl of type uretprobe has + // been registered + if (auto itr = attach_impls.find( + (int)bpf_event_type::BPF_TYPE_URETPROBE); + itr != attach_impls.end()) { + std::tie(attach_impl, priv_creator) = itr->second; + attach_type = (int)bpf_event_type::BPF_TYPE_URETPROBE; - } else if (std::holds_alternative( - handler.data)) { - cookie = std::get( - handler.data) - .entries[i] - .cookie; - } - if (cookie.has_value()) { - SPDLOG_DEBUG("Attach cookie is {}", - cookie.value()); - } - int attach_id = - attach_impl->create_attach_with_ebpf_callback( - [=](void *mem, size_t mem_size, - uint64_t *ret) -> int { - current_thread_bpf_cookie = - cookie; - int err = - prog->bpftime_prog_exec( - (void *)mem, - mem_size, ret); - return err; - }, - *priv_data, attach_type); - if (attach_id < 0) { - SPDLOG_ERROR( - "Unable to instantiate bpf link handler {} (sub perf id {}): {}", - id, target_id, attach_id); - return attach_id; - } - internal_attach_records.emplace_back(attach_id, - attach_impl); - i++; + } else { + SPDLOG_ERROR( + "Trying to instantiate uprobe multi (exit hook), but uretprobe is not registered"); + return {}; + } + } else { + // been registered + if (auto itr = attach_impls.find( + (int)bpf_event_type::BPF_TYPE_UPROBE); + itr != attach_impls.end()) { + std::tie(attach_impl, priv_creator) = itr->second; + attach_type = (int)bpf_event_type::BPF_TYPE_UPROBE; + + } else { + SPDLOG_ERROR( + "Trying to instantiate uprobe multi (entry hook), but uretprobe is not registered"); + return {}; + } + } + instantiated_link_record native_ids; + for (const auto &entry : link_data.entries) { + std::string arg_str = link_data.path.c_str(); + arg_str += ":"; + arg_str += std::to_string(entry.offset); + int err = 0; + auto priv_data = priv_creator(arg_str, err); + if (err < 0) { + SPDLOG_ERROR( + "Failed to create uprobe/uretprobe private data for arg string {}, err={}, uprobe multi link {}", + arg_str, err, id); + return {}; } - instantiated_attach_ids[id] = internal_attach_records; + auto cookie = entry.cookie; + int attach_id = attach_impl->create_attach_with_ebpf_callback( + [=](void *mem, size_t mem_size, uint64_t *ret) -> int { + current_thread_bpf_cookie = cookie; + int err = prog->bpftime_prog_exec( + (void *)mem, mem_size, ret); + return err; + }, + *priv_data, attach_type); + native_ids.emplace_back(attach_id, attach_impl); + } + return native_ids; +} +std::optional +bpf_attach_ctx::instantiate_perf_event_bpf_link_handler_at( + int id, const bpf_link_handler &handler, const handler_manager *manager) +{ + SPDLOG_DEBUG( + "Instantiating bpf link handler of type perf event at id {}, prog {}, target {}", + id, handler.prog_id, handler.target_id); + auto prog = instantiated_progs.at(handler.prog_id).get(); + // For perf event link, there should be an instantiated target + auto &[priv_data, attach_type] = + instantiated_perf_events[handler.target_id]; + SPDLOG_DEBUG("Attach private data is {}, attach type is ", + priv_data->to_string(), attach_type); + attach::base_attach_impl *attach_impl; + if (auto itr = attach_impls.find(attach_type); + itr != attach_impls.end()) { + attach_impl = itr->second.first; } else { - SPDLOG_ERROR("We does not support link with attach type {} yet", - handler.link_attach_type); - return -ENOTSUP; + SPDLOG_ERROR("Attach type {} is not registered", attach_type); + return {}; } - return 0; + auto cookie = + std::get(handler.data).attach_cookie; + if (cookie.has_value()) { + SPDLOG_DEBUG("Attach cookie is {}", cookie.value()); + } + int attach_id = attach_impl->create_attach_with_ebpf_callback( + [=](void *mem, size_t mem_size, uint64_t *ret) -> int { + current_thread_bpf_cookie = cookie; + int err = prog->bpftime_prog_exec((void *)mem, mem_size, + ret); + return err; + }, + *priv_data, attach_type); + if (attach_id < 0) { + SPDLOG_ERROR( + "Unable to instantiate bpf link handler {} (sub perf id {}): {}", + id, handler.target_id, attach_id); + return {}; + } + return std::optional( + { std::make_pair(attach_id, attach_impl) }); } + +// int bpf_attach_ctx::instantiate_bpf_link_handler_at( +// int id, const bpf_link_handler &handler) +// { +// SPDLOG_DEBUG( +// "Instantiating link handler ({}): prog {} -> perf event count ({}), link_attach_type {}", +// id, handler.prog_id, handler.attach_target_ids.size(), +// handler.link_attach_type); + +// auto prog = instantiated_progs.at(handler.prog_id).get(); +// if (handler.link_attach_type == BPF_PERF_EVENT || +// handler.link_attach_type == BPF_TRACE_UPROBE_MULTI) { +// std::vector > +// internal_attach_records; +// int i = 0; +// for (auto target_id : handler.attach_target_ids) { +// SPDLOG_DEBUG( +// "Handling sub attach target with target id {}, index {}", +// target_id, i); +// auto &[priv_data, attach_type] = +// instantiated_perf_events[target_id]; +// SPDLOG_DEBUG( +// "Attach private data is {}, attach type is ", +// priv_data->to_string(), attach_type); +// attach::base_attach_impl *attach_impl; +// if (auto itr = attach_impls.find(attach_type); +// itr != attach_impls.end()) { +// attach_impl = itr->second.first; +// } else { +// SPDLOG_ERROR("Attach type {} is not registered", +// attach_type); +// return -ENOTSUP; +// } + +// std::optional cookie; +// if (std::holds_alternative( +// handler.data)) { +// cookie = std::get( +// handler.data) +// .attach_cookie; + +// } else if (std::holds_alternative( +// handler.data)) { +// cookie = std::get( +// handler.data) +// .entries[i] +// .cookie; +// } +// if (cookie.has_value()) { +// SPDLOG_DEBUG("Attach cookie is {}", +// cookie.value()); +// } +// int attach_id = +// attach_impl->create_attach_with_ebpf_callback( +// [=](void *mem, size_t mem_size, +// uint64_t *ret) -> int { +// current_thread_bpf_cookie = +// cookie; +// int err = +// prog->bpftime_prog_exec( +// (void *)mem, +// mem_size, ret); +// return err; +// }, +// *priv_data, attach_type); +// if (attach_id < 0) { +// SPDLOG_ERROR( +// "Unable to instantiate bpf link handler {} (sub perf id {}): {}", +// id, target_id, attach_id); +// return attach_id; +// } +// internal_attach_records.emplace_back(attach_id, +// attach_impl); +// i++; +// } +// instantiated_attach_ids[id] = internal_attach_records; + +// } else { +// SPDLOG_ERROR("We does not support link with attach type {} yet", +// handler.link_attach_type); +// return -ENOTSUP; +// } +// return 0; +// } int bpf_attach_ctx::instantiate_perf_event_handler_at( int id, const bpf_perf_event_handler &perf_handler) { diff --git a/runtime/src/bpftime_shm_internal.cpp b/runtime/src/bpftime_shm_internal.cpp index 509294f88..8c9a960fe 100644 --- a/runtime/src/bpftime_shm_internal.cpp +++ b/runtime/src/bpftime_shm_internal.cpp @@ -487,24 +487,6 @@ int bpftime_shm::add_bpf_link(int fd, struct bpf_link_create_args *args) } int result = manager->set_handler( fd, bpftime::bpf_link_handler(*args, segment), segment); - auto &link = - std::get(manager->get_handler(fd)); - if (link.link_attach_type == BPF_TRACE_UPROBE_MULTI) { - auto &link_data = std::get(link.data); - for (auto &entry : link_data.entries) { - int id = - add_uprobe(-1, link_data.pid, - link_data.path.c_str(), entry.offset, - (link_data.flags & - BPF_F_UPROBE_MULTI_RETURN) != 0, - entry.ref_ctr_offset); - link.attach_target_ids.push_back(id); - SPDLOG_DEBUG( - "Created sub uprobe perf event for uprobe_multi {}: sub id {}, sub offset {:x}", - fd, id, entry.offset); - } - } - return result; } @@ -522,7 +504,7 @@ void bpftime_shm::enable_mpk() return; } if (pkey_set(pkey, PKEY_DISABLE_WRITE) == -1) { - SPDLOG_ERROR("pkey_set read only failed"); + SPDLOG_WARN("pkey_set read only failed"); } } diff --git a/runtime/src/bpftime_shm_json.cpp b/runtime/src/bpftime_shm_json.cpp index 643e1aee7..291399ad9 100644 --- a/runtime/src/bpftime_shm_json.cpp +++ b/runtime/src/bpftime_shm_json.cpp @@ -175,7 +175,7 @@ static int import_shm_handler_from_json(bpftime_shm &shm, json value, int fd) } } else if (handler_type == "bpf_link_handler") { unsigned int prog_fd = value["attr"]["prog_fd"]; - json target_ids = value["attr"]["attach_target_ids"]; + unsigned int target_id = value["attr"]["target_id"]; unsigned int link_attach_type = value["attr"]["link_attach_type"]; if (link_attach_type != BPF_PERF_EVENT) { @@ -184,7 +184,7 @@ static int import_shm_handler_from_json(bpftime_shm &shm, json value, int fd) return -ENOTSUP; } bpf_link_create_args args = { .prog_fd = prog_fd, - .target_fd = target_ids[0], + .target_fd = target_id, .attach_type = link_attach_type }; shm.add_bpf_link(fd, &args); } else { @@ -304,14 +304,14 @@ int bpftime::bpftime_export_shm_to_json(const bpftime_shm &shm, "We only support exporting links with attach type BPF_PERF_EVENT now"); return -ENOTSUP; } - json attach_target_ids; - for (auto x : h.attach_target_ids) - attach_target_ids.push_back(x); + // json attach_target_ids; + // for (auto x : h.attach_target_ids) + // attach_target_ids.push_back(x); j[std::to_string(i)] = { { "type", "bpf_link_handler" }, { "attr", { { "prog_fd", h.prog_id }, - { "attach_target_ids", attach_target_ids }, + { "target_id", h.target_id }, { "link_attach_type", h.link_attach_type } } } }; diff --git a/runtime/src/handler/handler_manager.cpp b/runtime/src/handler/handler_manager.cpp index 045506871..0603b6ffc 100644 --- a/runtime/src/handler/handler_manager.cpp +++ b/runtime/src/handler/handler_manager.cpp @@ -95,29 +95,11 @@ void handler_manager::clear_id_at(int fd, managed_shared_memory &memory) if (std::holds_alternative(handler)) { auto &link_handler = std::get(handler); - size_t new_len = - std::remove( - link_handler.attach_target_ids - .begin(), - link_handler.attach_target_ids - .end(), - fd) - - link_handler.attach_target_ids.begin(); - if (link_handler.attach_target_ids.size() != - new_len) { + if (link_handler.target_id == fd) { SPDLOG_DEBUG( - "Remove perf event id {} from the attach target list of link {}", - fd, i); - link_handler.attach_target_ids.resize( - new_len); - if (link_handler.attach_target_ids - .empty()) { - SPDLOG_DEBUG( - "Attach link {} has no attach target now, removing it..", - i); - - clear_id_at(i, memory); - } + "Removing link handler {} since its target is {}", + i, fd); + clear_id_at(i, memory); } } } diff --git a/runtime/src/handler/link_handler.cpp b/runtime/src/handler/link_handler.cpp index 7ebaa1a23..d27cf8a78 100644 --- a/runtime/src/handler/link_handler.cpp +++ b/runtime/src/handler/link_handler.cpp @@ -5,8 +5,8 @@ using namespace bpftime; bpf_link_handler::bpf_link_handler(struct bpf_link_create_args args, managed_shared_memory &mem) - : args(args), prog_id(args.prog_fd), - attach_target_ids(mem.get_segment_manager()), + : args(args), prog_id(args.prog_fd), target_id(args.target_fd), + // attach_target_ids(mem.get_segment_manager()), link_attach_type(args.attach_type) { if (args.attach_type == BPF_PERF_EVENT) { @@ -21,7 +21,7 @@ bpf_link_handler::bpf_link_handler(struct bpf_link_create_args args, } else { data = perf_event_link_data{}; } - attach_target_ids.push_back(args.target_fd); + // attach_target_ids.push_back(args.target_fd); } else if (args.attach_type == BPF_TRACE_UPROBE_MULTI) { SPDLOG_DEBUG( "Initializing bpf link of type uprobe_multi, using link create args"); @@ -60,18 +60,18 @@ bpf_link_handler::bpf_link_handler(struct bpf_link_create_args args, } bpf_link_handler::bpf_link_handler(int prog_id, int attach_target_id, managed_shared_memory &mem) - : prog_id(prog_id), attach_target_ids(mem.get_segment_manager()), + : prog_id(prog_id), target_id(attach_target_id), link_attach_type(BPF_PERF_EVENT), data(perf_event_link_data{ .attach_cookie = {} }) { - attach_target_ids.push_back(attach_target_id); + // attach_target_ids.push_back(attach_target_id); } bpf_link_handler::bpf_link_handler(int prog_id, int attach_target_id, std::optional cookie, managed_shared_memory &mem) - : prog_id(prog_id), attach_target_ids(mem.get_segment_manager()), + : prog_id(prog_id), target_id(attach_target_id), link_attach_type(BPF_PERF_EVENT), data(perf_event_link_data{ .attach_cookie = cookie }) { - attach_target_ids.push_back(attach_target_id); + // attach_target_ids.push_back(attach_target_id); } diff --git a/runtime/src/handler/link_handler.hpp b/runtime/src/handler/link_handler.hpp index 13e05b28e..077ac0376 100644 --- a/runtime/src/handler/link_handler.hpp +++ b/runtime/src/handler/link_handler.hpp @@ -46,16 +46,17 @@ struct uprobe_multi_link_data { using bpf_link_data = std::variant; -using i32_vec_allocator = boost::interprocess::allocator< - int32_t, boost::interprocess::managed_shared_memory::segment_manager>; -using i32_vec = boost::interprocess::vector; +// using i32_vec_allocator = boost::interprocess::allocator< +// int32_t, boost::interprocess::managed_shared_memory::segment_manager>; +// using i32_vec = boost::interprocess::vector; // handle the bpf link fd struct bpf_link_handler { struct bpf_link_create_args args; int prog_id; // Now we support multiple attach targets - mutable i32_vec attach_target_ids; + // mutable i32_vec attach_target_ids; + int target_id; int link_attach_type; bpf_link_data data; // Create a customized bpf_link From ea450e57841320466bb0b01c627896d0ca6981e7 Mon Sep 17 00:00:00 2001 From: officeyutong Date: Sun, 24 Mar 2024 23:18:41 +0800 Subject: [PATCH 13/14] Update --- runtime/src/attach/bpf_attach_ctx.cpp | 83 --------------------------- 1 file changed, 83 deletions(-) diff --git a/runtime/src/attach/bpf_attach_ctx.cpp b/runtime/src/attach/bpf_attach_ctx.cpp index 4d3d89877..11fba4281 100644 --- a/runtime/src/attach/bpf_attach_ctx.cpp +++ b/runtime/src/attach/bpf_attach_ctx.cpp @@ -356,89 +356,6 @@ bpf_attach_ctx::instantiate_perf_event_bpf_link_handler_at( { std::make_pair(attach_id, attach_impl) }); } -// int bpf_attach_ctx::instantiate_bpf_link_handler_at( -// int id, const bpf_link_handler &handler) -// { -// SPDLOG_DEBUG( -// "Instantiating link handler ({}): prog {} -> perf event count ({}), link_attach_type {}", -// id, handler.prog_id, handler.attach_target_ids.size(), -// handler.link_attach_type); - -// auto prog = instantiated_progs.at(handler.prog_id).get(); -// if (handler.link_attach_type == BPF_PERF_EVENT || -// handler.link_attach_type == BPF_TRACE_UPROBE_MULTI) { -// std::vector > -// internal_attach_records; -// int i = 0; -// for (auto target_id : handler.attach_target_ids) { -// SPDLOG_DEBUG( -// "Handling sub attach target with target id {}, index {}", -// target_id, i); -// auto &[priv_data, attach_type] = -// instantiated_perf_events[target_id]; -// SPDLOG_DEBUG( -// "Attach private data is {}, attach type is ", -// priv_data->to_string(), attach_type); -// attach::base_attach_impl *attach_impl; -// if (auto itr = attach_impls.find(attach_type); -// itr != attach_impls.end()) { -// attach_impl = itr->second.first; -// } else { -// SPDLOG_ERROR("Attach type {} is not registered", -// attach_type); -// return -ENOTSUP; -// } - -// std::optional cookie; -// if (std::holds_alternative( -// handler.data)) { -// cookie = std::get( -// handler.data) -// .attach_cookie; - -// } else if (std::holds_alternative( -// handler.data)) { -// cookie = std::get( -// handler.data) -// .entries[i] -// .cookie; -// } -// if (cookie.has_value()) { -// SPDLOG_DEBUG("Attach cookie is {}", -// cookie.value()); -// } -// int attach_id = -// attach_impl->create_attach_with_ebpf_callback( -// [=](void *mem, size_t mem_size, -// uint64_t *ret) -> int { -// current_thread_bpf_cookie = -// cookie; -// int err = -// prog->bpftime_prog_exec( -// (void *)mem, -// mem_size, ret); -// return err; -// }, -// *priv_data, attach_type); -// if (attach_id < 0) { -// SPDLOG_ERROR( -// "Unable to instantiate bpf link handler {} (sub perf id {}): {}", -// id, target_id, attach_id); -// return attach_id; -// } -// internal_attach_records.emplace_back(attach_id, -// attach_impl); -// i++; -// } -// instantiated_attach_ids[id] = internal_attach_records; - -// } else { -// SPDLOG_ERROR("We does not support link with attach type {} yet", -// handler.link_attach_type); -// return -ENOTSUP; -// } -// return 0; -// } int bpf_attach_ctx::instantiate_perf_event_handler_at( int id, const bpf_perf_event_handler &perf_handler) { From b1aeca1e1ef3400e85574174dbf03310a7d0d64c Mon Sep 17 00:00:00 2001 From: officeyutong Date: Sun, 24 Mar 2024 23:21:29 +0800 Subject: [PATCH 14/14] update --- runtime/src/handler/link_handler.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/runtime/src/handler/link_handler.hpp b/runtime/src/handler/link_handler.hpp index 077ac0376..0bd3deff5 100644 --- a/runtime/src/handler/link_handler.hpp +++ b/runtime/src/handler/link_handler.hpp @@ -46,16 +46,10 @@ struct uprobe_multi_link_data { using bpf_link_data = std::variant; -// using i32_vec_allocator = boost::interprocess::allocator< -// int32_t, boost::interprocess::managed_shared_memory::segment_manager>; -// using i32_vec = boost::interprocess::vector; - // handle the bpf link fd struct bpf_link_handler { struct bpf_link_create_args args; int prog_id; - // Now we support multiple attach targets - // mutable i32_vec attach_target_ids; int target_id; int link_attach_type; bpf_link_data data;