arm: some operands can get subtracted from base register, thus have '-' sign associated. this adds subtracted field into cs_arm_op to provide this info. issue reported by Yegor Derevenets
This commit is contained in:
parent
f2b699a716
commit
8fb2eab459
|
@ -758,6 +758,7 @@ static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
|
|||
MCOperand *MO1 = MCInst_getOperand(MI, Op);
|
||||
MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
|
||||
MCOperand *MO3 = MCInst_getOperand(MI, Op + 2);
|
||||
ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));
|
||||
|
||||
SStream_concat0(O, "[");
|
||||
set_mem_access(MI, true);
|
||||
|
@ -770,14 +771,17 @@ static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
|
|||
if (!MCOperand_getReg(MO2)) {
|
||||
unsigned tmp = getAM2Offset((unsigned int)MCOperand_getImm(MO3));
|
||||
if (tmp) { // Don't print +0.
|
||||
subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));
|
||||
|
||||
SStream_concat0(O, ", ");
|
||||
if (tmp > HEX_THRESHOLD)
|
||||
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO3))), tmp);
|
||||
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), tmp);
|
||||
else
|
||||
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO3))), tmp);
|
||||
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), tmp);
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)getAM2Op((unsigned int)MCOperand_getImm(MO3));
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = tmp;
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
|
||||
}
|
||||
}
|
||||
SStream_concat0(O, "]");
|
||||
|
@ -786,10 +790,11 @@ static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
|
|||
}
|
||||
|
||||
SStream_concat0(O, ", ");
|
||||
SStream_concat0(O, ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO3))));
|
||||
SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
|
||||
printRegName(MI->csh, O, MCOperand_getReg(MO2));
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
|
||||
}
|
||||
|
||||
printRegImmShift(MI, O, getAM2ShiftOpc((unsigned int)MCOperand_getImm(MO3)),
|
||||
|
@ -852,28 +857,31 @@ static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
|
|||
{
|
||||
MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
|
||||
MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
|
||||
ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO2));
|
||||
|
||||
if (!MCOperand_getReg(MO1)) {
|
||||
unsigned ImmOffs = getAM2Offset((unsigned int)MCOperand_getImm(MO2));
|
||||
if (ImmOffs > HEX_THRESHOLD)
|
||||
SStream_concat(O, "#%s0x%x",
|
||||
ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO2))), ImmOffs);
|
||||
ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
|
||||
else
|
||||
SStream_concat(O, "#%s%u",
|
||||
ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO2))), ImmOffs);
|
||||
ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
|
||||
MI->flat_insn->detail->arm.op_count++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
SStream_concat0(O, ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO2))));
|
||||
SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
|
||||
printRegName(MI->csh, O, MCOperand_getReg(MO1));
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
|
||||
MI->flat_insn->detail->arm.op_count++;
|
||||
}
|
||||
|
||||
|
@ -890,7 +898,7 @@ static void printAM3PostIndexOp(MCInst *MI, unsigned Op, SStream *O)
|
|||
MCOperand *MO1 = MCInst_getOperand(MI, Op);
|
||||
MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
|
||||
MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
|
||||
ARM_AM_AddrOpc op = getAM3Op((unsigned int)MCOperand_getImm(MO3));
|
||||
ARM_AM_AddrOpc subtracted = getAM3Op((unsigned int)MCOperand_getImm(MO3));
|
||||
unsigned ImmOffs;
|
||||
|
||||
SStream_concat0(O, "[");
|
||||
|
@ -902,11 +910,12 @@ static void printAM3PostIndexOp(MCInst *MI, unsigned Op, SStream *O)
|
|||
set_mem_access(MI, false);
|
||||
|
||||
if (MCOperand_getReg(MO2)) {
|
||||
SStream_concat(O, "%c", (char)op);
|
||||
SStream_concat(O, "%c", (char)subtracted);
|
||||
printRegName(MI->csh, O, MCOperand_getReg(MO2));
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO2);
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
|
||||
MI->flat_insn->detail->arm.op_count++;
|
||||
}
|
||||
return;
|
||||
|
@ -914,16 +923,17 @@ static void printAM3PostIndexOp(MCInst *MI, unsigned Op, SStream *O)
|
|||
|
||||
ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO3));
|
||||
if (ImmOffs > HEX_THRESHOLD)
|
||||
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(op), ImmOffs);
|
||||
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
|
||||
else
|
||||
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(op), ImmOffs);
|
||||
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
|
||||
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
|
||||
|
||||
if (op)
|
||||
if (subtracted) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
|
||||
else
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
|
||||
} else
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = -(int)ImmOffs;
|
||||
|
||||
MI->flat_insn->detail->arm.op_count++;
|
||||
|
@ -936,7 +946,7 @@ static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
|
|||
MCOperand *MO1 = MCInst_getOperand(MI, Op);
|
||||
MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
|
||||
MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
|
||||
ARM_AM_AddrOpc op = getAM3Op((unsigned int)MCOperand_getImm(MO3));
|
||||
ARM_AM_AddrOpc subtracted = getAM3Op((unsigned int)MCOperand_getImm(MO3));
|
||||
unsigned ImmOffs;
|
||||
|
||||
SStream_concat0(O, "[");
|
||||
|
@ -947,12 +957,14 @@ static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
|
|||
|
||||
if (MCOperand_getReg(MO2)) {
|
||||
SStream_concat0(O, ", ");
|
||||
SStream_concat0(O, ARM_AM_getAddrOpcStr(op));
|
||||
SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
|
||||
printRegName(MI->csh, O, MCOperand_getReg(MO2));
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
|
||||
if (op)
|
||||
if (subtracted) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = -1;
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
|
||||
}
|
||||
}
|
||||
SStream_concat0(O, "]");
|
||||
set_mem_access(MI, false);
|
||||
|
@ -962,17 +974,18 @@ static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
|
|||
//If the op is sub we have to print the immediate even if it is 0
|
||||
ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO3));
|
||||
|
||||
if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM_sub)) {
|
||||
if (AlwaysPrintImm0 || ImmOffs || (subtracted == ARM_AM_sub)) {
|
||||
if (ImmOffs > HEX_THRESHOLD)
|
||||
SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(op), ImmOffs);
|
||||
SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
|
||||
else
|
||||
SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(op), ImmOffs);
|
||||
SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
|
||||
}
|
||||
|
||||
if (MI->csh->detail) {
|
||||
if (op)
|
||||
if (subtracted) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = (int)MCOperand_getImm(MO3);
|
||||
else
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
|
||||
} else
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = (int)-MCOperand_getImm(MO3);
|
||||
}
|
||||
|
||||
|
@ -1006,15 +1019,16 @@ static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
|
|||
{
|
||||
MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
|
||||
MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
|
||||
ARM_AM_AddrOpc op = getAM3Op((unsigned int)MCOperand_getImm(MO2));
|
||||
ARM_AM_AddrOpc subtracted = getAM3Op((unsigned int)MCOperand_getImm(MO2));
|
||||
unsigned ImmOffs;
|
||||
|
||||
if (MCOperand_getReg(MO1)) {
|
||||
SStream_concat0(O, ARM_AM_getAddrOpcStr(op));
|
||||
SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
|
||||
printRegName(MI->csh, O, MCOperand_getReg(MO1));
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
|
||||
MI->flat_insn->detail->arm.op_count++;
|
||||
}
|
||||
return;
|
||||
|
@ -1022,15 +1036,16 @@ static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
|
|||
|
||||
ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO2));
|
||||
if (ImmOffs > HEX_THRESHOLD)
|
||||
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(op), ImmOffs);
|
||||
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
|
||||
else
|
||||
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(op), ImmOffs);
|
||||
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
|
||||
|
||||
if (op)
|
||||
if (subtracted) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
|
||||
else
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
|
||||
} else
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = -(int)ImmOffs;
|
||||
|
||||
MI->flat_insn->detail->arm.op_count++;
|
||||
|
@ -1081,7 +1096,9 @@ static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O,
|
|||
{
|
||||
MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
|
||||
MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
|
||||
ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO2));
|
||||
unsigned ImmOffs, Op;
|
||||
|
||||
if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
|
||||
printOperand(MI, OpNum, O);
|
||||
return;
|
||||
|
@ -1103,14 +1120,15 @@ static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O,
|
|||
if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM_sub) {
|
||||
if (ImmOffs * 4 > HEX_THRESHOLD)
|
||||
SStream_concat(O, ", #%s0x%x",
|
||||
ARM_AM_getAddrOpcStr(ARM_AM_getAM5Op((unsigned int)MCOperand_getImm(MO2))),
|
||||
ARM_AM_getAddrOpcStr(subtracted),
|
||||
ImmOffs * 4);
|
||||
else
|
||||
SStream_concat(O, ", #%s%u",
|
||||
ARM_AM_getAddrOpcStr(ARM_AM_getAM5Op((unsigned int)MCOperand_getImm(MO2))),
|
||||
ARM_AM_getAddrOpcStr(subtracted),
|
||||
ImmOffs * 4);
|
||||
if (MI->csh->detail) {
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = ImmOffs * 4;
|
||||
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
|
||||
}
|
||||
}
|
||||
SStream_concat0(O, "]");
|
||||
|
|
|
@ -212,6 +212,9 @@ typedef struct cs_arm_op {
|
|||
arm_op_mem mem; // base/index/scale/disp value for MEM operand
|
||||
arm_setend_type setend; // SETEND instruction's operand type
|
||||
};
|
||||
// in some instructions, an operand can be subtracted or added to
|
||||
// the base register,
|
||||
bool subtracted; // if TRUE, this operand is subtracted. otherwise, it is added.
|
||||
} cs_arm_op;
|
||||
|
||||
// Instruction structure
|
||||
|
|
|
@ -99,6 +99,9 @@ static void print_insn_detail(cs_insn *ins)
|
|||
if (op->vector_index != -1) {
|
||||
printf("\t\toperands[%u].vector_index = %u\n", i, op->vector_index);
|
||||
}
|
||||
|
||||
if (op->subtracted)
|
||||
printf("\t\tSubtracted: True\n");
|
||||
}
|
||||
|
||||
if (arm->cc != ARM_CC_AL && arm->cc != ARM_CC_INVALID)
|
||||
|
@ -176,7 +179,7 @@ static void test()
|
|||
//#define ARM_CODE "\x90\x04\x0E\x00" // muleq lr, r0, r4
|
||||
//#define ARM_CODE "\x90\x24\x0E\x00" // muleq lr, r0, r4
|
||||
//#define ARM_CODE "\xb6\x10\x5f\xe1" // ldrh r1, [pc, #-6]
|
||||
#define ARM_CODE "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3\x00\x02\x01\xf1\x05\x40\xd0\xe8"
|
||||
#define ARM_CODE "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3\x00\x02\x01\xf1\x05\x40\xd0\xe8\xf4\x80\x00\x00"
|
||||
//#define ARM_CODE2 "\xf0\x24"
|
||||
//#define ARM_CODE2 "\x83\xb0"
|
||||
#define ARM_CODE2 "\xd1\xe8\x00\xf0\xf0\x24\x04\x07\x1f\x3c\xf2\xc0\x00\x00\x4f\xf0\x00\x01\x46\x6c"
|
||||
|
|
Loading…
Reference in New Issue