Coverage Report

Created: 2026-04-29 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/BPF/BPFDisassembler.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* BPF Backend by david942j <david942j@gmail.com>, 2019 */
3
/* SPDX-FileCopyrightText: 2024 Roee Toledano <roeetoledano10@gmail.com> */
4
/* SPDX-License-Identifier: BSD-3 */
5
6
#ifdef CAPSTONE_HAS_BPF
7
8
#include <string.h>
9
#include <stddef.h> // offsetof macro
10
11
#include "BPFConstants.h"
12
#include "BPFDisassembler.h"
13
#include "BPFMapping.h"
14
#include "../../Mapping.h"
15
#include "../../cs_priv.h"
16
#include "../../utils.h"
17
18
///< Malloc bpf_internal, also checks if code_len is large enough.
19
static bpf_internal *alloc_bpf_internal(const size_t code_len)
20
35.2k
{
21
35.2k
  bpf_internal *bpf;
22
23
35.2k
  if (code_len < 8)
24
573
    return NULL;
25
34.6k
  bpf = cs_mem_malloc(sizeof(bpf_internal));
26
34.6k
  if (bpf == NULL)
27
0
    return NULL;
28
  /* default value */
29
34.6k
  bpf->insn_size = 8;
30
34.6k
  return bpf;
31
34.6k
}
32
33
///< Fetch a cBPF structure from code
34
static bpf_internal *fetch_cbpf(MCInst *instr, const uint8_t *code,
35
        const size_t code_len)
36
13.0k
{
37
13.0k
  bpf_internal *bpf;
38
39
13.0k
  bpf = alloc_bpf_internal(code_len);
40
13.0k
  if (bpf == NULL)
41
172
    return NULL;
42
43
12.8k
  bpf->op = readBytes16(instr, code);
44
12.8k
  bpf->jt = code[2];
45
12.8k
  bpf->jf = code[3];
46
12.8k
  bpf->k = readBytes32(instr, code + 4);
47
12.8k
  return bpf;
48
13.0k
}
49
50
///< Fetch an eBPF structure from code
51
static bpf_internal *fetch_ebpf(MCInst *instr, const uint8_t *code,
52
        const size_t code_len)
53
22.1k
{
54
22.1k
  bpf_internal *bpf;
55
56
22.1k
  bpf = alloc_bpf_internal(code_len);
57
22.1k
  if (bpf == NULL)
58
401
    return NULL;
59
60
21.7k
  bpf->op = (uint16_t)code[0];
61
21.7k
  bpf->dst = code[1] & 0xf;
62
21.7k
  bpf->src = (code[1] & 0xf0) >> 4;
63
64
  // eBPF has one 16-byte instruction: BPF_LD | BPF_DW | BPF_IMM,
65
  // in this case imm is combined with the next block's imm.
66
21.7k
  if (bpf->op == (BPF_CLASS_LD | BPF_SIZE_DW | BPF_MODE_IMM)) {
67
533
    if (code_len < 16) {
68
4
      cs_mem_free(bpf);
69
4
      return NULL;
70
4
    }
71
529
    bpf->k = readBytes32(instr, code + 4) |
72
529
       (((uint64_t)readBytes32(instr, code + 12)) << 32);
73
529
    bpf->insn_size = 16;
74
21.2k
  } else {
75
21.2k
    bpf->offset = readBytes16(instr, code + 2);
76
21.2k
    bpf->k = readBytes32(instr, code + 4);
77
21.2k
  }
78
21.7k
  return bpf;
79
21.7k
}
80
81
#define CHECK_READABLE_REG(ud, reg) \
82
11.7k
  do { \
83
11.7k
    if (!((reg) >= BPF_REG_R0 && (reg) <= BPF_REG_R10)) \
84
11.7k
      return false; \
85
11.7k
  } while (0)
86
87
#define CHECK_WRITEABLE_REG(ud, reg) \
88
6.35k
  do { \
89
6.35k
    if (!((reg) >= BPF_REG_R0 && (reg) < BPF_REG_R10)) \
90
6.35k
      return false; \
91
6.35k
  } while (0)
92
93
#define CHECK_READABLE_AND_PUSH(ud, MI, r) \
94
11.7k
  do { \
95
11.7k
    CHECK_READABLE_REG(ud, r + BPF_REG_R0); \
96
11.7k
    MCOperand_CreateReg0(MI, r + BPF_REG_R0); \
97
11.6k
  } while (0)
98
99
#define CHECK_WRITABLE_AND_PUSH(ud, MI, r) \
100
6.35k
  do { \
101
6.35k
    CHECK_WRITEABLE_REG(ud, r + BPF_REG_R0); \
102
6.35k
    MCOperand_CreateReg0(MI, r + BPF_REG_R0); \
103
6.34k
  } while (0)
