iovisor / iovisor/bcc

Convert BCC style source to libbpf style source and enable AOT/CO-RE for BCC framework

Open
#4,404 2 comments 2 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.