Skip to content

Commit 3677d0a

Browse files
DanielTimLeeAlexei Starovoitov
authored andcommitted
samples: bpf: Refactor kprobe tracing programs with libbpf
For the problem of increasing fragmentation of the bpf loader programs, instead of using bpf_loader.o, which is used in samples/bpf, this commit refactors the existing kprobe tracing programs with libbbpf bpf loader. - For kprobe events pointing to system calls, the SYSCALL() macro in trace_common.h was used. - Adding a kprobe event and attaching a bpf program to it was done through bpf_program_attach(). - Instead of using the existing BPF MAP definition, MAP definition has been refactored with the new BTF-defined MAP format. Signed-off-by: Daniel T. Lee <danieltimlee@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20200823085334.9413-3-danieltimlee@gmail.com
1 parent 35a8b6d commit 3677d0a

11 files changed

+272
-118
lines changed

samples/bpf/Makefile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@ tracex4-objs := tracex4_user.o
7171
tracex5-objs := tracex5_user.o $(TRACE_HELPERS)
7272
tracex6-objs := tracex6_user.o
7373
tracex7-objs := tracex7_user.o
74-
test_probe_write_user-objs := bpf_load.o test_probe_write_user_user.o
75-
trace_output-objs := bpf_load.o trace_output_user.o $(TRACE_HELPERS)
76-
lathist-objs := bpf_load.o lathist_user.o
74+
test_probe_write_user-objs := test_probe_write_user_user.o
75+
trace_output-objs := trace_output_user.o $(TRACE_HELPERS)
76+
lathist-objs := lathist_user.o
7777
offwaketime-objs := bpf_load.o offwaketime_user.o $(TRACE_HELPERS)
78-
spintest-objs := bpf_load.o spintest_user.o $(TRACE_HELPERS)
78+
spintest-objs := spintest_user.o $(TRACE_HELPERS)
7979
map_perf_test-objs := map_perf_test_user.o
8080
test_overhead-objs := bpf_load.o test_overhead_user.o
8181
test_cgrp2_array_pin-objs := test_cgrp2_array_pin.o
@@ -86,7 +86,7 @@ xdp1-objs := xdp1_user.o
8686
# reuse xdp1 source intentionally
8787
xdp2-objs := xdp1_user.o
8888
xdp_router_ipv4-objs := xdp_router_ipv4_user.o
89-
test_current_task_under_cgroup-objs := bpf_load.o $(CGROUP_HELPERS) \
89+
test_current_task_under_cgroup-objs := $(CGROUP_HELPERS) \
9090
test_current_task_under_cgroup_user.o
9191
trace_event-objs := trace_event_user.o $(TRACE_HELPERS)
9292
sampleip-objs := sampleip_user.o $(TRACE_HELPERS)

samples/bpf/lathist_kern.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
* trace_preempt_[on|off] tracepoints hooks is not supported.
1919
*/
2020

21-
struct bpf_map_def SEC("maps") my_map = {
22-
.type = BPF_MAP_TYPE_ARRAY,
23-
.key_size = sizeof(int),
24-
.value_size = sizeof(u64),
25-
.max_entries = MAX_CPU,
26-
};
21+
struct {
22+
__uint(type, BPF_MAP_TYPE_ARRAY);
23+
__type(key, int);
24+
__type(value, u64);
25+
__uint(max_entries, MAX_CPU);
26+
} my_map SEC(".maps");
2727

2828
SEC("kprobe/trace_preempt_off")
2929
int bpf_prog1(struct pt_regs *ctx)
@@ -61,12 +61,12 @@ static unsigned int log2l(unsigned long v)
6161
return log2(v);
6262
}
6363

64-
struct bpf_map_def SEC("maps") my_lat = {
65-
.type = BPF_MAP_TYPE_ARRAY,
66-
.key_size = sizeof(int),
67-
.value_size = sizeof(long),
68-
.max_entries = MAX_CPU * MAX_ENTRIES,
69-
};
64+
struct {
65+
__uint(type, BPF_MAP_TYPE_ARRAY);
66+
__type(key, int);
67+
__type(value, long);
68+
__uint(max_entries, MAX_CPU * MAX_ENTRIES);
69+
} my_lat SEC(".maps");
7070

