From f91e119b818e872e91757f5027b7b09d961ed9ef Mon Sep 17 00:00:00 2001 From: try-agaaain <52828870+try-agaaain@users.noreply.github.com> Date: Sat, 29 Apr 2023 16:50:34 +0800 Subject: [PATCH] add the compile method of profile (#30) --- src/12-profile/README.md | 78 +++++++++++++++++++----------------- src/12-profile/profile.bpf.c | 42 +++++++++++++++++++ src/12-profile/profile.h | 26 ++++++++++++ 3 files changed, 109 insertions(+), 37 deletions(-) create mode 100644 src/12-profile/profile.bpf.c create mode 100644 src/12-profile/profile.h diff --git a/src/12-profile/README.md b/src/12-profile/README.md index 0fdaedd..f48a4f4 100644 --- a/src/12-profile/README.md +++ b/src/12-profile/README.md @@ -50,55 +50,59 @@ static int open_and_attach_perf_event(int freq, struct bpf_program *prog, 其ebpf程序实现逻辑是对程序的堆栈进行定时采样,从而捕获程序的执行流程。 ```c SEC("perf_event") -int do_perf_event(struct bpf_perf_event_data *ctx) +int profile(void *ctx) { - __u64 id = bpf_get_current_pid_tgid(); - __u32 pid = id >> 32; - __u32 tid = id; - __u64 *valp; - static const __u64 zero; - struct key_t key = {}; + int pid = bpf_get_current_pid_tgid() >> 32; + int cpu_id = bpf_get_smp_processor_id(); + struct stacktrace_event *event; + int cp; - if (!include_idle && tid == 0) - return 0; + event = bpf_ringbuf_reserve(&events, sizeof(*event), 0); + if (!event) + return 1; - if (targ_pid != -1 && targ_pid != pid) - return 0; - if (targ_tid != -1 && targ_tid != tid) - return 0; + event->pid = pid; + event->cpu_id = cpu_id; - key.pid = pid; - bpf_get_current_comm(&key.name, sizeof(key.name)); + if (bpf_get_current_comm(event->comm, sizeof(event->comm))) + event->comm[0] = 0; - if (user_stacks_only) - key.kern_stack_id = -1; - else - key.kern_stack_id = bpf_get_stackid(&ctx->regs, &stackmap, 0); + event->kstack_sz = bpf_get_stack(ctx, event->kstack, sizeof(event->kstack), 0); - if (kernel_stacks_only) - key.user_stack_id = -1; - else - key.user_stack_id = bpf_get_stackid(&ctx->regs, &stackmap, BPF_F_USER_STACK); + event->ustack_sz = bpf_get_stack(ctx, event->ustack, sizeof(event->ustack), BPF_F_USER_STACK); - if (key.kern_stack_id >= 0) { - // populate extras to fix the kernel stack - __u64 ip = PT_REGS_IP(&ctx->regs); - - if (is_kernel_addr(ip)) { - key.kernel_ip = ip; - } - } - - valp = bpf_map_lookup_or_try_init(&counts, &key, &zero); - if (valp) - __sync_fetch_and_add(valp, 1); + bpf_ringbuf_submit(event, 0); return 0; } ``` 通过这种方式,它可以根据用户指令,简单的决定追踪用户态层面的执行流程或是内核态层面的执行流程。 -### Eunomia中使用方式 +### 编译运行 +```console +$ git clone https://github.com/libbpf/libbpf-bootstrap.git --recurse-submodules +$ cd examples/c +$ make profile +$ sudo ./profile +COMM: chronyd (pid=156) @ CPU 1 +Kernel: + 0 [] _raw_spin_lock_irqsave+0x16 + 1 [] remove_wait_queue+0x14 + 2 [] poll_freewait+0x3d + 3 [] do_select+0x7bf + 4 [] core_sys_select+0x182 + 5 [] __x64_sys_pselect6+0xea + 6 [] do_syscall_64+0x38 + 7 [] entry_SYSCALL_64_after_hwframe+0x61 +Userspace: + 0 [<00007fab187bfe09>] + 1 [<000000000ee6ae98>] +COMM: profile (pid=9843) @ CPU 6 +No Kernel Stack +Userspace: + 0 [<0000556deb068ac8>] + 1 [<0000556dec34cad0>] +``` ### 总结 -`profile` 实现了对程序执行流程的分析,在debug等操作中可以极大的帮助开发者提高效率。 \ No newline at end of file +`profile` 实现了对程序执行流程的分析,在debug等操作中可以极大的帮助开发者提高效率。 diff --git a/src/12-profile/profile.bpf.c b/src/12-profile/profile.bpf.c new file mode 100644 index 0000000..614b274 --- /dev/null +++ b/src/12-profile/profile.bpf.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright (c) 2022 Meta Platforms, Inc. */ +#include "vmlinux.h" +#include +#include +#include + +#include "profile.h" + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 256 * 1024); +} events SEC(".maps"); + +SEC("perf_event") +int profile(void *ctx) +{ + int pid = bpf_get_current_pid_tgid() >> 32; + int cpu_id = bpf_get_smp_processor_id(); + struct stacktrace_event *event; + int cp; + + event = bpf_ringbuf_reserve(&events, sizeof(*event), 0); + if (!event) + return 1; + + event->pid = pid; + event->cpu_id = cpu_id; + + if (bpf_get_current_comm(event->comm, sizeof(event->comm))) + event->comm[0] = 0; + + event->kstack_sz = bpf_get_stack(ctx, event->kstack, sizeof(event->kstack), 0); + + event->ustack_sz = bpf_get_stack(ctx, event->ustack, sizeof(event->ustack), BPF_F_USER_STACK); + + bpf_ringbuf_submit(event, 0); + + return 0; +} diff --git a/src/12-profile/profile.h b/src/12-profile/profile.h new file mode 100644 index 0000000..a651839 --- /dev/null +++ b/src/12-profile/profile.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +/* Copyright (c) 2022 Meta Platforms, Inc. */ +#ifndef __PROFILE_H_ +#define __PROFILE_H_ + +#ifndef TASK_COMM_LEN +#define TASK_COMM_LEN 16 +#endif + +#ifndef MAX_STACK_DEPTH +#define MAX_STACK_DEPTH 128 +#endif + +typedef __u64 stack_trace_t[MAX_STACK_DEPTH]; + +struct stacktrace_event { + __u32 pid; + __u32 cpu_id; + char comm[TASK_COMM_LEN]; + __s32 kstack_sz; + __s32 ustack_sz; + stack_trace_t kstack; + stack_trace_t ustack; +}; + +#endif /* __PROFILE_H_ */