-
Notifications
You must be signed in to change notification settings - Fork 6
/
HelloBuffer.java
111 lines (98 loc) · 3.78 KB
/
HelloBuffer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
* Record data in perf buffer
*/
package me.bechberger.ebpf.samples.chapter2;
import me.bechberger.ebpf.annotations.Size;
import me.bechberger.ebpf.bcc.BPF;
import me.bechberger.ebpf.bcc.BPFTable;
import me.bechberger.ebpf.type.BPFType;
import java.util.List;
/**
* {@snippet :
* #!/usr/bin/python3
* from bcc import BPF
*
* program = r"""
* BPF_PERF_OUTPUT(output);
*
* struct data_t {
* int pid;
* int uid;
* char command[16];
* char message[12];
* };
*
* int hello(void *ctx) {
* struct data_t data = {};
* char message[12] = "Hello World";
*
* data.pid = bpf_get_current_pid_tgid() >> 32;
* data.uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;
*
* bpf_get_current_comm(&data.command, sizeof(data.command));
* bpf_probe_read_kernel(&data.message, sizeof(data.message), message);
*
* output.perf_submit(ctx, &data, sizeof(data));
*
* return 0;
* }
* """
*
* b = BPF(text=program)
* syscall = b.get_syscall_fnname("execve")
* b.attach_kprobe(event=syscall, fn_name="hello")
*
* def print_event(cpu, data, size):
* data = b["output"].event(data)
* print(f"{data.pid}{data.uid}{data.command.decode()}{data.message.decode()}")
*
* b["output"].open_perf_buffer(print_event)
* while True:
* b.perf_buffer_poll()
*}
*/
public class HelloBuffer {
public record Data(int pid, int uid, @Size(16) String command, @Size(12) String message) {
}
public static final BPFType.BPFStructType<Data> DATA_TYPE = new BPFType.BPFStructType<>("data_t",
List.of(
new BPFType.BPFStructMember<>("pid", BPFType.BPFIntType.INT32, 0, Data::pid),
new BPFType.BPFStructMember<>("uid", BPFType.BPFIntType.INT32, 4, Data::uid),
new BPFType.BPFStructMember<>("command", new BPFType.StringType(16), 8, Data::command),
new BPFType.BPFStructMember<>("message", new BPFType.StringType(12), 24, Data::message)),
new BPFType.AnnotatedClass(Data.class, List.of()),
objects -> new Data((int) objects.get(0), (int) objects.get(1), (String) objects.get(2), (String) objects.get(3)));
public static void main(String[] args) throws InterruptedException {
try (var b = BPF.builder("""
BPF_PERF_OUTPUT(output);
struct data_t {
int pid;
int uid;
char command[16];
char message[12];
};
int hello(void *ctx) {
struct data_t data = {};
char message[12] = "Hello World";
data.pid = bpf_get_current_pid_tgid() >> 32;
data.uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;
bpf_get_current_comm(&data.command, sizeof(data.command));
bpf_probe_read_kernel(&data.message, sizeof(data.message), message);
output.perf_submit(ctx, &data, sizeof(data));
return 0;
}
""").build()) {
var syscall = b.get_syscall_fnname("execve");
b.attach_kprobe(syscall, "hello");
BPFTable.PerfEventArray.EventCallback<Data> print_event = (array, cpu, data, size) -> {
var d = array.event(data);
System.out.printf("%d %d %s %s%n", d.pid(), d.uid(), d.command(), d.message());
};
try (var output = b.get("output", BPFTable.PerfEventArray.<Data>createProvider(DATA_TYPE)).open_perf_buffer(print_event)) {
while (true) {
b.perf_buffer_poll();
}
}
}
}
}