104
105
static bool decodeLoad(MCInst *MI, bpf_internal *bpf)
106
9.29k
{
107
9.29k
  if (!EBPF_MODE(MI->csh->mode)) {
108
    /*
109
     *  +-----+-----------+--------------------+
110
     *  | ldb |    [k]    |       [x+k]        |
111
     *  | ldh |    [k]    |       [x+k]        |
112
     *  +-----+-----------+--------------------+
113
     */
114
5.47k
    if (BPF_SIZE(bpf->op) == BPF_SIZE_DW)
115
7
      return false;
116
5.46k
    if (BPF_SIZE(bpf->op) == BPF_SIZE_B ||
117
4.62k
        BPF_SIZE(bpf->op) == BPF_SIZE_H) {
118
      /* no ldx */
119
1.68k
      if (BPF_CLASS(bpf->op) != BPF_CLASS_LD)
120
6
        return false;
121
      /* can only be BPF_ABS and BPF_IND */
122
1.68k
      if (BPF_MODE(bpf->op) == BPF_MODE_ABS) {
123
1.04k
        MCOperand_CreateImm0(MI, bpf->k);
124
1.04k
        return true;
125
1.04k
      } else if (BPF_MODE(bpf->op) == BPF_MODE_IND) {
126
633
        MCOperand_CreateReg0(MI, BPF_REG_X);
127
633
        MCOperand_CreateImm0(MI, bpf->k);
128
633
        return true;
129
633
      }
130
4
      return false;
131
1.68k
    }
132
    /*
133
     *  +-----+----+------+------+-----+-------+
134
     *  | ld  | #k | #len | M[k] | [k] | [x+k] |
135
     *  +-----+----+------+------+-----+-------+
136
     *  | ldx | #k | #len | M[k] | 4*([k]&0xf) |
137
     *  +-----+----+------+------+-------------+
138
     */
139
3.78k
    switch (BPF_MODE(bpf->op)) {
140
1.30k
    default:
141
1.30k
      break;
142
1.66k
    case BPF_MODE_IMM:
143
1.66k
      MCOperand_CreateImm0(MI, bpf->k);
144
1.66k
      return true;
145
272
    case BPF_MODE_LEN:
146
272
      return true;
147
539
    case BPF_MODE_MEM:
148
539
      MCOperand_CreateImm0(MI, bpf->k);
149
539
      return true;
150
3.78k
    }
151
1.30k
    if (BPF_CLASS(bpf->op) == BPF_CLASS_LD) {
152
735
      if (BPF_MODE(bpf->op) == BPF_MODE_ABS) {
153
456
        MCOperand_CreateImm0(MI, bpf->k);
154
456
        return true;
155
456
      } else if (BPF_MODE(bpf->op) == BPF_MODE_IND) {
156
277
        MCOperand_CreateReg0(MI, BPF_REG_X);
157
277
        MCOperand_CreateImm0(MI, bpf->k);
158
277
        return true;
159
277
      }
160
735
    } else { /* LDX */
161
569
      if (BPF_MODE(bpf->op) == BPF_MODE_MSH) {
162
568
        MCOperand_CreateImm0(MI, bpf->k);
163
568
        return true;
164
568
      }
165
569
    }
166
3
    return false;
167
1.30k
  }
168
169
  /* eBPF mode */
170
  /*
171
   * - IMM: lddw dst, imm64
172
   * - ABS: ld{w,h,b} [k]
173
   * - IND: ld{w,h,b} [src]
174
   * - MEM: ldx{w,h,b,dw} dst, [src+off]
175
   */
176
3.81k
  if (BPF_CLASS(bpf->op) == BPF_CLASS_LD) {
177
2.63k
    switch (BPF_MODE(bpf->op)) {
178
570
    case BPF_MODE_IMM:
179
570
      if (bpf->op !=
180
570
          (BPF_CLASS_LD | BPF_SIZE_DW | BPF_MODE_IMM))
181
41
        return false;
182
529
      CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst);
183
525
      MCOperand_CreateImm0(MI, bpf->k);
184
525
      return true;
185
1.22k
    case BPF_MODE_ABS:
186
1.22k
      MCOperand_CreateImm0(MI, bpf->k);
187
1.22k
      return true;
188
818
    case BPF_MODE_IND:
189
818
      CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
190
816
      return true;
191
2.63k
    }
192
22
    return false;
193
2.63k
  }
194
  /* LDX */
195
1.18k
  if (BPF_MODE(bpf->op) == BPF_MODE_MEM) {
196
1.17k
    CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst);
197
1.16k
    CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
198
1.16k
    MCOperand_CreateImm0(MI, bpf->offset);
199
1.16k
    return true;
200
1.16k
  }
201
12
  return false;
