aboutsummaryrefslogtreecommitdiffstats
path: root/sys/linux/bpf_prog.txt
blob: 82ae0b217e3fd3193f5adcba0794135b085c8798 (plain)
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
# Copyright 2023 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

include <uapi/linux/bpf.h>
include <uapi/linux/bpf_common.h>

define BPF_LINE_INFO_SIZE	sizeof(struct bpf_line_info)
define BPF_FUNC_INFO_SIZE	sizeof(struct bpf_func_info)
define BPF_CORE_RELO_SIZE	sizeof(struct bpf_core_relo)

type bpf_prog_t[TYPE, ATTACH_TYPE, BTF_ID, PROG_FD] {
	type			TYPE
	ninsn			bytesize8[insns, int32]
	insns			ptr64[in, bpf_instructions]
	license			ptr64[in, string[bpf_licenses]]
	loglev			int32
	logsize			len[log, int32]
	log			ptr64[out, array[int8], opt]
	kern_version		flags[bpf_kern_version, int32]
	flags			flags[bpf_prog_load_flags, int32]
	prog_name		array[const[0, int8], BPF_OBJ_NAME_LEN]
	prog_ifindex		ifindex[opt]
	expected_attach_type	ATTACH_TYPE
	btf_fd			fd_btf[opt]
	func_info_rec_size	const[BPF_FUNC_INFO_SIZE, int32]
	func_info		ptr64[in, bpf_func_info, opt]
	func_info_cnt		len[func_info, int32]
	line_info_rec_size	const[BPF_LINE_INFO_SIZE, int32]
	line_info		ptr64[in, bpf_line_info, opt]
	line_info_cnt		len[line_info, int32]
	attach_btf_id		BTF_ID
	attach_prog_fd		PROG_FD
	core_relo_cnt		len[core_relos, int32]
	fd_array		ptr64[in, array[fd_bpf_map], opt]
	core_relos		ptr64[in, array[bpf_core_relo], opt]
	core_relo_rec_size	const[BPF_CORE_RELO_SIZE, int32]
	log_true_size		int32
	prog_token_fd		fd_bpf_token	(if[value[flags] & BPF_F_TOKEN_FD != 0])
	pad			const[0, int32]	(if[value[flags] & BPF_F_TOKEN_FD == 0])
} [packed]

# These flags should match the mappings in bpf_prog_load_check_attach and attach_type_to_prog_type upstream.
cgroup_sock_attach_types = BPF_CGROUP_INET_SOCK_CREATE, BPF_CGROUP_INET_SOCK_RELEASE, BPF_CGROUP_INET4_POST_BIND, BPF_CGROUP_INET6_POST_BIND
cgroup_sock_addr_attach_types = BPF_CGROUP_INET4_BIND, BPF_CGROUP_INET6_BIND, BPF_CGROUP_INET4_CONNECT, BPF_CGROUP_INET6_CONNECT, BPF_CGROUP_UNIX_CONNECT, BPF_CGROUP_INET4_GETPEERNAME, BPF_CGROUP_INET6_GETPEERNAME, BPF_CGROUP_UNIX_GETPEERNAME, BPF_CGROUP_INET4_GETSOCKNAME, BPF_CGROUP_INET6_GETSOCKNAME, BPF_CGROUP_UNIX_GETSOCKNAME, BPF_CGROUP_UDP4_SENDMSG, BPF_CGROUP_UDP6_SENDMSG, BPF_CGROUP_UNIX_SENDMSG, BPF_CGROUP_UDP4_RECVMSG, BPF_CGROUP_UDP6_RECVMSG, BPF_CGROUP_UNIX_RECVMSG
cgroup_skb_attach_types = BPF_CGROUP_INET_INGRESS, BPF_CGROUP_INET_EGRESS
cgroup_sockopt_attach_types = BPF_CGROUP_SETSOCKOPT, BPF_CGROUP_GETSOCKOPT
sk_lookup_attach_types = BPF_SK_LOOKUP
sk_reuseport_attach_types = BPF_SK_REUSEPORT_SELECT, BPF_SK_REUSEPORT_SELECT_OR_MIGRATE
netfilter_attach_types = BPF_NETFILTER
sock_ops_attach_types = BPF_CGROUP_SOCK_OPS
cgroup_device_attach_types = BPF_CGROUP_DEVICE
sk_msg_attach_types = BPF_SK_MSG_VERDICT
sk_skb_attach_types = BPF_SK_SKB_STREAM_PARSER, BPF_SK_SKB_STREAM_VERDICT, BPF_SK_SKB_VERDICT
lirc_mode2_attach_types = BPF_LIRC_MODE2
flow_dissector_attach_types = BPF_FLOW_DISSECTOR
cgroup_sysctl_attach_types = BPF_CGROUP_SYSCTL
tracing_attach_types = BPF_TRACE_ITER, BPF_TRACE_RAW_TP, BPF_TRACE_FENTRY, BPF_TRACE_FEXIT, BPF_MODIFY_RETURN
lsm_attach_types = BPF_LSM_MAC, BPF_LSM_CGROUP
xdp_attach_types = BPF_XDP
sched_cls_attach_types = BPF_TCX_INGRESS, BPF_TCX_EGRESS, BPF_NETKIT_PRIMARY, BPF_NETKIT_PEER