7171
SEC("kprobe/trace_preempt_on")
7272
int bpf_prog2(struct pt_regs *ctx)

samples/bpf/lathist_user.c

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
#include <unistd.h>
77
#include <stdlib.h>
88
#include <signal.h>
9-
#include <linux/bpf.h>
9+
#include <bpf/libbpf.h>
1010
#include <bpf/bpf.h>
11-
#include "bpf_load.h"
1211

1312
#define MAX_ENTRIES 20
1413
#define MAX_CPU 4
@@ -81,20 +80,51 @@ static void get_data(int fd)
8180

8281
int main(int argc, char **argv)
8382
{
83+
struct bpf_link *links[2];
84+
struct bpf_program *prog;
85+
struct bpf_object *obj;
8486
char filename[256];
87+
int map_fd, i = 0;
8588

8689
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
90+
obj = bpf_object__open_file(filename, NULL);
91+
if (libbpf_get_error(obj)) {
92+
fprintf(stderr, "ERROR: opening BPF object file failed\n");
93+
return 0;
94+
}
95+
96+
/* load BPF program */
97+
if (bpf_object__load(obj)) {
98+
fprintf(stderr, "ERROR: loading BPF object file failed\n");
99+
goto cleanup;
100+
}
87101

88-
if (load_bpf_file(filename)) {
89-
printf("%s", bpf_log_buf);
90-
return 1;
102+
map_fd = bpf_object__find_map_fd_by_name(obj, "my_lat");
103+
if (map_fd < 0) {
104+
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
105+
goto cleanup;
106+
}
107+
108+
bpf_object__for_each_program(prog, obj) {
109+
links[i] = bpf_program__attach(prog);
110+
if (libbpf_get_error(links[i])) {
111+
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
112+
links[i] = NULL;
113+
goto cleanup;
114+
}
115+
i++;
91116
}
92117

93118
while (1) {
94-
get_data(map_fd[1]);
119+
get_data(map_fd);
95120
print_hist();
96121
sleep(5);
97122
}
98123

124+
cleanup:
125+
for (i--; i >= 0; i--)
126+
bpf_link__destroy(links[i]);
127+
128+
bpf_object__close(obj);
99129
return 0;
100130
}

samples/bpf/spintest_kern.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,25 @@
1212
#include <bpf/bpf_helpers.h>
1313
#include <bpf/bpf_tracing.h>
1414

15-
struct bpf_map_def SEC("maps") my_map = {
16-
.type = BPF_MAP_TYPE_HASH,
17-
.key_size = sizeof(long),
18-
.value_size = sizeof(long),
19-
.max_entries = 1024,
20-
};
21-
struct bpf_map_def SEC("maps") my_map2 = {
22-
.type = BPF_MAP_TYPE_PERCPU_HASH,
23-
.key_size = sizeof(long),
24-
.value_size = sizeof(long),
25-
.max_entries = 1024,
26-
};
15+
struct {
16+
__uint(type, BPF_MAP_TYPE_HASH);
17+
__type(key, long);
18+
__type(value, long);
19+
__uint(max_entries, 1024);
20+
} my_map SEC(".maps");
21+
struct {
22+
__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
23+
__uint(key_size, sizeof(long));
24+
__uint(value_size, sizeof(long));
25+
__uint(max_entries, 1024);
26+
} my_map2 SEC(".maps");
2727

28-
struct bpf_map_def SEC("maps") stackmap = {
29-
.type = BPF_MAP_TYPE_STACK_TRACE,
30-
.key_size = sizeof(u32),
31-
.value_size = PERF_MAX_STACK_DEPTH * sizeof(u64),
32-
.max_entries = 10000,
33-
};
28+
struct {
29+
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
30+
__uint(key_size, sizeof(u32));
31+
__uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64));
32+
__uint(max_entries, 10000);
33+
} stackmap SEC(".maps");
3434

