Convert BCC style source to libbpf style source and enable AOT/CO-RE for BCC framework
- Dominant language
- C
- Stars
- 22.7k
- Forks
- 4.1k
- Avg merge
- 10d 4h
- Merged PRs (30d)
- 3
Description
Hi! I have some working PoC and ideas, and I would like to get some comments or feedbacks before I going on this.
## motivation
- Alrough the use of bcc for new BPF applications is strongly discouraged, there still exists a lot of tools base on bcc jit compile framework in the community. A number of bcc tools havn't been converted to libbpf in this repo yet. see #3976.
- A source to source converter can speed up python->libbpf tool conversions, which are encouraged #3976. Compared to generated libbpf style ELF file, some smaller code issues can be found and fix mannually in the converted libbpf source.
## A Prove of Concept converter for convert BCC style kernel source to libbpf style kernel source
we have created a source to source converter base on bcc frontend: see https://github.com/eunomia-bpf/bcc/tree/master/src/cc/converter
This work will introduce:
- A new clang frontend action: https://github.com/eunomia-bpf/bcc/blob/master/src/cc/frontends/clang/libbpf_frontend_action.cc, modified on the exising b_frontend_action.
- Some new include headers: https://github.com/eunomia-bpf/bcc/tree/master/src/cc/converter/bcc, modified on existing bcc internal headers.
A new flag `aot_mode` and an example converter may also works:
- (BPF.h#L116)[https://github.com/eunomia-bpf/bcc/blob/a4e1c71cedbab57f75b0a617a40323c831be73f8/src/cc/api/BPF.h#L116]
- (ConvertBCCtoLibbbpf)[https://github.com/eunomia-bpf/bcc/blob/master/examples/cpp/ConvertBCCtoLibbbpf.cc]
The `BPF(bool aot_mode = true)` may be used to enable the converter and aot build.
The converter may include two passes to generate a libbpf source from bcc source:
1. libbpf_frontend_action:
- change the map access to libbpf style map access, for example, `bpf_map_update_elem`
- change the `bpf_probe_read*` to `bpf_core_read*`
- change the `a->b->c` access to `BPF_CORE_READ(a, b, c)`
- change some bcc internal helpers to libbpf helpers, for example, `bpf_map_lookup_or_try_init`
- etc...
2. preprocesseo pass: work like `clang -E -P -C -nostdinc source_rewrite.bcc.c 1> pre_output.bpf.c`
- change the bcc style maps to libbpf style maps
- process and cleanup the bcc specified macros
- note: for this poc, the current preprocessor pass is done through makefile and clang cmd, which should be embed in bcc as the internal bcc includes in [export](https://github.com/eunomia-bpf/bcc/blob/master/src/cc/export/bpf_workaround.h).
- After the preprocessor pass, some libbpf specified includes will be added into the generated source file.
## example
A bcc source:
```c
#include
struct query_probe_t {
uint64_t ts;
pid_t pid;
char query[100];
};
BPF_HASH(queries, struct query_probe_t, int);
int probe_mysql_query(struct pt_regs *ctx, void* thd, char* query, size_t len) {
if (query) {
struct query_probe_t key = {};
key.ts = bpf_ktime_get_ns();
key.pid = bpf_get_current_pid_tgid();
bpf_probe_read_user_str(&key.query, sizeof(key.query), query);
bpf_trace_printk("Hello, World! Here I did a sys_clone call! %s\n", key.query);
int one = 1;
queries.update(&key, &one);
}
return 0;
}
```
will results in:
```c
#include
#include
#include
#include
#include "bits.bpf.h"
#include "maps.bpf.h"
struct query_probe_t {
uint64_t ts;
pid_t pid;
char query[100];
};
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 10240);
__type(key, struct query_probe_t);
__type(value, int);
} queries SEC(".maps");
SEC("kprobe")
int probe_mysql_query(struct pt_regs *ctx) {
void *thd = (void *)ctx->di;
char *query = (char *)ctx->si;
size_t len = (size_t)ctx->dx;
if (query) {
struct query_probe_t key = {};
key.ts = bpf_ktime_get_ns();
key.pid = bpf_get_current_pid_tgid();
bpf_core_read_user_str(&key.query, sizeof(key.query), query);
bpf_printk("Hello, World! Here I did a sys_clone call! %s\n", key.query);
int one = 1;
bpf_map_update_elem(&queries, &key, &one, BPF_ANY);
}
return 0;
}
/* No license defined, using GPL
* You can define your own BPF_LICENSE in your C code */
char LICENSE[] SEC("license") = "GPL";
```
which can be compile with clang and `CO-RE` enabled, and load with libbpf loader. The compiled BPF code can pass the verifier.
## Unsolved problems
1. `TracepointFrontendAction` support for libbpf source
2. fix more bcc maps and helpers support
3. tests on more existing bcc style code
## AOT support
I have tried to AOT load the compiled libbpf code through the `bpf-loader` in eunomia-bpf: https://github.com/eunomia-bpf/eunomia-bpf, maybe I can add a similar libbpf CO-RE ELF loader in bcc? It should not be difficult to add one with the high level libbpf API, compare to the bcc frontend implement.
(TODO: add more detail design and api examples for aot build)
## reference
- https://github.com/iovisor/bcc/issues/3090
- https://github.com/iovisor/bcc/issues/1887
- https://github.com/iovisor/bcc/issues/2564
- https://dxuuu.xyz/aot-bpftrace.html
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with src/cc/frontends/clang/libbpf_frontend_action.cc, src/cc/converter, src/cc/api/BPF.h, and examples/cpp/ConvertBCCtoLibbbpf.cc to understand the existing PoC. The issue identifies TracepointFrontendAction support, broader map and helper coverage, tests on existing BCC code, and AOT API design as unresolved; completion would need those areas specified and validated.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, linux
- Domain
- compilers, operating-systems, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100