202
1.18k
}
203
204
static bool decodeStore(MCInst *MI, bpf_internal *bpf)
205
3.84k
{
206
  /* in cBPF, only BPF_ST* | BPF_MEM | BPF_W is valid
207
   * while in eBPF:
208
   * - BPF_STX | BPF_XADD | BPF_{W,DW}
209
   * - BPF_ST* | BPF_MEM | BPF_{W,H,B,DW}
210
   * are valid
211
   */
212
3.84k
  if (!EBPF_MODE(MI->csh->mode)) {
213
    /* can only store to M[] */
214
235
    if (bpf->op != (BPF_CLASS(bpf->op) | BPF_MODE_MEM | BPF_SIZE_W))
215
26
      return false;
216
209
    MCOperand_CreateImm0(MI, bpf->k);
217
209
    return true;
218
235
  }
219
220
  /* eBPF */
221
3.60k
  if (BPF_MODE(bpf->op) == BPF_MODE_ATOMIC) {
222
680
    if (BPF_CLASS(bpf->op) != BPF_CLASS_STX)
223
2
      return false;
224
678
    if (BPF_SIZE(bpf->op) != BPF_SIZE_W &&
225
465
        BPF_SIZE(bpf->op) != BPF_SIZE_DW)
226
3
      return false;
227
    /* xadd [dst + off], src */
228
675
    CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst);
229
670
    MCOperand_CreateImm0(MI, bpf->offset);
230
670
    CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
231
668
    return true;
232
670
  }
233
234
2.92k
  if (BPF_MODE(bpf->op) != BPF_MODE_MEM)
235
28
    return false;
236
237
  /* st [dst + off], src */
238
2.89k
  CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst);
239
2.89k
  MCOperand_CreateImm0(MI, bpf->offset);
240
2.89k
  if (BPF_CLASS(bpf->op) == BPF_CLASS_ST)
241
1.66k
    MCOperand_CreateImm0(MI, bpf->k);
242
1.22k
  else
243
1.22k
    CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
244
2.88k
  return true;
245
2.89k
}
246
247
static bool decodeALU(MCInst *MI, bpf_internal *bpf)
248
6.80k
{
249
  /* Set MI->Operands */
250
251
  /* cBPF */
252
6.80k
  if (!EBPF_MODE(MI->csh->mode)) {
253
2.09k
    if (BPF_OP(bpf->op) > BPF_ALU_XOR)
254
5
      return false;
255
    /* cBPF's NEG has no operands */
256
2.09k
    if (BPF_OP(bpf->op) == BPF_ALU_NEG)
257
262
      return true;
258
1.82k
    if (BPF_SRC(bpf->op) == BPF_SRC_K)
259
826
      MCOperand_CreateImm0(MI, bpf->k);
260
1.00k
    else /* BPF_SRC_X */
261
1.00k
      MCOperand_CreateReg0(MI, BPF_REG_X);
262
1.82k
    return true;
263
2.09k
  }
264
265
  /* eBPF */
266
267
4.71k
  if (BPF_OP(bpf->op) > BPF_ALU_END)
268
13
    return false;
269
  /* ENDian's imm must be one of 16, 32, 64 */
270
4.69k
  if (BPF_OP(bpf->op) == BPF_ALU_END) {
271
421
    if (bpf->k != 16 && bpf->k != 32 && bpf->k != 64)
272
42
      return false;
273
379
    if (BPF_CLASS(bpf->op) == BPF_CLASS_ALU64 &&
274
125
        BPF_SRC(bpf->op) != BPF_SRC_LITTLE)
275
1
      return false;
276
379
  }
277
278
  /* - op dst, imm
279
   * - op dst, src
280
   * - neg dst
281
   * - le<imm> dst
282
   */
283
  /* every ALU instructions have dst op */
284
4.65k
  CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst);
285
286
  /* special cases */
287
4.64k
  if (BPF_OP(bpf->op) == BPF_ALU_NEG)
288
333
    return true;
289
4.31k
  if (BPF_OP(bpf->op) == BPF_ALU_END) {
290
    /* bpf->k must be one of 16, 32, 64 */
291
378
    bpf->op |= ((uint32_t)bpf->k << 4);
292
378
    return true;
293
378
  }
294
295
  /* normal cases */
296
3.93k
  if (BPF_SRC(bpf->op) == BPF_SRC_K) {
297
3.70k
    MCOperand_CreateImm0(MI, bpf->k);
298
3.70k
  } else { /* BPF_SRC_X */
299
237
    CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
300
237
  }
301
3.93k
  return true;