3535
#define PROG(foo) \
3636
int foo(struct pt_regs *ctx) \

samples/bpf/spintest_user.c

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,77 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <stdio.h>
33
#include <unistd.h>
4-
#include <linux/bpf.h>
54
#include <string.h>
65
#include <assert.h>
76
#include <sys/resource.h>
87
#include <bpf/libbpf.h>
9-
#include "bpf_load.h"
8+
#include <bpf/bpf.h>
109
#include "trace_helpers.h"
1110

1211
int main(int ac, char **argv)
1312
{
1413
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
14+
char filename[256], symbol[256];
15+
struct bpf_object *obj = NULL;
16+
struct bpf_link *links[20];
1517
long key, next_key, value;
16-
char filename[256];
18+
struct bpf_program *prog;
19+
int map_fd, i, j = 0;
20+
const char *title;
1721
struct ksym *sym;
18-
int i;
1922

20-
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
21-
setrlimit(RLIMIT_MEMLOCK, &r);
23+
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
24+
perror("setrlimit(RLIMIT_MEMLOCK)");
25+
return 1;
26+
}
2227

2328
if (load_kallsyms()) {
2429
printf("failed to process /proc/kallsyms\n");
2530
return 2;
2631
}
2732

28-
if (load_bpf_file(filename)) {
29-
printf("%s", bpf_log_buf);
30-
return 1;
33+
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
34+
obj = bpf_object__open_file(filename, NULL);
35+
if (libbpf_get_error(obj)) {
36+
fprintf(stderr, "ERROR: opening BPF object file failed\n");
37+
obj = NULL;
38+
goto cleanup;
39+
}
40+
41+
/* load BPF program */
42+
if (bpf_object__load(obj)) {
43+
fprintf(stderr, "ERROR: loading BPF object file failed\n");
44+
goto cleanup;
45+
}
46+
47+
map_fd = bpf_object__find_map_fd_by_name(obj, "my_map");
48+
if (map_fd < 0) {
49+
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
50+
goto cleanup;
51+
}
52+
53+
bpf_object__for_each_program(prog, obj) {
54+
title = bpf_program__title(prog, false);
55+
if (sscanf(title, "kprobe/%s", symbol) != 1)
56+
continue;
57+
58+
/* Attach prog only when symbol exists */
59+
if (ksym_get_addr(symbol)) {
60+
links[j] = bpf_program__attach(prog);
61+
if (libbpf_get_error(links[j])) {
62+
fprintf(stderr, "bpf_program__attach failed\n");
63+
links[j] = NULL;
64+
goto cleanup;
65+
}
66+
j++;
67+
}
3168
}
3269

3370
for (i = 0; i < 5; i++) {
3471
key = 0;
3572
printf("kprobing funcs:");
36-
while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0) {
37-
bpf_map_lookup_elem(map_fd[0], &next_key, &value);
73+
while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0) {
74+
bpf_map_lookup_elem(map_fd, &next_key, &value);
3875
assert(next_key == value);
3976
sym = ksym_search(value);
4077
key = next_key;
@@ -48,10 +85,15 @@ int main(int ac, char **argv)
4885
if (key)
4986
printf("\n");
5087
key = 0;
51-
while (bpf_map_get_next_key(map_fd[0], &key, &next_key) == 0)
52-
bpf_map_delete_elem(map_fd[0], &next_key);
88+
while (bpf_map_get_next_key(map_fd, &key, &next_key) == 0)
89+
bpf_map_delete_elem(map_fd, &next_key);
5390
sleep(1);
5491
}
5592

93+
cleanup:
94+
for (j--; j >= 0; j--)
95+
bpf_link__destroy(links[j]);
96+
97+
bpf_object__close(obj);
5698
return 0;
5799
}

samples/bpf/test_current_task_under_cgroup_kern.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,24 @@
1010
#include <linux/version.h>
1111
#include <bpf/bpf_helpers.h>
1212
#include <uapi/linux/utsname.h>
13+
#include "trace_common.h"
1314

