From 2c61e2e4ecd27783cdb83c924d5ea13b6f1c9d9e Mon Sep 17 00:00:00 2001 From: wargio Date: Wed, 28 Aug 2024 23:12:31 +0800 Subject: [PATCH] Add mips details --- arch/Mips/MipsInstPrinter.c | 21 +++++++-- arch/Mips/MipsMapping.c | 86 +++++++++++++++++++++++++---------- arch/Mips/MipsMapping.h | 17 ++----- include/capstone/cs_operand.h | 3 +- 4 files changed, 84 insertions(+), 43 deletions(-) diff --git a/arch/Mips/MipsInstPrinter.c b/arch/Mips/MipsInstPrinter.c index 589908fd2a..2d01d5de93 100644 --- a/arch/Mips/MipsInstPrinter.c +++ b/arch/Mips/MipsInstPrinter.c @@ -170,11 +170,15 @@ void printOperand(MCInst *MI, unsigned OpNo, SStream *O) { MCOperand *Op = MCInst_getOperand(MI, (OpNo)); if (MCOperand_isReg(Op)) { - printRegName(O, MCOperand_getReg(Op)); + MCRegister Reg = MCOperand_getReg(Op); + Mips_set_detail_op_reg(MI, OpNo, Reg); + printRegName(O, Reg); return; } - printInt64(O, MCOperand_getImm(Op)); + int64_t Imm = MCOperand_getImm(Op); + Mips_set_detail_op_imm(MI, OpNo, MIPS_OP_IMM, Imm); + printInt64(O, Imm); } static void printJumpOperand(MCInst *MI, unsigned OpNo, SStream *O) @@ -183,7 +187,9 @@ static void printJumpOperand(MCInst *MI, unsigned OpNo, SStream *O) if (!MCOperand_isImm(Op)) return printOperand((MCInst *)MI, OpNo, O); - printInt64(O, MCOperand_getImm(Op)); + int64_t Imm = MCOperand_getImm(Op); + Mips_set_detail_op_imm(MI, OpNo, MIPS_OP_IMM, Imm); + printInt64(O, Imm); } static void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo, SStream *O) @@ -193,6 +199,7 @@ static void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo, SStr return printOperand((MCInst *)MI, OpNo, O); uint64_t Target = Address + MCOperand_getImm(Op); + Mips_set_detail_op_imm(MI, OpNo, MIPS_OP_IMM, Target); printInt64(O, Target); } @@ -204,7 +211,8 @@ static void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo, SStr if (MCOperand_isImm(MO)) { \ uint64_t Imm = MCOperand_getImm(MO); \ Imm &= (1 << Bits) - 1; \ - printInt64(O, Imm); \ + Mips_set_detail_op_imm(MI, opNum, MIPS_OP_IMM, Imm); \ + printUInt64(O, Imm); \ return; \ } \ \ @@ -221,7 +229,8 @@ static void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo, SStr Imm -= Offset; \ Imm &= (1 << Bits) - 1; \ Imm += Offset; \ - printInt64(O, Imm); \ + Mips_set_detail_op_imm(MI, opNum, MIPS_OP_IMM, Imm); \ + printUInt64(O, Imm); \ return; \ } \ \ @@ -269,10 +278,12 @@ static void printMemOperand(MCInst *MI, int opNum, SStream *O) break; } + Mips_set_mem_access(MI, true); printOperand((MCInst *)MI, opNum + 1, O); SStream_concat0(O, "("); printOperand((MCInst *)MI, opNum, O); SStream_concat0(O, ")"); + Mips_set_mem_access(MI, false); } static void printMemOperandEA(MCInst *MI, int opNum, SStream *O) diff --git a/arch/Mips/MipsMapping.c b/arch/Mips/MipsMapping.c index c2be0c7eb2..f6c4f4eca4 100644 --- a/arch/Mips/MipsMapping.c +++ b/arch/Mips/MipsMapping.c @@ -92,6 +92,14 @@ const insn_map mips_insns[] = { #include "MipsGenCSMappingInsn.inc" }; +void Mips_set_instr_map_data(MCInst *MI) +{ + map_cs_id(MI, mips_insns, ARR_SIZE(mips_insns)); + map_implicit_reads(MI, mips_insns); + map_implicit_writes(MI, mips_insns); + map_groups(MI, mips_insns); +} + bool Mips_getInstruction(csh handle, const uint8_t *code, size_t code_len, MCInst *instr, uint16_t *size, uint64_t address, void *info) @@ -105,6 +113,9 @@ bool Mips_getInstruction(csh handle, const uint8_t *code, size_t code_len, code_len, address, info, ud->mode) != MCDisassembler_Fail; + if (result) { + Mips_set_instr_map_data(instr); + } *size = size64; return result; } @@ -143,12 +154,31 @@ static const map_insn_ops insn_operands[] = { #include "MipsGenCSMappingInsnOp.inc" }; -static void Mips_set_detail_op_imm(MCInst *MI, unsigned OpNum, +static void Mips_set_detail_op_mem_reg(MCInst *MI, unsigned OpNum, mips_reg Reg) +{ + Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; + Mips_get_detail_op(MI, 0)->mem.base = Reg; + Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); +} + +static void Mips_set_detail_op_mem_disp(MCInst *MI, unsigned OpNum, int64_t Imm) +{ + Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; + Mips_get_detail_op(MI, 0)->mem.disp = Imm; + Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); +} + +void Mips_set_detail_op_imm(MCInst *MI, unsigned OpNum, mips_op_type ImmType, int64_t Imm) { if (!detail_is_set(MI)) return; - assert((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_IMM); + + if (doing_mem(MI)) { + Mips_set_detail_op_mem_disp(MI, OpNum, Imm); + return; + } + assert(ImmType == MIPS_OP_IMM); Mips_get_detail_op(MI, 0)->type = ImmType; @@ -157,10 +187,16 @@ static void Mips_set_detail_op_imm(MCInst *MI, unsigned OpNum, Mips_inc_op_count(MI); } -static void Mips_set_detail_op_reg(MCInst *MI, unsigned OpNum, mips_reg Reg) +void Mips_set_detail_op_reg(MCInst *MI, unsigned OpNum, mips_reg Reg) { if (!detail_is_set(MI)) return; + + if (doing_mem(MI)) { + Mips_set_detail_op_mem_reg(MI, OpNum, Reg); + return; + } + assert((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG); Mips_get_detail_op(MI, 0)->type = MIPS_OP_REG; @@ -169,31 +205,33 @@ static void Mips_set_detail_op_reg(MCInst *MI, unsigned OpNum, mips_reg Reg) Mips_inc_op_count(MI); } -void Mips_add_cs_detail(MCInst *MI, int /* mips_op_group */ op_group, - va_list args) +void Mips_set_mem_access(MCInst *MI, bool status) { if (!detail_is_set(MI)) return; + set_doing_mem(MI, status); + if (status) { + if (Mips_get_detail(MI)->op_count > 0 && + Mips_get_detail_op(MI, -1)->type == MIPS_OP_MEM && + Mips_get_detail_op(MI, -1)->mem.disp == 0) { + // Previous memory operand not done yet. Select it. + Mips_dec_op_count(MI); + return; + } + + // Init a new one. + Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; + Mips_get_detail_op(MI, 0)->mem.base = MIPS_REG_INVALID; + Mips_get_detail_op(MI, 0)->mem.disp = 0; - unsigned OpNum = va_arg(args, unsigned); - // Handle memory operands later - cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM; - - // Fill cs_detail - switch (op_group) { - default: - printf("ERROR: Operand group %d not handled!\n", op_group); - assert(0); - case Mips_OP_GROUP_Operand: - if (op_type == CS_OP_IMM) { - Mips_set_detail_op_imm(MI, OpNum, MIPS_OP_IMM, - MCInst_getOpVal(MI, OpNum)); - } else if (op_type == CS_OP_REG) { - Mips_set_detail_op_reg(MI, OpNum, - MCInst_getOpVal(MI, OpNum)); - } else - assert(0 && "Op type not handled."); - break; +#ifndef CAPSTONE_DIET + uint8_t access = + map_get_op_access(MI, Mips_get_detail(MI)->op_count); + Mips_get_detail_op(MI, 0)->access = access; +#endif + } else { + // done, select the next operand slot + Mips_inc_op_count(MI); } } diff --git a/arch/Mips/MipsMapping.h b/arch/Mips/MipsMapping.h index d2b57c76b5..8d7de21bba 100644 --- a/arch/Mips/MipsMapping.h +++ b/arch/Mips/MipsMapping.h @@ -32,17 +32,10 @@ bool Mips_getInstruction(csh handle, const uint8_t *code, size_t code_len, // cs_detail related functions void Mips_init_cs_detail(MCInst *MI); -void Mips_add_cs_detail(MCInst *MI, int /* mips_op_group */ op_group, - va_list args); -static inline void add_cs_detail(MCInst *MI, - int /* mips_op_group */ op_group, ...) -{ - if (!MI->flat_insn->detail) - return; - va_list args; - va_start(args, op_group); - Mips_add_cs_detail(MI, op_group, args); - va_end(args); -} +void Mips_set_detail_op_imm(MCInst *MI, unsigned OpNum, + mips_op_type ImmType, int64_t Imm); +void Mips_set_detail_op_reg(MCInst *MI, unsigned OpNum, mips_reg Reg); +void Mips_set_mem_access(MCInst *MI, bool status); + #endif // CS_MIPS_MAPPING_H diff --git a/include/capstone/cs_operand.h b/include/capstone/cs_operand.h index 17ec7c72e1..3c3f8a9cc7 100644 --- a/include/capstone/cs_operand.h +++ b/include/capstone/cs_operand.h @@ -25,8 +25,7 @@ typedef enum cs_op_type { CS_OP_RESERVED_15 = 15, CS_OP_SPECIAL = 0x10, ///< Special operands from archs CS_OP_BOUND = 0x40, ///< Operand is associated with a previous operand. Used by AArch64 for SME operands. - CS_OP_MEM = - 0x80, ///< Memory operand. Can be ORed with another operand type. + CS_OP_MEM = 0x80, ///< Memory operand. Can be ORed with another operand type. CS_OP_MEM_REG = CS_OP_MEM | CS_OP_REG, ///< Memory referencing register operand. CS_OP_MEM_IMM = CS_OP_MEM | CS_OP_IMM, ///< Memory referencing immediate operand.