302
3.93k
}
303
304
static bool decodeJump(MCInst *MI, bpf_internal *bpf)
305
5.84k
{
306
  /* cBPF and eBPF are very different in class jump */
307
5.84k
  if (!EBPF_MODE(MI->csh->mode)) {
308
1.06k
    if (BPF_OP(bpf->op) > BPF_JUMP_JSET)
309
6
      return false;
310
311
    /* ja is a special case of jumps */
312
1.06k
    if (BPF_OP(bpf->op) == BPF_JUMP_JA) {
313
223
      MCOperand_CreateImm0(MI, bpf->k);
314
223
      return true;
315
223
    }
316
317
839
    if (BPF_SRC(bpf->op) == BPF_SRC_K)
318
244
      MCOperand_CreateImm0(MI, bpf->k);
319
595
    else /* BPF_SRC_X */
320
595
      MCOperand_CreateReg0(MI, BPF_REG_X);
321
839
    MCOperand_CreateImm0(MI, bpf->jt);
322
839
    MCOperand_CreateImm0(MI, bpf->jf);
323
4.77k
  } else {
324
4.77k
    if (BPF_OP(bpf->op) > BPF_JUMP_JSLE)
325
6
      return false;
326
327
    /* JMP32 has no CALL/EXIT instruction */
328
    /* No operands for exit */
329
4.76k
    if (BPF_OP(bpf->op) == BPF_JUMP_EXIT)
330
101
      return bpf->op == (BPF_CLASS_JMP | BPF_JUMP_EXIT);
331
4.66k
    if (BPF_OP(bpf->op) == BPF_JUMP_CALL) {
332
301
      if (bpf->op == (BPF_CLASS_JMP | BPF_JUMP_CALL)) {
333
262
        MCOperand_CreateImm0(MI, bpf->k);
334
262
        return true;
335
262
      }
336
39
      if (bpf->op ==
337
39
          (BPF_CLASS_JMP | BPF_JUMP_CALL | BPF_SRC_X)) {
338
37
        CHECK_READABLE_AND_PUSH(ud, MI, bpf->k);
339
4
        return true;
340
37
      }
341
2
      return false;
342
39
    }
343
344
    /* ja is a special case of jumps */
345
4.36k
    if (BPF_OP(bpf->op) == BPF_JUMP_JA) {
346
551
      if (BPF_SRC(bpf->op) != BPF_SRC_K)
347
4
        return false;
348
547
      if (BPF_CLASS(bpf->op) == BPF_CLASS_JMP)
349
235
        MCOperand_CreateImm0(MI, bpf->offset);
350
312
      else
351
312
        MCOperand_CreateImm0(MI, bpf->k);
352
353
547
      return true;
354
551
    }
355
356
    /* <j>  dst, src, +off */
357
3.81k
    CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst);
358
3.80k
    if (BPF_SRC(bpf->op) == BPF_SRC_K)
359
3.61k
      MCOperand_CreateImm0(MI, bpf->k);
360
187
    else
361
187
      CHECK_READABLE_AND_PUSH(ud, MI, bpf->src);
362
3.80k
    MCOperand_CreateImm0(MI, bpf->offset);
363
3.80k
  }
364
4.64k
  return true;
365
5.84k
}
366
367
static bool decodeReturn(MCInst *MI, bpf_internal *bpf)
368
1.61k
{
369
  /* Here only handles the BPF_RET class in cBPF */
370
1.61k
  switch (BPF_RVAL(bpf->op)) {
371
797
  case BPF_SRC_K:
372
797
    MCOperand_CreateImm0(MI, bpf->k);
373
797
    return true;
374
439
  case BPF_SRC_X:
375
439
    MCOperand_CreateReg0(MI, BPF_REG_X);
376
439
    return true;
377
372
  case BPF_SRC_A:
378
372
    MCOperand_CreateReg0(MI, BPF_REG_A);
379
372
    return true;
380
1.61k
  }
381
4
  return false;
382
1.61k
}
383
384
static bool decodeMISC(MCInst *MI, bpf_internal *bpf)
385
340
{
386
340
  uint16_t op = bpf->op ^ BPF_CLASS_MISC;
387
340
  return op == BPF_MISCOP_TAX || op == BPF_MISCOP_TXA;
388
340
}
389
390
///< 1. Check if the instruction is valid
391
///< 2. Set MI->opcode
392
///< 3. Set MI->Operands
393
static bool getInstruction(MCInst *MI, bpf_internal *bpf)
394
21.4k
{
395
21.4k
  cs_detail *detail;
396
397
21.4k
  detail = MI->flat_insn->detail;
398
  // initialize detail
399
21.4k
  if (detail) {
400
21.4k
    memset(detail, 0, offsetof(cs_detail, bpf) + sizeof(cs_bpf));
401
21.4k
  }
402
403
21.4k
  MCInst_clear(MI);
404
405
21.4k
  switch (BPF_CLASS(bpf->op)) {
406
0
  default: /* should never happen */
407
0
    return false;
408
4.46k
  case BPF_CLASS_LD:
409
5.43k
  case BPF_CLASS_LDX:
410
5.43k
    return decodeLoad(MI, bpf);
411
1.31k
  case BPF_CLASS_ST:
412
2.22k
  case BPF_CLASS_STX:
413
2.22k
    return decodeStore(MI, bpf);
414
3.64k
  case BPF_CLASS_ALU:
415
3.64k
    return decodeALU(MI, bpf);
416
3.15k
  case BPF_CLASS_JMP:
417
3.15k
    return decodeJump(MI, bpf);
418
3.71k
  case BPF_CLASS_RET:
419
    /* case BPF_CLASS_JMP32: */
420
3.71k
    if (EBPF_MODE(MI->csh->mode))
421
2.68k
      return decodeJump(MI, bpf);
422
1.02k
    else
423
1.02k
      return decodeReturn(MI, bpf);
424
3.29k
  case BPF_CLASS_MISC:
425
    /* case BPF_CLASS_ALU64: */
426
3.29k
    if (EBPF_MODE(MI->csh->mode))
427
3.16k
      return decodeALU(MI, bpf);
428
131
    else
429
131
      return decodeMISC(MI, bpf);
430
21.4k
  }
431
21.4k
}
432
433
// Check for regular load instructions
434
#define REG_LOAD_CASE(c) \
435
4.17k
  case BPF_SIZE_##c: \
