From dc1f1c9e6206140a41a86e2deb9097852bb57200 Mon Sep 17 00:00:00 2001 From: JagathP Date: Thu, 9 Apr 2026 21:31:47 +0530 Subject: [PATCH 01/16] Added disassembly and analysis support for eBPF --- librz/arch/meson.build | 2 + librz/arch/p/analysis/analysis_bpf_cs.c | 405 ++++++++++++++++++++++++ librz/arch/p/arch_bpf_cs.c | 8 + librz/arch/p/asm/asm_bpf_cs.c | 75 +++++ 4 files changed, 490 insertions(+) create mode 100644 librz/arch/p/analysis/analysis_bpf_cs.c create mode 100644 librz/arch/p/arch_bpf_cs.c create mode 100644 librz/arch/p/asm/asm_bpf_cs.c diff --git a/librz/arch/meson.build b/librz/arch/meson.build index 7d86bee3b17..24e20f45ec6 100644 --- a/librz/arch/meson.build +++ b/librz/arch/meson.build @@ -347,12 +347,14 @@ if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_i # plugins arch_plugins_list += [ 'cbpf_cs', + 'bpf_cs', 'riscv_cs', ] # plugins sources arch_plugin_sources += [ 'p/arch_cbpf_cs.c', + 'p/arch_bpf_cs.c', 'p/arch_riscv_cs.c', ] endif diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c new file mode 100644 index 00000000000..5f8e99729a3 --- /dev/null +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -0,0 +1,405 @@ +// SPDX-FileCopyrightText: 2026 Jagath-P jagathp0210@gmail.com +// SPDX-License-Identifier: LGPL-3.0-only + +#include "rz_util/rz_str.h" +#include +#include +#include +#include +#include + +typedef struct { + csh handle; + cs_mode omode; +} BPFContext; + +static char *bpf_get_reg_profile(RzAnalysis *analysis) { + const char *ebpg_reg_profile = + "=PC pc\n" + "=SP R10\n" + "=R0 R0\n" + "=A0 R1\n" + "=A1 R2\n" + "=A2 R3\n" + "=A3 R4\n" + "=A4 R5\n" + "gpr pc .64 0 0\n" // program counter + "gpr sp .64 8 0\n" // stack pointer + "gpr R0 .64 16 0\n" + "gpr R1 .64 24 0\n" + "gpr R2 .64 32 0\n" + "gpr R3 .64 40 0\n" + "gpr R4 .64 48 0\n" + "gpr R5 .64 56 0\n" + "gpr R6 .64 64 0\n" + "gpr R7 .64 72 0\n" + "gpr R8 .64 80 0\n" + "gpr R9 .64 88 0\n"; + + return rz_str_dup(ebpg_reg_profile); +} + +static RzStructuredData *bpf_opex(csh handle, cs_insn *insn) { + if (!insn->detail) { + return NULL; + } + + RzStructuredData *root = rz_structured_data_new_map(); + if (!root) { + return NULL; + } + + RzStructuredData *opex = rz_structured_data_map_add_map(root, "opex"); + if (!opex) { + rz_structured_data_free(root); + return NULL; + } + + RzStructuredData *operands = rz_structured_data_map_add_array(opex, "operands"); + cs_bpf *x = &insn->detail->bpf; + for (st32 i = 0; i < x->op_count; i++) { + cs_bpf_op *op = x->operands + i; + RzStructuredData *operand = rz_structured_data_array_add_map(operands); + switch (op->type) { + case BPF_OP_REG: { + const char *reg_name = cs_reg_name(handle, op->reg); + rz_structured_data_map_add_string(operand, "type", "reg"); + rz_structured_data_map_add_string(operand, "value", reg_name ? reg_name : "unknown"); + break; + } + case BPF_OP_IMM: + rz_structured_data_map_add_string(operand, "type", "imm"); + rz_structured_data_map_add_unsigned(operand, "value", op->imm, true); + break; + case BPF_OP_OFF: + rz_structured_data_map_add_string(operand, "type", "off"); + rz_structured_data_map_add_unsigned(operand, "value", op->off, true); + break; + case BPF_OP_MEM: { + const char *base_name = cs_reg_name(handle, (unsigned int)op->mem.base); + rz_structured_data_map_add_string(operand, "type", "mem"); + rz_structured_data_map_add_string(operand, "base", base_name ? base_name : "unknown"); + rz_structured_data_map_add_unsigned(operand, "disp", op->mem.disp, true); + break; + } + case BPF_OP_MMEM: + rz_structured_data_map_add_string(operand, "type", "mmem"); + rz_structured_data_map_add_unsigned(operand, "value", op->mmem, true); + break; + case BPF_OP_MSH: + rz_structured_data_map_add_string(operand, "type", "msh"); + rz_structured_data_map_add_unsigned(operand, "value", op->msh, true); + break; + case BPF_OP_EXT: + rz_structured_data_map_add_string(operand, "type", "ext"); + rz_structured_data_map_add_unsigned(operand, "value", op->ext, true); + break; + default: + rz_structured_data_map_add_string(operand, "type", "invalid"); + break; + } + } + + return root; +} +static bool bpf_anal_init(void **user) { + BPFContext *ctx = RZ_NEW0(BPFContext); + rz_return_val_if_fail(ctx, false); + ctx->handle = 0; + ctx->omode = -1; + *user = ctx; + return true; +} + +static bool bpf_anal_fini(void *user) { + BPFContext *ctx = (BPFContext *)user; + if (ctx) { + if (ctx->handle) { + cs_close(&ctx->handle); + } + RZ_FREE(ctx); + } + return true; +} + +static int bpf_arch_info(RzAnalysis *a, RzAnalysisInfoType query) { + switch (query) { + case RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE: + return 8; + case RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE: + return 16; + case RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN: + return 8; + case RZ_ANALYSIS_ARCHINFO_DATA_ALIGN: + return 1; + case RZ_ANALYSIS_ARCHINFO_CAN_USE_POINTERS: + return true; + default: + return -1; + } +} +static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { + switch (insn->id) { + case BPF_INS_ADD: op->type = RZ_ANALYSIS_OP_TYPE_ADD; break; + case BPF_INS_SUB: op->type = RZ_ANALYSIS_OP_TYPE_SUB; break; + case BPF_INS_MUL: op->type = RZ_ANALYSIS_OP_TYPE_MUL; break; + case BPF_INS_DIV: op->type = RZ_ANALYSIS_OP_TYPE_DIV; break; + case BPF_INS_OR: op->type = RZ_ANALYSIS_OP_TYPE_OR; break; + case BPF_INS_AND: op->type = RZ_ANALYSIS_OP_TYPE_AND; break; + case BPF_INS_LSH: op->type = RZ_ANALYSIS_OP_TYPE_SHL; break; + case BPF_INS_RSH: op->type = RZ_ANALYSIS_OP_TYPE_SHR; break; + case BPF_INS_NEG: op->type = RZ_ANALYSIS_OP_TYPE_UNK; break; + case BPF_INS_MOD: op->type = RZ_ANALYSIS_OP_TYPE_MOD; break; + case BPF_INS_XOR: op->type = RZ_ANALYSIS_OP_TYPE_XOR; break; + case BPF_INS_MOV: op->type = RZ_ANALYSIS_OP_TYPE_MOV; break; + case BPF_INS_ARSH: op->type = RZ_ANALYSIS_OP_TYPE_SAR; break; + + /* ALU64 */ + case BPF_INS_ADD64: op->type = RZ_ANALYSIS_OP_TYPE_ADD; break; + case BPF_INS_SUB64: op->type = RZ_ANALYSIS_OP_TYPE_SUB; break; + case BPF_INS_MUL64: op->type = RZ_ANALYSIS_OP_TYPE_MUL; break; + case BPF_INS_DIV64: op->type = RZ_ANALYSIS_OP_TYPE_DIV; break; + case BPF_INS_OR64: op->type = RZ_ANALYSIS_OP_TYPE_OR; break; + case BPF_INS_AND64: op->type = RZ_ANALYSIS_OP_TYPE_AND; break; + case BPF_INS_LSH64: op->type = RZ_ANALYSIS_OP_TYPE_SHL; break; + case BPF_INS_RSH64: op->type = RZ_ANALYSIS_OP_TYPE_SHR; break; + case BPF_INS_NEG64: op->type = RZ_ANALYSIS_OP_TYPE_UNK; break; + case BPF_INS_MOD64: op->type = RZ_ANALYSIS_OP_TYPE_MOD; break; + case BPF_INS_XOR64: op->type = RZ_ANALYSIS_OP_TYPE_XOR; break; + case BPF_INS_MOV64: op->type = RZ_ANALYSIS_OP_TYPE_MOV; break; + case BPF_INS_ARSH64: + op->type = RZ_ANALYSIS_OP_TYPE_SAR; + break; + +#if CS_API_MAJOR >= 6 + case BPF_INS_SDIV: + case BPF_INS_SDIV64: op->type = RZ_ANALYSIS_OP_TYPE_DIV; break; + case BPF_INS_SMOD: + case BPF_INS_SMOD64: op->type = RZ_ANALYSIS_OP_TYPE_MOD; break; + case BPF_INS_MOVSB: + case BPF_INS_MOVSH: + case BPF_INS_MOVSB64: + case BPF_INS_MOVSH64: + op->type = RZ_ANALYSIS_OP_TYPE_MOV; + op->sign = true; + break; +#endif /* CS_API_MAJOR >= 6 */ + + /* Byte Swap */ + case BPF_INS_LE16: + case BPF_INS_LE32: + case BPF_INS_LE64: + case BPF_INS_BE16: + case BPF_INS_BE32: + case BPF_INS_BE64: + op->type = RZ_ANALYSIS_OP_TYPE_MOV; // endian-swap into same reg + break; + + /* Load */ + case BPF_INS_LDXW: + case BPF_INS_LDXH: + case BPF_INS_LDXB: + case BPF_INS_LDXDW: + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + if (insn->detail->bpf.op_count > 0) { + // op->reg = insn->detail->bpf.operands[0].reg; // destination register + } + break; + case BPF_INS_LDW: // same value as BPF_INS_LD in Capstone v5 + case BPF_INS_LDH: + case BPF_INS_LDB: + case BPF_INS_LDDW: + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + break; +#if CS_API_MAJOR >= 6 + case BPF_INS_LDABSW: + case BPF_INS_LDABSH: + case BPF_INS_LDABSB: + case BPF_INS_LDINDW: + case BPF_INS_LDINDH: + case BPF_INS_LDINDB: + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + break; +#endif /* CS_API_MAJOR >= 6 */ + + /* Store */ + case BPF_INS_STXW: + case BPF_INS_STXH: + case BPF_INS_STXB: + case BPF_INS_STXDW: + op->type = RZ_ANALYSIS_OP_TYPE_STORE; + if (insn->detail->bpf.op_count > 1) { + // op->reg = insn->detail->bpf.operands[1].reg; // source register + } + break; + case BPF_INS_STW: // same value as BPF_INS_ST in Capstone v5 + case BPF_INS_STH: + case BPF_INS_STB: + case BPF_INS_STDW: + op->type = RZ_ANALYSIS_OP_TYPE_STORE; + break; + case BPF_INS_XADDW: + case BPF_INS_XADDDW: + op->type = RZ_ANALYSIS_OP_TYPE_STORE; // atomic add-and-store + break; + + /* + * Extended atomics (AFADD, AFOR, AFAND, AFXOR, AADD, AOR, AAND, AXOR) + * only exist in Capstone v6 onwards. + */ +#if CS_API_MAJOR >= 6 + case BPF_INS_AADD: + case BPF_INS_AOR: + case BPF_INS_AAND: + case BPF_INS_AXOR: + case BPF_INS_AFADD: + case BPF_INS_AFOR: + case BPF_INS_AFAND: + case BPF_INS_AFXOR: + op->type = RZ_ANALYSIS_OP_TYPE_STORE; + break; +#endif /* CS_API_MAJOR >= 6 */ + +#if CS_API_MAJOR >= 6 + case BPF_INS_JA: +#else + case BPF_INS_JMP: +#endif + if (insn->detail->bpf.op_count > 0) { + op->jump = addr + 8 + insn->detail->bpf.operands[0].off * 8; + } + op->type = RZ_ANALYSIS_OP_TYPE_JMP; + break; + + /* Conditional jump */ + case BPF_INS_JEQ: + case BPF_INS_JGT: + case BPF_INS_JGE: + case BPF_INS_JSET: + case BPF_INS_JNE: + case BPF_INS_JSGT: + case BPF_INS_JSGE: + case BPF_INS_JLT: + case BPF_INS_JLE: + case BPF_INS_JSLT: + case BPF_INS_JSLE: + // For conditional jumps: operands[2] holds the true-branch offset + if (insn->detail->bpf.op_count > 2) { + op->jump = addr + (insn->detail->bpf.operands[2].off + 1) * 8; + } + op->fail = addr + 8; // fall-through (false branch) + op->type = RZ_ANALYSIS_OP_TYPE_CJMP; + break; + + /* Conditional jumps 32-bit operands */ +#if CS_API_MAJOR >= 6 + case BPF_INS_JAL: + if (insn->detail->bpf.op_count > 0) { + op->jump = addr + (insn->detail->bpf.operands[0].imm + 1) * 8; + } + op->fail = addr + 8; + op->type = RZ_ANALYSIS_OP_TYPE_JMP; + break; + case BPF_INS_JSET32: + case BPF_INS_JSLT32: + case BPF_INS_JSLE32: + case BPF_INS_JSGT32: + case BPF_INS_JSGE32: + op->sign = true; + case BPF_INS_JEQ32: + case BPF_INS_JGT32: + case BPF_INS_JGE32: + case BPF_INS_JNE32: + case BPF_INS_JLT32: + case BPF_INS_JLE32: + if (insn->detail->bpf.op_count > 2) { + op->jump = addr + (insn->detail->bpf.operands[2].imm + 1) * 8; + } + op->fail = addr + 8; + op->type = RZ_ANALYSIS_OP_TYPE_CJMP; + break; +#endif /* CS_API_MAJOR >= 6 */ + + case BPF_INS_CALL: + op->type = RZ_ANALYSIS_OP_TYPE_CALL; + break; + case BPF_INS_CALLX: + op->type = RZ_ANALYSIS_OP_TYPE_RCALL; + break; + + /* Return */ + case BPF_INS_EXIT: + case BPF_INS_RET: // cBPF return + op->type = RZ_ANALYSIS_OP_TYPE_RET; + break; + + default: + op->type = RZ_ANALYSIS_OP_TYPE_UNK; + break; + } +} + +static int bpf_analysis_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) { + BPFContext *ctx = (BPFContext *)a->plugin_data; + cs_insn *insn; + int n; + cs_mode mode = CS_MODE_BPF_EXTENDED | (a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN); + + if (mode != ctx->omode) { + if (ctx->handle) { + cs_close(&ctx->handle); + } + ctx->omode = mode; + } + if (!ctx->handle) { + cs_err err = cs_open(CS_ARCH_BPF, mode, &ctx->handle); + if (err != CS_ERR_OK) { + return -1; + } + cs_option(ctx->handle, CS_OPT_DETAIL, CS_OPT_ON); + } + + n = cs_disasm(ctx->handle, buf, len, addr, 1, &insn); + if (n < 1) { + op->type = RZ_ANALYSIS_OP_TYPE_ILL; + if (mask & RZ_ANALYSIS_OP_MASK_DISASM) { + op->mnemonic = strdup("invalid"); + } + return -1; + } + op->size = insn->size; + op->id = insn->id; + if (op->size != 8 && op->size != 16) { + cs_free(insn, n); + return -1; + } + if (mask & RZ_ANALYSIS_OP_MASK_DISASM) { + op->mnemonic = rz_str_newf("%s%s%s", insn->mnemonic, insn->op_str[0] ? " " : "", insn->op_str); + } + if (mask & RZ_ANALYSIS_OP_MASK_OPEX) { + op->opex = bpf_opex(ctx->handle, insn); + } + ebpf_op_type(op, addr, insn); + cs_free(insn, n); + return op->size; +} +RzAnalysisPlugin rz_analysis_plugin_bpf_cs = { + .name = "bpf", + .desc = "Extended BPF analysis plugin", + .license = "LGPL3", + .arch = "bpf", + .bits = 64, + .op = &bpf_analysis_op, + .init = bpf_anal_init, + .fini = bpf_anal_fini, + .archinfo = bpf_arch_info, + .get_reg_profile = &bpf_get_reg_profile, +}; + +#ifndef RZ_PLUGIN_INCORE +RZ_API RzLibStruct rizin_plugin = { + .type = RZ_LIB_TYPE_ANALYSIS, + .data = &rz_analysis_plugin_bpf_cs, + .version = RZ_VERSION +}; +#endif diff --git a/librz/arch/p/arch_bpf_cs.c b/librz/arch/p/arch_bpf_cs.c new file mode 100644 index 00000000000..1cadebf0ac3 --- /dev/null +++ b/librz/arch/p/arch_bpf_cs.c @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: 2026 Jagath-P jagathp0210@gmail.com +// SPDX-License-Identifier: LGPL-3.0-only + +#include +#include "analysis/analysis_bpf_cs.c" +#include "asm/asm_bpf_cs.c" + +RZ_ARCH_PLUGIN_DEFINE_DEPRECATED(bpf_cs); diff --git a/librz/arch/p/asm/asm_bpf_cs.c b/librz/arch/p/asm/asm_bpf_cs.c new file mode 100644 index 00000000000..759df26eb06 --- /dev/null +++ b/librz/arch/p/asm/asm_bpf_cs.c @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: 2026 Jagath-P jagathp0210@gmail.com +// SPDX-License-Identifier: LGPL-3.0-only + +#include +#include +#include +#include "capstone.h" +#include "cs_helper.h" + +CAPSTONE_DEFINE_PLUGIN_FUNCTIONS(bpf_asm); + +static int bpf_disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) { + CapstoneContext *ctx = (CapstoneContext *)a->plugin_data; + cs_insn *insn; + int n, ret = -1; + cs_mode mode = CS_MODE_BPF_EXTENDED | (a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN); + memset(op, 0, sizeof(RzAsmOp)); + op->size = 8; + if (ctx->omode != mode) { + if (ctx->handle) { + cs_close(&ctx->handle); + } + ctx->omode = mode; + } + if (!ctx->handle) { + ret = cs_open(CS_ARCH_BPF, mode, &ctx->handle); + if (ret) { + return ret; + } + cs_option(ctx->handle, CS_OPT_DETAIL, CS_OPT_OFF); + } + + n = cs_disasm(ctx->handle, buf, len, a->pc, 1, &insn); + if (n < 1) { + rz_asm_op_set_asm(op, "invalid"); + ret = -1; + cs_free(insn, n); + return ret; + } + if (insn->size != 8 && insn->size != 16) { + cs_free(insn, n); + ret = -1; + return ret; + } + op->size = insn->size; + ret = op->size; + if (insn->op_str[0]) { + rz_asm_op_setf_asm(op, "%s %s", insn->mnemonic, insn->op_str); + } else { + rz_asm_op_set_asm(op, insn->mnemonic); + } + cs_free(insn, n); + return ret; +} + +RzAsmPlugin rz_asm_plugin_bpf_cs = { + .name = "bpf", + .license = "LGPL3", + .desc = "EBPF disassembly plugin", + .arch = "bpf", + .bits = 64, + .endian = RZ_SYS_ENDIAN_BIG | RZ_SYS_ENDIAN_LITTLE, + .init = &bpf_asm_init, + .fini = &bpf_asm_fini, + .disassemble = &bpf_disassemble, + .mnemonics = &bpf_asm_mnemonics +}; + +#ifndef RZ_PLUGIN_INCORE +RZ_API RzLibStruct rizin_plugin = { + .type = RZ_LIB_TYPE_ASM, + .data = &rz_asm_plugin_bpf_cs, + .version = RZ_VERSION +}; +#endif From d28932bde00f2ed4faf28027422e5cc75bc859f8 Mon Sep 17 00:00:00 2001 From: JagathP Date: Fri, 10 Apr 2026 22:12:00 +0530 Subject: [PATCH 02/16] Added tests for disassembly and analysis --- librz/arch/meson.build | 4 +- librz/arch/p/analysis/analysis_bpf_cs.c | 56 +++--- librz/arch/p/asm/asm_bpf_cs.c | 2 - test/db/analysis/bpf | 230 ++++++++++++++++++++++++ test/db/asm/bpf | 50 ++++++ 5 files changed, 315 insertions(+), 27 deletions(-) create mode 100644 test/db/analysis/bpf create mode 100644 test/db/asm/bpf diff --git a/librz/arch/meson.build b/librz/arch/meson.build index 24e20f45ec6..c4eb33c8569 100644 --- a/librz/arch/meson.build +++ b/librz/arch/meson.build @@ -347,14 +347,12 @@ if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_i # plugins arch_plugins_list += [ 'cbpf_cs', - 'bpf_cs', 'riscv_cs', ] # plugins sources arch_plugin_sources += [ 'p/arch_cbpf_cs.c', - 'p/arch_bpf_cs.c', 'p/arch_riscv_cs.c', ] endif @@ -363,11 +361,13 @@ if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_i # plugins arch_plugins_list += [ 'tricore_cs', + 'bpf_cs', ] # plugins sources arch_plugin_sources += [ 'p/arch_tricore_cs.c', + 'p/arch_bpf_cs.c', ] # isa sources diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index 5f8e99729a3..e2d064bed70 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -6,7 +6,6 @@ #include #include #include -#include typedef struct { csh handle; @@ -152,7 +151,10 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_MOD: op->type = RZ_ANALYSIS_OP_TYPE_MOD; break; case BPF_INS_XOR: op->type = RZ_ANALYSIS_OP_TYPE_XOR; break; case BPF_INS_MOV: op->type = RZ_ANALYSIS_OP_TYPE_MOV; break; - case BPF_INS_ARSH: op->type = RZ_ANALYSIS_OP_TYPE_SAR; break; + case BPF_INS_ARSH: + op->type = RZ_ANALYSIS_OP_TYPE_SAR; + op->sign = true; + break; /* ALU64 */ case BPF_INS_ADD64: op->type = RZ_ANALYSIS_OP_TYPE_ADD; break; @@ -169,13 +171,20 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_MOV64: op->type = RZ_ANALYSIS_OP_TYPE_MOV; break; case BPF_INS_ARSH64: op->type = RZ_ANALYSIS_OP_TYPE_SAR; + op->sign = true; break; #if CS_API_MAJOR >= 6 case BPF_INS_SDIV: - case BPF_INS_SDIV64: op->type = RZ_ANALYSIS_OP_TYPE_DIV; break; + case BPF_INS_SDIV64: + op->type = RZ_ANALYSIS_OP_TYPE_DIV; + op->sign = true; + break; case BPF_INS_SMOD: - case BPF_INS_SMOD64: op->type = RZ_ANALYSIS_OP_TYPE_MOD; break; + case BPF_INS_SMOD64: + op->type = RZ_ANALYSIS_OP_TYPE_MOD; + op->sign = true; + break; case BPF_INS_MOVSB: case BPF_INS_MOVSH: case BPF_INS_MOVSB64: @@ -201,11 +210,8 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_LDXB: case BPF_INS_LDXDW: op->type = RZ_ANALYSIS_OP_TYPE_LOAD; - if (insn->detail->bpf.op_count > 0) { - // op->reg = insn->detail->bpf.operands[0].reg; // destination register - } break; - case BPF_INS_LDW: // same value as BPF_INS_LD in Capstone v5 + case BPF_INS_LDW: case BPF_INS_LDH: case BPF_INS_LDB: case BPF_INS_LDDW: @@ -228,11 +234,8 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_STXB: case BPF_INS_STXDW: op->type = RZ_ANALYSIS_OP_TYPE_STORE; - if (insn->detail->bpf.op_count > 1) { - // op->reg = insn->detail->bpf.operands[1].reg; // source register - } break; - case BPF_INS_STW: // same value as BPF_INS_ST in Capstone v5 + case BPF_INS_STW: case BPF_INS_STH: case BPF_INS_STB: case BPF_INS_STDW: @@ -266,7 +269,7 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_JMP: #endif if (insn->detail->bpf.op_count > 0) { - op->jump = addr + 8 + insn->detail->bpf.operands[0].off * 8; + op->jump = addr + (insn->detail->bpf.operands[0].off + 1) * 8; } op->type = RZ_ANALYSIS_OP_TYPE_JMP; break; @@ -277,18 +280,24 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_JGE: case BPF_INS_JSET: case BPF_INS_JNE: - case BPF_INS_JSGT: - case BPF_INS_JSGE: case BPF_INS_JLT: case BPF_INS_JLE: + if (insn->detail->bpf.op_count > 2) { + op->jump = addr + (insn->detail->bpf.operands[2].off + 1) * 8; + } + op->fail = addr + 8; + op->type = RZ_ANALYSIS_OP_TYPE_CJMP; + break; + case BPF_INS_JSGT: + case BPF_INS_JSGE: case BPF_INS_JSLT: case BPF_INS_JSLE: - // For conditional jumps: operands[2] holds the true-branch offset if (insn->detail->bpf.op_count > 2) { op->jump = addr + (insn->detail->bpf.operands[2].off + 1) * 8; + op->fail = addr + 8; + op->type = RZ_ANALYSIS_OP_TYPE_CJMP; + op->sign = insn->detail->bpf.operands[2].is_signed; } - op->fail = addr + 8; // fall-through (false branch) - op->type = RZ_ANALYSIS_OP_TYPE_CJMP; break; /* Conditional jumps 32-bit operands */ @@ -297,7 +306,6 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { if (insn->detail->bpf.op_count > 0) { op->jump = addr + (insn->detail->bpf.operands[0].imm + 1) * 8; } - op->fail = addr + 8; op->type = RZ_ANALYSIS_OP_TYPE_JMP; break; case BPF_INS_JSET32: @@ -306,6 +314,7 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_JSGT32: case BPF_INS_JSGE32: op->sign = true; + /* fallthrough */ case BPF_INS_JEQ32: case BPF_INS_JGT32: case BPF_INS_JGE32: @@ -313,7 +322,7 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_JLT32: case BPF_INS_JLE32: if (insn->detail->bpf.op_count > 2) { - op->jump = addr + (insn->detail->bpf.operands[2].imm + 1) * 8; + op->jump = addr + (insn->detail->bpf.operands[2].off + 1) * 8; } op->fail = addr + 8; op->type = RZ_ANALYSIS_OP_TYPE_CJMP; @@ -322,14 +331,15 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_CALL: op->type = RZ_ANALYSIS_OP_TYPE_CALL; + if (insn->detail->bpf.op_count > 0) { + op->jump = addr + (insn->detail->bpf.operands[0].imm + 1) * 8; + } break; case BPF_INS_CALLX: op->type = RZ_ANALYSIS_OP_TYPE_RCALL; break; - /* Return */ case BPF_INS_EXIT: - case BPF_INS_RET: // cBPF return op->type = RZ_ANALYSIS_OP_TYPE_RET; break; @@ -374,7 +384,7 @@ static int bpf_analysis_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 return -1; } if (mask & RZ_ANALYSIS_OP_MASK_DISASM) { - op->mnemonic = rz_str_newf("%s%s%s", insn->mnemonic, insn->op_str[0] ? " " : "", insn->op_str); + op->mnemonic = rz_str_newf("%s %s", insn->mnemonic, insn->op_str); } if (mask & RZ_ANALYSIS_OP_MASK_OPEX) { op->opex = bpf_opex(ctx->handle, insn); diff --git a/librz/arch/p/asm/asm_bpf_cs.c b/librz/arch/p/asm/asm_bpf_cs.c index 759df26eb06..e02d0275d6e 100644 --- a/librz/arch/p/asm/asm_bpf_cs.c +++ b/librz/arch/p/asm/asm_bpf_cs.c @@ -2,8 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only #include -#include -#include #include "capstone.h" #include "cs_helper.h" diff --git a/test/db/analysis/bpf b/test/db/analysis/bpf new file mode 100644 index 00000000000..0736413baf2 --- /dev/null +++ b/test/db/analysis/bpf @@ -0,0 +1,230 @@ +NAME=ebpf analysis +FILE=bins/bpf/xdp_flowtable.bpf.o +ARGS=-a bpf -E little +CMDS=< 0x080001c8 mov64 r3, r10 +| ||||||| 0x080001d0 add64 r3, 0xffffffb8 +| ||||||| 0x080001d8 mov r5, 0x2 +| ||||||| 0x080001e0 stxb [r3], r5 +| ||||||| 0x080001e8 ldxb r5, [r2+0x1] +| ||||||| 0x080001f0 stxb [r3+0xc], r5 +| ||||||| 0x080001f8 ldxb r5, [r2+0x9] +| ||||||| 0x08000200 stxb [r3+0x1], r5 +| ||||||| 0x08000208 ldxh r5, [r2+0x2] +| ||||||| 0x08000210 be16 r5 +| ||||||| 0x08000218 stxh [r3+0x6], r5 +| ||||||| 0x08000220 ldxw r5, [r2+0xc] +| ||||||| 0x08000228 stxw [r3+0x10], r5 +| ||||||| 0x08000230 ldxw r2, [r2+0x10] +| ||||||| 0x08000238 stxw [r3+0x20], r2 +| ||||||| 0x08000240 ldxh r2, [r4] +| ||||||| 0x08000248 stxh [r3+0x2], r2 +| ||||||| 0x08000250 ldxh r2, [r4+0x2] +| ||||||| 0x08000258 stxh [r3+0x4], r2 +| ========< 0x08000260 ja +0x3c +| ||||||| ;-- LBB0_12: +| |||||`--> 0x08000268 mov64 r4, r10 +| ||||| | 0x08000270 add64 r4, 0xffffffb8 +| ||||| | 0x08000278 mov64 r5, r6 +| ||||| | 0x08000280 add64 r5, 0x3a +| |||||,==< 0x08000288 jgt r5, r3, +0x4a +| ||||||| 0x08000290 ldxb r5, [r2+0x7] +| ========< 0x08000298 jlt32 r5, 0x2, +0x48 +| ||||||| 0x080002a0 mov64 r5, r6 +| ||||||| 0x080002a8 add64 r5, 0x36 +| ||||||| 0x080002b0 ldxb r7, [r2+0x6] +| ========< 0x080002b8 jne32 r7, 0x6, +0x8 +| ||||||| 0x080002c0 add64 r6, 0x4a +| ========< 0x080002c8 jgt r6, r3, +0x42 +| ||||||| 0x080002d0 ldxh r3, [r5+0xc] +| ||||||| 0x080002d8 and r3, 0x100 +| ========< 0x080002e0 jne32 r3, 0x0, +0x3f +| ||||||| 0x080002e8 ldxh r3, [r5+0xc] +| ||||||| 0x080002f0 and r3, 0x400 +| ========< 0x080002f8 jne32 r3, 0x0, +0x3c +| ||||||| ;-- LBB0_18: +| --------> 0x08000300 mov64 r0, 0x20 +| ||||||| 0x08000308 mov64 r3, r4 +| ||||||| 0x08000310 add64 r3, r0 +| ||||||| 0x08000318 mov64 r0, 0x10 +| ||||||| 0x08000320 mov64 r6, r4 +| ||||||| 0x08000328 add64 r6, r0 +| ||||||| 0x08000330 mov64 r0, r10 +| ||||||| 0x08000338 add64 r0, 0xffffffb8 +| ||||||| 0x08000340 mov r7, 0xa +| ||||||| 0x08000348 stxb [r0], r7 +| ||||||| 0x08000350 ldxb r7, [r2+0x6] +| ||||||| 0x08000358 stxb [r0+0x1], r7 +| ||||||| 0x08000360 ldxh r7, [r2+0x4] +| ||||||| 0x08000368 be16 r7 +| ||||||| 0x08000370 stxh [r0+0x6], r7 +| ||||||| 0x08000378 mov64 r7, 0x8 +| ||||||| 0x08000380 mov64 r8, r2 +| ||||||| 0x08000388 add64 r8, r7 +| ||||||| 0x08000390 ldxw r7, [r8+0xc] +| ||||||| 0x08000398 stxw [r6+0xc], r7 +| ||||||| 0x080003a0 ldxw r7, [r8+0x8] +| ||||||| 0x080003a8 stxw [r6+0x8], r7 +| ||||||| 0x080003b0 ldxw r7, [r8+0x4] +| ||||||| 0x080003b8 stxw [r6+0x4], r7 +| ||||||| 0x080003c0 ldxw r6, [r2+0x8] +| ||||||| 0x080003c8 stxw [r4+0x10], r6 +| ||||||| 0x080003d0 mov64 r6, 0x18 +| ||||||| 0x080003d8 mov64 r7, r2 +| ||||||| 0x080003e0 add64 r7, r6 +| ||||||| 0x080003e8 ldxw r6, [r7+0x8] +| ||||||| 0x080003f0 stxw [r3+0x8], r6 +| ||||||| 0x080003f8 ldxw r6, [r7+0xc] +| ||||||| 0x08000400 stxw [r3+0xc], r6 +| ||||||| 0x08000408 ldxw r2, [r2+0x18] +| ||||||| 0x08000410 stxw [r4+0x20], r2 +| ||||||| 0x08000418 ldxw r2, [r7+0x4] +| ||||||| 0x08000420 stxw [r3+0x4], r2 +| ||||||| 0x08000428 ldxh r2, [r5] +| ||||||| 0x08000430 stxh [r0+0x2], r2 +| ||||||| 0x08000438 ldxh r2, [r5+0x2] +| ||||||| 0x08000440 stxh [r0+0x4], r2 +| ||||||| ; CODE XREF from sym.xdp_flowtable_do_lookup @ 0x8000260 +| ||||||| ;-- LBB0_19: +| --------> 0x08000448 mov64 r2, r10 +| ||||||| 0x08000450 add64 r2, 0xffffffb8 +| ||||||| 0x08000458 mov64 r3, r10 +| ||||||| 0x08000460 add64 r3, 0xfffffffc +| ||||||| 0x08000468 mov r4, 0x4 +| ||||||| 0x08000470 call -0x1 +| ||||||| 0x08000478 mov64 r1, r0 +| ||||||| 0x08000480 mov r0, 0x2 +| ========< 0x08000488 jeq r1, 0x0, +0xa +| ||||||| 0x08000490 mov64 r2, r10 +| ||||||| 0x08000498 add64 r2, 0xffffffb4 +| ||||||| 0x080004a0 lddw r1, 0x0 +| ||||||| 0x080004b0 call 0x1 ; int xdp_flowtable_do_lookup(struct xdp_md *ctx) +| ||||||| 0x080004b8 mov64 r1, r0 +| ||||||| ; CALL XREF from sym.xdp_flowtable_do_lookup @ 0x80004b0 +| ||||||| 0x080004c0 mov r0, 0x2 +| ========< 0x080004c8 jeq r1, 0x0, +0x2 +| ||||||| 0x080004d0 mov r2, 0x1 +| ||||||| 0x080004d8 aadd [r1], r2 +| ||||||| ;-- LBB0_22: +\ ```````-> 0x080004e0 exit +address: 0x8000338 +opcode: add64 r0, 0xffffffb8 +disasm: add64 r0, 0xffffffb8 +mnemonic: add64 +mask: ffffffffffffffff +prefix: 0 +id: 18 +bytes: 07000000b8ffffff +refptr: 0 +size: 8 +sign: false +type: add +cycles: 0 +opex: + operands: + - type: "reg" + value: "r0" + - type: "imm" + value: 0xffffffb8 +family: cpu +address: 0x80002e0 +opcode: jne32 r3, 0x0, +0x3f +disasm: jne32 r3, 0x0, +0x3f +mnemonic: jne32 +mask: ff00000000000000 +prefix: 0 +id: 89 +bytes: 56033f0000000000 +refptr: 0 +size: 8 +sign: false +type: cjmp +cycles: 0 +opex: + operands: + - type: "reg" + value: "r3" + - type: "imm" + value: 0x0 + - type: "off" + value: 0x3f +jump: 0x080004e0 +fail: 0x080002e8 +cond: al +family: cpu +pc = 0x0000000000000000 +sp = 0x0000000000000000 +R0 = 0x0000000000000000 +R1 = 0x0000000000000000 +R2 = 0x0000000000000000 +R3 = 0x0000000000000000 +R4 = 0x0000000000000000 +R5 = 0x0000000000000000 +R6 = 0x0000000000000000 +R7 = 0x0000000000000000 +R8 = 0x0000000000000000 +R9 = 0x0000000000000000 +EOF +RUN diff --git a/test/db/asm/bpf b/test/db/asm/bpf new file mode 100644 index 00000000000..8fe191f9de6 --- /dev/null +++ b/test/db/asm/bpf @@ -0,0 +1,50 @@ +d "add r4, 0xe15660e8" 04b497a8e86056e1 +d "ja -0x4f8f" 05c771b0431fb9f5 +d "add64 r6, 0x8bfe09c4" 07760128c409fe8b +d "add r2, r4" 0c420a4858c4ef37 +d "add64 r9, r0" 0f09405467242f88 +d "sub r9, 0x2a93076f" 14d9bab86f07932a +d "jeq r10, 0x4db79d1a, +0x389f" 156a9f381a9db74d +d "lddw r3, 0x2f2ba4d8ffa5f0de" 18a35c14def0a5ff9a7e10eed8a42b2f +d "sub r3, r7" 1c7368a48b5b931f +d "jeq r1, r2, +0x4d20" 1d21204de347af1b +d "ldabsw [skb-0x35e5be26]" 20c70c70da411aca +d "mul r6, 0x25ecefe3" 24b66966e3efec25 +d "jgt r9, -0x3f758ce7, +0x53da" 2589da5319738ac0 +d "mul64 r1, 0x8c2cabd4" 27b1961dd4ab2c8c +d "mul r8, r7" 2c7803f6292915fc +d "jgt r8, r1, -0x2a5" 2d185bfd8f533bf0 +d "ldabsb [skb+0x4b7c6685]" 305ffefc85667c4b +d "div r6, 0xcbd472e1" 34460000e172d4cb +d "jge r5, 0x3da1375b, -0x46be" 35a542b95b37a13d +d "div64 r6, r3" 3f3600007e07597a +d "ldindw [skb+r9]" 4095c2396be7d7c4 +d "or r6, 0x949202f7" 4416f798f7029294 +d "jset r2, 0x1e2de714, -0xd5e" 4512a2f214e72d1e +d "or64 r6, 0x4d5804be" 4736f4d5be04584d +d "or r1, r8" 4c810a66fc3261c4 +d "and r0, 0xfbabe84a" 54400a6a4ae8abfb +d "jne r9, -0x69374370, -0x7f5d" 55b9a38090bcc896 +d "ldxw r8, [r2-0x124e]" 6128b2edb8cfb5e4 +d "stw [r5-0x1f21], 0x78957d14" 62a5dfe0147d9578 +d "stxw [r7-0x30d1], r7" 63772fcf76b7d3fa +d "lsh r8, 0xebd29288" 6468c1f48892d2eb +d "ldxh r4, [r1-0x7139]" 6914c78e0bc1ad69 +d "stxh [r4-0xaa8], r3" 6b3458f5c8279e14 +d "ldxb r0, [r10-0x415]" 71a0ebfb3d6b5845 +d "stb [r2+0x1bc1], 0xdc4a2f25" 72e2c11b252f4adc +d "rsh r0, 0x3515042f" 74e023232f041535 +d "rsh64 r9, 0x23fa6e3c" 77093aa73c6efa23 +d "ldxdw r9, [r10+0x7b5c]" 79a95c7b161ffb01 +d "stdw [r8+0x46b], 0x7551f076" 7ad86b0476f05175 +d "neg r4" 8414d4af60e14118 +d "call 0x5dbd3d83" 85d3a5e2833dbd5d +d "exit" 95f2d18353a9099f +d "mov r1, 0x1f773ff9" b4a10000f93f771f +d "mov64 r0, 0x992a525b" b77000005b522a99 +d "mov r2, r7" bc720000c98a56d6 +d "mov64 r6, r8" bf860000b26d1403 +d "arsh r6, 0x2bc5687c" c4b6e2e07c68c52b +d "le64 r3" d4533f0c40000000 +d "be32 r2" dcb2a35020000000 +d "callx r2" 8d00000002000000 From 4f5e69e9a23015afec9f810d6d8505d559267ecc Mon Sep 17 00:00:00 2001 From: JagathP Date: Sat, 11 Apr 2026 22:43:56 +0530 Subject: [PATCH 03/16] Fixed ci error --- test/db/cmd/cmd_aL | 1 + test/db/cmd/cmd_list | 8 ++++++-- ystemctl list-timers systemd-tmpfiles-clean.timer | 9 +++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 ystemctl list-timers systemd-tmpfiles-clean.timer diff --git a/test/db/cmd/cmd_aL b/test/db/cmd/cmd_aL index 891249440f0..c95115f358c 100644 --- a/test/db/cmd/cmd_aL +++ b/test/db/cmd/cmd_aL @@ -12,6 +12,7 @@ a____ 16 32 64 arm.as LGPL3 as ARM Assembler (use RZ_ARM32_AS and RZ_AR adAeI 8 16 avr LGPL3 Atmel AVR disassembler adA_I 16 32 64 bf LGPL3 Brainfuck (by pancake, nibble) v4.0.0 _dA__ 16 c166 LGPL3 Siemens/Infineon C166 microcontroller disassembler +_dA__ 64 bpf LGPL3 EBPF disassembly plugin _dA__ 32 cbpf LGPL3 CBPF disassembly plugin _dA__ 32 chip8 LGPL3 Chip8 disassembler _dA__ 16 32 64 cil LGPL3 .NET CIL/MSIL (Common Intermediate Language) bytecode disassembler diff --git a/test/db/cmd/cmd_list b/test/db/cmd/cmd_list index 08a5332423a..1d5d13e3e87 100644 --- a/test/db/cmd/cmd_list +++ b/test/db/cmd/cmd_list @@ -750,6 +750,7 @@ adAeI 16 32 64 arm BSD ARM Capstone-based disassembler a____ 16 32 64 arm.as LGPL3 as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment) (by pancake) adAeI 8 16 avr LGPL3 Atmel AVR disassembler adA_I 16 32 64 bf LGPL3 Brainfuck (by pancake, nibble) v4.0.0 +_dA__ 64 bpf LGPL3 EBPF disassembly plugin _dA__ 16 c166 LGPL3 Siemens/Infineon C166 microcontroller disassembler _dA__ 32 cbpf LGPL3 CBPF disassembly plugin _dA__ 32 chip8 LGPL3 Chip8 disassembler @@ -810,7 +811,7 @@ _dA__ 16 xap PD Cambridge Consultants XAP4 RISC (CSR) disas _dA__ 32 xcore BSD XCore Capstone-based disassembler (by pancake) _dAeI 32 xtensa LGPL3 Tensilica Xtensa Capstone-based disassembler (by billow) adA__ 8 z80 GPL3 Zilog Z80 disassembler (by condret) -["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"alpha":{"bits":"32 64","license":"LGPL3","description":"DEC Alpha Capstone-based disassembler","features":"_dA__"},"amd29k":{"bits":"32 ","license":"LGPL3","description":"AMD 29k RISC disassembler","features":"_dA__","author":"deroad"},"arc":{"bits":"16 32 ","license":"GPL3","description":"Argonaut RISC Core","features":"_dA__"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"arm.as":{"bits":"16 32 64","license":"LGPL3","description":"as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment)","features":"a____","author":"pancake"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"c166":{"bits":"16 ","license":"LGPL3","description":"Siemens/Infineon C166 microcontroller disassembler","features":"_dA__"},"cbpf":{"bits":"32 ","license":"LGPL3","description":"CBPF disassembly plugin","features":"_dA__"},"chip8":{"bits":"32 ","license":"LGPL3","description":"Chip8 disassembler","features":"_dA__"},"cil":{"bits":"16 32 64","license":"LGPL3","description":".NET CIL/MSIL (Common Intermediate Language) bytecode disassembler","features":"_dA__"},"cr16":{"bits":"16 ","license":"LGPL3","description":"CompactRISC CR16 disassembler","features":"_dA__"},"cris":{"bits":"32 ","license":"GPL3","description":"Axis Communications 32-bit embedded processor disassembler","features":"_dA__","author":"pancake"},"dalvik":{"bits":"32 64","license":"LGPL3","description":"Dalvik (Android VM) bytecode disassembler","features":"adA__"},"dcpu16":{"bits":"16 ","license":"PD","description":"Mojang's DCPU-16 disassembler","features":"ad___"},"ebc":{"bits":"32 64","license":"LGPL3","description":"EFI bytecode disassembler","features":"_dA__","author":"Fedor Sakharov"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"h8500":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/500 disassembler","features":"_dA__","author":"billow"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"hppa":{"bits":"32 64","license":"LGPL3","description":"HP PA-RISC Capstone-based disassembler","features":"_dA__","author":"xvilka"},"i4004":{"bits":"4 ","license":"LGPL3","description":"Intel 4004 disassembler","features":"_dA__"},"i8080":{"bits":"8 ","license":"BSD","description":"Intel 8080 disassembler","features":"_dA__"},"java":{"bits":"32 ","license":"LGPL-3","description":"Java bytecode disassembler","features":"adA__","author":"deroad"},"lanai":{"bits":"32 ","license":"GPL3","description":"Google LANAI disassembler","features":"_d___"},"lh5801":{"bits":"8 ","license":"LGPL3","description":"SHARP LH5801 disassembler","features":"_d___"},"lm32":{"bits":"32 ","license":"BSD","description":"Lattice Micro 32 ISA disassembler","features":"_d___","author":"Felix Held"},"loongarch":{"bits":"32 64","license":"LGPL3","description":"Loongson LoongArch disassembler","features":"_dA__"},"luac":{"bits":"32 ","license":"LGPL3","description":"Lua bytecode (LUAC) disassembler","features":"adA__"},"m680x":{"bits":"8 32 ","license":"BSD","description":"Motorola 680X Capstone-based disassembler","features":"_dA__"},"m68k":{"bits":"32 ","license":"BSD","description":"Motorola 68K Capstone-based disassembler","features":"_dA__"},"malbolge":{"bits":"32 ","license":"LGPL3","description":"Malbolge Ternary VM bytecode disassembler","features":"_dA__","author":"condret"},"mcore":{"bits":"32 ","license":"LGPL3","description":"Motorola MCORE disassembler","features":"_dA__"},"mcs96":{"bits":"16 ","license":"LGPL3","description":"Intel MCS-96 disassembler","features":"_dA__","author":"condret"},"milstd1750":{"bits":"8 ","license":"MIT","description":"MIL-STD 1750 ISA disassembler","features":"_dA__"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"null":{"bits":"16 32 64","license":"MIT","description":"NULL (empty) disassembler","features":"adA__","author":"pancake","version":"1.0.0"},"or1k":{"bits":"32 ","license":"LGPL3","description":"OpenRISC 1000 disassembler","features":"_dA__"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"ppc.as":{"bits":"32 64","license":"LGPL3","description":"as PPC Assembler (use RZ_PPC_AS environment)","features":"a____","author":"eagleoflqj"},"propeller":{"bits":"32 ","license":"LGPL3","description":"Parallax Propeller disassembler","features":"_dA__"},"pyc":{"bits":"8 16 ","license":"LGPL3","description":"Python bytecode (PYC) disassembler","features":"_dA__"},"riscv":{"bits":"32 64","license":"BSD","description":"RISC-V Capstone-based disassembler","features":"_dA__"},"rl78":{"bits":"32 ","license":"LGPL3","description":"Renesas RL78 disassembler","features":"adA__","author":"Bastian Engel"},"rsp":{"bits":"32 ","license":"LGPL3","description":"Nintendo N64 Reality Signal Processor disassembler","features":"_dA__"},"rx":{"bits":"32 ","license":"LGPL3","description":"Renesas RX Family disassembler","features":"_dA__","author":"Heersin"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4/SuperH-3 disassembler","features":"adAeI","author":"DMaroo"},"snes":{"bits":"8 16 ","license":"LGPL3","description":"SuperNES CPU disassembler","features":"_dA__"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"spc700":{"bits":"16 ","license":"LGPL3","description":"Sony SPC700 (Nintendo SuperNES sound-chip) disassembler","features":"_dA__"},"sysz":{"bits":"32 64","license":"BSD","description":"IBM SystemZ (S/390) Capstone-based disassembler","features":"_dA__"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA_I"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"vax":{"bits":"32 ","license":"LGPL3","description":"DEC VAX-11 disassembler","features":"_dA__","author":"xvilka"},"wasm":{"bits":"32 ","license":"MIT","description":"WebAssembly disassembler","features":"adA__","author":"cgvwzq","version":"0.1.0"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"x86.as":{"bits":"16 32 64","license":"LGPL3","description":"Intel X86 GNU Assembler (Use RZ_X86_AS env)","features":"a____"},"x86.nasm":{"bits":"16 32 64","license":"LGPL3","description":"X86 nasm assembler","features":"a____"},"x86.nz":{"bits":"16 32 64","license":"LGPL3","description":"x86 handmade assembler","features":"a____"},"xap":{"bits":"16 ","license":"PD","description":"Cambridge Consultants XAP4 RISC (CSR) disassembler","features":"_dA__"},"xcore":{"bits":"32 ","license":"BSD","description":"XCore Capstone-based disassembler","features":"_dA__","author":"pancake"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"},"z80":{"bits":"8 ","license":"GPL3","description":"Zilog Z80 disassembler","features":"adA__","author":"condret"}] +["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"alpha":{"bits":"32 64","license":"LGPL3","description":"DEC Alpha Capstone-based disassembler","features":"_dA__"},"amd29k":{"bits":"32 ","license":"LGPL3","description":"AMD 29k RISC disassembler","features":"_dA__","author":"deroad"},"arc":{"bits":"16 32 ","license":"GPL3","description":"Argonaut RISC Core","features":"_dA__"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"arm.as":{"bits":"16 32 64","license":"LGPL3","description":"as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment)","features":"a____","author":"pancake"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"bpf":{"bits":"64","license":"LGPL3","description":"EBPF disassembly plugin","features":"__dA__"},"c166":{"bits":"16 ","license":"LGPL3","description":"Siemens/Infineon C166 microcontroller disassembler","features":"_dA__"},"cbpf":{"bits":"32 ","license":"LGPL3","description":"CBPF disassembly plugin","features":"_dA__"},"chip8":{"bits":"32 ","license":"LGPL3","description":"Chip8 disassembler","features":"_dA__"},"cil":{"bits":"16 32 64","license":"LGPL3","description":".NET CIL/MSIL (Common Intermediate Language) bytecode disassembler","features":"_dA__"},"cr16":{"bits":"16 ","license":"LGPL3","description":"CompactRISC CR16 disassembler","features":"_dA__"},"cris":{"bits":"32 ","license":"GPL3","description":"Axis Communications 32-bit embedded processor disassembler","features":"_dA__","author":"pancake"},"dalvik":{"bits":"32 64","license":"LGPL3","description":"Dalvik (Android VM) bytecode disassembler","features":"adA__"},"dcpu16":{"bits":"16 ","license":"PD","description":"Mojang's DCPU-16 disassembler","features":"ad___"},"ebc":{"bits":"32 64","license":"LGPL3","description":"EFI bytecode disassembler","features":"_dA__","author":"Fedor Sakharov"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"h8500":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/500 disassembler","features":"_dA__","author":"billow"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"hppa":{"bits":"32 64","license":"LGPL3","description":"HP PA-RISC Capstone-based disassembler","features":"_dA__","author":"xvilka"},"i4004":{"bits":"4 ","license":"LGPL3","description":"Intel 4004 disassembler","features":"_dA__"},"i8080":{"bits":"8 ","license":"BSD","description":"Intel 8080 disassembler","features":"_dA__"},"java":{"bits":"32 ","license":"LGPL-3","description":"Java bytecode disassembler","features":"adA__","author":"deroad"},"lanai":{"bits":"32 ","license":"GPL3","description":"Google LANAI disassembler","features":"_d___"},"lh5801":{"bits":"8 ","license":"LGPL3","description":"SHARP LH5801 disassembler","features":"_d___"},"lm32":{"bits":"32 ","license":"BSD","description":"Lattice Micro 32 ISA disassembler","features":"_d___","author":"Felix Held"},"loongarch":{"bits":"32 64","license":"LGPL3","description":"Loongson LoongArch disassembler","features":"_dA__"},"luac":{"bits":"32 ","license":"LGPL3","description":"Lua bytecode (LUAC) disassembler","features":"adA__"},"m680x":{"bits":"8 32 ","license":"BSD","description":"Motorola 680X Capstone-based disassembler","features":"_dA__"},"m68k":{"bits":"32 ","license":"BSD","description":"Motorola 68K Capstone-based disassembler","features":"_dA__"},"malbolge":{"bits":"32 ","license":"LGPL3","description":"Malbolge Ternary VM bytecode disassembler","features":"_dA__","author":"condret"},"mcore":{"bits":"32 ","license":"LGPL3","description":"Motorola MCORE disassembler","features":"_dA__"},"mcs96":{"bits":"16 ","license":"LGPL3","description":"Intel MCS-96 disassembler","features":"_dA__","author":"condret"},"milstd1750":{"bits":"8 ","license":"MIT","description":"MIL-STD 1750 ISA disassembler","features":"_dA__"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"null":{"bits":"16 32 64","license":"MIT","description":"NULL (empty) disassembler","features":"adA__","author":"pancake","version":"1.0.0"},"or1k":{"bits":"32 ","license":"LGPL3","description":"OpenRISC 1000 disassembler","features":"_dA__"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"ppc.as":{"bits":"32 64","license":"LGPL3","description":"as PPC Assembler (use RZ_PPC_AS environment)","features":"a____","author":"eagleoflqj"},"propeller":{"bits":"32 ","license":"LGPL3","description":"Parallax Propeller disassembler","features":"_dA__"},"pyc":{"bits":"8 16 ","license":"LGPL3","description":"Python bytecode (PYC) disassembler","features":"_dA__"},"riscv":{"bits":"32 64","license":"BSD","description":"RISC-V Capstone-based disassembler","features":"_dA__"},"rl78":{"bits":"32 ","license":"LGPL3","description":"Renesas RL78 disassembler","features":"adA__","author":"Bastian Engel"},"rsp":{"bits":"32 ","license":"LGPL3","description":"Nintendo N64 Reality Signal Processor disassembler","features":"_dA__"},"rx":{"bits":"32 ","license":"LGPL3","description":"Renesas RX Family disassembler","features":"_dA__","author":"Heersin"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4/SuperH-3 disassembler","features":"adAeI","author":"DMaroo"},"snes":{"bits":"8 16 ","license":"LGPL3","description":"SuperNES CPU disassembler","features":"_dA__"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"spc700":{"bits":"16 ","license":"LGPL3","description":"Sony SPC700 (Nintendo SuperNES sound-chip) disassembler","features":"_dA__"},"sysz":{"bits":"32 64","license":"BSD","description":"IBM SystemZ (S/390) Capstone-based disassembler","features":"_dA__"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA_I"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"vax":{"bits":"32 ","license":"LGPL3","description":"DEC VAX-11 disassembler","features":"_dA__","author":"xvilka"},"wasm":{"bits":"32 ","license":"MIT","description":"WebAssembly disassembler","features":"adA__","author":"cgvwzq","version":"0.1.0"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"x86.as":{"bits":"16 32 64","license":"LGPL3","description":"Intel X86 GNU Assembler (Use RZ_X86_AS env)","features":"a____"},"x86.nasm":{"bits":"16 32 64","license":"LGPL3","description":"X86 nasm assembler","features":"a____"},"x86.nz":{"bits":"16 32 64","license":"LGPL3","description":"x86 handmade assembler","features":"a____"},"xap":{"bits":"16 ","license":"PD","description":"Cambridge Consultants XAP4 RISC (CSR) disassembler","features":"_dA__"},"xcore":{"bits":"32 ","license":"BSD","description":"XCore Capstone-based disassembler","features":"_dA__","author":"pancake"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"},"z80":{"bits":"8 ","license":"GPL3","description":"Zilog Z80 disassembler","features":"adA__","author":"condret"}] name bits features license version author description ---------------------------------------------------------------------------------------------------------------------------------- _dAeI 8 16 6502 LGPL3 6502/NES/C64/Tamagotchi/T-1000 CPU @@ -822,6 +823,7 @@ adAeI 16 32 64 arm BSD ARM Capstone-based dis a____ 16 32 64 arm.as LGPL3 pancake as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment) adAeI 8 16 avr LGPL3 Atmel AVR disassembler adA_I 16 32 64 bf LGPL3 4.0.0 pancake, nibble Brainfuck +_dA__ 64 bpf LGPL3 EBPF disassembly plugin _dA__ 16 c166 LGPL3 Siemens/Infineon C166 microcontroller disassembler _dA__ 32 cbpf LGPL3 CBPF disassembly plugin _dA__ 32 chip8 LGPL3 Chip8 disassembler @@ -891,6 +893,7 @@ arm arm.as avr bf +bpf c166 cbpf chip8 @@ -1032,6 +1035,7 @@ arm arm.as avr bf +bpf c166 cbpf chip8 @@ -1162,7 +1166,7 @@ NAME=Print the asm/analysis plugins in JSON FILE== CMDS=Laj EXPECT=< Date: Sat, 11 Apr 2026 22:44:33 +0530 Subject: [PATCH 04/16] Made few extra changes --- librz/arch/p/analysis/analysis_bpf_cs.c | 39 ++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index e2d064bed70..f5dc381fef7 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -206,16 +206,44 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { /* Load */ case BPF_INS_LDXW: + op->refptr = 4; + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + op->direction = RZ_ANALYSIS_OP_DIR_READ; + break; case BPF_INS_LDXH: + op->refptr = 2; + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + op->direction = RZ_ANALYSIS_OP_DIR_READ; + break; case BPF_INS_LDXB: + op->refptr = 1; + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + op->direction = RZ_ANALYSIS_OP_DIR_READ; + break; case BPF_INS_LDXDW: + op->refptr = 8; op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + op->direction = RZ_ANALYSIS_OP_DIR_READ; break; case BPF_INS_LDW: + op->refptr = 4; + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + op->direction = RZ_ANALYSIS_OP_DIR_READ; + break; case BPF_INS_LDH: + op->refptr = 2; + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + op->direction = RZ_ANALYSIS_OP_DIR_READ; + break; case BPF_INS_LDB: + op->refptr = 1; + op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + op->direction = RZ_ANALYSIS_OP_DIR_READ; + break; case BPF_INS_LDDW: + op->refptr = 8; op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + op->direction = RZ_ANALYSIS_OP_DIR_READ; break; #if CS_API_MAJOR >= 6 case BPF_INS_LDABSW: @@ -225,6 +253,7 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_LDINDH: case BPF_INS_LDINDB: op->type = RZ_ANALYSIS_OP_TYPE_LOAD; + op->direction = RZ_ANALYSIS_OP_DIR_READ; break; #endif /* CS_API_MAJOR >= 6 */ @@ -234,16 +263,20 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_STXB: case BPF_INS_STXDW: op->type = RZ_ANALYSIS_OP_TYPE_STORE; + op->direction = RZ_ANALYSIS_OP_DIR_WRITE; break; case BPF_INS_STW: case BPF_INS_STH: case BPF_INS_STB: case BPF_INS_STDW: op->type = RZ_ANALYSIS_OP_TYPE_STORE; + op->direction = RZ_ANALYSIS_OP_DIR_WRITE; break; case BPF_INS_XADDW: case BPF_INS_XADDDW: - op->type = RZ_ANALYSIS_OP_TYPE_STORE; // atomic add-and-store + op->type = RZ_ANALYSIS_OP_TYPE_STORE; + // atomic add-and-store + op->direction = RZ_ANALYSIS_OP_DIR_WRITE; break; /* @@ -331,9 +364,6 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_CALL: op->type = RZ_ANALYSIS_OP_TYPE_CALL; - if (insn->detail->bpf.op_count > 0) { - op->jump = addr + (insn->detail->bpf.operands[0].imm + 1) * 8; - } break; case BPF_INS_CALLX: op->type = RZ_ANALYSIS_OP_TYPE_RCALL; @@ -389,6 +419,7 @@ static int bpf_analysis_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 if (mask & RZ_ANALYSIS_OP_MASK_OPEX) { op->opex = bpf_opex(ctx->handle, insn); } + op->nopcode = 1; ebpf_op_type(op, addr, insn); cs_free(insn, n); return op->size; From 652025e9a7f4053f0beef08a28b383bceef26373 Mon Sep 17 00:00:00 2001 From: JagathP Date: Sun, 26 Apr 2026 17:06:53 +0530 Subject: [PATCH 05/16] Made minor change --- librz/arch/p/analysis/analysis_bpf_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index f5dc381fef7..1f97210a576 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -13,7 +13,7 @@ typedef struct { } BPFContext; static char *bpf_get_reg_profile(RzAnalysis *analysis) { - const char *ebpg_reg_profile = + const char *ebpf_reg_profile = "=PC pc\n" "=SP R10\n" "=R0 R0\n" @@ -35,7 +35,7 @@ static char *bpf_get_reg_profile(RzAnalysis *analysis) { "gpr R8 .64 80 0\n" "gpr R9 .64 88 0\n"; - return rz_str_dup(ebpg_reg_profile); + return rz_str_dup(ebpf_reg_profile); } static RzStructuredData *bpf_opex(csh handle, cs_insn *insn) { From 9f8c527d68cc0fd1f3d57348552a163150124777 Mon Sep 17 00:00:00 2001 From: JagathP Date: Sun, 26 Apr 2026 17:51:16 +0530 Subject: [PATCH 06/16] Fixed minor error in register profile --- librz/arch/p/analysis/analysis_bpf_cs.c | 24 ++++++++++++------------ test/db/analysis/bpf | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index 1f97210a576..730a5649ba5 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -22,18 +22,18 @@ static char *bpf_get_reg_profile(RzAnalysis *analysis) { "=A2 R3\n" "=A3 R4\n" "=A4 R5\n" - "gpr pc .64 0 0\n" // program counter - "gpr sp .64 8 0\n" // stack pointer - "gpr R0 .64 16 0\n" - "gpr R1 .64 24 0\n" - "gpr R2 .64 32 0\n" - "gpr R3 .64 40 0\n" - "gpr R4 .64 48 0\n" - "gpr R5 .64 56 0\n" - "gpr R6 .64 64 0\n" - "gpr R7 .64 72 0\n" - "gpr R8 .64 80 0\n" - "gpr R9 .64 88 0\n"; + "gpr pc .64 0 0\n" // program counter + "gpr R0 .64 8 0\n" + "gpr R1 .64 16 0\n" + "gpr R2 .64 24 0\n" + "gpr R3 .64 32 0\n" + "gpr R4 .64 40 0\n" + "gpr R5 .64 48 0\n" + "gpr R6 .64 56 0\n" + "gpr R7 .64 64 0\n" + "gpr R8 .64 72 0\n" + "gpr R9 .64 80 0\n" + "gpr R10 .64 88 0\n"; // stack pointer return rz_str_dup(ebpf_reg_profile); } diff --git a/test/db/analysis/bpf b/test/db/analysis/bpf index 0736413baf2..6985ba2c6d9 100644 --- a/test/db/analysis/bpf +++ b/test/db/analysis/bpf @@ -215,7 +215,6 @@ fail: 0x080002e8 cond: al family: cpu pc = 0x0000000000000000 -sp = 0x0000000000000000 R0 = 0x0000000000000000 R1 = 0x0000000000000000 R2 = 0x0000000000000000 @@ -226,5 +225,6 @@ R6 = 0x0000000000000000 R7 = 0x0000000000000000 R8 = 0x0000000000000000 R9 = 0x0000000000000000 +R10 = 0x0000000000000000 EOF RUN From 82b4938942aba74f629bf8d397b2ca497cd27ca0 Mon Sep 17 00:00:00 2001 From: JagathP Date: Mon, 11 May 2026 12:10:24 +0530 Subject: [PATCH 07/16] Fixed minor errors and improved disassembly and analysis plugins --- librz/arch/p/analysis/analysis_bpf_cs.c | 23 ++++++++++++++++++----- librz/arch/p/asm/asm_bpf_cs.c | 18 +++++++----------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index 730a5649ba5..72e8e4d2b29 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: 2026 Jagath-P jagathp0210@gmail.com // SPDX-License-Identifier: LGPL-3.0-only -#include "rz_util/rz_str.h" -#include #include #include #include @@ -68,17 +66,32 @@ static RzStructuredData *bpf_opex(csh handle, cs_insn *insn) { } case BPF_OP_IMM: rz_structured_data_map_add_string(operand, "type", "imm"); - rz_structured_data_map_add_unsigned(operand, "value", op->imm, true); + if (op->is_signed) { + rz_structured_data_map_add_signed(operand, "value", op->imm); + } else { + rz_structured_data_map_add_unsigned(operand, "value", op->imm, true); + } break; case BPF_OP_OFF: rz_structured_data_map_add_string(operand, "type", "off"); - rz_structured_data_map_add_unsigned(operand, "value", op->off, true); + if (op->is_signed) { + rz_structured_data_map_add_signed(operand, "value", op->off); + } else { + rz_structured_data_map_add_unsigned(operand, "value", op->off, true); + } break; case BPF_OP_MEM: { const char *base_name = cs_reg_name(handle, (unsigned int)op->mem.base); rz_structured_data_map_add_string(operand, "type", "mem"); rz_structured_data_map_add_string(operand, "base", base_name ? base_name : "unknown"); - rz_structured_data_map_add_unsigned(operand, "disp", op->mem.disp, true); + if (op->is_signed) { + rz_structured_data_map_add_signed(operand, "disp", op->mem.disp); + } else { + rz_structured_data_map_add_unsigned(operand, "disp", op->mem.disp, true); + } + if (op->is_pkt) { + rz_structured_data_map_add_string(operand, "is_packet", "true"); + } break; } case BPF_OP_MMEM: diff --git a/librz/arch/p/asm/asm_bpf_cs.c b/librz/arch/p/asm/asm_bpf_cs.c index e02d0275d6e..261b61cc571 100644 --- a/librz/arch/p/asm/asm_bpf_cs.c +++ b/librz/arch/p/asm/asm_bpf_cs.c @@ -10,9 +10,8 @@ CAPSTONE_DEFINE_PLUGIN_FUNCTIONS(bpf_asm); static int bpf_disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) { CapstoneContext *ctx = (CapstoneContext *)a->plugin_data; cs_insn *insn; - int n, ret = -1; + int n; cs_mode mode = CS_MODE_BPF_EXTENDED | (a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN); - memset(op, 0, sizeof(RzAsmOp)); op->size = 8; if (ctx->omode != mode) { if (ctx->handle) { @@ -21,9 +20,9 @@ static int bpf_disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) ctx->omode = mode; } if (!ctx->handle) { - ret = cs_open(CS_ARCH_BPF, mode, &ctx->handle); - if (ret) { - return ret; + cs_err err = cs_open(CS_ARCH_BPF, mode, &ctx->handle); + if (err != CS_ERR_OK) { + return -1; } cs_option(ctx->handle, CS_OPT_DETAIL, CS_OPT_OFF); } @@ -31,24 +30,21 @@ static int bpf_disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) n = cs_disasm(ctx->handle, buf, len, a->pc, 1, &insn); if (n < 1) { rz_asm_op_set_asm(op, "invalid"); - ret = -1; cs_free(insn, n); - return ret; + return -1; } if (insn->size != 8 && insn->size != 16) { cs_free(insn, n); - ret = -1; - return ret; + return -1; } op->size = insn->size; - ret = op->size; if (insn->op_str[0]) { rz_asm_op_setf_asm(op, "%s %s", insn->mnemonic, insn->op_str); } else { rz_asm_op_set_asm(op, insn->mnemonic); } cs_free(insn, n); - return ret; + return op->size; } RzAsmPlugin rz_asm_plugin_bpf_cs = { From 9037342066d4fba9d9e0440bfaa93e834d6016cf Mon Sep 17 00:00:00 2001 From: JagathP Date: Mon, 11 May 2026 12:14:41 +0530 Subject: [PATCH 08/16] Improved test coverage --- test/db/analysis/bpf | 357 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 355 insertions(+), 2 deletions(-) diff --git a/test/db/analysis/bpf b/test/db/analysis/bpf index 6985ba2c6d9..bbbda332791 100644 --- a/test/db/analysis/bpf +++ b/test/db/analysis/bpf @@ -207,9 +207,9 @@ opex: - type: "reg" value: "r3" - type: "imm" - value: 0x0 + value: 0 - type: "off" - value: 0x3f + value: 63 jump: 0x080004e0 fail: 0x080002e8 cond: al @@ -228,3 +228,356 @@ R9 = 0x0000000000000000 R10 = 0x0000000000000000 EOF RUN + +NAME=ebpf covering more instructions +FILE= +CMDS=< Date: Mon, 25 May 2026 13:33:37 +0530 Subject: [PATCH 09/16] Resolved merge conflict --- test/db/analysis/bpf | 3 +-- test/db/cmd/cmd_aL | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/db/analysis/bpf b/test/db/analysis/bpf index bbbda332791..aa3d35da2a0 100644 --- a/test/db/analysis/bpf +++ b/test/db/analysis/bpf @@ -160,9 +160,8 @@ EXPECT=< Date: Mon, 25 May 2026 15:43:13 +0530 Subject: [PATCH 10/16] Fix email formatting --- librz/arch/p/analysis/analysis_bpf_cs.c | 2 +- librz/arch/p/arch_bpf_cs.c | 2 +- librz/arch/p/asm/asm_bpf_cs.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index 72e8e4d2b29..3ad97100b3c 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2026 Jagath-P jagathp0210@gmail.com +// SPDX-FileCopyrightText: 2026 Jagath-P // SPDX-License-Identifier: LGPL-3.0-only #include diff --git a/librz/arch/p/arch_bpf_cs.c b/librz/arch/p/arch_bpf_cs.c index 1cadebf0ac3..3d7639a74f3 100644 --- a/librz/arch/p/arch_bpf_cs.c +++ b/librz/arch/p/arch_bpf_cs.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2026 Jagath-P jagathp0210@gmail.com +// SPDX-FileCopyrightText: 2026 Jagath-P // SPDX-License-Identifier: LGPL-3.0-only #include diff --git a/librz/arch/p/asm/asm_bpf_cs.c b/librz/arch/p/asm/asm_bpf_cs.c index 261b61cc571..4dd23c8fc40 100644 --- a/librz/arch/p/asm/asm_bpf_cs.c +++ b/librz/arch/p/asm/asm_bpf_cs.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2026 Jagath-P jagathp0210@gmail.com +// SPDX-FileCopyrightText: 2026 Jagath-P // SPDX-License-Identifier: LGPL-3.0-only #include From 7ad14a28db495c98a8fdb8d267b65ff246901562 Mon Sep 17 00:00:00 2001 From: JagathP Date: Wed, 17 Jun 2026 21:58:03 +0530 Subject: [PATCH 11/16] Fix instruction leaks,warns wherever needed --- librz/arch/p/asm/asm_bpf_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/librz/arch/p/asm/asm_bpf_cs.c b/librz/arch/p/asm/asm_bpf_cs.c index 4dd23c8fc40..abc2e68b44d 100644 --- a/librz/arch/p/asm/asm_bpf_cs.c +++ b/librz/arch/p/asm/asm_bpf_cs.c @@ -22,6 +22,7 @@ static int bpf_disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) if (!ctx->handle) { cs_err err = cs_open(CS_ARCH_BPF, mode, &ctx->handle); if (err != CS_ERR_OK) { + rz_warn_if_reached(); return -1; } cs_option(ctx->handle, CS_OPT_DETAIL, CS_OPT_OFF); From 5e08f666ce92a77bbf57a458db8bc21810dd3919 Mon Sep 17 00:00:00 2001 From: JagathP Date: Wed, 17 Jun 2026 22:06:09 +0530 Subject: [PATCH 12/16] Gate ebpf plugin to capstone-next, fix analysis bugs --- librz/arch/meson.build | 4 +- librz/arch/p/analysis/analysis_bpf_cs.c | 84 ++++++++++++------------- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/librz/arch/meson.build b/librz/arch/meson.build index c4eb33c8569..23ccca5cfc9 100644 --- a/librz/arch/meson.build +++ b/librz/arch/meson.build @@ -346,12 +346,14 @@ arch_isa_includes = [ if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_int() > 6 # plugins arch_plugins_list += [ + 'bpf_cs', 'cbpf_cs', 'riscv_cs', ] # plugins sources arch_plugin_sources += [ + 'p/arch_bpf_cs.c', 'p/arch_cbpf_cs.c', 'p/arch_riscv_cs.c', ] @@ -361,13 +363,11 @@ if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_i # plugins arch_plugins_list += [ 'tricore_cs', - 'bpf_cs', ] # plugins sources arch_plugin_sources += [ 'p/arch_tricore_cs.c', - 'p/arch_bpf_cs.c', ] # isa sources diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index 3ad97100b3c..f3d7cac3a64 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2026 Jagath-P // SPDX-License-Identifier: LGPL-3.0-only +#include "rz_util/rz_assert.h" +#include "rz_util/rz_structured_data.h" #include #include #include @@ -67,7 +69,11 @@ static RzStructuredData *bpf_opex(csh handle, cs_insn *insn) { case BPF_OP_IMM: rz_structured_data_map_add_string(operand, "type", "imm"); if (op->is_signed) { - rz_structured_data_map_add_signed(operand, "value", op->imm); + if (op->imm & (0xffffffff00000000)) { + rz_structured_data_map_add_signed(operand, "value", (st64)op->imm); + } else { + rz_structured_data_map_add_signed(operand, "value", (st64)(st32)op->imm); + } } else { rz_structured_data_map_add_unsigned(operand, "value", op->imm, true); } @@ -75,7 +81,7 @@ static RzStructuredData *bpf_opex(csh handle, cs_insn *insn) { case BPF_OP_OFF: rz_structured_data_map_add_string(operand, "type", "off"); if (op->is_signed) { - rz_structured_data_map_add_signed(operand, "value", op->off); + rz_structured_data_map_add_signed(operand, "value", (st32)(st16)op->off); } else { rz_structured_data_map_add_unsigned(operand, "value", op->off, true); } @@ -84,28 +90,18 @@ static RzStructuredData *bpf_opex(csh handle, cs_insn *insn) { const char *base_name = cs_reg_name(handle, (unsigned int)op->mem.base); rz_structured_data_map_add_string(operand, "type", "mem"); rz_structured_data_map_add_string(operand, "base", base_name ? base_name : "unknown"); - if (op->is_signed) { - rz_structured_data_map_add_signed(operand, "disp", op->mem.disp); - } else { - rz_structured_data_map_add_unsigned(operand, "disp", op->mem.disp, true); - } if (op->is_pkt) { - rz_structured_data_map_add_string(operand, "is_packet", "true"); + rz_structured_data_map_add_boolean(operand, "is_packet", true); + rz_structured_data_map_add_unsigned(operand, "disp", op->mem.disp, true); + } else { + if (op->is_signed) { + rz_structured_data_map_add_signed(operand, "disp", (st32)(st16)op->mem.disp); + } else { + rz_structured_data_map_add_unsigned(operand, "disp", op->mem.disp, true); + } } break; } - case BPF_OP_MMEM: - rz_structured_data_map_add_string(operand, "type", "mmem"); - rz_structured_data_map_add_unsigned(operand, "value", op->mmem, true); - break; - case BPF_OP_MSH: - rz_structured_data_map_add_string(operand, "type", "msh"); - rz_structured_data_map_add_unsigned(operand, "value", op->msh, true); - break; - case BPF_OP_EXT: - rz_structured_data_map_add_string(operand, "type", "ext"); - rz_structured_data_map_add_unsigned(operand, "value", op->ext, true); - break; default: rz_structured_data_map_add_string(operand, "type", "invalid"); break; @@ -150,6 +146,7 @@ static int bpf_arch_info(RzAnalysis *a, RzAnalysisInfoType query) { return -1; } } + static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { switch (insn->id) { case BPF_INS_ADD: op->type = RZ_ANALYSIS_OP_TYPE_ADD; break; @@ -187,7 +184,6 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { op->sign = true; break; -#if CS_API_MAJOR >= 6 case BPF_INS_SDIV: case BPF_INS_SDIV64: op->type = RZ_ANALYSIS_OP_TYPE_DIV; @@ -205,7 +201,6 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { op->type = RZ_ANALYSIS_OP_TYPE_MOV; op->sign = true; break; -#endif /* CS_API_MAJOR >= 6 */ /* Byte Swap */ case BPF_INS_LE16: @@ -258,7 +253,7 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { op->type = RZ_ANALYSIS_OP_TYPE_LOAD; op->direction = RZ_ANALYSIS_OP_DIR_READ; break; -#if CS_API_MAJOR >= 6 + case BPF_INS_LDABSW: case BPF_INS_LDABSH: case BPF_INS_LDABSB: @@ -268,7 +263,6 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { op->type = RZ_ANALYSIS_OP_TYPE_LOAD; op->direction = RZ_ANALYSIS_OP_DIR_READ; break; -#endif /* CS_API_MAJOR >= 6 */ /* Store */ case BPF_INS_STXW: @@ -296,7 +290,6 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { * Extended atomics (AFADD, AFOR, AFAND, AFXOR, AADD, AOR, AAND, AXOR) * only exist in Capstone v6 onwards. */ -#if CS_API_MAJOR >= 6 case BPF_INS_AADD: case BPF_INS_AOR: case BPF_INS_AAND: @@ -307,20 +300,24 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_AFXOR: op->type = RZ_ANALYSIS_OP_TYPE_STORE; break; -#endif /* CS_API_MAJOR >= 6 */ -#if CS_API_MAJOR >= 6 case BPF_INS_JA: -#else - case BPF_INS_JMP: -#endif if (insn->detail->bpf.op_count > 0) { op->jump = addr + (insn->detail->bpf.operands[0].off + 1) * 8; + } else { + op->type = RZ_ANALYSIS_OP_TYPE_ILL; + break; } op->type = RZ_ANALYSIS_OP_TYPE_JMP; break; /* Conditional jump */ + case BPF_INS_JSGT: + case BPF_INS_JSGE: + case BPF_INS_JSLT: + case BPF_INS_JSLE: + op->sign = true; + /* fall through */ case BPF_INS_JEQ: case BPF_INS_JGT: case BPF_INS_JGE: @@ -330,31 +327,25 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_JLE: if (insn->detail->bpf.op_count > 2) { op->jump = addr + (insn->detail->bpf.operands[2].off + 1) * 8; + } else { + op->type = RZ_ANALYSIS_OP_TYPE_ILL; + break; } op->fail = addr + 8; op->type = RZ_ANALYSIS_OP_TYPE_CJMP; break; - case BPF_INS_JSGT: - case BPF_INS_JSGE: - case BPF_INS_JSLT: - case BPF_INS_JSLE: - if (insn->detail->bpf.op_count > 2) { - op->jump = addr + (insn->detail->bpf.operands[2].off + 1) * 8; - op->fail = addr + 8; - op->type = RZ_ANALYSIS_OP_TYPE_CJMP; - op->sign = insn->detail->bpf.operands[2].is_signed; - } - break; /* Conditional jumps 32-bit operands */ -#if CS_API_MAJOR >= 6 case BPF_INS_JAL: if (insn->detail->bpf.op_count > 0) { op->jump = addr + (insn->detail->bpf.operands[0].imm + 1) * 8; + } else { + op->type = RZ_ANALYSIS_OP_TYPE_ILL; + break; } op->type = RZ_ANALYSIS_OP_TYPE_JMP; break; - case BPF_INS_JSET32: + case BPF_INS_JSLT32: case BPF_INS_JSLE32: case BPF_INS_JSGT32: @@ -367,13 +358,16 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_JNE32: case BPF_INS_JLT32: case BPF_INS_JLE32: + case BPF_INS_JSET32: if (insn->detail->bpf.op_count > 2) { op->jump = addr + (insn->detail->bpf.operands[2].off + 1) * 8; + } else { + op->type = RZ_ANALYSIS_OP_TYPE_ILL; + break; } op->fail = addr + 8; op->type = RZ_ANALYSIS_OP_TYPE_CJMP; break; -#endif /* CS_API_MAJOR >= 6 */ case BPF_INS_CALL: op->type = RZ_ANALYSIS_OP_TYPE_CALL; @@ -407,6 +401,7 @@ static int bpf_analysis_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 if (!ctx->handle) { cs_err err = cs_open(CS_ARCH_BPF, mode, &ctx->handle); if (err != CS_ERR_OK) { + rz_warn_if_reached(); return -1; } cs_option(ctx->handle, CS_OPT_DETAIL, CS_OPT_ON); @@ -418,6 +413,7 @@ static int bpf_analysis_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 if (mask & RZ_ANALYSIS_OP_MASK_DISASM) { op->mnemonic = strdup("invalid"); } + cs_free(insn, n); return -1; } op->size = insn->size; From b53546debe1df4e464ef240d3f05ac3e8454d1bf Mon Sep 17 00:00:00 2001 From: JagathP Date: Wed, 17 Jun 2026 22:21:42 +0530 Subject: [PATCH 13/16] Increase test coverage for jumps and call instructions --- librz/arch/p/analysis/analysis_bpf_cs.c | 6 +- test/db/analysis/bpf | 477 +++++++++++++++++- test/db/asm/bpf | 85 ++++ test/db/cmd/cmd_list | 2 +- ...l list-timers systemd-tmpfiles-clean.timer | 9 - 5 files changed, 563 insertions(+), 16 deletions(-) delete mode 100644 ystemctl list-timers systemd-tmpfiles-clean.timer diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index f3d7cac3a64..8eb15f7e9bc 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -92,7 +92,11 @@ static RzStructuredData *bpf_opex(csh handle, cs_insn *insn) { rz_structured_data_map_add_string(operand, "base", base_name ? base_name : "unknown"); if (op->is_pkt) { rz_structured_data_map_add_boolean(operand, "is_packet", true); - rz_structured_data_map_add_unsigned(operand, "disp", op->mem.disp, true); + if (op->is_signed) { + rz_structured_data_map_add_signed(operand, "disp", (st32)op->mem.disp); + } else { + rz_structured_data_map_add_unsigned(operand, "disp", op->mem.disp, true); + } } else { if (op->is_signed) { rz_structured_data_map_add_signed(operand, "disp", (st32)(st16)op->mem.disp); diff --git a/test/db/analysis/bpf b/test/db/analysis/bpf index aa3d35da2a0..dbc908f6d5a 100644 --- a/test/db/analysis/bpf +++ b/test/db/analysis/bpf @@ -275,6 +275,57 @@ echo '----------' wx bf860000b26d1403 ao echo '----------' +wx ae21050000000000 +ao +echo '----------' +wx 6d21050000000000 +ao +echo '----------' +wx 7521050000000000 +ao +echo '----------' +wx 8d00000002000000 +ao +echo '----------' +wx 85d3a5e2833dbd5d +ao +echo '----------' +wx 2589da5319738ac0 +ao +echo '----------' +wx 35a542b95b37a13d +ao +echo '----------' +wx 4512a2f214e72d1e +ao +echo '----------' +wx 55b9a38090bcc896 +ao +echo '----------' +wx a5d4ef79d3bbdefd +ao +echo '----------' +wx bd1980e82985cf51 +ao +echo '----------' +wx d5e9f6b250fdb0e5 +ao +echo '----------' +wx dd95bfb1f25f7bc4 +ao +echo '----------' +wx 05c771b0431fb9f5 +ao +echo '----------' +wx 06c70fcc431fb9f5 +ao +echo '----------' +wx d6c70fcc431fb9f5 +ao +echo '----------' +wx 56c70fcc431fb9f5 +ao +echo '----------' EOF EXPECT=< Date: Wed, 8 Jul 2026 22:12:26 +0530 Subject: [PATCH 14/16] Add authorship --- librz/arch/p/analysis/analysis_bpf_cs.c | 40 +++++++++++++++---------- test/db/analysis/bpf | 22 +++++++------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index 8eb15f7e9bc..66b0cf85bbd 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: 2026 Jagath-P // SPDX-License-Identifier: LGPL-3.0-only -#include "rz_util/rz_assert.h" -#include "rz_util/rz_structured_data.h" #include #include #include @@ -111,9 +109,9 @@ static RzStructuredData *bpf_opex(csh handle, cs_insn *insn) { break; } } - return root; } + static bool bpf_anal_init(void **user) { BPFContext *ctx = RZ_NEW0(BPFContext); rz_return_val_if_fail(ctx, false); @@ -167,10 +165,9 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_MOV: op->type = RZ_ANALYSIS_OP_TYPE_MOV; break; case BPF_INS_ARSH: op->type = RZ_ANALYSIS_OP_TYPE_SAR; - op->sign = true; break; - /* ALU64 */ + /* ALU64 */ case BPF_INS_ADD64: op->type = RZ_ANALYSIS_OP_TYPE_ADD; break; case BPF_INS_SUB64: op->type = RZ_ANALYSIS_OP_TYPE_SUB; break; case BPF_INS_MUL64: op->type = RZ_ANALYSIS_OP_TYPE_MUL; break; @@ -185,7 +182,6 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_MOV64: op->type = RZ_ANALYSIS_OP_TYPE_MOV; break; case BPF_INS_ARSH64: op->type = RZ_ANALYSIS_OP_TYPE_SAR; - op->sign = true; break; case BPF_INS_SDIV: @@ -213,6 +209,9 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_BE16: case BPF_INS_BE32: case BPF_INS_BE64: + case BPF_INS_BSWAP16: + case BPF_INS_BSWAP32: + case BPF_INS_BSWAP64: op->type = RZ_ANALYSIS_OP_TYPE_MOV; // endian-swap into same reg break; @@ -268,14 +267,11 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { op->direction = RZ_ANALYSIS_OP_DIR_READ; break; - /* Store */ + /* Store */ case BPF_INS_STXW: case BPF_INS_STXH: case BPF_INS_STXB: case BPF_INS_STXDW: - op->type = RZ_ANALYSIS_OP_TYPE_STORE; - op->direction = RZ_ANALYSIS_OP_DIR_WRITE; - break; case BPF_INS_STW: case BPF_INS_STH: case BPF_INS_STB: @@ -291,8 +287,8 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { break; /* - * Extended atomics (AFADD, AFOR, AFAND, AFXOR, AADD, AOR, AAND, AXOR) - * only exist in Capstone v6 onwards. + * Atomics (AFADD, AFOR, AFAND, AFXOR, AADD, AOR, AAND, AXOR) + * only exist in Capstone versions after v6. */ case BPF_INS_AADD: case BPF_INS_AOR: @@ -302,12 +298,22 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_AFOR: case BPF_INS_AFAND: case BPF_INS_AFXOR: + case BPF_INS_AXCHG64: + case BPF_INS_ACMPXCHG64: + case BPF_INS_AADD64: + case BPF_INS_AOR64: + case BPF_INS_AAND64: + case BPF_INS_AXOR64: + case BPF_INS_AFADD64: + case BPF_INS_AFOR64: + case BPF_INS_AFAND64: + case BPF_INS_AFXOR64: op->type = RZ_ANALYSIS_OP_TYPE_STORE; break; case BPF_INS_JA: if (insn->detail->bpf.op_count > 0) { - op->jump = addr + (insn->detail->bpf.operands[0].off + 1) * 8; + op->jump = addr + 8 + ((st16)insn->detail->bpf.operands[0].off) * 8; } else { op->type = RZ_ANALYSIS_OP_TYPE_ILL; break; @@ -330,7 +336,7 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_JLT: case BPF_INS_JLE: if (insn->detail->bpf.op_count > 2) { - op->jump = addr + (insn->detail->bpf.operands[2].off + 1) * 8; + op->jump = addr + 8 + ((st16)insn->detail->bpf.operands[2].off) * 8; } else { op->type = RZ_ANALYSIS_OP_TYPE_ILL; break; @@ -342,7 +348,7 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { /* Conditional jumps 32-bit operands */ case BPF_INS_JAL: if (insn->detail->bpf.op_count > 0) { - op->jump = addr + (insn->detail->bpf.operands[0].imm + 1) * 8; + op->jump = addr + 8 + ((st32)insn->detail->bpf.operands[0].imm) * 8; } else { op->type = RZ_ANALYSIS_OP_TYPE_ILL; break; @@ -364,7 +370,7 @@ static void ebpf_op_type(RzAnalysisOp *op, ut64 addr, cs_insn *insn) { case BPF_INS_JLE32: case BPF_INS_JSET32: if (insn->detail->bpf.op_count > 2) { - op->jump = addr + (insn->detail->bpf.operands[2].off + 1) * 8; + op->jump = addr + 8 + ((st16)insn->detail->bpf.operands[2].off) * 8; } else { op->type = RZ_ANALYSIS_OP_TYPE_ILL; break; @@ -437,9 +443,11 @@ static int bpf_analysis_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 cs_free(insn, n); return op->size; } + RzAnalysisPlugin rz_analysis_plugin_bpf_cs = { .name = "bpf", .desc = "Extended BPF analysis plugin", + .author = "Jagath-P", .license = "LGPL3", .arch = "bpf", .bits = 64, diff --git a/test/db/analysis/bpf b/test/db/analysis/bpf index dbc908f6d5a..8e5c9e6bbc0 100644 --- a/test/db/analysis/bpf +++ b/test/db/analysis/bpf @@ -576,7 +576,7 @@ id: 17 bytes: c4b6e2e07c68c52b refptr: 0 size: 8 -sign: true +sign: false type: sar cycles: 0 opex: @@ -792,7 +792,7 @@ opex: value: 1033975643 - type: "off" value: -18110 -jump: 0x0005ca18 +jump: 0xfffffffffffdca18 fail: 0x00000008 cond: al family: cpu @@ -818,7 +818,7 @@ opex: value: 506324756 - type: "off" value: -3422 -jump: 0x00079518 +jump: 0xffffffffffff9518 fail: 0x00000008 cond: al family: cpu @@ -844,7 +844,7 @@ opex: value: -1765229424 - type: "off" value: -32605 -jump: 0x00040520 +jump: 0xfffffffffffc0520 fail: 0x00000008 cond: al family: cpu @@ -896,7 +896,7 @@ opex: value: "r1" - type: "off" value: -6016 -jump: 0x00074408 +jump: 0xffffffffffff4408 fail: 0x00000008 cond: al family: cpu @@ -922,7 +922,7 @@ opex: value: -441385648 - type: "off" value: -19722 -jump: 0x000597b8 +jump: 0xfffffffffffd97b8 fail: 0x00000008 cond: al family: cpu @@ -948,7 +948,7 @@ opex: value: "r9" - type: "off" value: -20033 -jump: 0x00058e00 +jump: 0xfffffffffffd8e00 fail: 0x00000008 cond: al family: cpu @@ -970,7 +970,7 @@ opex: operands: - type: "off" value: -20367 -jump: 0x00058390 +jump: 0xfffffffffffd8390 family: cpu ---------- address: 0x0 @@ -990,7 +990,7 @@ opex: operands: - type: "imm" value: -172417213 -jump: 0x7adc8fa20 +jump: 0xffffffffadc8fa20 family: cpu ---------- address: 0x0 @@ -1014,7 +1014,7 @@ opex: value: -172417213 - type: "off" value: -13297 -jump: 0x00066080 +jump: 0xfffffffffffe6080 fail: 0x00000008 cond: al family: cpu @@ -1040,7 +1040,7 @@ opex: value: -172417213 - type: "off" value: -13297 -jump: 0x00066080 +jump: 0xfffffffffffe6080 fail: 0x00000008 cond: al family: cpu From d649782040f51be82eb99004e0058d705f77d980 Mon Sep 17 00:00:00 2001 From: JagathP Date: Wed, 8 Jul 2026 22:12:56 +0530 Subject: [PATCH 15/16] Extend support to capstone v6 --- librz/arch/meson.build | 14 ++++++++++++-- .../packagefiles/capstone-6.0.0-alpha9/meson.build | 5 +++++ subprojects/packagefiles/capstone-next/meson.build | 12 ++++++------ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/librz/arch/meson.build b/librz/arch/meson.build index 23ccca5cfc9..93056607361 100644 --- a/librz/arch/meson.build +++ b/librz/arch/meson.build @@ -346,19 +346,29 @@ arch_isa_includes = [ if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_int() > 6 # plugins arch_plugins_list += [ - 'bpf_cs', 'cbpf_cs', 'riscv_cs', ] # plugins sources arch_plugin_sources += [ - 'p/arch_bpf_cs.c', 'p/arch_cbpf_cs.c', 'p/arch_riscv_cs.c', ] endif +if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_int() > 5 + # plugins + arch_plugins_list += [ + 'bpf_cs', + ] + + # plugins sources + arch_plugin_sources += [ + 'p/arch_bpf_cs.c', + ] +endif + if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_int() > 4 # plugins arch_plugins_list += [ diff --git a/subprojects/packagefiles/capstone-6.0.0-alpha9/meson.build b/subprojects/packagefiles/capstone-6.0.0-alpha9/meson.build index 47ce09660c6..96f43b4d194 100644 --- a/subprojects/packagefiles/capstone-6.0.0-alpha9/meson.build +++ b/subprojects/packagefiles/capstone-6.0.0-alpha9/meson.build @@ -32,6 +32,10 @@ cs_files = [ 'arch/ARM/ARMInstPrinter.c', 'arch/ARM/ARMMapping.c', 'arch/ARM/ARMModule.c', + 'arch/BPF/BPFDisassembler.c', + 'arch/BPF/BPFInstPrinter.c', + 'arch/BPF/BPFMapping.c', + 'arch/BPF/BPFModule.c', 'arch/HPPA/HPPADisassembler.c', 'arch/HPPA/HPPAInstPrinter.c', 'arch/HPPA/HPPAMapping.c', @@ -116,6 +120,7 @@ libcapstone_c_args = [ '-DCAPSTONE_HAS_ARC', '-DCAPSTONE_HAS_ALPHA', '-DCAPSTONE_HAS_ARM', + '-DCAPSTONE_HAS_BPF', '-DCAPSTONE_HAS_HPPA', '-DCAPSTONE_HAS_LOONGARCH', '-DCAPSTONE_HAS_M680X', diff --git a/subprojects/packagefiles/capstone-next/meson.build b/subprojects/packagefiles/capstone-next/meson.build index 2789ca07fc9..1ea95068bcc 100644 --- a/subprojects/packagefiles/capstone-next/meson.build +++ b/subprojects/packagefiles/capstone-next/meson.build @@ -32,6 +32,10 @@ cs_files = [ 'arch/ARM/ARMInstPrinter.c', 'arch/ARM/ARMMapping.c', 'arch/ARM/ARMModule.c', + 'arch/BPF/BPFDisassembler.c', + 'arch/BPF/BPFInstPrinter.c', + 'arch/BPF/BPFMapping.c', + 'arch/BPF/BPFModule.c', 'arch/HPPA/HPPADisassembler.c', 'arch/HPPA/HPPAInstPrinter.c', 'arch/HPPA/HPPAMapping.c', @@ -95,10 +99,6 @@ cs_files = [ 'arch/Xtensa/XtensaInstPrinter.c', 'arch/Xtensa/XtensaMapping.c', 'arch/Xtensa/XtensaModule.c', - 'arch/BPF/BPFDisassembler.c', - 'arch/BPF/BPFInstPrinter.c', - 'arch/BPF/BPFMapping.c', - 'arch/BPF/BPFModule.c', 'cs.c', 'Mapping.c', 'MCInst.c', @@ -120,6 +120,7 @@ libcapstone_c_args = [ '-DCAPSTONE_HAS_ARC', '-DCAPSTONE_HAS_ALPHA', '-DCAPSTONE_HAS_ARM', + '-DCAPSTONE_HAS_BPF', '-DCAPSTONE_HAS_HPPA', '-DCAPSTONE_HAS_LOONGARCH', '-DCAPSTONE_HAS_M680X', @@ -134,8 +135,7 @@ libcapstone_c_args = [ '-DCAPSTONE_HAS_XCORE', '-DCAPSTONE_HAS_XTENSA', '-DCAPSTONE_HAS_RISCV', - '-DCAPSTONE_HAS_BPF', -] + ] if meson.get_compiler('c').has_argument('-Wmaybe-uninitialized') libcapstone_c_args += '-Wno-maybe-uninitialized' From 47fdf3ef52517ce4a0280bf5ff26cd00ba6be803 Mon Sep 17 00:00:00 2001 From: JagathP Date: Mon, 13 Jul 2026 18:43:54 +0530 Subject: [PATCH 16/16] Fix description of eBPF, cBPF plugins and add authorship --- librz/arch/p/analysis/analysis_bpf_cs.c | 7 ++++++- librz/arch/p/asm/asm_bpf_cs.c | 3 ++- librz/arch/p/asm/asm_cbpf_cs.c | 3 ++- subprojects/packagefiles/capstone-next/meson.build | 2 +- test/db/cmd/cmd_aL | 4 ++-- test/db/cmd/cmd_list | 12 ++++++------ 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/librz/arch/p/analysis/analysis_bpf_cs.c b/librz/arch/p/analysis/analysis_bpf_cs.c index 66b0cf85bbd..30ee36155fc 100644 --- a/librz/arch/p/analysis/analysis_bpf_cs.c +++ b/librz/arch/p/analysis/analysis_bpf_cs.c @@ -1,6 +1,9 @@ // SPDX-FileCopyrightText: 2026 Jagath-P // SPDX-License-Identifier: LGPL-3.0-only +// https://www.kernel.org/doc/html/latest/bpf/standardization/instruction-set.html +// linux kernel 7.2.0-rc3 docs + #include #include #include @@ -68,8 +71,10 @@ static RzStructuredData *bpf_opex(csh handle, cs_insn *insn) { rz_structured_data_map_add_string(operand, "type", "imm"); if (op->is_signed) { if (op->imm & (0xffffffff00000000)) { + // 64-bit signed immediate rz_structured_data_map_add_signed(operand, "value", (st64)op->imm); } else { + // 32-bit signed immediate rz_structured_data_map_add_signed(operand, "value", (st64)(st32)op->imm); } } else { @@ -446,7 +451,7 @@ static int bpf_analysis_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 RzAnalysisPlugin rz_analysis_plugin_bpf_cs = { .name = "bpf", - .desc = "Extended BPF analysis plugin", + .desc = "Capstone eBPF analyzer", .author = "Jagath-P", .license = "LGPL3", .arch = "bpf", diff --git a/librz/arch/p/asm/asm_bpf_cs.c b/librz/arch/p/asm/asm_bpf_cs.c index abc2e68b44d..7da25daff47 100644 --- a/librz/arch/p/asm/asm_bpf_cs.c +++ b/librz/arch/p/asm/asm_bpf_cs.c @@ -50,8 +50,9 @@ static int bpf_disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) RzAsmPlugin rz_asm_plugin_bpf_cs = { .name = "bpf", + .author = "Jagath-P", .license = "LGPL3", - .desc = "EBPF disassembly plugin", + .desc = "eBPF disassembler", .arch = "bpf", .bits = 64, .endian = RZ_SYS_ENDIAN_BIG | RZ_SYS_ENDIAN_LITTLE, diff --git a/librz/arch/p/asm/asm_cbpf_cs.c b/librz/arch/p/asm/asm_cbpf_cs.c index 6c3214b31ef..c569b3dfcbf 100644 --- a/librz/arch/p/asm/asm_cbpf_cs.c +++ b/librz/arch/p/asm/asm_cbpf_cs.c @@ -51,7 +51,8 @@ static int cbpf_disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int len RzAsmPlugin rz_asm_plugin_cbpf_cs = { .name = "cbpf", .license = "LGPL3", - .desc = "CBPF disassembly plugin", + .desc = "cBPF disassembler", + .author = "Jagath-P", .arch = "cbpf", .bits = 32, .endian = RZ_SYS_ENDIAN_BIG | RZ_SYS_ENDIAN_LITTLE, diff --git a/subprojects/packagefiles/capstone-next/meson.build b/subprojects/packagefiles/capstone-next/meson.build index 1ea95068bcc..96f43b4d194 100644 --- a/subprojects/packagefiles/capstone-next/meson.build +++ b/subprojects/packagefiles/capstone-next/meson.build @@ -135,7 +135,7 @@ libcapstone_c_args = [ '-DCAPSTONE_HAS_XCORE', '-DCAPSTONE_HAS_XTENSA', '-DCAPSTONE_HAS_RISCV', - ] +] if meson.get_compiler('c').has_argument('-Wmaybe-uninitialized') libcapstone_c_args += '-Wno-maybe-uninitialized' diff --git a/test/db/cmd/cmd_aL b/test/db/cmd/cmd_aL index 37e29ff93aa..0937f28838c 100644 --- a/test/db/cmd/cmd_aL +++ b/test/db/cmd/cmd_aL @@ -11,9 +11,9 @@ adAeI 16 32 64 arm BSD ARM Capstone-based disassembler a____ 16 32 64 arm.as LGPL3 as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment) (by pancake) adAeI 8 16 avr LGPL3 Atmel AVR disassembler adA_I 16 32 64 bf LGPL3 Brainfuck (by pancake, nibble) v4.0.0 -_dA__ 64 bpf LGPL3 EBPF disassembly plugin +_dA__ 64 bpf LGPL3 eBPF disassembler (by Jagath-P) _dA__ 16 c166 LGPL3 Siemens/Infineon C166 microcontroller disassembler -_dA__ 32 cbpf LGPL3 CBPF disassembly plugin +_dA__ 32 cbpf LGPL3 cBPF disassembler (by Jagath-P) _dA__ 32 chip8 LGPL3 Chip8 disassembler _dA__ 16 32 64 cil LGPL3 .NET CIL/MSIL (Common Intermediate Language) bytecode disassembler _dA__ 16 cr16 LGPL3 CompactRISC CR16 disassembler diff --git a/test/db/cmd/cmd_list b/test/db/cmd/cmd_list index 73d0815a212..95199620957 100644 --- a/test/db/cmd/cmd_list +++ b/test/db/cmd/cmd_list @@ -750,9 +750,9 @@ adAeI 16 32 64 arm BSD ARM Capstone-based disassembler a____ 16 32 64 arm.as LGPL3 as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment) (by pancake) adAeI 8 16 avr LGPL3 Atmel AVR disassembler adA_I 16 32 64 bf LGPL3 Brainfuck (by pancake, nibble) v4.0.0 -_dA__ 64 bpf LGPL3 EBPF disassembly plugin +_dA__ 64 bpf LGPL3 eBPF disassembler (by Jagath-P) _dA__ 16 c166 LGPL3 Siemens/Infineon C166 microcontroller disassembler -_dA__ 32 cbpf LGPL3 CBPF disassembly plugin +_dA__ 32 cbpf LGPL3 cBPF disassembler (by Jagath-P) _dA__ 32 chip8 LGPL3 Chip8 disassembler _dA__ 16 32 64 cil LGPL3 .NET CIL/MSIL (Common Intermediate Language) bytecode disassembler _dA__ 16 cr16 LGPL3 CompactRISC CR16 disassembler @@ -811,7 +811,7 @@ _dA__ 16 xap PD Cambridge Consultants XAP4 RISC (CSR) disas _dA__ 32 xcore BSD XCore Capstone-based disassembler (by pancake) _dAeI 32 xtensa LGPL3 Tensilica Xtensa Capstone-based disassembler (by billow) adA__ 8 z80 GPL3 Zilog Z80 disassembler (by condret) -["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"alpha":{"bits":"32 64","license":"LGPL3","description":"DEC Alpha Capstone-based disassembler","features":"_dA__"},"amd29k":{"bits":"32 ","license":"LGPL3","description":"AMD 29k RISC disassembler","features":"_dA__","author":"deroad"},"arc":{"bits":"16 32 ","license":"GPL3","description":"Argonaut RISC Core","features":"_dA__"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"arm.as":{"bits":"16 32 64","license":"LGPL3","description":"as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment)","features":"a____","author":"pancake"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"bpf":{"bits":"64","license":"LGPL3","description":"EBPF disassembly plugin","features":"_dA__"},"c166":{"bits":"16 ","license":"LGPL3","description":"Siemens/Infineon C166 microcontroller disassembler","features":"_dA__"},"cbpf":{"bits":"32 ","license":"LGPL3","description":"CBPF disassembly plugin","features":"_dA__"},"chip8":{"bits":"32 ","license":"LGPL3","description":"Chip8 disassembler","features":"_dA__"},"cil":{"bits":"16 32 64","license":"LGPL3","description":".NET CIL/MSIL (Common Intermediate Language) bytecode disassembler","features":"_dA__"},"cr16":{"bits":"16 ","license":"LGPL3","description":"CompactRISC CR16 disassembler","features":"_dA__"},"cris":{"bits":"32 ","license":"GPL3","description":"Axis Communications 32-bit embedded processor disassembler","features":"_dA__","author":"pancake"},"dalvik":{"bits":"32 64","license":"LGPL3","description":"Dalvik (Android VM) bytecode disassembler","features":"adA__"},"dcpu16":{"bits":"16 ","license":"PD","description":"Mojang's DCPU-16 disassembler","features":"ad___"},"ebc":{"bits":"32 64","license":"LGPL3","description":"EFI bytecode disassembler","features":"_dA__","author":"Fedor Sakharov"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"h8500":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/500 disassembler","features":"_dA__","author":"billow"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"hppa":{"bits":"32 64","license":"LGPL3","description":"HP PA-RISC Capstone-based disassembler","features":"_dA__","author":"xvilka"},"i4004":{"bits":"4 ","license":"LGPL3","description":"Intel 4004 disassembler","features":"_dA__"},"i8080":{"bits":"8 ","license":"BSD","description":"Intel 8080 disassembler","features":"_dA__"},"java":{"bits":"32 ","license":"LGPL-3","description":"Java bytecode disassembler","features":"adA__","author":"deroad"},"lanai":{"bits":"32 ","license":"GPL3","description":"Google LANAI disassembler","features":"_d___"},"lh5801":{"bits":"8 ","license":"LGPL3","description":"SHARP LH5801 disassembler","features":"_d___"},"lm32":{"bits":"32 ","license":"BSD","description":"Lattice Micro 32 ISA disassembler","features":"_d___","author":"Felix Held"},"loongarch":{"bits":"32 64","license":"LGPL3","description":"Loongson LoongArch disassembler","features":"_dA__"},"luac":{"bits":"32 ","license":"LGPL3","description":"Lua bytecode (LUAC) disassembler","features":"adA__"},"m680x":{"bits":"8 32 ","license":"BSD","description":"Motorola 680X Capstone-based disassembler","features":"_dA__"},"m68k":{"bits":"32 ","license":"BSD","description":"Motorola 68K Capstone-based disassembler","features":"_dA__"},"malbolge":{"bits":"32 ","license":"LGPL3","description":"Malbolge Ternary VM bytecode disassembler","features":"_dA__","author":"condret"},"mcore":{"bits":"32 ","license":"LGPL3","description":"Motorola MCORE disassembler","features":"_dA__"},"mcs96":{"bits":"16 ","license":"LGPL3","description":"Intel MCS-96 disassembler","features":"_dA__","author":"condret"},"milstd1750":{"bits":"8 ","license":"MIT","description":"MIL-STD 1750 ISA disassembler","features":"_dA__"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"null":{"bits":"16 32 64","license":"MIT","description":"NULL (empty) disassembler","features":"adA__","author":"pancake","version":"1.0.0"},"or1k":{"bits":"32 ","license":"LGPL3","description":"OpenRISC 1000 disassembler","features":"_dA__"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"ppc.as":{"bits":"32 64","license":"LGPL3","description":"as PPC Assembler (use RZ_PPC_AS environment)","features":"a____","author":"eagleoflqj"},"propeller":{"bits":"32 ","license":"LGPL3","description":"Parallax Propeller disassembler","features":"_dA__"},"pyc":{"bits":"8 16 ","license":"LGPL3","description":"Python bytecode (PYC) disassembler","features":"_dA__"},"riscv":{"bits":"32 64","license":"BSD","description":"RISC-V Capstone-based disassembler","features":"_dA__"},"rl78":{"bits":"32 ","license":"LGPL3","description":"Renesas RL78 disassembler","features":"adA__","author":"Bastian Engel"},"rsp":{"bits":"32 ","license":"LGPL3","description":"Nintendo N64 Reality Signal Processor disassembler","features":"_dA__"},"rx":{"bits":"32 ","license":"LGPL3","description":"Renesas RX Family disassembler","features":"_dA__","author":"Heersin"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4/SuperH-3 disassembler","features":"adAeI","author":"DMaroo"},"snes":{"bits":"8 16 ","license":"LGPL3","description":"SuperNES CPU disassembler","features":"_dA__"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"spc700":{"bits":"16 ","license":"LGPL3","description":"Sony SPC700 (Nintendo SuperNES sound-chip) disassembler","features":"_dA__"},"sysz":{"bits":"32 64","license":"BSD","description":"IBM SystemZ (S/390) Capstone-based disassembler","features":"_dA__"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA_I"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"vax":{"bits":"32 ","license":"LGPL3","description":"DEC VAX-11 disassembler","features":"_dA__","author":"xvilka"},"wasm":{"bits":"32 ","license":"MIT","description":"WebAssembly disassembler","features":"adA__","author":"cgvwzq","version":"0.1.0"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"x86.as":{"bits":"16 32 64","license":"LGPL3","description":"Intel X86 GNU Assembler (Use RZ_X86_AS env)","features":"a____"},"x86.nasm":{"bits":"16 32 64","license":"LGPL3","description":"X86 nasm assembler","features":"a____"},"x86.nz":{"bits":"16 32 64","license":"LGPL3","description":"x86 handmade assembler","features":"a____"},"xap":{"bits":"16 ","license":"PD","description":"Cambridge Consultants XAP4 RISC (CSR) disassembler","features":"_dA__"},"xcore":{"bits":"32 ","license":"BSD","description":"XCore Capstone-based disassembler","features":"_dA__","author":"pancake"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"},"z80":{"bits":"8 ","license":"GPL3","description":"Zilog Z80 disassembler","features":"adA__","author":"condret"}] +["6502":{"bits":"8 16 ","license":"LGPL3","description":"6502/NES/C64/Tamagotchi/T-1000 CPU","features":"_dAeI"},"8051":{"bits":"8 ","license":"PD","description":"Intel 8051 disassembler","features":"adAeI"},"alpha":{"bits":"32 64","license":"LGPL3","description":"DEC Alpha Capstone-based disassembler","features":"_dA__"},"amd29k":{"bits":"32 ","license":"LGPL3","description":"AMD 29k RISC disassembler","features":"_dA__","author":"deroad"},"arc":{"bits":"16 32 ","license":"GPL3","description":"Argonaut RISC Core","features":"_dA__"},"arm":{"bits":"16 32 64","license":"BSD","description":"ARM Capstone-based disassembler","features":"adAeI"},"arm.as":{"bits":"16 32 64","license":"LGPL3","description":"as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment)","features":"a____","author":"pancake"},"avr":{"bits":"8 16 ","license":"LGPL3","description":"Atmel AVR disassembler","features":"adAeI"},"bf":{"bits":"16 32 64","license":"LGPL3","description":"Brainfuck","features":"adA_I","author":"pancake, nibble","version":"4.0.0"},"bpf":{"bits":"64","license":"LGPL3","description":"eBPF disassembler","features":"_dA__","author":"Jagath-P"},"c166":{"bits":"16 ","license":"LGPL3","description":"Siemens/Infineon C166 microcontroller disassembler","features":"_dA__"},"cbpf":{"bits":"32 ","license":"LGPL3","description":"cBPF disassembler","features":"_dA__","author":"Jagath-P"},"chip8":{"bits":"32 ","license":"LGPL3","description":"Chip8 disassembler","features":"_dA__"},"cil":{"bits":"16 32 64","license":"LGPL3","description":".NET CIL/MSIL (Common Intermediate Language) bytecode disassembler","features":"_dA__"},"cr16":{"bits":"16 ","license":"LGPL3","description":"CompactRISC CR16 disassembler","features":"_dA__"},"cris":{"bits":"32 ","license":"GPL3","description":"Axis Communications 32-bit embedded processor disassembler","features":"_dA__","author":"pancake"},"dalvik":{"bits":"32 64","license":"LGPL3","description":"Dalvik (Android VM) bytecode disassembler","features":"adA__"},"dcpu16":{"bits":"16 ","license":"PD","description":"Mojang's DCPU-16 disassembler","features":"ad___"},"ebc":{"bits":"32 64","license":"LGPL3","description":"EFI bytecode disassembler","features":"_dA__","author":"Fedor Sakharov"},"gb":{"bits":"16 ","license":"LGPL3","description":"GameBoy(TM) (z80-like)","features":"adAeI","author":"condret"},"h8300":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/300 disassembly plugin","features":"_dAeI"},"h8500":{"bits":"16 ","license":"LGPL3","description":"Hitachi/Renesas H8/500 disassembler","features":"_dA__","author":"billow"},"hexagon":{"bits":"32 ","license":"LGPL3","description":"Qualcomm Hexagon (QDSP6) V6","features":"_dA_I","author":"Rot127"},"hppa":{"bits":"32 64","license":"LGPL3","description":"HP PA-RISC Capstone-based disassembler","features":"_dA__","author":"xvilka"},"i4004":{"bits":"4 ","license":"LGPL3","description":"Intel 4004 disassembler","features":"_dA__"},"i8080":{"bits":"8 ","license":"BSD","description":"Intel 8080 disassembler","features":"_dA__"},"java":{"bits":"32 ","license":"LGPL-3","description":"Java bytecode disassembler","features":"adA__","author":"deroad"},"lanai":{"bits":"32 ","license":"GPL3","description":"Google LANAI disassembler","features":"_d___"},"lh5801":{"bits":"8 ","license":"LGPL3","description":"SHARP LH5801 disassembler","features":"_d___"},"lm32":{"bits":"32 ","license":"BSD","description":"Lattice Micro 32 ISA disassembler","features":"_d___","author":"Felix Held"},"loongarch":{"bits":"32 64","license":"LGPL3","description":"Loongson LoongArch disassembler","features":"_dA__"},"luac":{"bits":"32 ","license":"LGPL3","description":"Lua bytecode (LUAC) disassembler","features":"adA__"},"m680x":{"bits":"8 32 ","license":"BSD","description":"Motorola 680X Capstone-based disassembler","features":"_dA__"},"m68k":{"bits":"32 ","license":"BSD","description":"Motorola 68K Capstone-based disassembler","features":"_dA__"},"malbolge":{"bits":"32 ","license":"LGPL3","description":"Malbolge Ternary VM bytecode disassembler","features":"_dA__","author":"condret"},"mcore":{"bits":"32 ","license":"LGPL3","description":"Motorola MCORE disassembler","features":"_dA__"},"mcs96":{"bits":"16 ","license":"LGPL3","description":"Intel MCS-96 disassembler","features":"_dA__","author":"condret"},"milstd1750":{"bits":"8 ","license":"MIT","description":"MIL-STD 1750 ISA disassembler","features":"_dA__"},"mips":{"bits":"16 32 64","license":"BSD","description":"MIPS Capstone-based disassembler","features":"adAeI"},"msp430":{"bits":"16 ","license":"LGPL3","description":"Texas Instruments MSP430 disassembler","features":"_dA_I"},"null":{"bits":"16 32 64","license":"MIT","description":"NULL (empty) disassembler","features":"adA__","author":"pancake","version":"1.0.0"},"or1k":{"bits":"32 ","license":"LGPL3","description":"OpenRISC 1000 disassembler","features":"_dA__"},"pic":{"bits":"16 32 ","license":"LGPL3","description":"Microchip PIC disassembler","features":"_dAeI"},"ppc":{"bits":"32 64","license":"BSD","description":"PowerPC Capstone-based disassembler","features":"_dAeI","author":"pancake"},"ppc.as":{"bits":"32 64","license":"LGPL3","description":"as PPC Assembler (use RZ_PPC_AS environment)","features":"a____","author":"eagleoflqj"},"propeller":{"bits":"32 ","license":"LGPL3","description":"Parallax Propeller disassembler","features":"_dA__"},"pyc":{"bits":"8 16 ","license":"LGPL3","description":"Python bytecode (PYC) disassembler","features":"_dA__"},"riscv":{"bits":"32 64","license":"BSD","description":"RISC-V Capstone-based disassembler","features":"_dA__"},"rl78":{"bits":"32 ","license":"LGPL3","description":"Renesas RL78 disassembler","features":"adA__","author":"Bastian Engel"},"rsp":{"bits":"32 ","license":"LGPL3","description":"Nintendo N64 Reality Signal Processor disassembler","features":"_dA__"},"rx":{"bits":"32 ","license":"LGPL3","description":"Renesas RX Family disassembler","features":"_dA__","author":"Heersin"},"sh":{"bits":"32 ","license":"LGPL3","description":"Hitachi/Renesas SuperH-4/SuperH-3 disassembler","features":"adAeI","author":"DMaroo"},"snes":{"bits":"8 16 ","license":"LGPL3","description":"SuperNES CPU disassembler","features":"_dA__"},"sparc":{"bits":"32 64","license":"BSD","description":"Sun SPARC Capstone-based disassembler","features":"_dA_I"},"spc700":{"bits":"16 ","license":"LGPL3","description":"Sony SPC700 (Nintendo SuperNES sound-chip) disassembler","features":"_dA__"},"sysz":{"bits":"32 64","license":"BSD","description":"IBM SystemZ (S/390) Capstone-based disassembler","features":"_dA__"},"tms320":{"bits":"32 ","license":"LGPL3","description":"Texas Instruments TMS320 DSP family (c54x,c55x,c55x+,c64x) disassembler","features":"_dA_I"},"tricore":{"bits":"32 ","license":"BSD","description":"Siemens TriCore Capstone-based disassembler","features":"_dA_I","author":"billow"},"v810":{"bits":"32 ","license":"LGPL3","description":"NEC V810 disassembler","features":"_dAeI","author":"pancake"},"v850":{"bits":"32 ","license":"LGPL3","description":"NEC/Renesas V850 disassembler","features":"_dAeI"},"vax":{"bits":"32 ","license":"LGPL3","description":"DEC VAX-11 disassembler","features":"_dA__","author":"xvilka"},"wasm":{"bits":"32 ","license":"MIT","description":"WebAssembly disassembler","features":"adA__","author":"cgvwzq","version":"0.1.0"},"x86":{"bits":"16 32 64","license":"MIT","description":"X86/X86_64 Zydis-based disassembler","features":"_dAeI"},"x86.as":{"bits":"16 32 64","license":"LGPL3","description":"Intel X86 GNU Assembler (Use RZ_X86_AS env)","features":"a____"},"x86.nasm":{"bits":"16 32 64","license":"LGPL3","description":"X86 nasm assembler","features":"a____"},"x86.nz":{"bits":"16 32 64","license":"LGPL3","description":"x86 handmade assembler","features":"a____"},"xap":{"bits":"16 ","license":"PD","description":"Cambridge Consultants XAP4 RISC (CSR) disassembler","features":"_dA__"},"xcore":{"bits":"32 ","license":"BSD","description":"XCore Capstone-based disassembler","features":"_dA__","author":"pancake"},"xtensa":{"bits":"32 ","license":"LGPL3","description":"Tensilica Xtensa Capstone-based disassembler","features":"_dAeI","author":"billow"},"z80":{"bits":"8 ","license":"GPL3","description":"Zilog Z80 disassembler","features":"adA__","author":"condret"}] name bits features license version author description ---------------------------------------------------------------------------------------------------------------------------------- _dAeI 8 16 6502 LGPL3 6502/NES/C64/Tamagotchi/T-1000 CPU @@ -823,9 +823,9 @@ adAeI 16 32 64 arm BSD ARM Capstone-based dis a____ 16 32 64 arm.as LGPL3 pancake as ARM Assembler (use RZ_ARM32_AS and RZ_ARM64_AS environment) adAeI 8 16 avr LGPL3 Atmel AVR disassembler adA_I 16 32 64 bf LGPL3 4.0.0 pancake, nibble Brainfuck -_dA__ 64 bpf LGPL3 EBPF disassembly plugin +_dA__ 64 bpf LGPL3 Jagath-P eBPF disassembler _dA__ 16 c166 LGPL3 Siemens/Infineon C166 microcontroller disassembler -_dA__ 32 cbpf LGPL3 CBPF disassembly plugin +_dA__ 32 cbpf LGPL3 Jagath-P cBPF disassembler _dA__ 32 chip8 LGPL3 Chip8 disassembler _dA__ 16 32 64 cil LGPL3 .NET CIL/MSIL (Common Intermediate Language) bytecode disassembler _dA__ 16 cr16 LGPL3 CompactRISC CR16 disassembler @@ -1166,7 +1166,7 @@ NAME=Print the asm/analysis plugins in JSON FILE== CMDS=Laj EXPECT=<