bpf_prog_attach_types [
	cgroup_sock		flags[cgroup_sock_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_CGROUP_SOCK])
	cgroup_sock_addr	flags[cgroup_sock_addr_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_CGROUP_SOCK_ADDR])
	cgroup_skb		flags[cgroup_skb_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_CGROUP_SKB])
	cgroup_sockopt		flags[cgroup_sockopt_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_CGROUP_SOCKOPT])
	sk_lookup		flags[sk_lookup_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_SK_LOOKUP])
	sk_reuseport		flags[sk_reuseport_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_SK_REUSEPORT])
	netfilter		flags[netfilter_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_NETFILTER])
	sock_ops		flags[sock_ops_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_SOCK_OPS])
	cgroup_device		flags[cgroup_device_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_CGROUP_DEVICE])
	sk_msg			flags[sk_msg_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_SK_MSG])
	sk_skb			flags[sk_skb_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_SK_SKB])
	lirc_mode2		flags[lirc_mode2_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_LIRC_MODE2])
	flow_dissector		flags[flow_dissector_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_FLOW_DISSECTOR])
	cgroup_sysctl		flags[cgroup_sysctl_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_CGROUP_SYSCTL])
	tracing			flags[tracing_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_TRACING])
	lsm			flags[lsm_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_LSM])
	xdp			flags[xdp_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_XDP])
	sched_cls		flags[sched_cls_attach_types, int32]	(if[value[bpf_prog_t:type] == BPF_PROG_TYPE_SCHED_CLS])
	fallback		flags[bpf_attach_types, int32]
]

type bpf_prog bpf_prog_t[flags[bpf_prog_type, int32], bpf_prog_attach_types, bpf_btf_id[opt], fd_bpf_prog[opt]]

bpf_licenses = "GPL", "syzkaller"
bpf_kern_version = 0x40f00, 0x41000, 0x41100

bpf_func_info {
# This is instruction index, so should not be too large.
	insn_off	int32[0:10]
	type_id		btf_type_id
}

bpf_line_info {
# This is instruction index, so should not be too large.
	insn_off	int32[0:5]
	file_name_off	btf_opt_name_off
	line_off	int32
	line_col	int32
}

bpf_core_relo {
# This is instruction index, so should not be too large.
	insn_off	int32[0:5]
	type_id		btf_type_id
	access_str_off	btf_opt_name_off
	kind		flags[bpf_core_relo_kind, int32]
}

bpf_instructions [
	raw	array[bpf_insn]
	framed	bpf_framed_program
	ringbuf	bpf_program_ringbuf
] [varlen]

bpf_framed_program {
	initr0	bpf_insn_init_r0
	body	array[bpf_insn]
	exit	bpf_insn_exit
} [packed]

bpf_program_ringbuf {
	initr0		bpf_insn_init_r0
	reserve		bpf_insn_ringbuf_reserve
	null_check	bpf_insn_null_check[BPF_REG_9]
	body		array[bpf_insn]
	free		bpf_insn_ringbuf_free
	exit		bpf_insn_exit
} [packed]