436
4.17k
    if (BPF_CLASS(opcode) == BPF_CLASS_LD) \
437
4.17k
      return BPF_INS_LD##c; \
438
4.17k
    else \
439
4.17k
      return BPF_INS_LDX##c;
440
441
static bpf_insn op2insn_ld_cbpf(unsigned opcode)
442
4.17k
{
443
4.17k
  switch (BPF_SIZE(opcode)) {
444
2.28k
    REG_LOAD_CASE(W);
445
699
    REG_LOAD_CASE(H);
446
730
    REG_LOAD_CASE(B);
447
462
    REG_LOAD_CASE(DW);
448
4.17k
  }
449
450
0
  return BPF_INS_INVALID;
451
4.17k
}
452
#undef REG_LOAD_CASE
453
454
// Check for packet load instructions
455
#define PACKET_LOAD_CASE(c) \
456
1.19k
  case BPF_SIZE_##c: \
457
1.19k
    if (BPF_MODE(opcode) == BPF_MODE_ABS) \
458
1.19k
      return BPF_INS_LDABS##c; \
459
1.19k
    else if (BPF_MODE(opcode) == BPF_MODE_IND) \
460
427
      return BPF_INS_LDIND##c; \
461
427
    else \
462
427
      return BPF_INS_INVALID;
463
464
static bpf_insn op2insn_ld_ebpf(unsigned opcode)
465
2.14k
{
466
2.14k
  if (BPF_CLASS(opcode) == BPF_CLASS_LD) {
467
1.52k
    switch (BPF_SIZE(opcode)) {
468
454
      PACKET_LOAD_CASE(W);
469
388
      PACKET_LOAD_CASE(H);
470
351
      PACKET_LOAD_CASE(B);
471
1.52k
    }
472
1.52k
  }
473
474
  // If it's not a packet load instruction, it must be a regular load instruction
475
952
  return op2insn_ld_cbpf(opcode);
476
2.14k
}
477
#undef PACKET_LOAD_CASE
478
479
/* During parsing we already checked to make sure the size is D/DW and 
480
 * mode is STX and not ST, so we don't need to check again*/
481
#define ALU_CASE_REG(c) \
482
89
  case BPF_ALU_##c: \
483
89
    if (BPF_SIZE(opcode) == BPF_SIZE_W) \
484
89
      return BPF_INS_A##c; \
485
89
    else \
486
89
      return BPF_INS_A##c##64;
487
488
#define ALU_CASE_FETCH(c) \
489
166
  case BPF_ALU_##c | BPF_MODE_FETCH: \
490
166
    if (BPF_SIZE(opcode) == BPF_SIZE_W) \
491
166
      return BPF_INS_AF##c; \
492
166
    else \
493
166
      return BPF_INS_AF##c##64;
494
495
#define COMPLEX_CASE(c) \
496
33
  case BPF_ATOMIC_##c | BPF_MODE_FETCH: \
497
33
    if (BPF_SIZE(opcode) == BPF_SIZE_DW) \
498
33
      return BPF_INS_A##c##64; \
499
33
    else \
500
33
      return BPF_INS_INVALID;
501
502
#define CASE(c) \
503
1.87k
  case BPF_SIZE_##c: \
504
1.87k
    if (BPF_CLASS(opcode) == BPF_CLASS_ST) \
505
1.87k
      return BPF_INS_ST##c; \
506
1.87k
    else \
507
1.87k
      return BPF_INS_STX##c;
508
509
static bpf_insn op2insn_st(unsigned opcode, const uint32_t imm)
510
2.17k
{
511
  /*
512
   * - BPF_STX | ALU atomic operations | BPF_{W,DW}
513
   * - BPF_STX | Complex atomic operations | BPF_{DW}
514
   * - BPF_ST* | BPF_MEM | BPF_{W,H,B,DW}
515
   */
516
517
2.17k
  if (BPF_MODE(opcode) == BPF_MODE_ATOMIC) {
518
303
    switch (imm) {
519
34
      ALU_CASE_REG(ADD);
520
16
      ALU_CASE_REG(OR);
521
7
      ALU_CASE_REG(AND);
522
32
      ALU_CASE_REG(XOR);
523
16
      ALU_CASE_FETCH(ADD);
524
50
      ALU_CASE_FETCH(OR);
525
40
      ALU_CASE_FETCH(AND);
526
60
      ALU_CASE_FETCH(XOR);
527
12
      COMPLEX_CASE(XCHG);
528
21
      COMPLEX_CASE(CMPXCHG);
529
15
    default: // Reached if complex atomic operation is used without fetch modifier
530
15
      return BPF_INS_INVALID;
531
303
    }
532
303
  }
533
534
  /* should be BPF_MEM */
535
1.87k
  switch (BPF_SIZE(opcode)) {
536
567
    CASE(W);
537
268
    CASE(H);
538
388
    CASE(B);
539
651
    CASE(DW);
540
1.87k
  }
541
542
0
  return BPF_INS_INVALID;
543
1.87k
}
544
#undef CASE
545
546
#define CASE(c) \
547
5.35k
  case BPF_ALU_##c: \
