162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 262306a36Sopenharmony_ci/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com 362306a36Sopenharmony_ci * Copyright (c) 2016 Facebook 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/bpf.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "disasm.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#define __BPF_FUNC_STR_FN(x) [BPF_FUNC_ ## x] = __stringify(bpf_ ## x) 1162306a36Sopenharmony_cistatic const char * const func_id_str[] = { 1262306a36Sopenharmony_ci __BPF_FUNC_MAPPER(__BPF_FUNC_STR_FN) 1362306a36Sopenharmony_ci}; 1462306a36Sopenharmony_ci#undef __BPF_FUNC_STR_FN 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistatic const char *__func_get_name(const struct bpf_insn_cbs *cbs, 1762306a36Sopenharmony_ci const struct bpf_insn *insn, 1862306a36Sopenharmony_ci char *buff, size_t len) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(func_id_str) != __BPF_FUNC_MAX_ID); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci if (!insn->src_reg && 2362306a36Sopenharmony_ci insn->imm >= 0 && insn->imm < __BPF_FUNC_MAX_ID && 2462306a36Sopenharmony_ci func_id_str[insn->imm]) 2562306a36Sopenharmony_ci return func_id_str[insn->imm]; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci if (cbs && cbs->cb_call) { 2862306a36Sopenharmony_ci const char *res; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci res = cbs->cb_call(cbs->private_data, insn); 3162306a36Sopenharmony_ci if (res) 3262306a36Sopenharmony_ci return res; 3362306a36Sopenharmony_ci } 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci if (insn->src_reg == BPF_PSEUDO_CALL) 3662306a36Sopenharmony_ci snprintf(buff, len, "%+d", insn->imm); 3762306a36Sopenharmony_ci else if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) 3862306a36Sopenharmony_ci snprintf(buff, len, "kernel-function"); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci return buff; 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic const char *__func_imm_name(const struct bpf_insn_cbs *cbs, 4462306a36Sopenharmony_ci const struct bpf_insn *insn, 4562306a36Sopenharmony_ci u64 full_imm, char *buff, size_t len) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci if (cbs && cbs->cb_imm) 4862306a36Sopenharmony_ci return cbs->cb_imm(cbs->private_data, insn, full_imm); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci snprintf(buff, len, "0x%llx", (unsigned long long)full_imm); 5162306a36Sopenharmony_ci return buff; 5262306a36Sopenharmony_ci} 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ciconst char *func_id_name(int id) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci if (id >= 0 && id < __BPF_FUNC_MAX_ID && func_id_str[id]) 5762306a36Sopenharmony_ci return func_id_str[id]; 5862306a36Sopenharmony_ci else 5962306a36Sopenharmony_ci return "unknown"; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciconst char *const bpf_class_string[8] = { 6362306a36Sopenharmony_ci [BPF_LD] = "ld", 6462306a36Sopenharmony_ci [BPF_LDX] = "ldx", 6562306a36Sopenharmony_ci [BPF_ST] = "st", 6662306a36Sopenharmony_ci [BPF_STX] = "stx", 6762306a36Sopenharmony_ci [BPF_ALU] = "alu", 6862306a36Sopenharmony_ci [BPF_JMP] = "jmp", 6962306a36Sopenharmony_ci [BPF_JMP32] = "jmp32", 7062306a36Sopenharmony_ci [BPF_ALU64] = "alu64", 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ciconst char *const bpf_alu_string[16] = { 7462306a36Sopenharmony_ci [BPF_ADD >> 4] = "+=", 7562306a36Sopenharmony_ci [BPF_SUB >> 4] = "-=", 7662306a36Sopenharmony_ci [BPF_MUL >> 4] = "*=", 7762306a36Sopenharmony_ci [BPF_DIV >> 4] = "/=", 7862306a36Sopenharmony_ci [BPF_OR >> 4] = "|=", 7962306a36Sopenharmony_ci [BPF_AND >> 4] = "&=", 8062306a36Sopenharmony_ci [BPF_LSH >> 4] = "<<=", 8162306a36Sopenharmony_ci [BPF_RSH >> 4] = ">>=", 8262306a36Sopenharmony_ci [BPF_NEG >> 4] = "neg", 8362306a36Sopenharmony_ci [BPF_MOD >> 4] = "%=", 8462306a36Sopenharmony_ci [BPF_XOR >> 4] = "^=", 8562306a36Sopenharmony_ci [BPF_MOV >> 4] = "=", 8662306a36Sopenharmony_ci [BPF_ARSH >> 4] = "s>>=", 8762306a36Sopenharmony_ci [BPF_END >> 4] = "endian", 8862306a36Sopenharmony_ci}; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic const char *const bpf_alu_sign_string[16] = { 9162306a36Sopenharmony_ci [BPF_DIV >> 4] = "s/=", 9262306a36Sopenharmony_ci [BPF_MOD >> 4] = "s%=", 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic const char *const bpf_movsx_string[4] = { 9662306a36Sopenharmony_ci [0] = "(s8)", 9762306a36Sopenharmony_ci [1] = "(s16)", 9862306a36Sopenharmony_ci [3] = "(s32)", 9962306a36Sopenharmony_ci}; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic const char *const bpf_atomic_alu_string[16] = { 10262306a36Sopenharmony_ci [BPF_ADD >> 4] = "add", 10362306a36Sopenharmony_ci [BPF_AND >> 4] = "and", 10462306a36Sopenharmony_ci [BPF_OR >> 4] = "or", 10562306a36Sopenharmony_ci [BPF_XOR >> 4] = "xor", 10662306a36Sopenharmony_ci}; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic const char *const bpf_ldst_string[] = { 10962306a36Sopenharmony_ci [BPF_W >> 3] = "u32", 11062306a36Sopenharmony_ci [BPF_H >> 3] = "u16", 11162306a36Sopenharmony_ci [BPF_B >> 3] = "u8", 11262306a36Sopenharmony_ci [BPF_DW >> 3] = "u64", 11362306a36Sopenharmony_ci}; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic const char *const bpf_ldsx_string[] = { 11662306a36Sopenharmony_ci [BPF_W >> 3] = "s32", 11762306a36Sopenharmony_ci [BPF_H >> 3] = "s16", 11862306a36Sopenharmony_ci [BPF_B >> 3] = "s8", 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cistatic const char *const bpf_jmp_string[16] = { 12262306a36Sopenharmony_ci [BPF_JA >> 4] = "jmp", 12362306a36Sopenharmony_ci [BPF_JEQ >> 4] = "==", 12462306a36Sopenharmony_ci [BPF_JGT >> 4] = ">", 12562306a36Sopenharmony_ci [BPF_JLT >> 4] = "<", 12662306a36Sopenharmony_ci [BPF_JGE >> 4] = ">=", 12762306a36Sopenharmony_ci [BPF_JLE >> 4] = "<=", 12862306a36Sopenharmony_ci [BPF_JSET >> 4] = "&", 12962306a36Sopenharmony_ci [BPF_JNE >> 4] = "!=", 13062306a36Sopenharmony_ci [BPF_JSGT >> 4] = "s>", 13162306a36Sopenharmony_ci [BPF_JSLT >> 4] = "s<", 13262306a36Sopenharmony_ci [BPF_JSGE >> 4] = "s>=", 13362306a36Sopenharmony_ci [BPF_JSLE >> 4] = "s<=", 13462306a36Sopenharmony_ci [BPF_CALL >> 4] = "call", 13562306a36Sopenharmony_ci [BPF_EXIT >> 4] = "exit", 13662306a36Sopenharmony_ci}; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic void print_bpf_end_insn(bpf_insn_print_t verbose, 13962306a36Sopenharmony_ci void *private_data, 14062306a36Sopenharmony_ci const struct bpf_insn *insn) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci verbose(private_data, "(%02x) r%d = %s%d r%d\n", 14362306a36Sopenharmony_ci insn->code, insn->dst_reg, 14462306a36Sopenharmony_ci BPF_SRC(insn->code) == BPF_TO_BE ? "be" : "le", 14562306a36Sopenharmony_ci insn->imm, insn->dst_reg); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic void print_bpf_bswap_insn(bpf_insn_print_t verbose, 14962306a36Sopenharmony_ci void *private_data, 15062306a36Sopenharmony_ci const struct bpf_insn *insn) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci verbose(private_data, "(%02x) r%d = bswap%d r%d\n", 15362306a36Sopenharmony_ci insn->code, insn->dst_reg, 15462306a36Sopenharmony_ci insn->imm, insn->dst_reg); 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic bool is_sdiv_smod(const struct bpf_insn *insn) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci return (BPF_OP(insn->code) == BPF_DIV || BPF_OP(insn->code) == BPF_MOD) && 16062306a36Sopenharmony_ci insn->off == 1; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic bool is_movsx(const struct bpf_insn *insn) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci return BPF_OP(insn->code) == BPF_MOV && 16662306a36Sopenharmony_ci (insn->off == 8 || insn->off == 16 || insn->off == 32); 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_civoid print_bpf_insn(const struct bpf_insn_cbs *cbs, 17062306a36Sopenharmony_ci const struct bpf_insn *insn, 17162306a36Sopenharmony_ci bool allow_ptr_leaks) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci const bpf_insn_print_t verbose = cbs->cb_print; 17462306a36Sopenharmony_ci u8 class = BPF_CLASS(insn->code); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci if (class == BPF_ALU || class == BPF_ALU64) { 17762306a36Sopenharmony_ci if (BPF_OP(insn->code) == BPF_END) { 17862306a36Sopenharmony_ci if (class == BPF_ALU64) 17962306a36Sopenharmony_ci print_bpf_bswap_insn(verbose, cbs->private_data, insn); 18062306a36Sopenharmony_ci else 18162306a36Sopenharmony_ci print_bpf_end_insn(verbose, cbs->private_data, insn); 18262306a36Sopenharmony_ci } else if (BPF_OP(insn->code) == BPF_NEG) { 18362306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) %c%d = -%c%d\n", 18462306a36Sopenharmony_ci insn->code, class == BPF_ALU ? 'w' : 'r', 18562306a36Sopenharmony_ci insn->dst_reg, class == BPF_ALU ? 'w' : 'r', 18662306a36Sopenharmony_ci insn->dst_reg); 18762306a36Sopenharmony_ci } else if (BPF_SRC(insn->code) == BPF_X) { 18862306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) %c%d %s %s%c%d\n", 18962306a36Sopenharmony_ci insn->code, class == BPF_ALU ? 'w' : 'r', 19062306a36Sopenharmony_ci insn->dst_reg, 19162306a36Sopenharmony_ci is_sdiv_smod(insn) ? bpf_alu_sign_string[BPF_OP(insn->code) >> 4] 19262306a36Sopenharmony_ci : bpf_alu_string[BPF_OP(insn->code) >> 4], 19362306a36Sopenharmony_ci is_movsx(insn) ? bpf_movsx_string[(insn->off >> 3) - 1] : "", 19462306a36Sopenharmony_ci class == BPF_ALU ? 'w' : 'r', 19562306a36Sopenharmony_ci insn->src_reg); 19662306a36Sopenharmony_ci } else { 19762306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) %c%d %s %d\n", 19862306a36Sopenharmony_ci insn->code, class == BPF_ALU ? 'w' : 'r', 19962306a36Sopenharmony_ci insn->dst_reg, 20062306a36Sopenharmony_ci is_sdiv_smod(insn) ? bpf_alu_sign_string[BPF_OP(insn->code) >> 4] 20162306a36Sopenharmony_ci : bpf_alu_string[BPF_OP(insn->code) >> 4], 20262306a36Sopenharmony_ci insn->imm); 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci } else if (class == BPF_STX) { 20562306a36Sopenharmony_ci if (BPF_MODE(insn->code) == BPF_MEM) 20662306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) *(%s *)(r%d %+d) = r%d\n", 20762306a36Sopenharmony_ci insn->code, 20862306a36Sopenharmony_ci bpf_ldst_string[BPF_SIZE(insn->code) >> 3], 20962306a36Sopenharmony_ci insn->dst_reg, 21062306a36Sopenharmony_ci insn->off, insn->src_reg); 21162306a36Sopenharmony_ci else if (BPF_MODE(insn->code) == BPF_ATOMIC && 21262306a36Sopenharmony_ci (insn->imm == BPF_ADD || insn->imm == BPF_AND || 21362306a36Sopenharmony_ci insn->imm == BPF_OR || insn->imm == BPF_XOR)) { 21462306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) lock *(%s *)(r%d %+d) %s r%d\n", 21562306a36Sopenharmony_ci insn->code, 21662306a36Sopenharmony_ci bpf_ldst_string[BPF_SIZE(insn->code) >> 3], 21762306a36Sopenharmony_ci insn->dst_reg, insn->off, 21862306a36Sopenharmony_ci bpf_alu_string[BPF_OP(insn->imm) >> 4], 21962306a36Sopenharmony_ci insn->src_reg); 22062306a36Sopenharmony_ci } else if (BPF_MODE(insn->code) == BPF_ATOMIC && 22162306a36Sopenharmony_ci (insn->imm == (BPF_ADD | BPF_FETCH) || 22262306a36Sopenharmony_ci insn->imm == (BPF_AND | BPF_FETCH) || 22362306a36Sopenharmony_ci insn->imm == (BPF_OR | BPF_FETCH) || 22462306a36Sopenharmony_ci insn->imm == (BPF_XOR | BPF_FETCH))) { 22562306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) r%d = atomic%s_fetch_%s((%s *)(r%d %+d), r%d)\n", 22662306a36Sopenharmony_ci insn->code, insn->src_reg, 22762306a36Sopenharmony_ci BPF_SIZE(insn->code) == BPF_DW ? "64" : "", 22862306a36Sopenharmony_ci bpf_atomic_alu_string[BPF_OP(insn->imm) >> 4], 22962306a36Sopenharmony_ci bpf_ldst_string[BPF_SIZE(insn->code) >> 3], 23062306a36Sopenharmony_ci insn->dst_reg, insn->off, insn->src_reg); 23162306a36Sopenharmony_ci } else if (BPF_MODE(insn->code) == BPF_ATOMIC && 23262306a36Sopenharmony_ci insn->imm == BPF_CMPXCHG) { 23362306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) r0 = atomic%s_cmpxchg((%s *)(r%d %+d), r0, r%d)\n", 23462306a36Sopenharmony_ci insn->code, 23562306a36Sopenharmony_ci BPF_SIZE(insn->code) == BPF_DW ? "64" : "", 23662306a36Sopenharmony_ci bpf_ldst_string[BPF_SIZE(insn->code) >> 3], 23762306a36Sopenharmony_ci insn->dst_reg, insn->off, 23862306a36Sopenharmony_ci insn->src_reg); 23962306a36Sopenharmony_ci } else if (BPF_MODE(insn->code) == BPF_ATOMIC && 24062306a36Sopenharmony_ci insn->imm == BPF_XCHG) { 24162306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) r%d = atomic%s_xchg((%s *)(r%d %+d), r%d)\n", 24262306a36Sopenharmony_ci insn->code, insn->src_reg, 24362306a36Sopenharmony_ci BPF_SIZE(insn->code) == BPF_DW ? "64" : "", 24462306a36Sopenharmony_ci bpf_ldst_string[BPF_SIZE(insn->code) >> 3], 24562306a36Sopenharmony_ci insn->dst_reg, insn->off, insn->src_reg); 24662306a36Sopenharmony_ci } else { 24762306a36Sopenharmony_ci verbose(cbs->private_data, "BUG_%02x\n", insn->code); 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci } else if (class == BPF_ST) { 25062306a36Sopenharmony_ci if (BPF_MODE(insn->code) == BPF_MEM) { 25162306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) *(%s *)(r%d %+d) = %d\n", 25262306a36Sopenharmony_ci insn->code, 25362306a36Sopenharmony_ci bpf_ldst_string[BPF_SIZE(insn->code) >> 3], 25462306a36Sopenharmony_ci insn->dst_reg, 25562306a36Sopenharmony_ci insn->off, insn->imm); 25662306a36Sopenharmony_ci } else if (BPF_MODE(insn->code) == 0xc0 /* BPF_NOSPEC, no UAPI */) { 25762306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) nospec\n", insn->code); 25862306a36Sopenharmony_ci } else { 25962306a36Sopenharmony_ci verbose(cbs->private_data, "BUG_st_%02x\n", insn->code); 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci } else if (class == BPF_LDX) { 26262306a36Sopenharmony_ci if (BPF_MODE(insn->code) != BPF_MEM && BPF_MODE(insn->code) != BPF_MEMSX) { 26362306a36Sopenharmony_ci verbose(cbs->private_data, "BUG_ldx_%02x\n", insn->code); 26462306a36Sopenharmony_ci return; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) r%d = *(%s *)(r%d %+d)\n", 26762306a36Sopenharmony_ci insn->code, insn->dst_reg, 26862306a36Sopenharmony_ci BPF_MODE(insn->code) == BPF_MEM ? 26962306a36Sopenharmony_ci bpf_ldst_string[BPF_SIZE(insn->code) >> 3] : 27062306a36Sopenharmony_ci bpf_ldsx_string[BPF_SIZE(insn->code) >> 3], 27162306a36Sopenharmony_ci insn->src_reg, insn->off); 27262306a36Sopenharmony_ci } else if (class == BPF_LD) { 27362306a36Sopenharmony_ci if (BPF_MODE(insn->code) == BPF_ABS) { 27462306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) r0 = *(%s *)skb[%d]\n", 27562306a36Sopenharmony_ci insn->code, 27662306a36Sopenharmony_ci bpf_ldst_string[BPF_SIZE(insn->code) >> 3], 27762306a36Sopenharmony_ci insn->imm); 27862306a36Sopenharmony_ci } else if (BPF_MODE(insn->code) == BPF_IND) { 27962306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) r0 = *(%s *)skb[r%d + %d]\n", 28062306a36Sopenharmony_ci insn->code, 28162306a36Sopenharmony_ci bpf_ldst_string[BPF_SIZE(insn->code) >> 3], 28262306a36Sopenharmony_ci insn->src_reg, insn->imm); 28362306a36Sopenharmony_ci } else if (BPF_MODE(insn->code) == BPF_IMM && 28462306a36Sopenharmony_ci BPF_SIZE(insn->code) == BPF_DW) { 28562306a36Sopenharmony_ci /* At this point, we already made sure that the second 28662306a36Sopenharmony_ci * part of the ldimm64 insn is accessible. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_ci u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm; 28962306a36Sopenharmony_ci bool is_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD || 29062306a36Sopenharmony_ci insn->src_reg == BPF_PSEUDO_MAP_VALUE; 29162306a36Sopenharmony_ci char tmp[64]; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci if (is_ptr && !allow_ptr_leaks) 29462306a36Sopenharmony_ci imm = 0; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) r%d = %s\n", 29762306a36Sopenharmony_ci insn->code, insn->dst_reg, 29862306a36Sopenharmony_ci __func_imm_name(cbs, insn, imm, 29962306a36Sopenharmony_ci tmp, sizeof(tmp))); 30062306a36Sopenharmony_ci } else { 30162306a36Sopenharmony_ci verbose(cbs->private_data, "BUG_ld_%02x\n", insn->code); 30262306a36Sopenharmony_ci return; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci } else if (class == BPF_JMP32 || class == BPF_JMP) { 30562306a36Sopenharmony_ci u8 opcode = BPF_OP(insn->code); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (opcode == BPF_CALL) { 30862306a36Sopenharmony_ci char tmp[64]; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci if (insn->src_reg == BPF_PSEUDO_CALL) { 31162306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) call pc%s\n", 31262306a36Sopenharmony_ci insn->code, 31362306a36Sopenharmony_ci __func_get_name(cbs, insn, 31462306a36Sopenharmony_ci tmp, sizeof(tmp))); 31562306a36Sopenharmony_ci } else { 31662306a36Sopenharmony_ci strcpy(tmp, "unknown"); 31762306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) call %s#%d\n", insn->code, 31862306a36Sopenharmony_ci __func_get_name(cbs, insn, 31962306a36Sopenharmony_ci tmp, sizeof(tmp)), 32062306a36Sopenharmony_ci insn->imm); 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci } else if (insn->code == (BPF_JMP | BPF_JA)) { 32362306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) goto pc%+d\n", 32462306a36Sopenharmony_ci insn->code, insn->off); 32562306a36Sopenharmony_ci } else if (insn->code == (BPF_JMP32 | BPF_JA)) { 32662306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) gotol pc%+d\n", 32762306a36Sopenharmony_ci insn->code, insn->imm); 32862306a36Sopenharmony_ci } else if (insn->code == (BPF_JMP | BPF_EXIT)) { 32962306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) exit\n", insn->code); 33062306a36Sopenharmony_ci } else if (BPF_SRC(insn->code) == BPF_X) { 33162306a36Sopenharmony_ci verbose(cbs->private_data, 33262306a36Sopenharmony_ci "(%02x) if %c%d %s %c%d goto pc%+d\n", 33362306a36Sopenharmony_ci insn->code, class == BPF_JMP32 ? 'w' : 'r', 33462306a36Sopenharmony_ci insn->dst_reg, 33562306a36Sopenharmony_ci bpf_jmp_string[BPF_OP(insn->code) >> 4], 33662306a36Sopenharmony_ci class == BPF_JMP32 ? 'w' : 'r', 33762306a36Sopenharmony_ci insn->src_reg, insn->off); 33862306a36Sopenharmony_ci } else { 33962306a36Sopenharmony_ci verbose(cbs->private_data, 34062306a36Sopenharmony_ci "(%02x) if %c%d %s 0x%x goto pc%+d\n", 34162306a36Sopenharmony_ci insn->code, class == BPF_JMP32 ? 'w' : 'r', 34262306a36Sopenharmony_ci insn->dst_reg, 34362306a36Sopenharmony_ci bpf_jmp_string[BPF_OP(insn->code) >> 4], 34462306a36Sopenharmony_ci insn->imm, insn->off); 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci } else { 34762306a36Sopenharmony_ci verbose(cbs->private_data, "(%02x) %s\n", 34862306a36Sopenharmony_ci insn->code, bpf_class_string[class]); 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci} 351