-
Notifications
You must be signed in to change notification settings - Fork 4k
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 [DRAFT Proposal] bcc / tools repo evolution #3976.
- A source to source converter can speed up python->libbpf tool conversions, which are encouraged [DRAFT Proposal] bcc / tools repo evolution #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:
-
libbpf_frontend_action:
- change the map access to libbpf style map access, for example,
bpf_map_update_elem
- change the
bpf_probe_read*
tobpf_core_read*
- change the
a->b->c
access toBPF_CORE_READ(a, b, c)
- change some bcc internal helpers to libbpf helpers, for example,
bpf_map_lookup_or_try_init
- etc...
- change the map access to libbpf style map access, for example,
-
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.
- After the preprocessor pass, some libbpf specified includes will be added into the generated source file.
example
A bcc source:
#include <linux/ptrace.h>
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:
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <vmlinux.h>
#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
TracepointFrontendAction
support for libbpf source- fix more bcc maps and helpers support
- 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)