548
5.35k
    CASE_IF(c)
549
550
#define CASE_IF(c) \
551
6.33k
  do { \
552
6.33k
    if (BPF_CLASS(opcode) == BPF_CLASS_ALU) \
553
6.33k
      return BPF_INS_##c; \
554
6.33k
    else \
555
6.33k
      return BPF_INS_##c##64; \
556
6.33k
  } while (0)
557
558
static bpf_insn op2insn_alu(unsigned opcode, const uint16_t off,
559
          const bool is_ebpf)
560
6.73k
{
561
  /* Endian is a special case */
562
6.73k
  if (BPF_OP(opcode) == BPF_ALU_END) {
563
378
    if (BPF_CLASS(opcode) == BPF_CLASS_ALU64) {
564
124
      switch (opcode ^ BPF_CLASS_ALU64 ^ BPF_ALU_END ^
565
124
        BPF_SRC_LITTLE) {
566
63
      case (16 << 4):
567
63
        return BPF_INS_BSWAP16;
568
50
      case (32 << 4):
569
50
        return BPF_INS_BSWAP32;
570
11
      case (64 << 4):
571
11
        return BPF_INS_BSWAP64;
572
0
      default:
573
0
        return BPF_INS_INVALID;
574
124
      }
575
124
    }
576
577
254
    switch (opcode ^ BPF_CLASS_ALU ^ BPF_ALU_END) {
578
18
    case BPF_SRC_LITTLE | (16 << 4):
579
18
      return BPF_INS_LE16;
580
43
    case BPF_SRC_LITTLE | (32 << 4):
581
43
      return BPF_INS_LE32;
582
40
    case BPF_SRC_LITTLE | (64 << 4):
583
40
      return BPF_INS_LE64;
584
10
    case BPF_SRC_BIG | (16 << 4):
585
10
      return BPF_INS_BE16;
586
3
    case BPF_SRC_BIG | (32 << 4):
587
3
      return BPF_INS_BE32;
588
140
    case BPF_SRC_BIG | (64 << 4):
589
140
      return BPF_INS_BE64;
590
254
    }
591
0
    return BPF_INS_INVALID;
592
254
  }
593
594
6.35k
  switch (BPF_OP(opcode)) {
595
672
    CASE(ADD);
596
307
    CASE(SUB);
597
934
    CASE(MUL);
598
533
    CASE(OR);
599
480
    CASE(AND);
600
429
    CASE(LSH);
601
505
    CASE(RSH);
602
595
    CASE(NEG);
603
388
    CASE(XOR);
604
509
    CASE(ARSH);
605
557
  case BPF_ALU_DIV:
606
557
    if (!is_ebpf || off == 0)
607
276
      CASE_IF(DIV);
608
281
    else if (off == 1)
609
277
      CASE_IF(SDIV);
610
4
    else
611
4
      return BPF_INS_INVALID;
612
337
  case BPF_ALU_MOD:
613
337
    if (!is_ebpf || off == 0)
614
239
      CASE_IF(MOD);
615
98
    else if (off == 1)
616
97
      CASE_IF(SMOD);
617
1
    else
618
1
      return BPF_INS_INVALID;
619
111
  case BPF_ALU_MOV:
620
    /* BPF_CLASS_ALU can have: mov, mov8s, mov16s
621
     * BPF_CLASS_ALU64 can have: mov, mov8s, mov16s, mov32s
622
     * */
623
111
    if (off == 0)
624
30
      CASE_IF(MOV);
625
81
    else if (off == 8)
626
26
      CASE_IF(MOVSB);
627
55
    else if (off == 16)
628
36
      CASE_IF(MOVSH);
629
19
    else if (off == 32 && BPF_CLASS(opcode) == BPF_CLASS_ALU64)
630
3
      return BPF_INS_MOVSW64;
631
16
    else
632
16
      return BPF_INS_INVALID;
633
6.35k
  }
634
635
0
  return BPF_INS_INVALID;
636
6.35k
}
637
#undef CASE_IF
638
#undef CASE
639
640
5.77k
#define BPF_CALLX (BPF_CLASS_JMP | BPF_JUMP_CALL | BPF_SRC_X)
641
642
#define CASE(c) \
643
4.64k
  case BPF_JUMP_##c: \
644
4.64k
    if (BPF_CLASS(opcode) == BPF_CLASS_JMP) \
645
4.64k
      return BPF_INS_##c; \
646
4.64k
    else \
