add the compile method of profile (#30)

This commit is contained in:
try-agaaain
2023-04-29 16:50:34 +08:00
committed by GitHub
parent 39a0f4a1a7
commit f91e119b81
3 changed files with 109 additions and 37 deletions

View File

@@ -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 [<ffffffff81ee9f56>] _raw_spin_lock_irqsave+0x16
1 [<ffffffff811527b4>] remove_wait_queue+0x14
2 [<ffffffff8132611d>] poll_freewait+0x3d
3 [<ffffffff81326d3f>] do_select+0x7bf
4 [<ffffffff81327af2>] core_sys_select+0x182
5 [<ffffffff81327f3a>] __x64_sys_pselect6+0xea
6 [<ffffffff81ed9e38>] do_syscall_64+0x38
7 [<ffffffff82000099>] 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等操作中可以极大的帮助开发者提高效率。
`profile` 实现了对程序执行流程的分析在debug等操作中可以极大的帮助开发者提高效率。

View File

@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright (c) 2022 Meta Platforms, Inc. */
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#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;
}

26
src/12-profile/profile.h Normal file
View File

@@ -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_ */