bpf_insn [
	generic		bpf_insn_generic
	ldst		bpf_insn_ldst
	alu		bpf_insn_alu
	jmp		bpf_insn_jmp
	call		bpf_insn_call_helper
	func		bpf_insn_call_func
	kfunc		bpf_insn_call_kfunc
	exit		bpf_insn_exit
	initr0		bpf_insn_init_r0
	map_fd		bpf_insn_map_fd
	map_idx		bpf_insn_map_idx
	map_val		bpf_insn_map_value
	map_idx_val	bpf_insn_map_idx_value
	btf_id		bpf_insn_btf_id
	cb_func		bpf_insn_cb_func
	printk		bpf_insn_trace_printk
	snprintf	bpf_insn_snprintf
	tail_call	bpf_insn_tail_call
	ringbuf_query	bpf_insn_ringbuf_query
	ringbuf_output	bpf_insn_ringbuf_output
] [varlen]

bpf_insn_generic {
	code	int8
	dst	int8:4
	src	int8:4
	off	int16
	imm	int32
}

type bpf_insn_ldst_t[CLASS, SZ, MODE, DST, SRC, OFF, IMM] {
	code_class	int8:3[CLASS]
	code_size	int8:2[SZ]
	code_mode	int8:3[MODE]
	dst		DST
	src		SRC
	off		OFF
	imm		IMM
}

type bpf_insn_ldst bpf_insn_ldst_t[bpf_ldst_insn, bpf_ldst_size, bpf_ldst_mode, flags[bpf_reg, int8:4], flags[bpf_reg, int8:4], flags[bpf_insn_offsets, int16], flags[bpf_insn_immediates, int32]]
type bpf_insn_st64_reg[SRC, DST, OFF] bpf_insn_ldst_t[BPF_STX, BPF_DW0, BPF_MEM0, const[DST, int8:4], const[SRC, int8:4], const[OFF, int16], const[0, int32]]

bpf_ldst_insn = BPF_LD, BPF_LDX, BPF_ST, BPF_STX
bpf_ldst_size = BPF_W0, BPF_H0, BPF_B0, BPF_DW0
bpf_ldst_mode = BPF_IMM0, BPF_ABS0, BPF_IND0, BPF_MEM0, BPF_XADD0, BPF_MEMSX0

define BPF_W0	BPF_W >> 3
define BPF_H0	BPF_H >> 3
define BPF_B0	BPF_B >> 3
define BPF_DW0	BPF_DW >> 3

define BPF_IMM0	BPF_IMM >> 5
define BPF_ABS0	BPF_ABS >> 5
define BPF_IND0	BPF_IND >> 5
define BPF_MEM0	BPF_MEM >> 5
define BPF_XADD0	BPF_XADD >> 5
define BPF_MEMSX0	BPF_MEMSX >> 5

type bpf_insn_alu_t[CLASS, SOURCE, OP, DST, SRC, OFF, IMM] {
	code_class	int8:3[CLASS]
	code_s		int8:1[SOURCE]
	code_op		int8:4[OP]
	dst		DST
	src		SRC
	off		OFF
	imm		IMM
}

type bpf_insn_alu bpf_insn_alu_t[bpf_alu_insn, bpf_alu_source, bpf_alu_op, flags[bpf_reg, int8:4], flags[bpf_reg, int8:4], flags[bpf_insn_offsets, int16], flags[bpf_insn_immediates, int32]]
type bpf_insn_mov_imm[DST, IMM] bpf_insn_alu_t[BPF_ALU64, BPF_K0, BPF_MOV0, const[DST, int8:4], const[0, int8:4], const[0, int16], const[IMM, int32]]
type bpf_insn_mov_imm_any[DST] bpf_insn_alu_t[BPF_ALU64, BPF_K0, BPF_MOV0, const[DST, int8:4], const[0, int8:4], const[0, int16], int32]
type bpf_insn_mov_imm_flag[DST, FLAG] bpf_insn_alu_t[BPF_ALU64, BPF_K0, BPF_MOV0, const[DST, int8:4], const[0, int8:4], const[0, int16], flags[FLAG, int32]]
type bpf_insn_mov_reg[SRC, DST] bpf_insn_alu_t[BPF_ALU64, BPF_X0, BPF_MOV0, const[DST, int8:4], const[SRC, int8:4], const[0, int16], const[0, int32]]
type bpf_insn_op_imm[DST, OP, IMM] bpf_insn_alu_t[BPF_ALU64, BPF_K0, OP, const[DST, int8:4], const[0, int8:4], const[0, int16], const[IMM, int32]]