647
4.64k
      return BPF_INS_##c##32;
648
649
#define SPEC_CASE(c) \
650
360
  case BPF_JUMP_##c: \
651
360
    if (BPF_CLASS(opcode) == BPF_CLASS_JMP) \
652
360
      return BPF_INS_##c; \
653
360
    else \
654
360
      return BPF_INS_INVALID;
655
656
static bpf_insn op2insn_jmp(unsigned opcode)
657
5.77k
{
658
5.77k
  if (opcode == BPF_CALLX) {
659
4
    return BPF_INS_CALLX;
660
4
  }
661
662
5.77k
  switch (BPF_OP(opcode)) {
663
770
  case BPF_JUMP_JA:
664
770
    if (BPF_CLASS(opcode) == BPF_CLASS_JMP)
665
458
      return BPF_INS_JA;
666
312
    else
667
312
      return BPF_INS_JAL;
668
431
    CASE(JEQ);
669
505
    CASE(JGT);
670
285
    CASE(JGE);
671
560
    CASE(JSET);
672
122
    CASE(JNE);
673
868
    CASE(JSGT);
674
264
    CASE(JSGE);
675
262
    SPEC_CASE(CALL);
676
98
    SPEC_CASE(EXIT);
677
466
    CASE(JLT);
678
522
    CASE(JLE);
679
444
    CASE(JSLT);
680
173
    CASE(JSLE);
681
5.77k
  }
682
683
0
  return BPF_INS_INVALID;
684
5.77k
}
685
#undef SPEC_CASE
686
#undef CASE
687
#undef BPF_CALLX
688
689
#ifndef CAPSTONE_DIET
690
691
static void update_regs_access(MCInst *MI, cs_detail *detail, bpf_insn insn_id,
692
             unsigned int opcode)
