Skip to content

Commit

Permalink
Add mips details
Browse files Browse the repository at this point in the history
  • Loading branch information
wargio committed Aug 28, 2024
1 parent 640edd5 commit 2c61e2e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 43 deletions.
21 changes: 16 additions & 5 deletions arch/Mips/MipsInstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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);
}

Expand All @@ -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; \
} \
\
Expand All @@ -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; \
} \
\
Expand Down Expand Up @@ -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)
Expand Down
86 changes: 62 additions & 24 deletions arch/Mips/MipsMapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);
}
}

Expand Down
17 changes: 5 additions & 12 deletions arch/Mips/MipsMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 1 addition & 2 deletions include/capstone/cs_operand.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down

0 comments on commit 2c61e2e

Please sign in to comment.