bpf_alu_source = BPF_K0, BPF_X0
bpf_alu_insn = BPF_ALU, BPF_ALU64
bpf_alu_op = BPF_ADD0, BPF_SUB0, BPF_MUL0, BPF_DIV0, BPF_OR0, BPF_AND0, BPF_LSH0, BPF_RSH0, BPF_NEG0, BPF_MOD0, BPF_XOR0, BPF_MOV0, BPF_ARSH0, BPF_END0

define BPF_ADD0	BPF_ADD >> 4
define BPF_SUB0	BPF_SUB >> 4
define BPF_MUL0	BPF_MUL >> 4
define BPF_DIV0	BPF_DIV >> 4
define BPF_OR0	BPF_OR >> 4
define BPF_AND0	BPF_AND >> 4
define BPF_LSH0	BPF_LSH >> 4
define BPF_RSH0	BPF_RSH >> 4
define BPF_NEG0	BPF_NEG >> 4
define BPF_MOD0	BPF_MOD >> 4
define BPF_XOR0	BPF_XOR >> 4
define BPF_MOV0	BPF_MOV >> 4
define BPF_ARSH0	BPF_ARSH >> 4
define BPF_END0	BPF_END >> 4

define BPF_K0	BPF_K >> 3
define BPF_X0	BPF_X >> 3

bpf_insn_jmp {
	code_class	const[BPF_JMP, int8:3]
	code_s		int8:1
	code_op		flags[bpf_jmp_op, int8:4]
	dst		flags[bpf_reg, int8:4]
	src		flags[bpf_reg, int8:4]
	off		flags[bpf_insn_offsets, int16]
	imm		flags[bpf_insn_immediates, int32]
}

# Equivalent to: if reg != 0 goto +1;
type bpf_insn_not_null_jmp[REG] {
	code_class	const[BPF_JMP, int8:3]
	code_s		const[BPF_K0, int8:1]
	code_op		const[BPF_JNE0, int8:4]
	dst		const[REG, int8:4]
	src		const[0, int8:4]
	off		const[1, int16]
	imm		const[0, int32]
}

bpf_jmp_op = BPF_JA0, BPF_JEQ0, BPF_JGT0, BPF_JGE0, BPF_JSET0, BPF_JNE0, BPF_JSGT0, BPF_JSGE0, BPF_CALL0, BPF_EXIT0, BPF_JLT0, BPF_JLE0, BPF_JSLT0, BPF_JSLE0

define BPF_JA0	BPF_JA >> 4
define BPF_JEQ0	BPF_JEQ >> 4
define BPF_JGT0	BPF_JGT >> 4
define BPF_JGE0	BPF_JGE >> 4
define BPF_JSET0	BPF_JSET >> 4
define BPF_JNE0	BPF_JNE >> 4
define BPF_JSGT0	BPF_JSGT >> 4
define BPF_JSGE0	BPF_JSGE >> 4
define BPF_CALL0	BPF_CALL >> 4
define BPF_EXIT0	BPF_EXIT >> 4
define BPF_JLT0	BPF_JLT >> 4
define BPF_JLE0	BPF_JLE >> 4
define BPF_JSLT0	BPF_JSLT >> 4
define BPF_JSLE0	BPF_JSLE >> 4

type bpf_insn_call_helper_t[FUNC] {
	code	const[bpf_call_code, int8]
	regs	const[0, int8]
	off	const[0, int16]
	func	FUNC
}

type bpf_insn_call_helper bpf_insn_call_helper_t[int32[0:__BPF_FUNC_MAX_ID]]

bpf_insn_call_func {
	code	const[bpf_call_code, int8]
	dst	const[0, int8:4]
	src	const[BPF_PSEUDO_CALL, int8:4]
	off	const[0, int16]
# NEED: to limit the call offset to the program size, we'd need support for path expressions inside ranges of values.
	func	int32[-8:8]
}

bpf_insn_call_kfunc {
	code	const[bpf_call_code, int8]
	dst	const[0, int8:4]
	src	const[BPF_PSEUDO_KFUNC_CALL, int8:4]
	off	const[0, int16]
	kfunc	btf_type_id
}