693
21.1k
{
694
21.1k
  if (insn_id == BPF_INS_INVALID)
695
0
    return;
696
  /*
697
   * In eBPF mode, only these instructions have implicit registers access:
698
   * - legacy ld{w,h,b,dw} * // w: r0
699
   * - exit // r: r0
700
   */
701
21.1k
  if (EBPF_MODE(MI->csh->mode)) {
702
13.5k
    switch (insn_id) {
703
11.9k
    default:
704
11.9k
      break;
705
11.9k
    case BPF_INS_LDABSW:
706
521
    case BPF_INS_LDABSH:
707
766
    case BPF_INS_LDABSB:
708
968
    case BPF_INS_LDINDW:
709
1.08k
    case BPF_INS_LDINDH:
710
1.19k
    case BPF_INS_LDINDB:
711
1.52k
    case BPF_INS_LDDW:
712
1.52k
      if (BPF_MODE(opcode) == BPF_MODE_ABS ||
713
752
          BPF_MODE(opcode) == BPF_MODE_IND)
714
1.27k
        map_add_implicit_write(MI, BPF_REG_R0);
715
1.52k
      break;
716
98
    case BPF_INS_EXIT:
717
98
      map_add_implicit_read(MI, BPF_REG_R0);
718
98
      break;
719
13.5k
    }
720
13.5k
    return;
721
13.5k
  }
722
723
  /* cBPF mode */
724
7.61k
  switch (BPF_CLASS(opcode)) {
725
1.02k
  default:
726
1.02k
    break;
727
2.89k
  case BPF_CLASS_LD:
728
2.89k
    map_add_implicit_write(MI, BPF_REG_A);
729
2.89k
    break;
730
326
  case BPF_CLASS_LDX:
731
326
    map_add_implicit_write(MI, BPF_REG_X);
732
326
    break;
733
98
  case BPF_CLASS_ST:
734
98
    map_add_implicit_read(MI, BPF_REG_A);
735
98
    break;
736
18
  case BPF_CLASS_STX:
737
18
    map_add_implicit_read(MI, BPF_REG_X);
738
18
    break;
739
2.09k
  case BPF_CLASS_ALU:
740
2.09k
    map_add_implicit_read(MI, BPF_REG_A);
741
2.09k
    map_add_implicit_write(MI, BPF_REG_A);
742
2.09k
    break;
743
1.06k
  case BPF_CLASS_JMP:
744
1.06k
    if (insn_id != BPF_INS_JA) // except the unconditional jump
745
839
      map_add_implicit_read(MI, BPF_REG_A);
746
1.06k
    break;
747
  /* case BPF_CLASS_RET: */
748
109
  case BPF_CLASS_MISC:
749
109
    if (insn_id == BPF_INS_TAX) {
750
73
      map_add_implicit_read(MI, BPF_REG_A);
751
73
      map_add_implicit_write(MI, BPF_REG_X);
752
73
    } else {
753
36
      map_add_implicit_read(MI, BPF_REG_X);
754
36
      map_add_implicit_write(MI, BPF_REG_A);
755
36
    }
756
109
    break;
757
7.61k
  }
758
7.61k
}
759
#endif
760
761
static bool setFinalOpcode(MCInst *MI, const bpf_internal *bpf)
762
21.1k
{
763
21.1k
  bpf_insn id = BPF_INS_INVALID;
764
21.1k
#ifndef CAPSTONE_DIET
765
21.1k
  cs_detail *detail;
766
767
21.1k
  detail = get_detail(MI);
768
21.1k
#endif
769
770
21.1k
  const uint16_t opcode = bpf->op;
771
21.1k
  switch (BPF_CLASS(opcode)) {
772
0
  default: // will never happen
773
0
    break;
774
4.42k
  case BPF_CLASS_LD:
775
5.36k
  case BPF_CLASS_LDX:
776
5.36k
    if (EBPF_MODE(MI->csh->mode))
777
2.14k
      id = op2insn_ld_ebpf(opcode);
778
3.22k
    else
779
3.22k
      id = op2insn_ld_cbpf(opcode);
780
5.36k
    add_group(MI, BPF_GRP_LOAD);
781
5.36k
    break;
782
1.29k
  case BPF_CLASS_ST:
783
2.17k
  case BPF_CLASS_STX:
784
2.17k
    id = op2insn_st(opcode, bpf->k);
785
2.17k
    add_group(MI, BPF_GRP_STORE);
786
2.17k
    break;
787
3.60k
  case BPF_CLASS_ALU:
788
3.60k
    id = op2insn_alu(opcode, bpf->offset, EBPF_MODE(MI->csh->mode));
789
3.60k
    add_group(MI, BPF_GRP_ALU);
790
3.60k
    break;
791
3.10k
  case BPF_CLASS_JMP:
792
3.10k
    id = op2insn_jmp(opcode);
793
3.10k
#ifndef CAPSTONE_DIET
794
3.10k
    if (id == BPF_INS_CALL || id == BPF_INS_CALLX)
795
266
      add_group(MI, BPF_GRP_CALL);
796
2.83k
    else if (id == BPF_INS_EXIT)
797
98
      add_group(MI, BPF_GRP_RETURN);
798
2.73k
    else
799
2.73k
      add_group(MI, BPF_GRP_JUMP);
800
3.10k
#endif
801
3.10k
    break;
802
3.69k
  case BPF_CLASS_RET:
803
    /* case BPF_CLASS_JMP32: */
804
3.69k
    if (EBPF_MODE(MI->csh->mode)) {
805
2.67k
      id = op2insn_jmp(opcode);
806
2.67k
      add_group(MI, BPF_GRP_JUMP);
807
2.67k
    } else {
808
1.02k
      id = BPF_INS_RET;
809
1.02k
      add_group(MI, BPF_GRP_RETURN);
810
1.02k
    }
811
3.69k
    break;
812
  // BPF_CLASS_MISC and BPF_CLASS_ALU64 have exactly same value
813
3.23k
  case BPF_CLASS_MISC:
814
    /* case BPF_CLASS_ALU64: */
815
3.23k
    if (EBPF_MODE(MI->csh->mode)) {
816
      // ALU64 in eBPF
817
3.12k
      id = op2insn_alu(opcode, bpf->offset, true);
818
3.12k
      add_group(MI, BPF_GRP_ALU);
819
3.12k
    } else {
820
109
      if (BPF_MISCOP(opcode) == BPF_MISCOP_TXA)
821
36
        id = BPF_INS_TXA;
822
73
      else
823
73
        id = BPF_INS_TAX;
824
109
      add_group(MI, BPF_GRP_MISC);
825
109
    }
826
3.23k
    break;
827
21.1k
  }
828
829
21.1k
  if (id == BPF_INS_INVALID)
830
39
    return false;
831
832
21.1k
  MCInst_setOpcodePub(MI, id);
833
21.1k
#undef PUSH_GROUP
834
835
21.1k
#ifndef CAPSTONE_DIET
836
21.1k
  if (detail) {
837
21.1k
    update_regs_access(MI, detail, id, opcode);
838
21.1k
  }
839
21.1k
#endif
840
21.1k
  return true;
841
21.1k
}
842
843
bool BPF_getInstruction(csh ud, const uint8_t *code, size_t code_len,
844
      MCInst *instr, uint16_t *size, uint64_t address,
845
      void *info)
846
21.8k
{
847
21.8k
  bpf_internal *bpf;
848
849
21.8k
  if (EBPF_MODE(instr->csh->mode))
850
14.0k
    bpf = fetch_ebpf(instr, code, code_len);
851
7.79k
  else
852
7.79k
    bpf = fetch_cbpf(instr, code, code_len);
853
21.8k
  if (bpf == NULL)
854
412
    return false;
855
21.4k
  if (!getInstruction(instr, bpf) || !setFinalOpcode(instr, bpf)) {
856
315
    cs_mem_free(bpf);
857
315
    return false;
858
315
  }
859
21.1k
  MCInst_setOpcode(instr, bpf->op);
860
861
21.1k
  *size = bpf->insn_size;
862
21.1k
  cs_mem_free(bpf);
863
864
  return true;
865
21.4k
}
866
867
#endif