aboutsummaryrefslogtreecommitdiff
path: root/include/opcode/bpf.h
blob: dc1b6e7ae57eb8bbb215d5ce3b79f503e44c3c2f (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
/* bpf.h - BPF opcode list for binutils.
   Copyright (C) 2023 Free Software Foundation, Inc.

   Contributed by Oracle Inc.

   This file is part of the GNU binutils.

   This is free software; you can redistribute them and/or modify them
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYING3. If not,
   see <http://www.gnu.org/licenses/>.  */

#ifndef _BPF_H_
#define _BPF_H_

#include <stdint.h>

/* The BPF ISA has little-endian and big-endian variants.  */

enum bpf_endian
{
  BPF_ENDIAN_LITTLE,
  BPF_ENDIAN_BIG
};

/* Most BPF instructions are conformed by a single 64-bit instruction
   word.  The lddw instruction is conformed by two consecutive 64-bit
   instruction words.  */

typedef uint64_t bpf_insn_word;

/* There are several versions of the BPF ISA.  */

#define BPF_V1 0x1
#define BPF_V2 0x2
#define BPF_V3 0x3
#define BPF_V4 0x4
#define BPF_XBPF 0xff

/* Masks for the several instruction fields in a BPF instruction.
   These assume big-endian BPF instructions.  */

#define BPF_CODE     0xff00000000000000UL
#define BPF_REGS     0x00ff000000000000UL
#define BPF_DST      0x00f0000000000000UL
#define BPF_SRC      0x000f000000000000UL
#define BPF_OFFSET16 0x0000ffff00000000UL
#define BPF_IMM32    0x00000000ffffffffUL

/* The BPF opcode instruction field is eight bits long and its
   interpretation depends on the instruction class.

   For arithmetic and jump instructions the 8-bit opcode field is
   subdivided in:

     op-code:4 op-src:1 op-class:3

   For load/store instructions, the 8-bit opcode field is subdivided
   in:

     op-mode:3 op-size:2 op-class:3

   All the constants defined below are to be applied on the first
   64-bit word of a BPF instruction.  Please define them assuming
   big-endian instructions; the matching and writing routines using
   the instruction table know how to handle the endianness groups.  */

#define BPF_SRC_X ((uint64_t)0x08 << 56)
#define BPF_SRC_K ((uint64_t)0x00 << 56)

#define BPF_CODE_ADD ((uint64_t)0x00 << 56)
#define BPF_CODE_SUB ((uint64_t)0x10 << 56)
#define BPF_CODE_MUL ((uint64_t)0x20 << 56)
#define BPF_CODE_DIV ((uint64_t)0x30 << 56)
#define BPF_CODE_OR  ((uint64_t)0x40 << 56)
#define BPF_CODE_AND ((uint64_t)0x50 << 56)
#define BPF_CODE_LSH ((uint64_t)0x60 << 56)
#define BPF_CODE_RSH ((uint64_t)0x70 << 56)
#define BPF_CODE_NEG ((uint64_t)0x80 << 56)
#define BPF_CODE_MOD ((uint64_t)0x90 << 56)
#define BPF_CODE_XOR ((uint64_t)0xa0 << 56)
#define BPF_CODE_MOV ((uint64_t)0xb0 << 56)
#define BPF_CODE_ARSH ((uint64_t)0xc0 << 56)
#define BPF_CODE_END ((uint64_t)0xd0 << 56)

#define BPF_CODE_JA   ((uint64_t)0x00 << 56)
#define BPF_CODE_JEQ  ((uint64_t)0x10 << 56)
#define BPF_CODE_JGT  ((uint64_t)0x20 << 56)
#define BPF_CODE_JGE  ((uint64_t)0x30 << 56)
#define BPF_CODE_JSET ((uint64_t)0x40 << 56)
#define BPF_CODE_JNE  ((uint64_t)0x50 << 56)
#define BPF_CODE_JSGT ((uint64_t)0x60 << 56)
#define BPF_CODE_JSGE ((uint64_t)0x70 << 56)
#define BPF_CODE_CALL ((uint64_t)0x80 << 56)
#define BPF_CODE_EXIT ((uint64_t)0x90 << 56)
#define BPF_CODE_JLT  ((uint64_t)0xa0 << 56)
#define BPF_CODE_JLE  ((uint64_t)0xb0 << 56)
#define BPF_CODE_JSLT ((uint64_t)0xc0 << 56)
#define BPF_CODE_JSLE ((uint64_t)0xd0 << 56)

#define BPF_MODE_IMM  ((uint64_t)0x00 << 56)
#define BPF_MODE_ABS  ((uint64_t)0x20 << 56)
#define BPF_MODE_IND  ((uint64_t)0x40 << 56)
#define BPF_MODE_MEM  ((uint64_t)0x60 << 56)
#define BPF_MODE_ATOMIC ((uint64_t)0xc0 << 56)
#define BPF_MODE_SMEM ((uint64_t)0x80 << 56)

#define BPF_SIZE_W  ((uint64_t)0x00 << 56)
#define BPF_SIZE_H  ((uint64_t)0x08 << 56)
#define BPF_SIZE_B  ((uint64_t)0x10 << 56)
#define BPF_SIZE_DW ((uint64_t)0x18 << 56)

#define BPF_CLASS_LD    ((uint64_t)0x00 << 56)
#define BPF_CLASS_LDX   ((uint64_t)0x01 << 56)
#define BPF_CLASS_ST    ((uint64_t)0x02 << 56)
#define BPF_CLASS_STX   ((uint64_t)0x03 << 56)
#define BPF_CLASS_ALU   ((uint64_t)0x04 << 56)
#define BPF_CLASS_JMP   ((uint64_t)0x05 << 56)
#define BPF_CLASS_JMP32 ((uint64_t)0x06 << 56)
#define BPF_CLASS_ALU64 ((uint64_t)0x07 << 56)

/* Certain instructions (ab)use other instruction fields as opcodes,
   even if these are multi-byte or infra-byte.  Bleh.  */

#define BPF_OFFSET16_SDIVMOD ((uint64_t)0x1 << 32)
#define BPF_OFFSET16_MOVS8 ((uint64_t)8 << 32)
#define BPF_OFFSET16_MOVS16 ((uint64_t)16 << 32)
#define BPF_OFFSET16_MOVS32 ((uint64_t)32 << 32)

#define BPF_IMM32_END16 ((uint64_t)0x00000010)
#define BPF_IMM32_END32 ((uint64_t)0x00000020)
#define BPF_IMM32_END64 ((uint64_t)0x00000040)

#define BPF_IMM32_AADD ((uint64_t)0x00000000)
#define BPF_IMM32_AOR  ((uint64_t)0x00000040)
#define BPF_IMM32_AAND ((uint64_t)0x00000050)
#define BPF_IMM32_AXOR ((uint64_t)0x000000a0)
#define BPF_IMM32_AFADD ((uint64_t)0x00000001)
#define BPF_IMM32_AFOR  ((uint64_t)0x00000041)
#define BPF_IMM32_AFAND ((uint64_t)0x00000051)
#define BPF_IMM32_AFXOR ((uint64_t)0x000000a1)
#define BPF_IMM32_AXCHG ((uint64_t)0x000000e1)
#define BPF_IMM32_ACMP  ((uint64_t)b0x000000f1)

/* Unique identifiers for BPF instructions.  */

enum bpf_insn_id
{
  BPF_NOINSN = 0,
  /* 64-bit load instruction.  */
  BPF_INSN_LDDW,
  /* ALU instructions.  */
  BPF_INSN_ADDR, BPF_INSN_ADDI, BPF_INSN_SUBR, BPF_INSN_SUBI,
  BPF_INSN_MULR, BPF_INSN_MULI, BPF_INSN_SDIVR, BPF_INSN_SDIVI,
  BPF_INSN_SMODR, BPF_INSN_SMODI, BPF_INSN_DIVR, BPF_INSN_DIVI,
  BPF_INSN_MODR, BPF_INSN_MODI, BPF_INSN_ORR, BPF_INSN_ORI,
  BPF_INSN_ANDR, BPF_INSN_ANDI, BPF_INSN_XORR, BPF_INSN_XORI,
  BPF_INSN_NEGR, BPF_INSN_NEGI, BPF_INSN_LSHR, BPF_INSN_LSHI,
  BPF_INSN_RSHR, BPF_INSN_RSHI, BPF_INSN_ARSHR, BPF_INSN_ARSHI,
  BPF_INSN_MOVS8R, BPF_INSN_MOVS16R, BPF_INSN_MOVS32R,
  BPF_INSN_MOVR, BPF_INSN_MOVI,
  /* ALU32 instructions.  */
  BPF_INSN_ADD32R, BPF_INSN_ADD32I, BPF_INSN_SUB32R, BPF_INSN_SUB32I,
  BPF_INSN_MUL32R, BPF_INSN_MUL32I, BPF_INSN_SDIV32R, BPF_INSN_SDIV32I,
  BPF_INSN_SMOD32R, BPF_INSN_SMOD32I, BPF_INSN_DIV32R, BPF_INSN_DIV32I,
  BPF_INSN_MOD32R, BPF_INSN_MOD32I, BPF_INSN_OR32R, BPF_INSN_OR32I,
  BPF_INSN_AND32R, BPF_INSN_AND32I, BPF_INSN_XOR32R, BPF_INSN_XOR32I,
  BPF_INSN_NEG32R, BPF_INSN_NEG32I, BPF_INSN_LSH32R, BPF_INSN_LSH32I,
  BPF_INSN_RSH32R, BPF_INSN_RSH32I, BPF_INSN_ARSH32R, BPF_INSN_ARSH32I,
  BPF_INSN_MOVS328R, BPF_INSN_MOVS3216R, BPF_INSN_MOVS3232R,
  BPF_INSN_MOV32R, BPF_INSN_MOV32I,
  /* Endianness conversion instructions.  */
  BPF_INSN_ENDLE16, BPF_INSN_ENDLE32, BPF_INSN_ENDLE64,
  BPF_INSN_ENDBE16, BPF_INSN_ENDBE32, BPF_INSN_ENDBE64,
  /* Absolute load instructions.  */
  BPF_INSN_LDABSB, BPF_INSN_LDABSH, BPF_INSN_LDABSW, BPF_INSN_LDABSDW,
  /* Indirect load instructions.  */
  BPF_INSN_LDINDB, BPF_INSN_LDINDH, BPF_INSN_LDINDW, BPF_INSN_LDINDDW,
  /* Generic load instructions (to register.)  */
  BPF_INSN_LDXB, BPF_INSN_LDXH, BPF_INSN_LDXW, BPF_INSN_LDXDW,
  /* Generic signed load instructions.  */
  BPF_INSN_LDXSB, BPF_INSN_LDXSH, BPF_INSN_LDXSW, BPF_INSN_LDXSDW,
  /* Generic store instructions (from register.)  */
  BPF_INSN_STXBR, BPF_INSN_STXHR, BPF_INSN_STXWR, BPF_INSN_STXDWR,
  BPF_INSN_STXBI, BPF_INSN_STXHI, BPF_INSN_STXWI, BPF_INSN_STXDWI,
  /* Compare-and-jump instructions (reg OP reg.)  */
  BPF_INSN_JAR, BPF_INSN_JEQR, BPF_INSN_JGTR, BPF_INSN_JSGTR,
  BPF_INSN_JGER, BPF_INSN_JSGER, BPF_INSN_JLTR, BPF_INSN_JSLTR,
  BPF_INSN_JSLER, BPF_INSN_JLER, BPF_INSN_JSETR, BPF_INSN_JNER,
  BPF_INSN_CALLR, BPF_INSN_CALL, BPF_INSN_EXIT,
  /* Compare-and-jump instructions (reg OP imm.)  */
  BPF_INSN_JEQI, BPF_INSN_JGTI, BPF_INSN_JSGTI,
  BPF_INSN_JGEI, BPF_INSN_JSGEI, BPF_INSN_JLTI, BPF_INSN_JSLTI,
  BPF_INSN_JSLEI, BPF_INSN_JLEI, BPF_INSN_JSETI, BPF_INSN_JNEI,
  /* jump-always with 32-bit offset.  */
  BPF_INSN_JAL,
  /* 32-bit compare-and-jump instructions (reg OP reg.)  */
  BPF_INSN_JEQ32R, BPF_INSN_JGT32R, BPF_INSN_JSGT32R,
  BPF_INSN_JGE32R, BPF_INSN_JSGE32R, BPF_INSN_JLT32R, BPF_INSN_JSLT32R,
  BPF_INSN_JSLE32R, BPF_INSN_JLE32R, BPF_INSN_JSET32R, BPF_INSN_JNE32R,
  /* 32-bit compare-and-jump instructions (reg OP imm.)  */
  BPF_INSN_JEQ32I, BPF_INSN_JGT32I, BPF_INSN_JSGT32I,
  BPF_INSN_JGE32I, BPF_INSN_JSGE32I, BPF_INSN_JLT32I, BPF_INSN_JSLT32I,
  BPF_INSN_JSLE32I, BPF_INSN_JLE32I, BPF_INSN_JSET32I, BPF_INSN_JNE32I,
  /* Atomic instructions.  */
  BPF_INSN_AADD, BPF_INSN_AOR, BPF_INSN_AAND, BPF_INSN_AXOR,
  /* Atomic instructions with fetching.  */
  BPF_INSN_AFADD, BPF_INSN_AFOR, BPF_INSN_AFAND, BPF_INSN_AFXOR,
  /* Atomic instructions (32-bit.)  */
  BPF_INSN_AADD32, BPF_INSN_AOR32, BPF_INSN_AAND32, BPF_INSN_AXOR32,
  /* Atomic instructions with fetching (32-bit.)  */
  BPF_INSN_AFADD32, BPF_INSN_AFOR32, BPF_INSN_AFAND32, BPF_INSN_AFXOR32,
  /* GNU simulator specific instruction.  */
  BPF_INSN_BRKPT,
};

/* Entry for a BPF instruction in the opcodes table.  */

struct bpf_opcode
{
  /* Unique numerical code for the instruction.  */
  enum bpf_insn_id id;

  /* The instruction template defines both the syntax of the
     instruction and the set of the different operands that appear in
     the instruction.

     Tags:
     %% - literal %.
     %dr - destination 64-bit register.
     %dw - destination 32-bit register.
     %sr - source 64-bit register.
     %sw - source 32-bit register.
     %d32 - 32-bit signed displacement (in 64-bit words minus one.)
     %d16 - 16-bit signed displacement (in 64-bit words minus one.)
     %o16 - 16-bit signed offset (in bytes.)
     %i32 - 32-bit signed immediate.
     %I32 - Like %i32.
     %i64 - 64-bit signed immediate.
     %w - expect zero or more white spaces and print a single space.
     %W - expect one or more white spaces and print a single space.

     When parsing and printing %o16 and %I32 (but not %i32) an
     explicit sign is always expected and included.  Therefore, to
     denote something like `[%r3 + 10]', please use a template like `[
     %sr %o16]' instead of `[ %sr + %o16 ]'.
     
     If %dr, %dw, %sr or %sw are found multiple times in a template,
     they refer to the same register, i.e. `%rd = le64 %rd' denotes
     `r2 = le64 r2', but not `r2 = le64 r1'.

     If %i64 appears in a template then the instruction is 128-bits
     long and composed by two consecutive 64-bit instruction words.

     A white space character means to expect zero or more white
     spaces, and to print no space.

     There are two templates defined per instruction, corresponding to
     two used different dialects: a "normal" assembly-like syntax and
     a "pseudo-c" syntax.  Some toolchains support just one of these
     dialects.  The GNU Toolchain supports both.  */
  const char *normal;
  const char *pseudoc;

  /* The version that introduced this instruction.  Instructions are
     generally not removed once they get introduced.  */
  uint8_t version;

  /* Maks marking the opcode fields in the instruction, and the
     opcodes characterizing it.

     In multi-word instructions these apply to the first word in the
     instruction.  Note that these values assumes big-endian
     instructions; code using these field must be aware of the
     endianness groups to which BPF instructions must conform to and
     DTRT.  */
  bpf_insn_word mask;
  bpf_insn_word opcode;
};

/* Try to match a BPF instruction given its first instruction word.
   If no matching instruction is found, return NULL.  */

const struct bpf_opcode *bpf_match_insn (bpf_insn_word word,
                                         enum bpf_endian endian,
                                         int version);

/* Operand extractors.

   These all get big-endian instruction words.  Note how the extractor
   for 64-bit signed immediates requires two instruction words.  */

uint8_t bpf_extract_src (bpf_insn_word word, enum bpf_endian endian);
uint8_t bpf_extract_dst (bpf_insn_word word, enum bpf_endian endian);
int16_t bpf_extract_offset16 (bpf_insn_word word, enum bpf_endian endian);
int32_t bpf_extract_imm32 (bpf_insn_word word, enum bpf_endian endian);
int64_t bpf_extract_imm64 (bpf_insn_word word1, bpf_insn_word word2,
                           enum bpf_endian endian);

/* Get the opcode occupying the INDEX position in the opcodes table.
   The INDEX is zero based.  If the provided index overflows the
   opcodes table then NULL is returned.  */

const struct bpf_opcode *bpf_get_opcode (unsigned int index);

#endif /* !_BPF_H_ */