/src/capstonenext/arch/BPF/BPFDisassembler.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Capstone Disassembly Engine */ |
2 | | /* BPF Backend by david942j <david942j@gmail.com>, 2019 */ |
3 | | |
4 | | #ifdef CAPSTONE_HAS_BPF |
5 | | |
6 | | #include <string.h> |
7 | | #include <stddef.h> // offsetof macro |
8 | | |
9 | | #include "BPFConstants.h" |
10 | | #include "BPFDisassembler.h" |
11 | | #include "BPFMapping.h" |
12 | | #include "../../cs_priv.h" |
13 | | |
14 | | static uint16_t read_u16(cs_struct *ud, const uint8_t *code) |
15 | 92.0k | { |
16 | 92.0k | if (MODE_IS_BIG_ENDIAN(ud->mode)) |
17 | 41.5k | return (((uint16_t)code[0] << 8) | code[1]); |
18 | 50.5k | else |
19 | 50.5k | return (((uint16_t)code[1] << 8) | code[0]); |
20 | 92.0k | } |
21 | | |
22 | | static uint32_t read_u32(cs_struct *ud, const uint8_t *code) |
23 | 31.2k | { |
24 | 31.2k | if (MODE_IS_BIG_ENDIAN(ud->mode)) |
25 | 14.1k | return ((uint32_t)read_u16(ud, code) << 16) | read_u16(ud, code + 2); |
26 | 17.1k | else |
27 | 17.1k | return ((uint32_t)read_u16(ud, code + 2) << 16) | read_u16(ud, code); |
28 | 31.2k | } |
29 | | |
30 | | ///< Malloc bpf_internal, also checks if code_len is large enough. |
31 | | static bpf_internal *alloc_bpf_internal(size_t code_len) |
32 | 30.7k | { |
33 | 30.7k | bpf_internal *bpf; |
34 | | |
35 | 30.7k | if (code_len < 8) |
36 | 396 | return NULL; |
37 | 30.3k | bpf = cs_mem_malloc(sizeof(bpf_internal)); |
38 | 30.3k | if (bpf == NULL) |
39 | 0 | return NULL; |
40 | | /* default value */ |
41 | 30.3k | bpf->insn_size = 8; |
42 | 30.3k | return bpf; |
43 | 30.3k | } |
44 | | |
45 | | ///< Fetch a cBPF structure from code |
46 | | static bpf_internal* fetch_cbpf(cs_struct *ud, const uint8_t *code, |
47 | | size_t code_len) |
48 | 13.9k | { |
49 | 13.9k | bpf_internal *bpf; |
50 | | |
51 | 13.9k | bpf = alloc_bpf_internal(code_len); |
52 | 13.9k | if (bpf == NULL) |
53 | 165 | return NULL; |
54 | | |
55 | 13.7k | bpf->op = read_u16(ud, code); |
56 | 13.7k | bpf->jt = code[2]; |
57 | 13.7k | bpf->jf = code[3]; |
58 | 13.7k | bpf->k = read_u32(ud, code + 4); |
59 | 13.7k | return bpf; |
60 | 13.9k | } |
61 | | |
62 | | ///< Fetch an eBPF structure from code |
63 | | static bpf_internal* fetch_ebpf(cs_struct *ud, const uint8_t *code, |
64 | | size_t code_len) |
65 | 16.8k | { |
66 | 16.8k | bpf_internal *bpf; |
67 | | |
68 | 16.8k | bpf = alloc_bpf_internal(code_len); |
69 | 16.8k | if (bpf == NULL) |
70 | 231 | return NULL; |
71 | | |
72 | 16.5k | bpf->op = (uint16_t)code[0]; |
73 | 16.5k | bpf->dst = code[1] & 0xf; |
74 | 16.5k | bpf->src = (code[1] & 0xf0) >> 4; |
75 | | |
76 | | // eBPF has one 16-byte instruction: BPF_LD | BPF_DW | BPF_IMM, |
77 | | // in this case imm is combined with the next block's imm. |
78 | 16.5k | if (bpf->op == (BPF_CLASS_LD | BPF_SIZE_DW | BPF_MODE_IMM)) { |
79 | 931 | if (code_len < 16) { |
80 | 3 | cs_mem_free(bpf); |
81 | 3 | return NULL; |
82 | 3 | } |
83 | 928 | bpf->k = read_u32(ud, code + 4) | (((uint64_t)read_u32(ud, code + 12)) << 32); |
84 | 928 | bpf->insn_size = 16; |
85 | 928 | } |
86 | 15.6k | else { |
87 | 15.6k | bpf->offset = read_u16(ud, code + 2); |
88 | 15.6k | bpf->k = read_u32(ud, code + 4); |
89 | 15.6k | } |
90 | 16.5k | return bpf; |
91 | 16.5k | } |
92 | | |
93 | 9.66k | #define CHECK_READABLE_REG(ud, reg) do { \ |
94 | 9.66k | if (! ((reg) >= BPF_REG_R0 && (reg) <= BPF_REG_R10)) \ |
95 | 9.66k | return false; \ |
96 | 9.66k | } while (0) |
97 | | |
98 | 4.68k | #define CHECK_WRITABLE_REG(ud, reg) do { \ |
99 | 4.68k | if (! ((reg) >= BPF_REG_R0 && (reg) < BPF_REG_R10)) \ |
100 | 4.68k | return false; \ |
101 | 4.68k | } while (0) |
102 | | |
103 | 9.66k | #define CHECK_READABLE_AND_PUSH(ud, MI, r) do { \ |
104 | 9.66k | CHECK_READABLE_REG(ud, r + BPF_REG_R0); \ |
105 | 9.66k | MCOperand_CreateReg0(MI, r + BPF_REG_R0); \ |
106 | 9.57k | } while (0) |
107 | | |
108 | 4.68k | #define CHECK_WRITABLE_AND_PUSH(ud, MI, r) do { \ |
109 | 4.68k | CHECK_WRITABLE_REG(ud, r + BPF_REG_R0); \ |
110 | 4.68k | MCOperand_CreateReg0(MI, r + BPF_REG_R0); \ |
111 | 4.67k | } while (0) |
112 | | |
113 | | static bool decodeLoad(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
114 | 9.44k | { |
115 | 9.44k | if (!EBPF_MODE(ud)) { |
116 | | /* |
117 | | * +-----+-----------+--------------------+ |
118 | | * | ldb | [k] | [x+k] | |
119 | | * | ldh | [k] | [x+k] | |
120 | | * +-----+-----------+--------------------+ |
121 | | */ |
122 | 4.98k | if (BPF_SIZE(bpf->op) == BPF_SIZE_DW) |
123 | 8 | return false; |
124 | 4.97k | if (BPF_SIZE(bpf->op) == BPF_SIZE_B || BPF_SIZE(bpf->op) == BPF_SIZE_H) { |
125 | | /* no ldx */ |
126 | 1.13k | if (BPF_CLASS(bpf->op) != BPF_CLASS_LD) |
127 | 12 | return false; |
128 | | /* can only be BPF_ABS and BPF_IND */ |
129 | 1.12k | if (BPF_MODE(bpf->op) == BPF_MODE_ABS) { |
130 | 498 | MCOperand_CreateImm0(MI, bpf->k); |
131 | 498 | return true; |
132 | 498 | } |
133 | 625 | else if (BPF_MODE(bpf->op) == BPF_MODE_IND) { |
134 | 614 | MCOperand_CreateReg0(MI, BPF_REG_X); |
135 | 614 | MCOperand_CreateImm0(MI, bpf->k); |
136 | 614 | return true; |
137 | 614 | } |
138 | 11 | return false; |
139 | 1.12k | } |
140 | | /* |
141 | | * +-----+----+------+------+-----+-------+ |
142 | | * | ld | #k | #len | M[k] | [k] | [x+k] | |
143 | | * +-----+----+------+------+-----+-------+ |
144 | | * | ldx | #k | #len | M[k] | 4*([k]&0xf) | |
145 | | * +-----+----+------+------+-------------+ |
146 | | */ |
147 | 3.83k | switch (BPF_MODE(bpf->op)) { |
148 | 1.21k | default: |
149 | 1.21k | break; |
150 | 1.70k | case BPF_MODE_IMM: |
151 | 1.70k | MCOperand_CreateImm0(MI, bpf->k); |
152 | 1.70k | return true; |
153 | 326 | case BPF_MODE_LEN: |
154 | 326 | return true; |
155 | 588 | case BPF_MODE_MEM: |
156 | 588 | MCOperand_CreateImm0(MI, bpf->k); |
157 | 588 | return true; |
158 | 3.83k | } |
159 | 1.21k | if (BPF_CLASS(bpf->op) == BPF_CLASS_LD) { |
160 | 691 | if (BPF_MODE(bpf->op) == BPF_MODE_ABS) { |
161 | 344 | MCOperand_CreateImm0(MI, bpf->k); |
162 | 344 | return true; |
163 | 344 | } |
164 | 347 | else if (BPF_MODE(bpf->op) == BPF_MODE_IND) { |
165 | 342 | MCOperand_CreateReg0(MI, BPF_REG_X); |
166 | 342 | MCOperand_CreateImm0(MI, bpf->k); |
167 | 342 | return true; |
168 | 342 | } |
169 | 691 | } |
170 | 524 | else { /* LDX */ |
171 | 524 | if (BPF_MODE(bpf->op) == BPF_MODE_MSH) { |
172 | 518 | MCOperand_CreateImm0(MI, bpf->k); |
173 | 518 | return true; |
174 | 518 | } |
175 | 524 | } |
176 | 11 | return false; |
177 | 1.21k | } |
178 | | |
179 | | /* eBPF mode */ |
180 | | /* |
181 | | * - IMM: lddw dst, imm64 |
182 | | * - ABS: ld{w,h,b,dw} [k] |
183 | | * - IND: ld{w,h,b,dw} [src+k] |
184 | | * - MEM: ldx{w,h,b,dw} dst, [src+off] |
185 | | */ |
186 | 4.46k | if (BPF_CLASS(bpf->op) == BPF_CLASS_LD) { |
187 | 3.23k | switch (BPF_MODE(bpf->op)) { |
188 | 968 | case BPF_MODE_IMM: |
189 | 968 | if (bpf->op != (BPF_CLASS_LD | BPF_SIZE_DW | BPF_MODE_IMM)) |
190 | 40 | return false; |
191 | 928 | CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst); |
192 | 923 | MCOperand_CreateImm0(MI, bpf->k); |
193 | 923 | return true; |
194 | 846 | case BPF_MODE_ABS: |
195 | 846 | MCOperand_CreateImm0(MI, bpf->k); |
196 | 846 | return true; |
197 | 1.40k | case BPF_MODE_IND: |
198 | 1.40k | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
199 | 1.39k | MCOperand_CreateImm0(MI, bpf->k); |
200 | 1.39k | return true; |
201 | 3.23k | } |
202 | 18 | return false; |
203 | | |
204 | 3.23k | } |
205 | | /* LDX */ |
206 | 1.23k | if (BPF_MODE(bpf->op) == BPF_MODE_MEM) { |
207 | 1.21k | CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst); |
208 | 1.21k | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
209 | 1.21k | MCOperand_CreateImm0(MI, bpf->offset); |
210 | 1.21k | return true; |
211 | 1.21k | } |
212 | 15 | return false; |
213 | 1.23k | } |
214 | | |
215 | | static bool decodeStore(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
216 | 2.76k | { |
217 | | /* in cBPF, only BPF_ST* | BPF_MEM | BPF_W is valid |
218 | | * while in eBPF: |
219 | | * - BPF_STX | BPF_XADD | BPF_{W,DW} |
220 | | * - BPF_ST* | BPF_MEM | BPF_{W,H,B,DW} |
221 | | * are valid |
222 | | */ |
223 | 2.76k | if (!EBPF_MODE(ud)) { |
224 | | /* can only store to M[] */ |
225 | 170 | if (bpf->op != (BPF_CLASS(bpf->op) | BPF_MODE_MEM | BPF_SIZE_W)) |
226 | 32 | return false; |
227 | 138 | MCOperand_CreateImm0(MI, bpf->k); |
228 | 138 | return true; |
229 | 170 | } |
230 | | |
231 | | /* eBPF */ |
232 | | |
233 | 2.59k | if (BPF_MODE(bpf->op) == BPF_MODE_XADD) { |
234 | 112 | if (BPF_CLASS(bpf->op) != BPF_CLASS_STX) |
235 | 3 | return false; |
236 | 109 | if (BPF_SIZE(bpf->op) != BPF_SIZE_W && BPF_SIZE(bpf->op) != BPF_SIZE_DW) |
237 | 2 | return false; |
238 | | /* xadd [dst + off], src */ |
239 | 107 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst); |
240 | 104 | MCOperand_CreateImm0(MI, bpf->offset); |
241 | 104 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
242 | 101 | return true; |
243 | 104 | } |
244 | | |
245 | 2.48k | if (BPF_MODE(bpf->op) != BPF_MODE_MEM) |
246 | 21 | return false; |
247 | | |
248 | | /* st [dst + off], src */ |
249 | 2.46k | CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst); |
250 | 2.45k | MCOperand_CreateImm0(MI, bpf->offset); |
251 | 2.45k | if (BPF_CLASS(bpf->op) == BPF_CLASS_ST) |
252 | 1.35k | MCOperand_CreateImm0(MI, bpf->k); |
253 | 1.10k | else |
254 | 1.10k | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
255 | 2.45k | return true; |
256 | 2.45k | } |
257 | | |
258 | | static bool decodeALU(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
259 | 4.48k | { |
260 | | /* Set MI->Operands */ |
261 | | |
262 | | /* cBPF */ |
263 | 4.48k | if (!EBPF_MODE(ud)) { |
264 | 1.90k | if (BPF_OP(bpf->op) > BPF_ALU_XOR) |
265 | 2 | return false; |
266 | | /* cBPF's NEG has no operands */ |
267 | 1.90k | if (BPF_OP(bpf->op) == BPF_ALU_NEG) |
268 | 267 | return true; |
269 | 1.63k | if (BPF_SRC(bpf->op) == BPF_SRC_K) |
270 | 1.03k | MCOperand_CreateImm0(MI, bpf->k); |
271 | 601 | else /* BPF_SRC_X */ |
272 | 601 | MCOperand_CreateReg0(MI, BPF_REG_X); |
273 | 1.63k | return true; |
274 | 1.90k | } |
275 | | |
276 | | /* eBPF */ |
277 | | |
278 | 2.57k | if (BPF_OP(bpf->op) > BPF_ALU_END) |
279 | 2 | return false; |
280 | | /* ENDian's imm must be one of 16, 32, 64 */ |
281 | 2.57k | if (BPF_OP(bpf->op) == BPF_ALU_END) { |
282 | 89 | if (bpf->k != 16 && bpf->k != 32 && bpf->k != 64) |
283 | 39 | return false; |
284 | 50 | if (BPF_CLASS(bpf->op) == BPF_CLASS_ALU64 && BPF_SRC(bpf->op) != BPF_SRC_LITTLE) |
285 | 1 | return false; |
286 | 50 | } |
287 | | |
288 | | /* - op dst, imm |
289 | | * - op dst, src |
290 | | * - neg dst |
291 | | * - le<imm> dst |
292 | | */ |
293 | | /* every ALU instructions have dst op */ |
294 | 2.53k | CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst); |
295 | | |
296 | | /* special cases */ |
297 | 2.53k | if (BPF_OP(bpf->op) == BPF_ALU_NEG) |
298 | 300 | return true; |
299 | 2.23k | if (BPF_OP(bpf->op) == BPF_ALU_END) { |
300 | | /* bpf->k must be one of 16, 32, 64 */ |
301 | 47 | MCInst_setOpcode(MI, MCInst_getOpcode(MI) | ((uint32_t)bpf->k << 4)); |
302 | 47 | return true; |
303 | 47 | } |
304 | | |
305 | | /* normal cases */ |
306 | 2.18k | if (BPF_SRC(bpf->op) == BPF_SRC_K) { |
307 | 1.80k | MCOperand_CreateImm0(MI, bpf->k); |
308 | 1.80k | } |
309 | 384 | else { /* BPF_SRC_X */ |
310 | 384 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
311 | 384 | } |
312 | 2.18k | return true; |
313 | 2.18k | } |
314 | | |
315 | | static bool decodeJump(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
316 | 6.52k | { |
317 | | /* cBPF and eBPF are very different in class jump */ |
318 | 6.52k | if (!EBPF_MODE(ud)) { |
319 | 2.38k | if (BPF_OP(bpf->op) > BPF_JUMP_JSET) |
320 | 8 | return false; |
321 | | |
322 | | /* ja is a special case of jumps */ |
323 | 2.37k | if (BPF_OP(bpf->op) == BPF_JUMP_JA) { |
324 | 887 | MCOperand_CreateImm0(MI, bpf->k); |
325 | 887 | return true; |
326 | 887 | } |
327 | | |
328 | 1.48k | if (BPF_SRC(bpf->op) == BPF_SRC_K) |
329 | 761 | MCOperand_CreateImm0(MI, bpf->k); |
330 | 726 | else /* BPF_SRC_X */ |
331 | 726 | MCOperand_CreateReg0(MI, BPF_REG_X); |
332 | 1.48k | MCOperand_CreateImm0(MI, bpf->jt); |
333 | 1.48k | MCOperand_CreateImm0(MI, bpf->jf); |
334 | 1.48k | } |
335 | 4.14k | else { |
336 | 4.14k | if (BPF_OP(bpf->op) > BPF_JUMP_JSLE) |
337 | 2 | return false; |
338 | | |
339 | | /* No operands for exit */ |
340 | 4.14k | if (BPF_OP(bpf->op) == BPF_JUMP_EXIT) |
341 | 377 | return bpf->op == (BPF_CLASS_JMP | BPF_JUMP_EXIT); |
342 | 3.76k | if (BPF_OP(bpf->op) == BPF_JUMP_CALL) { |
343 | 776 | if (bpf->op == (BPF_CLASS_JMP | BPF_JUMP_CALL)) { |
344 | 704 | MCOperand_CreateImm0(MI, bpf->k); |
345 | 704 | return true; |
346 | 704 | } |
347 | 72 | if (bpf->op == (BPF_CLASS_JMP | BPF_JUMP_CALL | BPF_SRC_X)) { |
348 | 72 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->k); |
349 | 14 | return true; |
350 | 72 | } |
351 | 0 | return false; |
352 | 72 | } |
353 | | |
354 | | /* ja is a special case of jumps */ |
355 | 2.99k | if (BPF_OP(bpf->op) == BPF_JUMP_JA) { |
356 | 369 | if (BPF_SRC(bpf->op) != BPF_SRC_K) |
357 | 2 | return false; |
358 | 367 | MCOperand_CreateImm0(MI, bpf->offset); |
359 | 367 | return true; |
360 | 369 | } |
361 | | |
362 | | /* <j> dst, src, +off */ |
363 | 2.62k | CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst); |
364 | 2.61k | if (BPF_SRC(bpf->op) == BPF_SRC_K) |
365 | 2.41k | MCOperand_CreateImm0(MI, bpf->k); |
366 | 197 | else |
367 | 197 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
368 | 2.60k | MCOperand_CreateImm0(MI, bpf->offset); |
369 | 2.60k | } |
370 | 4.09k | return true; |
371 | 6.52k | } |
372 | | |
373 | | static bool decodeReturn(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
374 | 2.42k | { |
375 | | /* Here only handles the BPF_RET class in cBPF */ |
376 | 2.42k | switch (BPF_RVAL(bpf->op)) { |
377 | 759 | case BPF_SRC_K: |
378 | 759 | MCOperand_CreateImm0(MI, bpf->k); |
379 | 759 | return true; |
380 | 971 | case BPF_SRC_X: |
381 | 971 | MCOperand_CreateReg0(MI, BPF_REG_X); |
382 | 971 | return true; |
383 | 691 | case BPF_SRC_A: |
384 | 691 | MCOperand_CreateReg0(MI, BPF_REG_A); |
385 | 691 | return true; |
386 | 2.42k | } |
387 | 5 | return false; |
388 | 2.42k | } |
389 | | |
390 | | static bool decodeMISC(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
391 | 90 | { |
392 | 90 | uint16_t op = bpf->op ^ BPF_CLASS_MISC; |
393 | 90 | return op == BPF_MISCOP_TAX || op == BPF_MISCOP_TXA; |
394 | 90 | } |
395 | | |
396 | | ///< 1. Check if the instruction is valid |
397 | | ///< 2. Set MI->opcode |
398 | | ///< 3. Set MI->Operands |
399 | | static bool getInstruction(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
400 | 30.3k | { |
401 | 30.3k | cs_detail *detail; |
402 | | |
403 | 30.3k | detail = MI->flat_insn->detail; |
404 | | // initialize detail |
405 | 30.3k | if (detail) { |
406 | 30.3k | memset(detail, 0, offsetof(cs_detail, bpf) + sizeof(cs_bpf)); |
407 | 30.3k | } |
408 | | |
409 | 30.3k | MCInst_clear(MI); |
410 | 30.3k | MCInst_setOpcode(MI, bpf->op); |
411 | | |
412 | 30.3k | switch (BPF_CLASS(bpf->op)) { |
413 | 0 | default: /* should never happen */ |
414 | 0 | return false; |
415 | 6.91k | case BPF_CLASS_LD: |
416 | 9.44k | case BPF_CLASS_LDX: |
417 | 9.44k | return decodeLoad(ud, MI, bpf); |
418 | 1.48k | case BPF_CLASS_ST: |
419 | 2.76k | case BPF_CLASS_STX: |
420 | 2.76k | return decodeStore(ud, MI, bpf); |
421 | 5.20k | case BPF_CLASS_ALU: |
422 | 5.20k | return decodeALU(ud, MI, bpf); |
423 | 6.52k | case BPF_CLASS_JMP: |
424 | 6.52k | return decodeJump(ud, MI, bpf); |
425 | 2.44k | case BPF_CLASS_RET: |
426 | | /* eBPF doesn't have this class */ |
427 | 2.44k | if (EBPF_MODE(ud)) |
428 | 21 | return false; |
429 | 2.42k | return decodeReturn(ud, MI, bpf); |
430 | 3.98k | case BPF_CLASS_MISC: |
431 | | /* case BPF_CLASS_ALU64: */ |
432 | 3.98k | if (EBPF_MODE(ud)) |
433 | 3.89k | return decodeALU(ud, MI, bpf); |
434 | 90 | else |
435 | 90 | return decodeMISC(ud, MI, bpf); |
436 | 30.3k | } |
437 | 30.3k | } |
438 | | |
439 | | bool BPF_getInstruction(csh ud, const uint8_t *code, size_t code_len, |
440 | | MCInst *instr, uint16_t *size, uint64_t address, void *info) |
441 | 30.7k | { |
442 | 30.7k | cs_struct *cs; |
443 | 30.7k | bpf_internal *bpf; |
444 | | |
445 | 30.7k | cs = (cs_struct*)ud; |
446 | 30.7k | if (EBPF_MODE(cs)) |
447 | 16.8k | bpf = fetch_ebpf(cs, code, code_len); |
448 | 13.9k | else |
449 | 13.9k | bpf = fetch_cbpf(cs, code, code_len); |
450 | 30.7k | if (bpf == NULL) |
451 | 399 | return false; |
452 | 30.3k | if (!getInstruction(cs, instr, bpf)) { |
453 | 427 | cs_mem_free(bpf); |
454 | 427 | return false; |
455 | 427 | } |
456 | | |
457 | 29.9k | *size = bpf->insn_size; |
458 | 29.9k | cs_mem_free(bpf); |
459 | | |
460 | 29.9k | return true; |
461 | 30.3k | } |
462 | | |
463 | | #endif |