define bpf_call_code	BPF_JMP | BPF_CALL

bpf_insn_exit {
	code	const[bpf_exit_code, int8]
	regs	const[0, int8]
	off	const[0, int16]
	imm	const[0, int32]
}

define bpf_exit_code	BPF_JMP | BPF_EXIT

bpf_insn_init_r0 {
	code	const[bpf_insn_load_imm_dw, int8]
	dst	const[BPF_REG_0, int8:4]
	src	const[0, int8:4]
	off	const[0, int16]
	imm	int32
	code2	const[0, int8]
	regs2	const[0, int8]
	off2	const[0, int16]
	imm2	int32
}

type bpf_insn_mov_imm64[DST, IMM1, IMM2] {
	code	const[bpf_insn_load_imm_dw, int8]
	dst	const[DST, int8:4]
	src	const[0, int8:4]
	off	const[0, int16]
	imm	const[IMM1, int32]
	code2	const[0, int8]
	regs2	const[0, int8]
	off2	const[0, int16]
	imm2	const[IMM2, int32]
}

type bpf_insn_map_fd_t[DST, MAP_FD] {
	code	const[bpf_insn_load_imm_dw, int8]
	dst	DST
	src	const[BPF_PSEUDO_MAP_FD, int8:4]
	off	const[0, int16]
	imm	MAP_FD
	code2	const[0, int8]
	regs2	const[0, int8]
	off2	const[0, int16]
	imm2	const[0, int32]
}

type bpf_insn_map_fd bpf_insn_map_fd_t[flags[bpf_reg, int8:4], fd_bpf_map]
type bpf_insn_tail_call_map_fd[DST] bpf_insn_map_fd_t[const[DST, int8:4], tail_call_map]
type bpf_insn_ringbuf_fd[DST] bpf_insn_map_fd_t[const[DST, int8:4], ringbuf_map_fd]

bpf_insn_map_idx {
	code	const[bpf_insn_load_imm_dw, int8]
	dst	flags[bpf_reg, int8:4]
	src	const[BPF_PSEUDO_MAP_IDX, int8:4]
	off	const[0, int16]
	imm	map_fd_id
	code2	const[0, int8]
	regs2	const[0, int8]
	off2	const[0, int16]
	imm2	const[0, int32]
}

type bpf_insn_map_value_t[DST, MAP_FD, VALUE_OFFSET] {
	code	const[bpf_insn_load_imm_dw, int8]
	dst	DST
	src	const[BPF_PSEUDO_MAP_VALUE, int8:4]
	off	const[0, int16]
	imm	MAP_FD
	code2	const[0, int8]
	regs2	const[0, int8]
	off2	const[0, int16]
	imm2	VALUE_OFFSET
}

type bpf_insn_map_value bpf_insn_map_value_t[flags[bpf_reg, int8:4], fd_bpf_map, int32]
type bpf_insn_const_str[DST] bpf_insn_map_value_t[const[DST, int8:4], bpf_frozen_const_str, const[0, int32]]

bpf_insn_map_idx_value {
	code	const[bpf_insn_load_imm_dw, int8]
	dst	flags[bpf_reg, int8:4]
	src	const[BPF_PSEUDO_MAP_IDX_VALUE, int8:4]
	off	const[0, int16]
	imm	map_fd_id
	code2	const[0, int8]
	regs2	const[0, int8]
	off2	const[0, int16]
	imm2	int32
}

bpf_insn_cb_func {
	code	const[bpf_insn_load_imm_dw, int8]
	dst	flags[bpf_reg, int8:4]
	src	const[BPF_PSEUDO_FUNC, int8:4]
	off	const[0, int16]
# NEED: to limit the call offset to the program size, we'd need support for path expressions inside ranges of values.
	imm	int32[-8:8]
	code2	const[0, int8]
	regs2	const[0, int8]
	off2	const[0, int16]
	imm2	const[0, int32]
}

bpf_insn_btf_id {
	code	const[bpf_insn_load_imm_dw, int8]
	dst	flags[bpf_reg, int8:4]
	src	const[BPF_PSEUDO_BTF_ID, int8:4]
	off	const[0, int16]
	imm	btf_type_id
	code2	const[0, int8]
	regs2	const[0, int8]
	off2	const[0, int16]
	imm2	const[0, int32]
}

