diff --git a/arch/BPF/BPFDisassembler.c b/arch/BPF/BPFDisassembler.c index 975a827d..cc137c01 100644 --- a/arch/BPF/BPFDisassembler.c +++ b/arch/BPF/BPFDisassembler.c @@ -341,10 +341,15 @@ static bool decodeJump(cs_struct *ud, MCInst *MI, bpf_internal *bpf) if (BPF_OP(bpf->op) == BPF_JUMP_EXIT) return bpf->op == (BPF_CLASS_JMP | BPF_JUMP_EXIT); if (BPF_OP(bpf->op) == BPF_JUMP_CALL) { - if (bpf->op != (BPF_CLASS_JMP | BPF_JUMP_CALL)) - return false; - MCOperand_CreateImm0(MI, bpf->k); - return true; + if (bpf->op == (BPF_CLASS_JMP | BPF_JUMP_CALL)) { + MCOperand_CreateImm0(MI, bpf->k); + return true; + } + if (bpf->op == (BPF_CLASS_JMP | BPF_JUMP_CALL | BPF_SRC_X)) { + CHECK_READABLE_AND_PUSH(ud, MI, bpf->k); + return true; + } + return false; } /* ja is a special case of jumps */ diff --git a/arch/BPF/BPFMapping.c b/arch/BPF/BPFMapping.c index 2c2be424..fc804dad 100644 --- a/arch/BPF/BPFMapping.c +++ b/arch/BPF/BPFMapping.c @@ -98,6 +98,7 @@ static const name_map insn_name_maps[BPF_INS_ENDING] = { { BPF_INS_JSGT, "jsgt" }, { BPF_INS_JSGE, "jsge" }, { BPF_INS_CALL, "call" }, + { BPF_INS_CALLX, "callx" }, { BPF_INS_EXIT, "exit" }, { BPF_INS_JLT, "jlt" }, { BPF_INS_JLE, "jle" }, @@ -254,6 +255,10 @@ static bpf_insn op2insn_alu(unsigned opcode) static bpf_insn op2insn_jmp(unsigned opcode) { + if (opcode == (BPF_CLASS_JMP | BPF_JUMP_CALL | BPF_SRC_X)) { + return BPF_INS_CALLX; + } + #define CASE(c) case BPF_JUMP_##c: return BPF_INS_##c switch (BPF_OP(opcode)) { case BPF_JUMP_JA: @@ -396,7 +401,7 @@ void BPF_get_insn_id(cs_struct *ud, cs_insn *insn, unsigned int opcode) case BPF_CLASS_JMP: grp = BPF_GRP_JUMP; id = op2insn_jmp(opcode); - if (id == BPF_INS_CALL) + if (id == BPF_INS_CALL || id == BPF_INS_CALLX) grp = BPF_GRP_CALL; else if (id == BPF_INS_EXIT) grp = BPF_GRP_RETURN; diff --git a/include/capstone/bpf.h b/include/capstone/bpf.h index c2ccff6d..5a5c927d 100644 --- a/include/capstone/bpf.h +++ b/include/capstone/bpf.h @@ -164,6 +164,7 @@ typedef enum bpf_insn { BPF_INS_JSGT, ///< eBPF only BPF_INS_JSGE, ///< eBPF only BPF_INS_CALL, ///< eBPF only + BPF_INS_CALLX, ///< eBPF only BPF_INS_EXIT, ///< eBPF only BPF_INS_JLT, ///< eBPF only BPF_INS_JLE, ///< eBPF only diff --git a/suite/MC/BPF/extended-all.cs b/suite/MC/BPF/extended-all.cs index 39efd04b..0f9f5cbb 100644 --- a/suite/MC/BPF/extended-all.cs +++ b/suite/MC/BPF/extended-all.cs @@ -95,3 +95,4 @@ 0xd5,0xe9,0xf6,0xb2,0x50,0xfd,0xb0,0xe5 = jsle r9, 0xe5b0fd50, +0xb2f6 0xdc,0xb2,0xa3,0x50,0x20,0x00,0x00,0x00 = be32 r2 0xdd,0x95,0xbf,0xb1,0xf2,0x5f,0x7b,0xc4 = jsle r5, r9, +0xb1bf +0x8d,0x00,0x00,0x00,0x02,0x00,0x00,0x00 = callx r2 diff --git a/suite/MC/BPF/extended-be.cs b/suite/MC/BPF/extended-be.cs index 63454025..eada5347 100644 --- a/suite/MC/BPF/extended-be.cs +++ b/suite/MC/BPF/extended-be.cs @@ -13,3 +13,4 @@ 0xa5,0x35,0x30,0x00,0x10,0x00,0x00,0x00 = jlt r5, 0x10000000, +0x3000 0xc3,0x12,0x00,0x10,0x00,0x00,0x00,0x00 = xaddw [r2+0x10], r1 0xdb,0xa9,0x00,0x01,0x00,0x00,0x00,0x00 = xadddw [r9+0x1], r10 +0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x02 = callx r2