14-
struct bpf_map_def SEC("maps") cgroup_map = {
15-
.type = BPF_MAP_TYPE_CGROUP_ARRAY,
16-
.key_size = sizeof(u32),
17-
.value_size = sizeof(u32),
18-
.max_entries = 1,
19-
};
15+
struct {
16+
__uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
17+
__uint(key_size, sizeof(u32));
18+
__uint(value_size, sizeof(u32));
19+
__uint(max_entries, 1);
20+
} cgroup_map SEC(".maps");
2021

21-
struct bpf_map_def SEC("maps") perf_map = {
22-
.type = BPF_MAP_TYPE_ARRAY,
23-
.key_size = sizeof(u32),
24-
.value_size = sizeof(u64),
25-
.max_entries = 1,
26-
};
22+
struct {
23+
__uint(type, BPF_MAP_TYPE_ARRAY);
24+
__type(key, u32);
25+
__type(value, u64);
26+
__uint(max_entries, 1);
27+
} perf_map SEC(".maps");
2728

2829
/* Writes the last PID that called sync to a map at index 0 */
29-
SEC("kprobe/sys_sync")
30+
SEC("kprobe/" SYSCALL(sys_sync))
3031
int bpf_prog1(struct pt_regs *ctx)
3132
{
3233
u64 pid = bpf_get_current_pid_tgid();

samples/bpf/test_current_task_under_cgroup_user.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,54 @@
44

55
#define _GNU_SOURCE
66
#include <stdio.h>
7-
#include <linux/bpf.h>
87
#include <unistd.h>
98
#include <bpf/bpf.h>
10-
#include "bpf_load.h"
9+
#include <bpf/libbpf.h>
1110
#include "cgroup_helpers.h"
1211

1312
#define CGROUP_PATH "/my-cgroup"
1413

1514
int main(int argc, char **argv)
1615
{
1716
pid_t remote_pid, local_pid = getpid();
18-
int cg2, idx = 0, rc = 0;
17+
struct bpf_link *link = NULL;
18+
struct bpf_program *prog;
19+
int cg2, idx = 0, rc = 1;
20+
struct bpf_object *obj;
1921
char filename[256];
22+
int map_fd[2];
2023

2124
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
22-
if (load_bpf_file(filename)) {
23-
printf("%s", bpf_log_buf);
24-
return 1;
25+
obj = bpf_object__open_file(filename, NULL);
26+
if (libbpf_get_error(obj)) {
27+
fprintf(stderr, "ERROR: opening BPF object file failed\n");
28+
return 0;
29+
}
30+
31+
prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
32+
if (!prog) {
33+
printf("finding a prog in obj file failed\n");
34+
goto cleanup;
35+
}
36+
37+
/* load BPF program */
38+
if (bpf_object__load(obj)) {
39+
fprintf(stderr, "ERROR: loading BPF object file failed\n");
40+
goto cleanup;
41+
}
42+
43+
map_fd[0] = bpf_object__find_map_fd_by_name(obj, "cgroup_map");
44+
map_fd[1] = bpf_object__find_map_fd_by_name(obj, "perf_map");
45+
if (map_fd[0] < 0 || map_fd[1] < 0) {
46+
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
47+
goto cleanup;
48+
}
49+
50+
link = bpf_program__attach(prog);
51+
if (libbpf_get_error(link)) {
52+
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
53+
link = NULL;
54+
goto cleanup;
2555
}
2656

2757
if (setup_cgroup_environment())
@@ -70,12 +100,14 @@ int main(int argc, char **argv)
70100
goto err;
71101
}
72102

73-
goto out;
74-
err:
75-
rc = 1;
103+
rc = 0;
76104

77-
out:
105+
err:
78106
close(cg2);
79107
cleanup_cgroup_environment();
108+
109+
cleanup:
110+
bpf_link__destroy(link);
111+
bpf_object__close(obj);
80112
return rc;
81113
}

0 commit comments

Comments
 (0)