define bpf_insn_load_imm_dw	BPF_LD | BPF_DW | BPF_IMM

# Slightly prune state space, these values frequently must be 0.
bpf_insn_offsets = 0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 80, 128, 256, -1, -2, -4, -8, -12, -16, -32, -64
bpf_insn_immediates = 0, 1, 4, 8, 16, -1, -4, -16
bpf_reg = BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5, BPF_REG_6, BPF_REG_7, BPF_REG_8, BPF_REG_9, BPF_REG_10, __MAX_BPF_REG

# Equivalent to:
# if reg != 0 goto +1;
# exit;
# This is useful to check null pointers. We exit if the pointer is null and
# continue the normal flow otherwise.
type bpf_insn_null_check[REG] {
	cond_jump	bpf_insn_not_null_jmp[REG]
	exit		bpf_insn_exit
}

# Format specifiers for bpf_trace_printk, encoded as a zero-terminated string
# of 7 characters. For example, field 'p' corresponds to "%p     ".
type bpf_insn_mov_printk_str_hex[DST] [
	p	bpf_insn_mov_imm64[DST, 0x25702020, 0x20202000]
	d	bpf_insn_mov_imm64[DST, 0x25642020, 0x20202000]
	i	bpf_insn_mov_imm64[DST, 0x25692020, 0x20202000]
	u	bpf_insn_mov_imm64[DST, 0x25752020, 0x20202000]
	x	bpf_insn_mov_imm64[DST, 0x25782020, 0x20202000]
	ld	bpf_insn_mov_imm64[DST, 0x256c6420, 0x20202000]
	li	bpf_insn_mov_imm64[DST, 0x256c6920, 0x20202000]
	lu	bpf_insn_mov_imm64[DST, 0x256c7520, 0x20202000]
	lx	bpf_insn_mov_imm64[DST, 0x256c7820, 0x20202000]
	lld	bpf_insn_mov_imm64[DST, 0x256c6c64, 0x20202000]
	lli	bpf_insn_mov_imm64[DST, 0x256c6c69, 0x20202000]
	llu	bpf_insn_mov_imm64[DST, 0x256c6c75, 0x20202000]
	llx	bpf_insn_mov_imm64[DST, 0x256c6c78, 0x20202000]
	s	bpf_insn_mov_imm64[DST, 0x25732020, 0x20202000]
]

# (18) r1 = "%d     "
# (7b) *(u64 *)(r10 -8) = r1
# (bf) r1 = r10
# (07) r1 += -8
# (b7) r2 = 8
# (b7) r3 = X
# (85) call bpf_trace_printk#-108352
bpf_insn_trace_printk {
	insn1	bpf_insn_mov_printk_str_hex[BPF_REG_1]
	insn2	bpf_insn_st64_reg[BPF_REG_1, BPF_REG_10, -8]
	insn3	bpf_insn_mov_reg[BPF_REG_10, BPF_REG_1]
	insn4	bpf_insn_op_imm[BPF_REG_1, BPF_ADD0, -8]
	insn5	bpf_insn_mov_imm[BPF_REG_2, 8]
	insn6	bpf_insn_mov_imm_any[BPF_REG_3]
	insn7	bpf_insn_call_helper_t[const[BPF_FUNC_trace_printk, int32]]
}

# (b7) r8 = 0
# (7b) *(u64 *)(r10 -8) = r8
# (b7) r8 = X
# (7b) *(u64 *)(r10 -16) = r8
# (bf) r1 = r10
# (07) r1 += -8
# (bf) r4 = r10
# (07) r4 += -16
# (b7) r2 = 8
# (18) r3 = map[id:31][0]+0
# (b7) r5 = 8
# (85) call bpf_snprintf#168880
bpf_insn_snprintf {
	insn1	bpf_insn_mov_imm[BPF_REG_8, 0]
	insn2	bpf_insn_st64_reg[BPF_REG_8, BPF_REG_10, -8]
	insn3	bpf_insn_mov_imm_any[BPF_REG_8]
	insn4	bpf_insn_st64_reg[BPF_REG_8, BPF_REG_10, -16]
	insn5	bpf_insn_mov_reg[BPF_REG_10, BPF_REG_1]
	insn6	bpf_insn_op_imm[BPF_REG_1, BPF_ADD0, -8]
	insn7	bpf_insn_mov_reg[BPF_REG_10, BPF_REG_4]
	insn8	bpf_insn_op_imm[BPF_REG_4, BPF_ADD0, -16]
	insn9	bpf_insn_mov_imm[BPF_REG_2, 8]
	insn10	bpf_insn_const_str[BPF_REG_3]
	insn11	bpf_insn_mov_imm[BPF_REG_5, 8]
	insn12	bpf_insn_call_helper_t[const[BPF_FUNC_snprintf, int32]]
}

