From f9f2ce71ff7e3727c36f161828065431ba6427fa Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Tue, 9 Apr 2024 10:43:00 +0000 Subject: [PATCH 01/23] fix symbolization Signed-off-by: LiuLingze --- .../src/bpf_wapper/eBPFStackCollector.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp index f69a509f1..6d2ce144a 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp @@ -132,7 +132,7 @@ StackCollector::operator std::string() sym.name = demangleCppSym(sym.name); } std::stringstream ss(""); - ss << "+0x" << std::hex << (addr - sym.start); + ss << "+0x" << std::hex << (sym.ip - sym.start); sym.name += ss.str(); g_symbol_parser.putin_symbol_cache(id.pid, addr, sym.name); } @@ -160,7 +160,11 @@ StackCollector::operator std::string() symbol sym; sym.reset(addr); if (g_symbol_parser.find_kernel_symbol(sym)) - ; + { + std::stringstream ss(""); + ss << "+0x" << std::hex << (sym.ip - sym.start); + sym.name += ss.str(); + } else { std::stringstream ss(""); @@ -224,4 +228,4 @@ StackCollector::operator std::string() oss << _BLUE "OK" _RE "\n"; return oss.str(); -} \ No newline at end of file +} From ac1604ab0197d5d8456c6b7bab04f7ad49b0ac04 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Wed, 10 Apr 2024 09:38:52 +0000 Subject: [PATCH 02/23] update Makefile Signed-off-by: LiuLingze --- eBPF_Supermarket/Stack_Analyser/Makefile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/Makefile b/eBPF_Supermarket/Stack_Analyser/Makefile index 132bb1c85..37cbf813e 100644 --- a/eBPF_Supermarket/Stack_Analyser/Makefile +++ b/eBPF_Supermarket/Stack_Analyser/Makefile @@ -115,18 +115,16 @@ $(BPF_SKEL)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL) $(BPF_SKEL) $(call msg,GEN-SKEL,$@) $(Q)$(BPFTOOL) gen skeleton $< > $@ -$(patsubst %,include/bpf_wapper/%.h,$(BPF)): include/bpf_wapper/%.h: $(BPF_SKEL)/%.skel.h - -$(patsubst %,$(OUTPUT)/%.o,$(BPF)): $(OUTPUT)/%.o: src/bpf_wapper/%.cpp include/bpf_wapper/%.h $(OUTPUT)/eBPFStackCollector.o +$(patsubst %,$(OUTPUT)/%.o,$(BPF)): $(OUTPUT)/%.o: src/bpf_wapper/%.cpp include/bpf_wapper/%.h $(BPF_SKEL)/%.skel.h $(OUTPUT)/eBPFStackCollector.o $(call msg,CXX,$@) $(Q)$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $@ # Build depending library -$(patsubst %,$(OUTPUT)/%.o,$(BIN)): $(OUTPUT)/%.o: src/%.cpp $(patsubst %,include/bpf_wapper/%.h,$(BPF)) +$(patsubst %,$(OUTPUT)/%.o,$(BIN)): $(OUTPUT)/%.o: src/%.cpp $(patsubst %,$(BPF_SKEL)/%.skel.h,$(BPF)) $(call msg,CXX,$@) $(Q)$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $@ -$(OUTPUT)/eBPFStackCollector.o: src/bpf_wapper/eBPFStackCollector.cpp | $(LIBBPF_OBJ) +$(OUTPUT)/eBPFStackCollector.o: src/bpf_wapper/eBPFStackCollector.cpp include/bpf_wapper/eBPFStackCollector.h | $(LIBBPF_OBJ) $(call msg,CXX,$@) $(Q)$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $@ From 865e237f0f3e53f5d69a0caddb409fccfa3fc33e Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Wed, 10 Apr 2024 09:39:55 +0000 Subject: [PATCH 03/23] add filter Signed-off-by: LiuLingze --- eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c | 14 +++++++---- .../Stack_Analyser/bpf/llc_stat.bpf.c | 14 ++++++++--- .../Stack_Analyser/bpf/memleak.bpf.c | 22 ++++++++++-------- .../Stack_Analyser/bpf/off_cpu.bpf.c | 23 +++++++++++++++---- .../Stack_Analyser/bpf/on_cpu.bpf.c | 14 +++++++---- .../Stack_Analyser/bpf/probe.bpf.c | 15 ++++++++---- .../Stack_Analyser/bpf/readahead.bpf.c | 15 ++++++++---- 7 files changed, 82 insertions(+), 35 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c index 65a9a60a7..4f490e794 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c @@ -27,7 +27,6 @@ COMMON_MAPS(io_tuple); COMMON_VALS; -const volatile int target_pid = 0; const char LICENSE[] SEC("license") = "GPL"; @@ -35,12 +34,19 @@ static int do_stack(struct trace_event_raw_sys_enter *ctx) { CHECK_ACTIVE; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk - RET_IF_KERN(curr); + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid - if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + return 0; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) + return 0; + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) return 0; - SAVE_TASK_INFO(pid, curr); + SAVE_TASK_INFO(pid, curr, knode); // record time delta psid apsid = GET_COUNT_KEY(pid, ctx); diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c index 89c444690..70121bc6f 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c @@ -32,11 +32,19 @@ static __always_inline int trace_event(__u64 sample_period, bool miss, struct bp { CHECK_ACTIVE; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); - RET_IF_KERN(curr); + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid - if (!pid || pid == self_pid) + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + return 0; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) return 0; - SAVE_TASK_INFO(pid, curr); + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) + return 0; + + SAVE_TASK_INFO(pid, curr, knode); psid apsid = GET_COUNT_KEY(pid, ctx); llc_stat *infop = bpf_map_lookup_elem(&psid_count_map, &apsid); if (!infop) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c index 239a7edba..70a80e2e4 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c @@ -41,21 +41,25 @@ const char LICENSE[] SEC("license") = "GPL"; static int gen_alloc_enter(size_t size) { CHECK_ACTIVE; - if (!size) + if (!size || (sample_rate > 1 && bpf_ktime_get_ns() % sample_rate != 0)) + return 0; + struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) return 0; - if (sample_rate > 1) { - if (bpf_ktime_get_ns() % sample_rate != 0) + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) return 0; } - struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); - RET_IF_KERN(curr); - // update group - // group share memory u32 tgid = BPF_CORE_READ(curr, tgid); - if (tgid == self_pid) + if (target_tgid > 0 && tgid != target_tgid) + return 0; + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) return 0; - SAVE_TASK_INFO(tgid, curr); + + SAVE_TASK_INFO(tgid, curr, knode); if (trace_all) bpf_printk("alloc entered, size = %lu\n", size); // record size diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c index 10445e9db..b06a44572 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c @@ -27,7 +27,6 @@ COMMON_MAPS(u32); COMMON_VALS; -const volatile int target_pid = 0; BPF_HASH(pid_offTs_map, u32, u64); // 记录进程运行的起始时间 const char LICENSE[] SEC("license") = "GPL"; @@ -36,9 +35,20 @@ SEC("kprobe/finish_task_switch") // 动态挂载点finish_task_switch.isra.0 int BPF_KPROBE(do_stack, struct task_struct *curr) { CHECK_ACTIVE; - u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获取换出进程tsk的pid - RET_IF_KERN(curr); - if ((target_pid >= 0 && pid == target_pid) || (target_pid < 0 && pid && pid != self_pid)) + bool record = true; + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + record = false; + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + record = false; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) + record = false; + { + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) + record = false; + } + if (record) { // record curr block time u64 ts = bpf_ktime_get_ns(); // ts=当前的时间戳(ns) @@ -57,7 +67,10 @@ int BPF_KPROBE(do_stack, struct task_struct *curr) return 0; // record data - SAVE_TASK_INFO(pid, next); + { + SET_KNODE(next, knode); + SAVE_TASK_INFO(pid, next, knode); + } psid apsid = GET_COUNT_KEY(pid, ctx); // record time delta diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/on_cpu.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/on_cpu.bpf.c index 7830850ad..642965b45 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/on_cpu.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/on_cpu.bpf.c @@ -34,11 +34,17 @@ int do_stack(void *ctx) { CHECK_ACTIVE; struct task_struct *curr = (void *)bpf_get_current_task(); // curr指向当前进程的tsk - RET_IF_KERN(curr); // 忽略内核线程 - u32 pid = BPF_CORE_READ(curr, pid); // pid保存当前进程的pid,是cgroup pid 对应的level 0 pid - if (!pid || pid == self_pid) + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) return 0; - SAVE_TASK_INFO(pid, curr); + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) + return 0; + + SAVE_TASK_INFO(pid, curr, knode); psid apsid = GET_COUNT_KEY(pid, ctx); // add cosunt diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c index a5e29f6d0..c7c08e7cf 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c @@ -26,7 +26,6 @@ COMMON_MAPS(u32); COMMON_VALS; -const volatile int target_pid = 0; const char LICENSE[] SEC("license") = "GPL"; @@ -34,13 +33,19 @@ static int handle_func(void *ctx) { CHECK_ACTIVE; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk - RET_IF_KERN(curr); - u32 pid = get_task_ns_pid(curr); // 利用帮助函数获得当前进程的pid - if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + return 0; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) + return 0; + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) return 0; - SAVE_TASK_INFO(pid, curr); + SAVE_TASK_INFO(pid, curr, knode); psid a_psid = GET_COUNT_KEY(pid, ctx); u32 *cnt = bpf_map_lookup_elem(&psid_count_map, &a_psid); diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c index 59c390076..f5b34a869 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c @@ -31,7 +31,6 @@ COMMON_MAPS(ra_tuple); COMMON_VALS; -int target_pid = 0; BPF_HASH(in_ra_map, u32, psid); BPF_HASH(page_psid_map, struct page *, psid); @@ -40,13 +39,19 @@ int BPF_PROG(page_cache_ra_unbounded) { CHECK_ACTIVE; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); - RET_IF_KERN(curr); - u32 pid = get_task_ns_pid(curr); // 获取当前进程tgid,用户空间的pid即是tgid - if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + return 0; + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + return 0; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) + return 0; + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) return 0; - SAVE_TASK_INFO(pid, curr); + SAVE_TASK_INFO(pid, curr, knode); psid apsid = GET_COUNT_KEY(pid, ctx); ra_tuple *d = bpf_map_lookup_elem(&psid_count_map, &apsid); // d指向psid_count表中的apsid对应的类型为tuple的值 From c8eed17e1caf934b2a0868f3d8c12159a03cbdc3 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Wed, 10 Apr 2024 09:41:23 +0000 Subject: [PATCH 04/23] add filter Signed-off-by: LiuLingze --- .../include/bpf_wapper/eBPFStackCollector.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h index 08bf2cb04..ee91cb274 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h @@ -58,8 +58,11 @@ class StackCollector public: Scale *scales; - int pid = -1; // 用于设置ebpf程序跟踪的pid - int err = 0; // 用于保存错误代码 + short top = 10; + uint64_t cgroup = 0; + uint32_t tgid = 0; + uint32_t pid = 0; // 用于设置ebpf程序跟踪的pid + int err = 0; // 用于保存错误代码 bool ustack = false; // 是否跟踪用户栈 bool kstack = false; // 是否跟踪内核栈 @@ -114,6 +117,9 @@ class StackCollector skel->rodata->trace_user = ustack; \ skel->rodata->trace_kernel = kstack; \ skel->rodata->self_pid = self_pid; \ + skel->rodata->target_pid = pid; \ + skel->rodata->target_tgid = tgid; \ + skel->rodata->target_cgroupid = cgroup; \ err = skel->load(skel); \ CHECK_ERR(err, "Fail to load BPF skeleton"); \ obj = skel->obj; \ From 3b0c60e9738ec6591b905c0d883a6a212096ed8c Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Wed, 10 Apr 2024 09:43:58 +0000 Subject: [PATCH 05/23] split cgroup from thread info Signed-off-by: LiuLingze --- .../Stack_Analyser/include/sa_common.h | 1 - .../Stack_Analyser/include/sa_ebpf.h | 31 ++-- eBPF_Supermarket/Stack_Analyser/src/main.cpp | 148 +++++++++++++----- 3 files changed, 129 insertions(+), 51 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/include/sa_common.h b/eBPF_Supermarket/Stack_Analyser/include/sa_common.h index 0a181ca70..b29bc51b1 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/sa_common.h +++ b/eBPF_Supermarket/Stack_Analyser/include/sa_common.h @@ -35,7 +35,6 @@ typedef struct { typedef struct { __u32 pid; __u32 tgid; - char cid[CONTAINER_ID_LEN]; char comm[COMM_LEN]; } task_info; diff --git a/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h b/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h index 433068353..f26314031 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h +++ b/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h @@ -22,13 +22,6 @@ #include "sa_common.h" #define PF_KTHREAD 0x00200000 -#define RET_IF_KERN(task) \ - do \ - { \ - int flags = BPF_CORE_READ(task, flags); \ - if (flags & PF_KTHREAD) \ - return 0; \ - } while (false) /// @brief 创建一个指定名字的ebpf调用栈表 /// @param 新栈表的名字 @@ -65,25 +58,39 @@ #define COMMON_MAPS(count_type) \ BPF_HASH(psid_count_map, psid, count_type); \ BPF_STACK_TRACE(sid_trace_map); \ + BPF_HASH(tgid_cgroup_map, __u32, \ + char[CONTAINER_ID_LEN]); \ BPF_HASH(pid_info_map, u32, task_info); #define COMMON_VALS \ const volatile bool trace_user = false; \ const volatile bool trace_kernel = false; \ - const volatile int self_pid = 0; \ + const volatile __u64 target_cgroupid = 0; \ + const volatile __u32 target_tgid = 0; \ + const volatile __u32 target_pid = 0; \ + const volatile __u32 self_pid = 0; \ bool __active = false; -#define CHECK_ACTIVE if(!__active) return 0; +#define CHECK_ACTIVE \ + if (!__active) \ + return 0; -#define SAVE_TASK_INFO(_pid, _task) \ +#define SET_KNODE(_task, _knode) \ + struct kernfs_node *_knode = BPF_CORE_READ(_task, cgroups, dfl_cgrp, kn); + +#define SAVE_TASK_INFO(_pid, _task, _knode) \ if (!bpf_map_lookup_elem(&pid_info_map, &_pid)) \ { \ - task_info info; \ + task_info info = {0}; \ info.pid = get_task_ns_pid(_task); \ bpf_get_current_comm(info.comm, COMM_LEN); \ info.tgid = get_task_ns_tgid(_task); \ - fill_container_id(_task, info.cid); \ bpf_map_update_elem(&pid_info_map, &_pid, &info, BPF_NOEXIST); \ + \ + char cgroup_name[CONTAINER_ID_LEN] = {0}; \ + fill_container_id(_knode, cgroup_name); \ + bpf_map_update_elem(&tgid_cgroup_map, &(info.tgid), \ + &cgroup_name, BPF_NOEXIST); \ } #define GET_COUNT_KEY(_pid, _ctx) \ diff --git a/eBPF_Supermarket/Stack_Analyser/src/main.cpp b/eBPF_Supermarket/Stack_Analyser/src/main.cpp index 06f8e5d86..72a466bd4 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/main.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/main.cpp @@ -38,18 +38,82 @@ bool timeout = false; uint64_t IntTmp; std::string StrTmp; clipp::man_page *man_page; +std::vector StackCollectorList; namespace MainConfig { uint64_t run_time = -1; // 运行时间 unsigned delay = 5; // 设置输出间隔 std::string command = ""; - int32_t target_pid = -1; + uint32_t target_pid = 0; + uint32_t target_tgid = 0; + uint64_t target_cgroup = 0; std::string trigger = ""; // 触发器 std::string trig_event = ""; // 触发事件 + short top = 10; + bool trace_user = false; + bool trace_kernel = false; } -std::vector StackCollectorList; +namespace helper +{ +#include +#include + struct cgid_file_handle + { + // struct file_handle handle; + unsigned int handle_bytes; + int handle_type; + uint64_t cgid; + }; + uint64_t get_cgroupid(const char *pathname) + { + struct statfs fs; + int err; + struct cgid_file_handle *h; + int mount_id; + uint64_t ret; + + err = statfs(pathname, &fs); + if (err != 0) + { + fprintf(stderr, "statfs on %s failed: %s\n", pathname, strerror(errno)); + exit(1); + } + + if ((fs.f_type != (typeof(fs.f_type))CGROUP2_SUPER_MAGIC)) + { + fprintf(stderr, "File %s is not on a cgroup2 mount.\n", pathname); + exit(1); + } + + h = (cgid_file_handle *)malloc(sizeof(struct cgid_file_handle)); + if (!h) + { + fprintf(stderr, "Cannot allocate memory.\n"); + exit(1); + } + + h->handle_bytes = 8; + err = name_to_handle_at(AT_FDCWD, pathname, (struct file_handle *)h, &mount_id, 0); + if (err != 0) + { + fprintf(stderr, "name_to_handle_at failed: %s\n", strerror(errno)); + exit(1); + } + + if (h->handle_bytes != 8) + { + fprintf(stderr, "Unexpected handle size: %d. \n", h->handle_bytes); + exit(1); + } + + ret = h->cgid; + free(h); + + return ret; + } +} void end_handle(void) { @@ -75,15 +139,6 @@ int main(int argc, char *argv[]) man_page = new clipp::man_page(); clipp::group cli; { - auto TraceOption = (clipp::option("-u") - .call([] - { StackCollectorList.back()->ustack = true; }) % - "Sample user stacks", - clipp::option("-k") - .call([] - { StackCollectorList.back()->kstack = true; }) % - "Sample kernel stacks\n"); - auto OnCpuOption = (clipp::option("on_cpu") .call([] { StackCollectorList.push_back(new OnCPUStackCollector()); }) % @@ -93,14 +148,12 @@ int main(int argc, char *argv[]) .call([] { static_cast(StackCollectorList.back()) ->setScale(IntTmp); })) % - "Set sampling frequency; default is 49", - TraceOption); + "Set sampling frequency; default is 49"); auto OffCpuOption = clipp::option("off_cpu") - .call([] - { StackCollectorList.push_back(new OffCPUStackCollector()); }) % - COLLECTOR_INFO("off-cpu") & - (TraceOption); + .call([] + { StackCollectorList.push_back(new OffCPUStackCollector()); }) % + COLLECTOR_INFO("off-cpu"); auto MemleakOption = (clipp::option("memleak") .call([] @@ -116,31 +169,27 @@ int main(int argc, char *argv[]) .call([] { static_cast(StackCollectorList.back()) ->wa_missing_free = true; }) % - "Free when missing in kernel to alleviate misjudgments", - TraceOption); + "Free when missing in kernel to alleviate misjudgments"); auto IOOption = clipp::option("io") - .call([] - { StackCollectorList.push_back(new IOStackCollector()); }) % - COLLECTOR_INFO("io") & - (TraceOption); + .call([] + { StackCollectorList.push_back(new IOStackCollector()); }) % + COLLECTOR_INFO("io"); auto ReadaheadOption = clipp::option("readahead") - .call([] - { StackCollectorList.push_back(new ReadaheadStackCollector()); }) % - COLLECTOR_INFO("readahead") & - (TraceOption); + .call([] + { StackCollectorList.push_back(new ReadaheadStackCollector()); }) % + COLLECTOR_INFO("readahead"); auto ProbeOption = clipp::option("probe") .call([] { StackCollectorList.push_back(new ProbeStackCollector()); }) % COLLECTOR_INFO("probe") & (clipp::value("probe", StrTmp) - .call([] - { static_cast(StackCollectorList.back()) - ->setScale(StrTmp); }) % - "Set the probe string" & - TraceOption); + .call([] + { static_cast(StackCollectorList.back()) + ->setScale(StrTmp); }) % + "Set the probe string"); auto LlcStatOption = clipp::option("llc_stat").call([] { StackCollectorList.push_back(new LlcStatStackCollector()); }) % @@ -150,17 +199,27 @@ int main(int argc, char *argv[]) .call([] { static_cast(StackCollectorList.back()) ->setScale(IntTmp); })) % - "Set sampling period; default is 100", - TraceOption); + "Set sampling period; default is 100"); auto MainOption = _GREEN "Some overall options" _RE % (( - ((clipp::option("-p") & - clipp::value("pid", MainConfig::target_pid)) % + ((clipp::option("-G") & + clipp::value("cgroup path", StrTmp) + .call([] + { MainConfig::target_cgroup = helper::get_cgroupid(StrTmp.c_str()); printf("Trace cgroup %ld\n", MainConfig::target_cgroup); })) % + "Set the cgroup of the process to be tracked; default is -1, which keeps track of all cgroups") | + ((clipp::option("-P") & + clipp::value("pid", MainConfig::target_tgid)) % "Set the pid of the process to be tracked; default is -1, which keeps track of all processes") | - ((clipp::option("-c") & + ((clipp::option("-T") & + clipp::value("tid", MainConfig::target_pid)) % + "Set the tid of the thread to be tracked; default is -1, which keeps track of all threads") | + ((clipp::option("-C") & clipp::value("command", MainConfig::command)) % "Set the command to be run and sampled; defaults is none")), + (clipp::option("-O") & + clipp::value("top", MainConfig::top)) % + "Set the top number; default is 10", (clipp::option("-d") & clipp::value("interval", MainConfig::delay)) % "Set the output delay time (seconds); default is 5", @@ -169,6 +228,14 @@ int main(int argc, char *argv[]) .call([] { stop_time = time(NULL) + MainConfig::run_time; })) % "Set the total sampling time; default is __INT_MAX__", + (clipp::option("-u") + .call([] + { MainConfig::trace_user = true; }) % + "Sample user stacks", + clipp::option("-k") + .call([] + { MainConfig::trace_kernel = true; }) % + "Sample kernel stacks"), (clipp::option("-T") & ((clipp::required("cpu").set(MainConfig::trigger) | clipp::required("memory").set(MainConfig::trigger) | @@ -228,7 +295,7 @@ int main(int argc, char *argv[]) MainConfig::target_pid = fork(); switch (MainConfig::target_pid) { - case -1: + case (uint32_t)-1: { CHECK_ERR(true, "Command create failed."); } @@ -254,6 +321,11 @@ int main(int argc, char *argv[]) fprintf(stderr, _RED "Attach collecotor%d %s.\n" _RE, (int)(Item - StackCollectorList.begin()) + 1, (*Item)->getName()); (*Item)->pid = MainConfig::target_pid; + (*Item)->tgid = MainConfig::target_tgid; + (*Item)->cgroup = MainConfig::target_cgroup; + (*Item)->top = MainConfig::top; + (*Item)->kstack = MainConfig::trace_kernel; + (*Item)->ustack = MainConfig::trace_user; if ((*Item)->load() || (*Item)->attach()) goto err; Item++; From 8713cf24e7ac51a92a9b787273e6467aa0de1deb Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Wed, 10 Apr 2024 09:45:54 +0000 Subject: [PATCH 06/23] opt stringing Signed-off-by: LiuLingze --- .../src/bpf_wapper/eBPFStackCollector.cpp | 56 ++++++++++++------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp index 6d2ce144a..a30835e77 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp @@ -93,6 +93,11 @@ StackCollector::operator std::string() auto D = sortedCountList(); if (!D) return oss.str(); + if ((*D).size() > top) + { + auto end = (*D).end(); + (*D).assign(end - top, end); + } oss << _GREEN "pid\tusid\tksid"; for (int i = 0; i < scale_num; i++) oss << '\t' << scales[i].Type << "/" << scales[i].Period << scales[i].Unit; @@ -112,11 +117,11 @@ StackCollector::operator std::string() auto trace_fd = bpf_object__find_map_fd_by_name(obj, "sid_trace_map"); if (id.usid > 0 && traces.find(id.usid) == traces.end()) { - std::vector sym_trace; bpf_map_lookup_elem(trace_fd, &id.usid, trace); for (p = trace + MAX_STACKS - 1; !*p; p--) ; - for (; p >= trace; p--) + std::vector sym_trace(p - trace + 1); + for (int i = 0; p >= trace; p--) { uint64_t &addr = *p; symbol sym; @@ -127,10 +132,8 @@ StackCollector::operator std::string() else if (g_symbol_parser.get_symbol_info(id.pid, sym, file) && g_symbol_parser.find_elf_symbol(sym, file, id.pid, id.pid)) { if (sym.name[0] == '_' && sym.name[1] == 'Z') - // 代表是C++符号,则调用demangle解析 - { + // 代表是C++符号,则调用demangle解析 sym.name = demangleCppSym(sym.name); - } std::stringstream ss(""); ss << "+0x" << std::hex << (sym.ip - sym.start); sym.name += ss.str(); @@ -144,36 +147,35 @@ StackCollector::operator std::string() g_symbol_parser.putin_symbol_cache(id.pid, addr, sym.name); } clearSpace(sym.name); - sym_trace.push_back(sym.name); + sym_trace[i++] = sym.name; } traces[id.usid] = sym_trace; } if (id.ksid > 0 && traces.find(id.ksid) == traces.end()) { - std::vector sym_trace; bpf_map_lookup_elem(trace_fd, &id.ksid, trace); for (p = trace + MAX_STACKS - 1; !*p; p--) ; - for (; p >= trace; p--) + std::vector sym_trace(p - trace + 1); + for (int i = 0; p >= trace; p--) { uint64_t &addr = *p; symbol sym; sym.reset(addr); + std::stringstream ss(""); if (g_symbol_parser.find_kernel_symbol(sym)) - { - std::stringstream ss(""); + { ss << "+0x" << std::hex << (sym.ip - sym.start); sym.name += ss.str(); - } + } else { - std::stringstream ss(""); ss << "0x" << std::hex << addr; sym.name = ss.str(); g_symbol_parser.putin_symbol_cache(pid, addr, sym.name); } clearSpace(sym.name); - sym_trace.push_back(sym.name); + sym_trace[i++] = sym.name; } traces[id.ksid] = sym_trace; } @@ -195,16 +197,29 @@ StackCollector::operator std::string() oss << _BLUE "info:" _RE "\n"; { - auto info_fd = bpf_object__find_map_fd_by_name(obj, "pid_info_map"); - if (info_fd < 0) + std::map tgid_cgroup_map; + auto cgroups = new char[MAX_ENTRIES][CONTAINER_ID_LEN]; + uint32_t count = MAX_ENTRIES; { - return oss.str(); + auto tgids = new uint32_t[MAX_ENTRIES]; + auto cgroup_fd = bpf_object__find_map_fd_by_name(obj, "tgid_cgroup_map"); + if (cgroup_fd < 0) + return oss.str(); + uint32_t next_key; + err = bpf_map_lookup_batch(cgroup_fd, NULL, &next_key, tgids, cgroups, &count, NULL); + for (auto i = 0; i < count; i++) + tgid_cgroup_map[tgids[i]] = cgroups[i]; + delete[] tgids; } + auto keys = new uint32_t[MAX_ENTRIES]; auto vals = new task_info[MAX_ENTRIES]; - uint32_t count = MAX_ENTRIES; - uint32_t next_key; + count = MAX_ENTRIES; { + auto info_fd = bpf_object__find_map_fd_by_name(obj, "pid_info_map"); + if (info_fd < 0) + return oss.str(); + uint32_t next_key; int err; if (showDelta) err = bpf_map_lookup_and_delete_batch(info_fd, NULL, &next_key, @@ -215,15 +230,16 @@ StackCollector::operator std::string() if (err == EFAULT) return oss.str(); } - oss << _GREEN "pid\tNSpid\tcomm\ttgid\tcgroup" _RE "\n"; + oss << _GREEN "pid\tNSpid\tcomm\ttgid\tcgroup\t" _RE "\n"; for (uint32_t i = 0; i < count; i++) oss << keys[i] << '\t' << vals[i].pid << '\t' << vals[i].comm << '\t' << vals[i].tgid << '\t' - << vals[i].cid << '\n'; + << tgid_cgroup_map[vals[i].tgid] << '\n'; delete[] keys; delete[] vals; + delete[] cgroups; } oss << _BLUE "OK" _RE "\n"; From 5f347e617dcc5baf558b32db0bdf3360129cde07 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Wed, 10 Apr 2024 09:46:35 +0000 Subject: [PATCH 07/23] fix filter err Signed-off-by: LiuLingze --- eBPF_Supermarket/Stack_Analyser/include/task.h | 5 ++--- .../Stack_Analyser/src/bpf_wapper/llc_stat.cpp | 7 ++++--- .../Stack_Analyser/src/bpf_wapper/memleak.cpp | 9 ++++----- .../Stack_Analyser/src/bpf_wapper/on_cpu.cpp | 6 +++--- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/include/task.h b/eBPF_Supermarket/Stack_Analyser/include/task.h index 79f532543..db2e9b388 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/task.h +++ b/eBPF_Supermarket/Stack_Analyser/include/task.h @@ -71,13 +71,12 @@ statfunc u32 get_task_ns_ppid(struct task_struct *task) return get_task_pid_vnr(real_parent); } -static void fill_container_id(struct task_struct *task, char *container_id) +static void fill_container_id(struct kernfs_node *knode, char *container_id) { - struct kernfs_node *knode = BPF_CORE_READ(task, cgroups, subsys[0], cgroup, kn); if (BPF_CORE_READ(knode, parent) != NULL) { char *aus; - bpf_probe_read(&aus, sizeof(void *), &knode->name); + bpf_probe_read(&aus, sizeof(void *), &(knode->name)); bpf_probe_read_str(container_id, CONTAINER_ID_LEN, aus); } } diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp index a6bdc3986..a95bd9362 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp @@ -78,7 +78,7 @@ int LlcStatStackCollector::attach(void) } /* Set up performance monitoring on a CPU/Core */ attr.config = PERF_COUNT_HW_CACHE_MISSES; - int pefd = syscall(SYS_perf_event_open, &attr, pid, cpu, -1, 0); + int pefd = syscall(SYS_perf_event_open, &attr, pid ? pid : -1, cpu, -1, 0); CHECK_ERR(pefd < 0, "Fail to set up performance monitor on a CPU/Core"); mpefds[cpu] = pefd; /* Attach a BPF program on a CPU */ @@ -86,7 +86,7 @@ int LlcStatStackCollector::attach(void) CHECK_ERR(!mlinks[cpu], "Fail to attach bpf program"); attr.config = PERF_COUNT_HW_CACHE_REFERENCES; - pefd = syscall(SYS_perf_event_open, &attr, pid, cpu, -1, 0); + pefd = syscall(SYS_perf_event_open, &attr, pid ? pid : -1, cpu, -1, 0); CHECK_ERR(pefd < 0, "Fail to set up performance monitor on a CPU/Core"); rpefds[cpu] = pefd; /* Attach a BPF program on a CPU */ @@ -141,6 +141,7 @@ LlcStatStackCollector::LlcStatStackCollector() }; }; -void LlcStatStackCollector::setScale(uint64_t p) { +void LlcStatStackCollector::setScale(uint64_t p) +{ scales[0].Period = scales[1].Period = p; } \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp index e0edb6cda..21c72c588 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp @@ -119,9 +119,7 @@ int MemleakStackCollector::load(void) disable_kernel_node_tracepoints(skel); if (!percpu) disable_kernel_percpu_tracepoints(skel); - } else { - disable_kernel_tracepoints(skel); - }; + } else disable_kernel_tracepoints(skel); skel->rodata->sample_rate = sample_rate; skel->rodata->wa_missing_free = wa_missing_free; skel->rodata->page_size = sysconf(_SC_PAGE_SIZE);); @@ -152,6 +150,7 @@ void MemleakStackCollector::activate(bool tf) ACTIVE_SET(tf); } -const char *MemleakStackCollector::getName(void) { +const char *MemleakStackCollector::getName(void) +{ return "MemleakStackCollector"; -} \ No newline at end of file +} diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp index 8e4e1cf4a..5fa58a537 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp @@ -62,7 +62,6 @@ uint64_t *OnCPUStackCollector::count_values(void *data) int OnCPUStackCollector::load(void) { EBPF_LOAD_OPEN_INIT(); - return 0; }; @@ -99,7 +98,7 @@ int OnCPUStackCollector::attach(void) continue; } /* Set up performance monitoring on a CPU/Core */ - int pefd = perf_event_open(&attr, pid, cpu, -1, 0); + int pefd = perf_event_open(&attr, pid ? pid : -1, cpu, -1, 0); CHECK_ERR(pefd < 0, "Fail to set up performance monitor on a CPU/Core"); pefds[cpu] = pefd; /* Attach a BPF program on a CPU */ @@ -144,6 +143,7 @@ void OnCPUStackCollector::activate(bool tf) ACTIVE_SET(tf); } -const char *OnCPUStackCollector::getName(void) { +const char *OnCPUStackCollector::getName(void) +{ return "OnCPUStackCollector"; } \ No newline at end of file From 42700064423ac2ccd20d7071c56ab2e59b3b1f45 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Thu, 11 Apr 2024 12:42:09 +0000 Subject: [PATCH 08/23] opt stringing Signed-off-by: LiuLingze --- .../src/bpf_wapper/eBPFStackCollector.cpp | 59 ++++++------------- 1 file changed, 18 insertions(+), 41 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp index a30835e77..7fa24cc1c 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp @@ -87,6 +87,7 @@ StackCollector::operator std::string() std::ostringstream oss; oss << _RED "time:" << getLocalDateTime() << _RE "\n"; std::map> traces; + std::map infos; oss << _BLUE "counts:" _RE "\n"; { @@ -96,7 +97,10 @@ StackCollector::operator std::string() if ((*D).size() > top) { auto end = (*D).end(); - (*D).assign(end - top, end); + auto begin = end - top; + for (auto i = (*D).begin(); i < begin; i++) + delete i->v; + (*D).assign(begin, end); } oss << _GREEN "pid\tusid\tksid"; for (int i = 0; i < scale_num; i++) @@ -179,6 +183,10 @@ StackCollector::operator std::string() } traces[id.ksid] = sym_trace; } + auto info_fd = bpf_object__find_map_fd_by_name(obj, "pid_info_map"); + task_info info; + bpf_map_lookup_elem(info_fd, &id.pid, &info); + infos[id.pid] = info; } delete D; } @@ -197,49 +205,18 @@ StackCollector::operator std::string() oss << _BLUE "info:" _RE "\n"; { - std::map tgid_cgroup_map; - auto cgroups = new char[MAX_ENTRIES][CONTAINER_ID_LEN]; - uint32_t count = MAX_ENTRIES; + oss << _GREEN "pid\tNSpid\tcomm\ttgid\tcgroup\t" _RE "\n"; + for (auto i : infos) { - auto tgids = new uint32_t[MAX_ENTRIES]; auto cgroup_fd = bpf_object__find_map_fd_by_name(obj, "tgid_cgroup_map"); - if (cgroup_fd < 0) - return oss.str(); - uint32_t next_key; - err = bpf_map_lookup_batch(cgroup_fd, NULL, &next_key, tgids, cgroups, &count, NULL); - for (auto i = 0; i < count; i++) - tgid_cgroup_map[tgids[i]] = cgroups[i]; - delete[] tgids; - } - - auto keys = new uint32_t[MAX_ENTRIES]; - auto vals = new task_info[MAX_ENTRIES]; - count = MAX_ENTRIES; - { - auto info_fd = bpf_object__find_map_fd_by_name(obj, "pid_info_map"); - if (info_fd < 0) - return oss.str(); - uint32_t next_key; - int err; - if (showDelta) - err = bpf_map_lookup_and_delete_batch(info_fd, NULL, &next_key, - keys, vals, &count, NULL); - else - err = bpf_map_lookup_batch(info_fd, NULL, &next_key, - keys, vals, &count, NULL); - if (err == EFAULT) - return oss.str(); + char group[CONTAINER_ID_LEN]; + bpf_map_lookup_elem(cgroup_fd, &(i.second.tgid), &group); + oss << i.first << '\t' + << i.second.pid << '\t' + << i.second.comm << '\t' + << i.second.tgid << '\t' + << group << '\n'; } - oss << _GREEN "pid\tNSpid\tcomm\ttgid\tcgroup\t" _RE "\n"; - for (uint32_t i = 0; i < count; i++) - oss << keys[i] << '\t' - << vals[i].pid << '\t' - << vals[i].comm << '\t' - << vals[i].tgid << '\t' - << tgid_cgroup_map[vals[i].tgid] << '\n'; - delete[] keys; - delete[] vals; - delete[] cgroups; } oss << _BLUE "OK" _RE "\n"; From 7025a34f3602f43f820b070136a762e9d5431a7f Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Thu, 11 Apr 2024 14:06:53 +0000 Subject: [PATCH 09/23] add global freq option Signed-off-by: LiuLingze --- eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c | 1 + .../Stack_Analyser/bpf/llc_stat.bpf.c | 1 + .../Stack_Analyser/bpf/memleak.bpf.c | 4 +--- .../Stack_Analyser/bpf/off_cpu.bpf.c | 1 + .../Stack_Analyser/bpf/probe.bpf.c | 1 + .../Stack_Analyser/bpf/readahead.bpf.c | 1 + .../include/bpf_wapper/eBPFStackCollector.h | 4 +++- .../include/bpf_wapper/on_cpu.h | 1 - .../Stack_Analyser/include/sa_ebpf.h | 21 +++++++++++++++++-- .../Stack_Analyser/src/bpf_wapper/memleak.cpp | 1 - eBPF_Supermarket/Stack_Analyser/src/main.cpp | 15 +++++++------ 11 files changed, 35 insertions(+), 16 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c index 4f490e794..328c9c448 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/io.bpf.c @@ -33,6 +33,7 @@ const char LICENSE[] SEC("license") = "GPL"; static int do_stack(struct trace_event_raw_sys_enter *ctx) { CHECK_ACTIVE; + CHECK_FREQ; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c index 70121bc6f..d14f8922f 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/llc_stat.bpf.c @@ -31,6 +31,7 @@ COMMON_VALS; static __always_inline int trace_event(__u64 sample_period, bool miss, struct bpf_perf_event_data *ctx) { CHECK_ACTIVE; + CHECK_FREQ; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c index 70a80e2e4..edf090a41 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/memleak.bpf.c @@ -27,7 +27,6 @@ COMMON_MAPS(union combined_alloc_info); COMMON_VALS; -const volatile __u64 sample_rate = 1; const volatile bool wa_missing_free = false; const volatile size_t page_size = 4096; const volatile bool trace_all = false; @@ -41,8 +40,7 @@ const char LICENSE[] SEC("license") = "GPL"; static int gen_alloc_enter(size_t size) { CHECK_ACTIVE; - if (!size || (sample_rate > 1 && bpf_ktime_get_ns() % sample_rate != 0)) - return 0; + CHECK_FREQ; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c index b06a44572..1387d0712 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c @@ -35,6 +35,7 @@ SEC("kprobe/finish_task_switch") // 动态挂载点finish_task_switch.isra.0 int BPF_KPROBE(do_stack, struct task_struct *curr) { CHECK_ACTIVE; + CHECK_FREQ; bool record = true; if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) record = false; diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c index c7c08e7cf..f608f4fc9 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c @@ -32,6 +32,7 @@ const char LICENSE[] SEC("license") = "GPL"; static int handle_func(void *ctx) { CHECK_ACTIVE; + CHECK_FREQ; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c index f5b34a869..c9fc3c3c3 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/readahead.bpf.c @@ -38,6 +38,7 @@ SEC("fentry/page_cache_ra_unbounded") // fentry在内核函数page_cache_ra_unbo int BPF_PROG(page_cache_ra_unbounded) { CHECK_ACTIVE; + CHECK_FREQ; struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h index ee91cb274..01d989367 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/eBPFStackCollector.h @@ -58,7 +58,8 @@ class StackCollector public: Scale *scales; - short top = 10; + uint32_t top = 10; + uint32_t freq = 49; uint64_t cgroup = 0; uint32_t tgid = 0; uint32_t pid = 0; // 用于设置ebpf程序跟踪的pid @@ -120,6 +121,7 @@ class StackCollector skel->rodata->target_pid = pid; \ skel->rodata->target_tgid = tgid; \ skel->rodata->target_cgroupid = cgroup; \ + skel->rodata->freq = freq; \ err = skel->load(skel); \ CHECK_ERR(err, "Fail to load BPF skeleton"); \ obj = skel->obj; \ diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/on_cpu.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/on_cpu.h index cd79dfccc..34f66be85 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/on_cpu.h +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/on_cpu.h @@ -31,7 +31,6 @@ class OnCPUStackCollector : public StackCollector int *pefds = NULL; int num_cpus = 0; struct bpf_link **links = NULL; - unsigned long long freq = 49; protected: virtual uint64_t *count_values(void *); diff --git a/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h b/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h index f26314031..e3f409eed 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h +++ b/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h @@ -69,12 +69,29 @@ const volatile __u32 target_tgid = 0; \ const volatile __u32 target_pid = 0; \ const volatile __u32 self_pid = 0; \ - bool __active = false; + const volatile __u32 freq = 0; \ + bool __active = false; \ + __u32 __last_n = 0; \ + __u32 __next_n = 0; \ + bool __recorded = false; #define CHECK_ACTIVE \ if (!__active) \ return 0; +#define CHECK_FREQ \ + if (freq) \ + { \ + __next_n = ((bpf_ktime_get_ns() & ((1ul << 30) - 1)) * freq) >> 30; \ + if ((__last_n == __next_n) && __recorded) \ + return 0; \ + else \ + { \ + __recorded == true; \ + __last_n = __next_n; \ + } \ + } + #define SET_KNODE(_task, _knode) \ struct kernfs_node *_knode = BPF_CORE_READ(_task, cgroups, dfl_cgrp, kn); @@ -84,7 +101,7 @@ task_info info = {0}; \ info.pid = get_task_ns_pid(_task); \ bpf_get_current_comm(info.comm, COMM_LEN); \ - info.tgid = get_task_ns_tgid(_task); \ + info.tgid = BPF_CORE_READ(_task, tgid); \ bpf_map_update_elem(&pid_info_map, &_pid, &info, BPF_NOEXIST); \ \ char cgroup_name[CONTAINER_ID_LEN] = {0}; \ diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp index 21c72c588..b7603036f 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/memleak.cpp @@ -120,7 +120,6 @@ int MemleakStackCollector::load(void) if (!percpu) disable_kernel_percpu_tracepoints(skel); } else disable_kernel_tracepoints(skel); - skel->rodata->sample_rate = sample_rate; skel->rodata->wa_missing_free = wa_missing_free; skel->rodata->page_size = sysconf(_SC_PAGE_SIZE);); return 0; diff --git a/eBPF_Supermarket/Stack_Analyser/src/main.cpp b/eBPF_Supermarket/Stack_Analyser/src/main.cpp index 72a466bd4..343e3ce75 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/main.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/main.cpp @@ -50,7 +50,8 @@ namespace MainConfig uint64_t target_cgroup = 0; std::string trigger = ""; // 触发器 std::string trig_event = ""; // 触发事件 - short top = 10; + uint32_t top = 10; + uint32_t freq = 49; bool trace_user = false; bool trace_kernel = false; } @@ -142,13 +143,7 @@ int main(int argc, char *argv[]) auto OnCpuOption = (clipp::option("on_cpu") .call([] { StackCollectorList.push_back(new OnCPUStackCollector()); }) % - COLLECTOR_INFO("on-cpu")) & - ((clipp::option("-f") & - clipp::value("freq", IntTmp) - .call([] - { static_cast(StackCollectorList.back()) - ->setScale(IntTmp); })) % - "Set sampling frequency; default is 49"); + COLLECTOR_INFO("on-cpu")); auto OffCpuOption = clipp::option("off_cpu") .call([] @@ -220,6 +215,9 @@ int main(int argc, char *argv[]) (clipp::option("-O") & clipp::value("top", MainConfig::top)) % "Set the top number; default is 10", + (clipp::option("-f") & + clipp::value("freq", MainConfig::freq)) % + "Set sampling frequency, 0 for close; default is 49", (clipp::option("-d") & clipp::value("interval", MainConfig::delay)) % "Set the output delay time (seconds); default is 5", @@ -324,6 +322,7 @@ int main(int argc, char *argv[]) (*Item)->tgid = MainConfig::target_tgid; (*Item)->cgroup = MainConfig::target_cgroup; (*Item)->top = MainConfig::top; + (*Item)->freq = MainConfig::freq; (*Item)->kstack = MainConfig::trace_kernel; (*Item)->ustack = MainConfig::trace_user; if ((*Item)->load() || (*Item)->attach()) From 917c2fcd98a1a956e3d5ecac2d31492723464ad0 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Thu, 18 Apr 2024 05:20:07 +0000 Subject: [PATCH 10/23] add service name Signed-off-by: LiuLingze --- eBPF_Supermarket/Stack_Analyser/exporter/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/eBPF_Supermarket/Stack_Analyser/exporter/main.go b/eBPF_Supermarket/Stack_Analyser/exporter/main.go index 66a074f54..f81dbb098 100644 --- a/eBPF_Supermarket/Stack_Analyser/exporter/main.go +++ b/eBPF_Supermarket/Stack_Analyser/exporter/main.go @@ -292,6 +292,7 @@ func CollectProfiles(cb CollectProfilesCallback) error { for i, s := range scales { target := sd.NewTarget("", k.pid, sd.DiscoveryTarget{ "__container_id__": info[k.pid].cid, + "service_name": "Stack_Analyzer", labels.MetricName: s.Type, }) cb(target, group_trace, v[i], s, true) From 2ed56a11adb2522db769e0273f8f6a8a28544817 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Thu, 18 Apr 2024 05:20:58 +0000 Subject: [PATCH 11/23] remove unused symbol Signed-off-by: LiuLingze --- eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/memleak.h | 1 - 1 file changed, 1 deletion(-) diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/memleak.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/memleak.h index 08afd79fb..544b3b7c6 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/memleak.h +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/memleak.h @@ -60,7 +60,6 @@ class MemleakStackCollector : public StackCollector public: char *object = (char *)"libc.so.6"; bool percpu = false; - __u64 sample_rate = 1; bool wa_missing_free = false; protected: From 95b2dba40d9cfcf82920dbd53f4f45f1e322953b Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Thu, 18 Apr 2024 20:48:28 +0000 Subject: [PATCH 12/23] fix filter logic Signed-off-by: LiuLingze --- .../Stack_Analyser/bpf/off_cpu.bpf.c | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c index 1387d0712..b79e894fb 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/off_cpu.bpf.c @@ -35,30 +35,42 @@ SEC("kprobe/finish_task_switch") // 动态挂载点finish_task_switch.isra.0 int BPF_KPROBE(do_stack, struct task_struct *curr) { CHECK_ACTIVE; - CHECK_FREQ; - bool record = true; - if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) - record = false; - u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid - if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) - record = false; - if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) - record = false; - { - SET_KNODE(curr, knode); - if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) - record = false; - } - if (record) + do { + if (freq) + { + __next_n = ((bpf_ktime_get_ns() & ((1ul << 30) - 1)) * freq) >> 30; + if (__last_n == __next_n) + { + if (__recorded) + break; + } + else + __last_n = __next_n; + } + + if (BPF_CORE_READ(curr, flags) & PF_KTHREAD) + break; + u32 pid = BPF_CORE_READ(curr, pid); // 利用帮助函数获得当前进程的pid + if ((!pid) || (pid == self_pid) || (target_pid > 0 && pid != target_pid)) + break; + if (target_tgid > 0 && BPF_CORE_READ(curr, tgid) != target_tgid) + break; + { + SET_KNODE(curr, knode); + if (target_cgroupid > 0 && BPF_CORE_READ(knode, id) != target_cgroupid) + break; + } + // record curr block time u64 ts = bpf_ktime_get_ns(); // ts=当前的时间戳(ns) bpf_map_update_elem(&pid_offTs_map, &pid, &ts, BPF_NOEXIST); // 如果start表中不存在pid对应的时间,则就创建pid-->ts - } + __recorded = true; + } while (false); // calculate time delta, next ready to run struct task_struct *next = (struct task_struct *)bpf_get_current_task(); // next指向换入进程结构体 - pid = BPF_CORE_READ(next, pid); // 利用帮助函数获取next指向的tsk的pid + u32 pid = BPF_CORE_READ(next, pid); // 利用帮助函数获取next指向的tsk的pid u64 *tsp = bpf_map_lookup_elem(&pid_offTs_map, &pid); // tsp指向start表中的pid的值 if (!tsp) return 0; From 1e76576c49c018af4ee5f985d6a072f115da2db9 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Thu, 18 Apr 2024 21:05:12 +0000 Subject: [PATCH 13/23] fix some err Signed-off-by: LiuLingze --- .../Stack_Analyser/include/sa_ebpf.h | 16 ++++------ eBPF_Supermarket/Stack_Analyser/new_bpf.sh | 2 +- .../src/bpf_wapper/eBPFStackCollector.cpp | 2 +- .../src/bpf_wapper/llc_stat.cpp | 4 +-- .../Stack_Analyser/src/bpf_wapper/on_cpu.cpp | 2 +- .../Stack_Analyser/src/dt_symbol.cpp | 7 +++- eBPF_Supermarket/Stack_Analyser/src/main.cpp | 32 ++++++++----------- 7 files changed, 31 insertions(+), 34 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h b/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h index e3f409eed..925844796 100644 --- a/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h +++ b/eBPF_Supermarket/Stack_Analyser/include/sa_ebpf.h @@ -86,10 +86,7 @@ if ((__last_n == __next_n) && __recorded) \ return 0; \ else \ - { \ - __recorded == true; \ __last_n = __next_n; \ - } \ } #define SET_KNODE(_task, _knode) \ @@ -110,11 +107,12 @@ &cgroup_name, BPF_NOEXIST); \ } -#define GET_COUNT_KEY(_pid, _ctx) \ - ((psid){ \ - .pid = _pid, \ - .usid = trace_user ? bpf_get_stackid(_ctx, &sid_trace_map, BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK) : -1, \ - .ksid = trace_kernel ? bpf_get_stackid(_ctx, &sid_trace_map, BPF_F_FAST_STACK_CMP) : -1, \ - }) +#define GET_COUNT_KEY(_pid, _ctx) \ + (__recorded == true, \ + (psid){ \ + .pid = _pid, \ + .usid = trace_user ? bpf_get_stackid(_ctx, &sid_trace_map, BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK) : -1, \ + .ksid = trace_kernel ? bpf_get_stackid(_ctx, &sid_trace_map, BPF_F_FAST_STACK_CMP) : -1, \ + }) #endif \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/new_bpf.sh b/eBPF_Supermarket/Stack_Analyser/new_bpf.sh index 8ed45cdb9..8aa1507a2 100755 --- a/eBPF_Supermarket/Stack_Analyser/new_bpf.sh +++ b/eBPF_Supermarket/Stack_Analyser/new_bpf.sh @@ -27,6 +27,6 @@ sed -i 's/template/'$origin_name'/g' bpf/$origin_name.bpf.c sed -i '/#include "bpf_wapper\/on_cpu.h"/a#include "bpf_wapper\/'$origin_name'.h"' src/main.cpp -sed -i '/auto MainOption = _GREEN "Some overall options" _RE %/iauto '$name'Option = clipp::option("'$origin_name'").call([]{ StackCollectorList.push_back(new '$class_name'()); }) % COLLECTOR_INFO("'$origin_name'") & (TraceOption);' src/main.cpp +sed -i '/auto MainOption = _GREEN "Some overall options" _RE %/iauto '$name'Option = clipp::option("'$origin_name'").call([]{ StackCollectorList.push_back(new '$class_name'()); }) % COLLECTOR_INFO("'$origin_name'");' src/main.cpp sed -i '/MainOption,/i'$name'Option,' src/main.cpp \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp index 7fa24cc1c..d4f95de50 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/eBPFStackCollector.cpp @@ -146,7 +146,7 @@ StackCollector::operator std::string() else { std::stringstream ss(""); - ss << "0x" << std::hex << addr; + ss << "0x" << std::hex << sym.ip; sym.name = ss.str(); g_symbol_parser.putin_symbol_cache(id.pid, addr, sym.name); } diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp index a95bd9362..ecedcc450 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/llc_stat.cpp @@ -78,7 +78,7 @@ int LlcStatStackCollector::attach(void) } /* Set up performance monitoring on a CPU/Core */ attr.config = PERF_COUNT_HW_CACHE_MISSES; - int pefd = syscall(SYS_perf_event_open, &attr, pid ? pid : -1, cpu, -1, 0); + int pefd = syscall(SYS_perf_event_open, &attr, tgid ? tgid : -1, cpu, -1, 0); CHECK_ERR(pefd < 0, "Fail to set up performance monitor on a CPU/Core"); mpefds[cpu] = pefd; /* Attach a BPF program on a CPU */ @@ -86,7 +86,7 @@ int LlcStatStackCollector::attach(void) CHECK_ERR(!mlinks[cpu], "Fail to attach bpf program"); attr.config = PERF_COUNT_HW_CACHE_REFERENCES; - pefd = syscall(SYS_perf_event_open, &attr, pid ? pid : -1, cpu, -1, 0); + pefd = syscall(SYS_perf_event_open, &attr, tgid ? tgid : -1, cpu, -1, 0); CHECK_ERR(pefd < 0, "Fail to set up performance monitor on a CPU/Core"); rpefds[cpu] = pefd; /* Attach a BPF program on a CPU */ diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp index 5fa58a537..287bec493 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/on_cpu.cpp @@ -98,7 +98,7 @@ int OnCPUStackCollector::attach(void) continue; } /* Set up performance monitoring on a CPU/Core */ - int pefd = perf_event_open(&attr, pid ? pid : -1, cpu, -1, 0); + int pefd = perf_event_open(&attr, tgid ? tgid : -1, cpu, -1, 0); CHECK_ERR(pefd < 0, "Fail to set up performance monitor on a CPU/Core"); pefds[cpu] = pefd; /* Attach a BPF program on a CPU */ diff --git a/eBPF_Supermarket/Stack_Analyser/src/dt_symbol.cpp b/eBPF_Supermarket/Stack_Analyser/src/dt_symbol.cpp index 92feb0d7b..d3c848fbc 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/dt_symbol.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/dt_symbol.cpp @@ -49,7 +49,7 @@ bool symbol_parser::load_pid_maps(int pid) } proc_vma proc; - char fn[256]; + char fn[23]; sprintf(fn, "/proc/%d/maps", pid); FILE *fp = fopen(fn, "r"); if (!fp) { @@ -335,6 +335,11 @@ bool symbol_parser::putin_symbol_cache(int tgid, unsigned long addr, std::string return false; } +/// @brief 找到指定进程中的虚拟地址对应的在可执行文件中相对于文件开始的偏移,赋给sym.ip +/// @param pid 指定进程的pid +/// @param sym 提供进程虚拟地址 +/// @param file 文件信息 +/// @return 成功找到返回true bool symbol_parser::get_symbol_info(int pid, symbol &sym, elf_file &file) { std::map::iterator proc_vma_info; diff --git a/eBPF_Supermarket/Stack_Analyser/src/main.cpp b/eBPF_Supermarket/Stack_Analyser/src/main.cpp index 343e3ce75..178722504 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/main.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/main.cpp @@ -154,17 +154,11 @@ int main(int argc, char *argv[]) .call([] { StackCollectorList.push_back(new MemleakStackCollector()); }) % COLLECTOR_INFO("memleak")) & - ((clipp::option("-i") & - clipp::value("interval", IntTmp) - .call([] - { static_cast(StackCollectorList.back()) - ->sample_rate = IntTmp; })) % - "Set the sampling interval; default is 1", - clipp::option("-w") - .call([] - { static_cast(StackCollectorList.back()) - ->wa_missing_free = true; }) % - "Free when missing in kernel to alleviate misjudgments"); + (clipp::option("-W") + .call([] + { static_cast(StackCollectorList.back()) + ->wa_missing_free = true; }) % + "Free when missing in kernel to alleviate misjudgments"); auto IOOption = clipp::option("io") .call([] @@ -189,7 +183,7 @@ int main(int argc, char *argv[]) auto LlcStatOption = clipp::option("llc_stat").call([] { StackCollectorList.push_back(new LlcStatStackCollector()); }) % COLLECTOR_INFO("llc_stat") & - ((clipp::option("-i") & + ((clipp::option("-P") & clipp::value("period", IntTmp) .call([] { static_cast(StackCollectorList.back()) @@ -198,30 +192,30 @@ int main(int argc, char *argv[]) auto MainOption = _GREEN "Some overall options" _RE % (( - ((clipp::option("-G") & + ((clipp::option("-g") & clipp::value("cgroup path", StrTmp) .call([] { MainConfig::target_cgroup = helper::get_cgroupid(StrTmp.c_str()); printf("Trace cgroup %ld\n", MainConfig::target_cgroup); })) % "Set the cgroup of the process to be tracked; default is -1, which keeps track of all cgroups") | - ((clipp::option("-P") & + ((clipp::option("-p") & clipp::value("pid", MainConfig::target_tgid)) % "Set the pid of the process to be tracked; default is -1, which keeps track of all processes") | - ((clipp::option("-T") & + ((clipp::option("-t") & clipp::value("tid", MainConfig::target_pid)) % "Set the tid of the thread to be tracked; default is -1, which keeps track of all threads") | - ((clipp::option("-C") & + ((clipp::option("-c") & clipp::value("command", MainConfig::command)) % "Set the command to be run and sampled; defaults is none")), - (clipp::option("-O") & + (clipp::option("-o") & clipp::value("top", MainConfig::top)) % "Set the top number; default is 10", (clipp::option("-f") & clipp::value("freq", MainConfig::freq)) % "Set sampling frequency, 0 for close; default is 49", - (clipp::option("-d") & + (clipp::option("-i") & clipp::value("interval", MainConfig::delay)) % "Set the output delay time (seconds); default is 5", - (clipp::option("-t") & + (clipp::option("-d") & clipp::value("duration", MainConfig::run_time) .call([] { stop_time = time(NULL) + MainConfig::run_time; })) % From 19afafdebba3986ab71e3aacca7f217954d5c5b4 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Thu, 18 Apr 2024 21:09:37 +0000 Subject: [PATCH 14/23] update docs Signed-off-by: LiuLingze --- .../Stack_Analyser/frame-use-guide.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename "eBPF_Supermarket/Stack_Analyser/\346\241\206\346\236\266\344\275\277\347\224\250\346\226\271\346\263\225.md" => eBPF_Supermarket/Stack_Analyser/frame-use-guide.md (87%) diff --git "a/eBPF_Supermarket/Stack_Analyser/\346\241\206\346\236\266\344\275\277\347\224\250\346\226\271\346\263\225.md" b/eBPF_Supermarket/Stack_Analyser/frame-use-guide.md similarity index 87% rename from "eBPF_Supermarket/Stack_Analyser/\346\241\206\346\236\266\344\275\277\347\224\250\346\226\271\346\263\225.md" rename to eBPF_Supermarket/Stack_Analyser/frame-use-guide.md index 2f393cbd5..8d829a678 100644 --- "a/eBPF_Supermarket/Stack_Analyser/\346\241\206\346\236\266\344\275\277\347\224\250\346\226\271\346\263\225.md" +++ b/eBPF_Supermarket/Stack_Analyser/frame-use-guide.md @@ -32,18 +32,18 @@ new_ebpf.sh 1. 实现包装类初始化函数,若数据标度`scale`的值可以确定,请在此初始化 2. 若标度无法确定,则实现`setScale`,对标度及包装类参数进行设置 -3. 实现一系列虚函数:`count_value, load, attach, detach, unload` +3. 实现一系列虚函数:`count_values, load, attach, detach, unload` 4. 可实现一些辅助函数 ## src/bpf/.bpf.c -1. 通过修改`DeclareCommonMaps(__u32)`中的`__u32`设置计数变量类型 +1. 通过修改`COMMON_MAPS(__u32)`中的`__u32`设置计数变量类型 2. 可声明额外的map和全局变量在eBPF程序内部使用,但不会被框架输出。 3. 实现eBPF程序,请使用通用的`eBPF map`进行数据存储,使用通用的全局变量进行进程和数据过滤,否则无法正确输出数据 通用的map分别为: - 1. psid_count:键为psid类型,值为 1. 中设置的计数变量类型 - 2. stack_trace:键为uint32类型,标识唯一的栈嗲用路径,值为void*[]类型,存储栈上的调用地址 + 1. psid_count_map:键为psid类型,值为 1. 中设置的计数变量类型 + 2. sid_trace_map:键为uint32类型,标识唯一的栈嗲用路径,值为void*[]类型,存储栈上的调用地址 3. pid_tgid:键为uint32类型,表示pid,值为uint32类型,表示tgid 4. pid_comm:键为uint32类型,表示pid,值为comm类型,表示进程名 From cf076534e6b1f2ae0aa75391713c5399b5933639 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Mon, 22 Apr 2024 02:37:14 +0000 Subject: [PATCH 15/23] fix action Signed-off-by: LiuLingze --- .github/workflows/ebpf_stack_analyser.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ebpf_stack_analyser.yml b/.github/workflows/ebpf_stack_analyser.yml index 907288ffd..2e3fbc406 100644 --- a/.github/workflows/ebpf_stack_analyser.yml +++ b/.github/workflows/ebpf_stack_analyser.yml @@ -30,7 +30,7 @@ jobs: run: | cd eBPF_Supermarket/Stack_Analyser make - sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -t 5 + sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 magic-eyes-build-and-test: runs-on: ubuntu-22.04 @@ -48,4 +48,4 @@ jobs: cd MagicEyes/build cmake -DBUILD_STACK_ANALYZER=ON .. make - sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -t 5 \ No newline at end of file + sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 \ No newline at end of file From 99ffc433bddd40b984f2b5dd0d776cff12b5e9d0 Mon Sep 17 00:00:00 2001 From: gyxforeveryoung <1739037263@qq.com> Date: Mon, 22 Apr 2024 10:53:24 +0800 Subject: [PATCH 16/23] add flunclatency and user-defined probe --- .../Stack_Analyser/bpf/funclatency.bpf.c | 132 +++++++++++ .../include/bpf_wapper/funclatency.h | 59 +++++ .../src/bpf_wapper/funclatency.cpp | 220 ++++++++++++++++++ eBPF_Supermarket/Stack_Analyser/src/main.cpp | 12 +- 4 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 eBPF_Supermarket/Stack_Analyser/bpf/funclatency.bpf.c create mode 100644 eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/funclatency.h create mode 100644 eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/funclatency.cpp diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/funclatency.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/funclatency.bpf.c new file mode 100644 index 000000000..e69f199bc --- /dev/null +++ b/eBPF_Supermarket/Stack_Analyser/bpf/funclatency.bpf.c @@ -0,0 +1,132 @@ +// Copyright 2024 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: luiyanbing@foxmail.com +// +// 内核态bpf程序的模板代码 + +#include "vmlinux.h" +#include +#include +#include +#include + +#include "sa_ebpf.h" +#include "bpf_wapper/funclatency.h" +#include "task.h" + +COMMON_MAPS(time_tuple); +COMMON_VALS; +BPF_HASH(starts,psid,u64); +const volatile int target_pid = 0; + +static int entry(void *ctx) +{ + CHECK_ACTIVE; + struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk + RET_IF_KERN(curr); + + u32 pid = get_task_ns_pid(curr); // 利用帮助函数获得当前进程的pid + if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + return 0; + + SAVE_TASK_INFO(pid, curr); + + psid a_psid =GET_COUNT_KEY(pid,ctx); + u64 nsec; + + nsec = bpf_ktime_get_ns(); + bpf_map_update_elem(&starts, &a_psid, &nsec, BPF_ANY); +} + + + +SEC("kprobe/dummy_kprobe") +int BPF_KPROBE(dummy_kprobe) +{ + entry(ctx); + return 0; +} +SEC("tp/sched/dummy_tp") +int tp_entry(void *ctx) +{ + entry(ctx); + return 0; +} +SEC("usdt") +int usdt_entry(void *ctx) +{ + entry(ctx); + return 0; +} +static int exit(void *ctx) +{ + u64 *start; + u64 nsec = bpf_ktime_get_ns(); + u64 delta; + + + + CHECK_ACTIVE; + struct task_struct *curr = (struct task_struct *)bpf_get_current_task(); // 利用bpf_get_current_task()获得当前的进程tsk + RET_IF_KERN(curr); + + u32 pid = get_task_ns_pid(curr); // 利用帮助函数获得当前进程的pid + if ((target_pid >= 0 && pid != target_pid) || !pid || pid == self_pid) + return 0; + + SAVE_TASK_INFO(pid, curr); + + psid b_psid = GET_COUNT_KEY(pid, ctx); + + start = bpf_map_lookup_elem(&starts, &b_psid); + if (!start) + return 0; + + delta = nsec - *start; + + time_tuple *d = bpf_map_lookup_elem(&psid_count_map, &b_psid); + if (!d) + { + time_tuple tmp = {.lat = delta,.count=1}; + bpf_map_update_elem(&psid_count_map, &b_psid, &tmp, BPF_NOEXIST); + } + else + { + d->lat+=delta; + d->count++; + } +} + + + +SEC("kretprobe/dummy_kretprobe") +int BPF_KRETPROBE(dummy_kretprobe) +{ + exit(ctx); + return 0; +} +SEC("tp/sched/dummy_tp") +int tp_exit(void *ctx) +{ + exit(ctx); + return 0; +} +SEC("usdt") +int usdt_exit(void *ctx) +{ + exit(ctx); + return 0; +} +const char LICENSE[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/funclatency.h b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/funclatency.h new file mode 100644 index 000000000..1f826942c --- /dev/null +++ b/eBPF_Supermarket/Stack_Analyser/include/bpf_wapper/funclatency.h @@ -0,0 +1,59 @@ +// Copyright 2024 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: luiyanbing@foxmail.com +// +// ebpf程序的包装类的模板,声明接口和一些自定义方法,以及辅助结构 + +#ifndef _SA_FUNCLANTENCY_H__ +#define _SA_FUNCLANTENCY_H__ + +// ========== C code part ========== +#include +typedef struct +{ + __u64 lat; + __u64 count; +} time_tuple; +// ========== C code end ========== + +#ifdef __cplusplus +// ========== C++ code part ========== +#include "funclatency.skel.h" +#include "bpf_wapper/eBPFStackCollector.h" + +class FunclatencyStackCollector : public StackCollector +{ +private: + DECL_SKEL(funclatency); +public: + std::string probe; + +protected: + virtual uint64_t *count_values(void *); + +public: + void setScale(std::string probe); + FunclatencyStackCollector(); + virtual int load(void); + virtual int attach(void); + virtual void detach(void); + virtual void unload(void); + virtual void activate(bool tf); + virtual const char *getName(void); +}; +// ========== C++ code end ========== +#endif + +#endif \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/funclatency.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/funclatency.cpp new file mode 100644 index 000000000..ffa9f8273 --- /dev/null +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/funclatency.cpp @@ -0,0 +1,220 @@ +// Copyright 2024 The LMP Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// author: luiyanbing@foxmail.com +// +// ebpf程序包装类的模板,实现接口和一些自定义方法 + +#include "bpf_wapper/funclatency.h" +#include "trace_helpers.h" +#include "uprobe_helpers.h" + +// ========== implement virtual func ========== + +uint64_t *FunclatencyStackCollector::count_values(void *data) +{ + time_tuple *p = (time_tuple *)data; + return new uint64_t[scale_num]{ + p->lat, + p->count}; +}; + +void FunclatencyStackCollector::setScale(std::string probe) +{ + this->probe = probe; + scales->Type = probe + "Delay"; +}; +int FunclatencyStackCollector::load(void) +{ + EBPF_LOAD_OPEN_INIT(skel->rodata->target_pid = pid;); + return 0; +}; +void splitStr(std::string symbol, const char split, std::vector &res) +{ + if (symbol == "") + return; + std::string strs = symbol + split; + size_t pos = strs.find(split); + while (pos != strs.npos) + { + std::string temp = strs.substr(0, pos); + res.push_back(temp); + strs = strs.substr(pos + 1, strs.size()); + pos = strs.find(split); + } +} + +static int get_binpath(char *path, int pid) +{ + char mode[16], line[128], buf[64]; + size_t seg_start, seg_end, seg_off; + FILE *f; + int i = 0; + + sprintf(buf, "/proc/%d/maps", pid); + f = fopen(buf, "r"); + if (!f) + return -1; + + while (fscanf(f, "%zx-%zx %s %zx %*s %*d%[^\n]\n", + &seg_start, &seg_end, mode, &seg_off, line) == 5) + { + i = 0; + while (isblank(line[i])) + i++; + if (strstr(line + i, "libc.so.6")) + { + break; + } + } + + strcpy(path, line + i); + fclose(f); + return 0; +} +static int attach_kprobes(struct funclatency_bpf *skel, std::string func) +{ + skel->links.dummy_kprobe = + bpf_program__attach_kprobe(skel->progs.dummy_kprobe, false, func.c_str()); + CHECK_ERR(!skel->links.dummy_kprobe, "Fail to attach kprobe"); + skel->links.dummy_kretprobe = + bpf_program__attach_kprobe(skel->progs.dummy_kretprobe, true, func.c_str()); + CHECK_ERR(!skel->links.dummy_kretprobe, "Fail to attach ketprobe"); + return 0; +} +static int attach_uprobes(struct funclatency_bpf *skel, std::string probe, int pid) +{ + char *binary, *function; + char bin_path[128]; + std::string func = probe; + off_t func_off; + + binary = strdup(func.c_str()); + function = strchr(binary, ':'); // 查找:首次出现的位置 + *function = '\0'; + function++; + + if (resolve_binary_path(binary, pid, bin_path, sizeof(bin_path))) + free(binary); + + func_off = get_elf_func_offset(bin_path, function); + if (func_off < 0) + free(binary); + skel->links.dummy_kprobe = + bpf_program__attach_uprobe(skel->progs.dummy_kprobe, false, pid, + bin_path, func_off); + CHECK_ERR(!skel->links.dummy_kprobe, "Fail to attach uprobe"); + skel->links.dummy_kretprobe = + bpf_program__attach_uprobe(skel->progs.dummy_kretprobe, true, pid, + bin_path, func_off); + CHECK_ERR(!skel->links.dummy_kretprobe, "Fail to attach uprobe"); + return 0; +} + +static int attach_tp(struct funclatency_bpf *skel, std::string tp_class, std::string func) +{ + + skel->links.tp_entry = + bpf_program__attach_tracepoint(skel->progs.tp_entry, tp_class.c_str(), func.c_str()); + CHECK_ERR(!skel->links.tp_entry, "Fail to attach tracepoint"); + skel->links.tp_exit = + bpf_program__attach_tracepoint(skel->progs.tp_exit, tp_class.c_str(), func.c_str()); + CHECK_ERR(!skel->links.tp_exit, "Fail to attach tracepoint"); + return 0; +} +static int attach_usdt(struct funclatency_bpf *skel, std::string func, int pid) +{ + char bin_path[128]; + int err = get_binpath(bin_path, pid); + CHECK_ERR(err, "Fail to get lib path"); + skel->links.usdt_entry = + bpf_program__attach_usdt(skel->progs.usdt_entry, pid, bin_path, "libc", func.c_str(), NULL); + CHECK_ERR(!skel->links.usdt_entry, "Fail to attach usdt"); + skel->links.usdt_exit = + bpf_program__attach_usdt(skel->progs.usdt_exit, pid, bin_path, "libc", func.c_str(), NULL); + CHECK_ERR(!skel->links.usdt_exit, "Fail to attach usdt"); +} +int FunclatencyStackCollector::attach(void) +{ + // dynamic mounting + std::vector strList; + splitStr(probe, ':', strList); + std::string func = probe; + int err; + + if (strList.size() == 3 && strList[0] == "p" && strList[1] == "") + func = strList[2]; + if (strList.size() == 1 || (strList.size() == 3 && strList[0] == "p" && strList[1] == "")) + { + err = attach_kprobes(skel, func); + } + else if (strList.size() == 3 && strList[0] == "t") + { + err = attach_tp(skel, strList[1], strList[2]); + } + else if (strList.size() == 2 || (strList.size() == 3 && strList[0] == "p" && strList[1] != "")) + { + if (strList.size() == 3) + func = strList[1] + ":" + strList[2]; + err = attach_uprobes(skel, func, pid); + } + else if (strList.size() == 3 && strList[0] == "u") + { + char path[128]; + int err = get_binpath(path,pid); + CHECK_ERR(err, "Fail to get lib path"); + skel->links.usdt_entry = + bpf_program__attach_usdt(skel->progs.usdt_entry ,pid,path,"libc",strList[2].c_str(),NULL); + CHECK_ERR(!skel->links.usdt_entry , "Fail to attach usdt"); + } + else + { + printf("Type must be 'p', 't', or 'u' or too any args"); + } + + CHECK_ERR(err, "Fail to attach"); + + return 0; +}; + +void FunclatencyStackCollector::detach(void) +{ + DETACH_PROTO; +}; + +void FunclatencyStackCollector::unload(void) +{ + UNLOAD_PROTO; +}; + +void FunclatencyStackCollector::activate(bool tf) +{ + ACTIVE_SET(tf); +} + +const char *FunclatencyStackCollector::getName(void) +{ + return "FunclatencyStackCollector"; +} + +// ========== other implementations ========== + +FunclatencyStackCollector::FunclatencyStackCollector() +{ + scale_num = 2; + scales = new Scale[scale_num]{ + {"latencyTime", 1, "us"}, + {"latencyCount", 1, "counts"}, + }; +}; \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/main.cpp b/eBPF_Supermarket/Stack_Analyser/src/main.cpp index 842363627..6f3105212 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/main.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/main.cpp @@ -23,6 +23,7 @@ #include #include "bpf_wapper/on_cpu.h" +#include "bpf_wapper/funclatency.h" #include "bpf_wapper/llc_stat.h" #include "bpf_wapper/off_cpu.h" #include "bpf_wapper/memleak.h" @@ -151,7 +152,15 @@ int main(int argc, char *argv[]) ->setScale(IntTmp); })) % "Set sampling period; default is 100", TraceOption); - + auto FunclatencyOption = clipp::option("funclatency").call([] + { StackCollectorList.push_back(new FunclatencyStackCollector()); }) % + COLLECTOR_INFO("funclatency") & + (clipp::value("probe", StrTmp) + .call([] + { static_cast(StackCollectorList.back()) + ->setScale(StrTmp); }) % + "set the probe string to time specfic func; default period is ns" & + TraceOption); auto MainOption = _GREEN "Some overall options" _RE % (( ((clipp::option("-p") & @@ -194,6 +203,7 @@ int main(int argc, char *argv[]) ReadaheadOption, ProbeOption, LlcStatOption, + FunclatencyOption, MainOption, Info); } From 9e1171f9a5e04d980256bfda9e54c5a02470ef60 Mon Sep 17 00:00:00 2001 From: LiuLingze Date: Sun, 28 Apr 2024 10:22:30 +0000 Subject: [PATCH 17/23] fix probe usdt Signed-off-by: LiuLingze --- .../Stack_Analyser/src/bpf_wapper/probe.cpp | 10 +++------- eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread.c | 8 +++++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp index 1f0306743..e77008f60 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp @@ -149,6 +149,7 @@ static int attach_usdt(struct probe_bpf *skel, std::string func, int pid) skel->links.usdt_exit = bpf_program__attach_usdt(skel->progs.usdt_exit, pid, bin_path, "libc", func.c_str(), NULL); CHECK_ERR(!skel->links.usdt_exit, "Fail to attach usdt"); + return 0; } int ProbeStackCollector::attach(void) @@ -157,7 +158,7 @@ int ProbeStackCollector::attach(void) std::vector strList; splitStr(probe, ':', strList); std::string func = probe; - int err; + int err = 0; if (strList.size() == 3 && strList[0] == "p" && strList[1] == "") func = strList[2]; @@ -177,12 +178,7 @@ int ProbeStackCollector::attach(void) } else if (strList.size() == 3 && strList[0] == "u") { - char path[128]; - int err = get_binpath(path, pid); - CHECK_ERR(err, "Fail to get lib path"); - skel->links.usdt_entry = - bpf_program__attach_usdt(skel->progs.usdt_entry, pid, path, "libc", strList[2].c_str(), NULL); - CHECK_ERR(!skel->links.usdt_entry, "Fail to attach usdt"); + err = attach_usdt(skel, strList[2], pid); } else { diff --git a/eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread.c b/eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread.c index 6c9729b8d..47acf0b06 100644 --- a/eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread.c +++ b/eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread.c @@ -1,13 +1,15 @@ +#define _GNU_SOURCE #include #include #include #include +#include // 线程函数 void *thread_function(void *arg) { while (1) { // 打印当前线程的pid - printf("Thread PID: %d\n", getpid()); + printf("Thread ID: %d\n", gettid()); // 等待一秒 sleep(1); } @@ -29,14 +31,14 @@ void create_thread() { int main() { // 打印主进程的pid - printf("Main process PID: %d\n", getpid()); + printf("Main process ID: %d\n", gettid()); // 调用函数创建线程 create_thread(); // 主进程死循环打印pid while (1) { - printf("Main process PID: %d\n", getpid()); + printf("Main process ID: %d\n", getpid()); // 等待一秒 sleep(1); } From 6ef536acc16fabbdf9de62c2f7ef4942b309dbdf Mon Sep 17 00:00:00 2001 From: gyxforeveryoung <1739037263@qq.com> Date: Sat, 11 May 2024 22:54:32 +0800 Subject: [PATCH 18/23] fix usdt and tracepoint --- .github/workflows/ebpf_stack_analyser.yml | 8 ++++ .../Stack_Analyser/bpf/probe.bpf.c | 39 ++++++++++++------- .../Stack_Analyser/src/bpf_wapper/probe.cpp | 8 +--- eBPF_Supermarket/Stack_Analyser/src/main.cpp | 1 - 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ebpf_stack_analyser.yml b/.github/workflows/ebpf_stack_analyser.yml index 80522307c..8ad3aa57b 100644 --- a/.github/workflows/ebpf_stack_analyser.yml +++ b/.github/workflows/ebpf_stack_analyser.yml @@ -31,10 +31,15 @@ jobs: cd eBPF_Supermarket/Stack_Analyser make sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 + sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe p::vfs_open -d 5 + sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe t:sched:sched_switch -d 5 gcc -o ./testdir/usdt_pthread ./testdir/usdt_pthread.c sudo ./stack_analyzer probe u:pthread:pthread_create -c "./testdir/usdt_pthread" -d 5 + gcc -o ./testdir/uprobe_malloc ./testdir/uprobe_malloc.c + sudo ./stack_analyzer probe c:malloc -c "./testdir/uprobe_malloc" -d 5 + magic-eyes-build-and-test: runs-on: ubuntu-22.04 steps: @@ -52,4 +57,7 @@ jobs: cmake -DBUILD_STACK_ANALYZER=ON .. make sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 + sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe p::vfs_open -d 5 + sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe t:sched:sched_switch -d 5 + sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe c:malloc -c "../../eBPF_Supermarket/Stack_Analyser/testdir/uprobe_malloc" -d 5 sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe u:pthread:pthread_create -c "../../eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread" -d 5 diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c index 258f4158f..e37fc26c9 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c @@ -60,18 +60,7 @@ int BPF_KPROBE(dummy_kprobe) entry(ctx); return 0; } -SEC("tp/sched/dummy_tp") -int tp_entry(void *ctx) -{ - entry(ctx); - return 0; -} -SEC("usdt") -int usdt_entry(void *ctx) -{ - entry(ctx); - return 0; -} + static int exit(void *ctx) { CHECK_ACTIVE; @@ -104,16 +93,38 @@ int BPF_KRETPROBE(dummy_kretprobe) exit(ctx); return 0; } + + +static int handleCounts(void *ctx) +{ + CHECK_ACTIVE; + u32 pid = bpf_get_current_pid_tgid() >> 32; + + + psid a_psid = GET_COUNT_KEY(pid, ctx); + time_tuple *d = bpf_map_lookup_elem(&psid_count_map, &a_psid); + if (!d) + { + time_tuple tmp = {.lat = 0, .count = 1}; + bpf_map_update_elem(&psid_count_map, &a_psid, &tmp, BPF_NOEXIST); + } + else + { + d->lat = 0; + d->count++; + } + return 0; +} SEC("tp/sched/dummy_tp") int tp_exit(void *ctx) { - exit(ctx); + handleCounts(ctx); return 0; } SEC("usdt") int usdt_exit(void *ctx) { - exit(ctx); + handleCounts(ctx); return 0; } const char LICENSE[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp index e77008f60..d4db31cac 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp @@ -40,7 +40,7 @@ void ProbeStackCollector::setScale(std::string probe) int ProbeStackCollector::load(void) { - EBPF_LOAD_OPEN_INIT(); + EBPF_LOAD_OPEN_INIT(skel->rodata->target_pid = pid;); return 0; }; @@ -129,9 +129,6 @@ static int attach_uprobes(struct probe_bpf *skel, std::string probe, int pid) static int attach_tp(struct probe_bpf *skel, std::string tp_class, std::string func) { - skel->links.tp_entry = - bpf_program__attach_tracepoint(skel->progs.tp_entry, tp_class.c_str(), func.c_str()); - CHECK_ERR(!skel->links.tp_entry, "Fail to attach tracepoint"); skel->links.tp_exit = bpf_program__attach_tracepoint(skel->progs.tp_exit, tp_class.c_str(), func.c_str()); CHECK_ERR(!skel->links.tp_exit, "Fail to attach tracepoint"); @@ -143,9 +140,6 @@ static int attach_usdt(struct probe_bpf *skel, std::string func, int pid) char bin_path[128]; int err = get_binpath(bin_path, pid); CHECK_ERR(err, "Fail to get lib path"); - skel->links.usdt_entry = - bpf_program__attach_usdt(skel->progs.usdt_entry, pid, bin_path, "libc", func.c_str(), NULL); - CHECK_ERR(!skel->links.usdt_entry, "Fail to attach usdt"); skel->links.usdt_exit = bpf_program__attach_usdt(skel->progs.usdt_exit, pid, bin_path, "libc", func.c_str(), NULL); CHECK_ERR(!skel->links.usdt_exit, "Fail to attach usdt"); diff --git a/eBPF_Supermarket/Stack_Analyser/src/main.cpp b/eBPF_Supermarket/Stack_Analyser/src/main.cpp index c3c38e81d..dfb270895 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/main.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/main.cpp @@ -23,7 +23,6 @@ #include #include "bpf_wapper/on_cpu.h" -#include "bpf_wapper/probe.h" #include "bpf_wapper/llc_stat.h" #include "bpf_wapper/off_cpu.h" #include "bpf_wapper/memleak.h" From 3b3c921606190cc5f5c446c3a3153bf025ef87c6 Mon Sep 17 00:00:00 2001 From: gyxforeveryoung <1739037263@qq.com> Date: Sat, 11 May 2024 22:58:39 +0800 Subject: [PATCH 19/23] fix workflow --- .github/workflows/ebpf_stack_analyser.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ebpf_stack_analyser.yml b/.github/workflows/ebpf_stack_analyser.yml index 8ad3aa57b..f1f6a4d83 100644 --- a/.github/workflows/ebpf_stack_analyser.yml +++ b/.github/workflows/ebpf_stack_analyser.yml @@ -31,8 +31,8 @@ jobs: cd eBPF_Supermarket/Stack_Analyser make sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 - sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe p::vfs_open -d 5 - sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe t:sched:sched_switch -d 5 + sudo ./stack_analyzer probe p::vfs_open -d 5 + sudo ./stack_analyzer probe t:sched:sched_switch -d 5 gcc -o ./testdir/usdt_pthread ./testdir/usdt_pthread.c sudo ./stack_analyzer probe u:pthread:pthread_create -c "./testdir/usdt_pthread" -d 5 From d4203899edbdfbe9261a2417d7df4425b16e8e97 Mon Sep 17 00:00:00 2001 From: gyxforeveryoung <1739037263@qq.com> Date: Sat, 11 May 2024 23:03:47 +0800 Subject: [PATCH 20/23] add test prog Signed-off-by: gyxforeveryoung <1739037263@qq.com> --- .github/workflows/ebpf_stack_analyser.yml | 4 -- .../Stack_Analyser/testdir/usdt_malloc.c | 69 +++++++++++++++++++ 2 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 eBPF_Supermarket/Stack_Analyser/testdir/usdt_malloc.c diff --git a/.github/workflows/ebpf_stack_analyser.yml b/.github/workflows/ebpf_stack_analyser.yml index f1f6a4d83..8d4926cb9 100644 --- a/.github/workflows/ebpf_stack_analyser.yml +++ b/.github/workflows/ebpf_stack_analyser.yml @@ -37,9 +37,6 @@ jobs: gcc -o ./testdir/usdt_pthread ./testdir/usdt_pthread.c sudo ./stack_analyzer probe u:pthread:pthread_create -c "./testdir/usdt_pthread" -d 5 - gcc -o ./testdir/uprobe_malloc ./testdir/uprobe_malloc.c - sudo ./stack_analyzer probe c:malloc -c "./testdir/uprobe_malloc" -d 5 - magic-eyes-build-and-test: runs-on: ubuntu-22.04 steps: @@ -59,5 +56,4 @@ jobs: sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe p::vfs_open -d 5 sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe t:sched:sched_switch -d 5 - sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe c:malloc -c "../../eBPF_Supermarket/Stack_Analyser/testdir/uprobe_malloc" -d 5 sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe u:pthread:pthread_create -c "../../eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread" -d 5 diff --git a/eBPF_Supermarket/Stack_Analyser/testdir/usdt_malloc.c b/eBPF_Supermarket/Stack_Analyser/testdir/usdt_malloc.c new file mode 100644 index 000000000..182a29555 --- /dev/null +++ b/eBPF_Supermarket/Stack_Analyser/testdir/usdt_malloc.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +#define BUFFER_SIZE 1024 + +int main() { + // 打印当前进程号 + printf("Process ID: %d\n", getpid()); + + // 申请内存 + char *buffer = (char *)malloc(BUFFER_SIZE * sizeof(char)); + if (buffer == NULL) { + fprintf(stderr, "Memory allocation failed\n"); + return 1; + } + + // 文件描述符 + int fd = open("data.txt", O_CREAT | O_WRONLY, 0644); + if (fd == -1) { + fprintf(stderr, "Failed to open file\n"); + free(buffer); + return 1; + } + + // 写数据 + printf("Writing data. Process ID: %d\n", getpid()); + write(fd, "Hello, World!\n", 14); + + // 关闭文件描述符 + close(fd); + + // 打开文件以读取数据 + fd = open("data.txt", O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Failed to open file for reading\n"); + free(buffer); + return 1; + } + + // 读取数据 + printf("Reading data. Process ID: %d\n", getpid()); + ssize_t bytesRead = read(fd, buffer, BUFFER_SIZE); + if (bytesRead == -1) { + fprintf(stderr, "Failed to read data from file\n"); + free(buffer); + close(fd); + return 1; + } + + // 输出读取的数据 + printf("Data read: %s\n", buffer); + + // 关闭文件描述符 + close(fd); + + // 持续打印进程号 + while(1) { + printf("Still running. Process ID: %d\n", getpid()); + sleep(1); // 暂停一秒钟 + } + + // 释放内存 + free(buffer); + printf("Memory freed. Process ID: %d\n", getpid()); + + return 0; +} From ad936bd33c9ab3e0d2ba8dc30e59d50480281bb8 Mon Sep 17 00:00:00 2001 From: gyxforeveryoung <1739037263@qq.com> Date: Sat, 11 May 2024 23:08:23 +0800 Subject: [PATCH 21/23] modify workflow --- .github/workflows/ebpf_stack_analyser.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ebpf_stack_analyser.yml b/.github/workflows/ebpf_stack_analyser.yml index 8d4926cb9..ae4640ae6 100644 --- a/.github/workflows/ebpf_stack_analyser.yml +++ b/.github/workflows/ebpf_stack_analyser.yml @@ -33,10 +33,13 @@ jobs: sudo ./stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 sudo ./stack_analyzer probe p::vfs_open -d 5 sudo ./stack_analyzer probe t:sched:sched_switch -d 5 - + gcc -o ./testdir/usdt_pthread ./testdir/usdt_pthread.c sudo ./stack_analyzer probe u:pthread:pthread_create -c "./testdir/usdt_pthread" -d 5 + gcc -o ./testdir/uprobe_malloc ./testdir/uprobe_malloc.c + sudo ./stack_analyzer probe c:malloc -c "./testdir/uprobe_malloc" -d 5 + magic-eyes-build-and-test: runs-on: ubuntu-22.04 steps: @@ -56,4 +59,5 @@ jobs: sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer on_cpu off_cpu memleak io readahead llc_stat probe vfs_open -d 5 sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe p::vfs_open -d 5 sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe t:sched:sched_switch -d 5 + sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe c:malloc -c "../../eBPF_Supermarket/Stack_Analyser/testdir/uprobe_malloc" -d 5 sudo ./src/backend/system_diagnosis/stack_analyzer/stack_analyzer probe u:pthread:pthread_create -c "../../eBPF_Supermarket/Stack_Analyser/testdir/usdt_pthread" -d 5 From 6831b625e079f8589d3f8f7e5026e6e4bb53eedd Mon Sep 17 00:00:00 2001 From: gaoyixiang1 <45355878+gaoyixiang1@users.noreply.github.com> Date: Sat, 11 May 2024 23:12:28 +0800 Subject: [PATCH 22/23] Rename usdt_malloc.c to uprobe_malloc.c --- .../Stack_Analyser/testdir/{usdt_malloc.c => uprobe_malloc.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename eBPF_Supermarket/Stack_Analyser/testdir/{usdt_malloc.c => uprobe_malloc.c} (100%) diff --git a/eBPF_Supermarket/Stack_Analyser/testdir/usdt_malloc.c b/eBPF_Supermarket/Stack_Analyser/testdir/uprobe_malloc.c similarity index 100% rename from eBPF_Supermarket/Stack_Analyser/testdir/usdt_malloc.c rename to eBPF_Supermarket/Stack_Analyser/testdir/uprobe_malloc.c From dd09c837b6164ee29cff8a3546b05a4f904cb960 Mon Sep 17 00:00:00 2001 From: gyxforeveryoung <1739037263@qq.com> Date: Fri, 17 May 2024 18:03:24 +0800 Subject: [PATCH 23/23] kprobe transform fentry Signed-off-by: gyxforeveryoung <1739037263@qq.com> --- .../Stack_Analyser/bpf/probe.bpf.c | 19 ++- .../Stack_Analyser/src/bpf_wapper/probe.cpp | 112 ++++++++++++++---- 2 files changed, 106 insertions(+), 25 deletions(-) diff --git a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c index e37fc26c9..23a2288c8 100644 --- a/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c +++ b/eBPF_Supermarket/Stack_Analyser/bpf/probe.bpf.c @@ -53,7 +53,12 @@ static int entry(void *ctx) bpf_map_update_elem(&starts, &pid, &nsec, BPF_ANY); return 0; } - +SEC("fentry/dummy_fentry") +int BPF_PROG(dummy_fentry) +{ + entry(ctx); + return 0; +} SEC("kprobe/dummy_kprobe") int BPF_KPROBE(dummy_kprobe) { @@ -64,8 +69,7 @@ int BPF_KPROBE(dummy_kprobe) static int exit(void *ctx) { CHECK_ACTIVE; - u32 pid = bpf_get_current_pid_tgid() >> 32; - + u32 pid = bpf_get_current_pid_tgid() >> 32; u64 *start = bpf_map_lookup_elem(&starts, &pid); if (!start) return 0; @@ -87,6 +91,14 @@ static int exit(void *ctx) return 0; } +SEC("fexit/dummy_fexit") +int BPF_PROG(dummy_fexit) +{ + exit(ctx); + return 0; +} + + SEC("kretprobe/dummy_kretprobe") int BPF_KRETPROBE(dummy_kretprobe) { @@ -94,7 +106,6 @@ int BPF_KRETPROBE(dummy_kretprobe) return 0; } - static int handleCounts(void *ctx) { CHECK_ACTIVE; diff --git a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp index d4db31cac..db883abbb 100644 --- a/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp +++ b/eBPF_Supermarket/Stack_Analyser/src/bpf_wapper/probe.cpp @@ -21,7 +21,23 @@ #include "uprobe_helpers.h" // ========== implement virtual func ========== - +bool tryf; +std::vector strList; +std::string func; +void splitStr(std::string symbol, const char split, std::vector &res) +{ + if (symbol == "") + return; + std::string strs = symbol + split; + size_t pos = strs.find(split); + while (pos != strs.npos) + { + std::string temp = strs.substr(0, pos); + res.push_back(temp); + strs = strs.substr(pos + 1, strs.size()); + pos = strs.find(split); + } +} uint64_t *ProbeStackCollector::count_values(void *data) { time_tuple *p = (time_tuple *)data; @@ -34,31 +50,67 @@ uint64_t *ProbeStackCollector::count_values(void *data) void ProbeStackCollector::setScale(std::string probe) { this->probe = probe; + splitStr(probe, ':', strList); + func = probe; for (int i = 0; i < scale_num; i++) scales[i].Type = probe + scales[i].Type; }; -int ProbeStackCollector::load(void) +static bool try_fentry(struct probe_bpf *skel, std::string func) { - EBPF_LOAD_OPEN_INIT(skel->rodata->target_pid = pid;); - return 0; -}; + long err; -void splitStr(std::string symbol, const char split, std::vector &res) -{ - if (symbol == "") - return; - std::string strs = symbol + split; - size_t pos = strs.find(split); - while (pos != strs.npos) + if (!fentry_can_attach(func.c_str(), NULL)) { - std::string temp = strs.substr(0, pos); - res.push_back(temp); - strs = strs.substr(pos + 1, strs.size()); - pos = strs.find(split); + return false; } + err = bpf_program__set_attach_target(skel->progs.dummy_fentry, 0, func.c_str()); + if (err) + { + bpf_program__set_autoload(skel->progs.dummy_fentry, false); + bpf_program__set_autoload(skel->progs.dummy_fexit, false); + return false; + } + err = bpf_program__set_attach_target(skel->progs.dummy_fexit, 0, func.c_str()); + if (err) + { + bpf_program__set_autoload(skel->progs.dummy_fentry, false); + bpf_program__set_autoload(skel->progs.dummy_fexit, false); + + return false; + } + + bpf_program__set_autoload(skel->progs.dummy_kprobe, false); + bpf_program__set_autoload(skel->progs.dummy_kretprobe, false); + return true; } +int ProbeStackCollector::load(void) +{ + std::string str = func; + skel = skel->open(NULL); + CHECK_ERR(!skel, "Fail to open BPF skeleton"); + if (strList.size() == 3 && strList[0] == "p" && strList[1] == "") + str = strList[2]; + if (strList.size() == 1 || (strList.size() == 3 && strList[0] == "p" && strList[1] == "")){ + tryf = try_fentry(skel, str); + }else{ + bpf_program__set_autoload(skel->progs.dummy_fentry, false); + bpf_program__set_autoload(skel->progs.dummy_fexit, false); + } + skel->rodata->target_pid = pid; + skel->rodata->trace_user = ustack; + skel->rodata->trace_kernel = kstack; + skel->rodata->self_pid = self_pid; + skel->rodata->target_tgid = tgid; + skel->rodata->target_cgroupid = cgroup; + skel->rodata->freq = freq; + err = skel->load(skel); + CHECK_ERR(err, "Fail to load BPF skeleton"); + obj = skel->obj; + return 0; +}; + static int get_binpath(char *path, int pid) { char mode[16], line[128], buf[64]; @@ -97,6 +149,16 @@ static int attach_kprobes(struct probe_bpf *skel, std::string func) CHECK_ERR(!skel->links.dummy_kretprobe, "Fail to attach ketprobe"); return 0; } +static int attach_fentry(struct probe_bpf *skel) +{ + skel->links.dummy_fentry = + bpf_program__attach(skel->progs.dummy_fentry); + CHECK_ERR(!skel->links.dummy_fentry, "Fail to attach fentry"); + skel->links.dummy_fexit = + bpf_program__attach(skel->progs.dummy_fexit); + CHECK_ERR(!skel->links.dummy_fexit, "Fail to attach fexit"); + return 0; +} static int attach_uprobes(struct probe_bpf *skel, std::string probe, int pid) { char *binary, *function; @@ -149,16 +211,24 @@ static int attach_usdt(struct probe_bpf *skel, std::string func, int pid) int ProbeStackCollector::attach(void) { // dynamic mounting - std::vector strList; - splitStr(probe, ':', strList); - std::string func = probe; + // std::vector strList; + // splitStr(probe, ':', strList); + // std::string func = probe; int err = 0; - if (strList.size() == 3 && strList[0] == "p" && strList[1] == "") func = strList[2]; if (strList.size() == 1 || (strList.size() == 3 && strList[0] == "p" && strList[1] == "")) { - err = attach_kprobes(skel, func); + if (!tryf) + { + err = attach_kprobes(skel, func); + return 0; + } + else + { + err = attach_fentry(skel); + return 0; + } } else if (strList.size() == 3 && strList[0] == "t") {