# (18) r2 = map[id:10]
# (b7) r3 = 2
# (85) call bpf_tail_call#12
# (b7) r0 = 0
bpf_insn_tail_call {
	insn1	bpf_insn_tail_call_map_fd[BPF_REG_2]
	insn2	bpf_insn_mov_imm[BPF_REG_3, 0]
	insn3	bpf_insn_call_helper_t[const[BPF_FUNC_tail_call, int32]]
	insn4	bpf_insn_mov_imm[BPF_REG_0, 0]
}

# (18) r1 = map[id:16]
# (b7) r2 = 8
# (b7) r3 = 0
# (85) call bpf_ringbuf_reserve#320112
# (bf) r9 = r0
bpf_insn_ringbuf_reserve {
	insn1	bpf_insn_ringbuf_fd[BPF_REG_1]
	insn2	bpf_insn_mov_imm[BPF_REG_2, 20]
	insn3	bpf_insn_mov_imm[BPF_REG_3, 0]
	insn4	bpf_insn_call_helper_t[const[BPF_FUNC_ringbuf_reserve, int32]]
	insn5	bpf_insn_mov_reg[BPF_REG_0, BPF_REG_9]
}

# (bf) r1 = r9
# (b7) r2 = BPF_RB_X
# (85) call bpf_ringbuf_{submit,discard}#322192
# (bf) r0 = 0
bpf_insn_ringbuf_free {
	insn1	bpf_insn_mov_reg[BPF_REG_9, BPF_REG_1]
	insn2	bpf_insn_mov_imm_flag[BPF_REG_2, bpf_ringbuf_wakeup_flags]
	insn3	bpf_insn_call_helper_t[flags[bpf_helpers_ringbuf_free, int32]]
	insn4	bpf_insn_mov_imm[BPF_REG_0, 0]
}

bpf_helpers_ringbuf_free = BPF_FUNC_ringbuf_submit, BPF_FUNC_ringbuf_discard

# (18) r1 = map[id:16]
# (b7) r2 = 0
# (85) call bpf_ringbuf_query#322192
bpf_insn_ringbuf_query {
	insn1	bpf_insn_tail_call_map_fd[BPF_REG_1]
	insn2	bpf_insn_mov_imm[BPF_REG_2, 0]
	insn3	bpf_insn_call_helper_t[const[BPF_FUNC_ringbuf_query, int32]]
}

# (18) r1 = map[id:16]
# (b7) r8 = X
# (7b) *(u64 *)(r10 -8) = r8
# (bf) r2 = r10
# (07) r2 += -8
# (b7) r3 = 8
# (b7) r4 = BPF_RB_X
# (85) call bpf_ringbuf_output#322192
bpf_insn_ringbuf_output {
	insn1	bpf_insn_tail_call_map_fd[BPF_REG_1]
	insn2	bpf_insn_mov_imm_any[BPF_REG_8]
	insn3	bpf_insn_st64_reg[BPF_REG_8, BPF_REG_10, -8]
	insn4	bpf_insn_mov_reg[BPF_REG_10, BPF_REG_2]
	insn5	bpf_insn_op_imm[BPF_REG_2, BPF_ADD0, -8]
	insn6	bpf_insn_mov_imm[BPF_REG_3, 8]
	insn7	bpf_insn_mov_imm_flag[BPF_REG_4, bpf_ringbuf_wakeup_flags]
	insn8	bpf_insn_call_helper_t[const[BPF_FUNC_ringbuf_output, int32]]
}

define MAX_BPF_REG	__MAX_BPF_REG

bpf_ringbuf_wakeup_flags = 0, BPF_RB_NO_WAKEUP, BPF_RB_FORCE_WAKEUP