arm: some load/store instructions writeback without bang letter. bug reported by @jabba2989

This commit is contained in:
Nguyen Anh Quynh 2015-01-21 12:15:14 +08:00
parent b238628e37
commit e19490e8f7
4 changed files with 106 additions and 4 deletions

View File

@ -16,6 +16,7 @@ void MCInst_Init(MCInst *inst)
inst->size = 0; inst->size = 0;
inst->has_imm = false; inst->has_imm = false;
inst->op1_size = 0; inst->op1_size = 0;
inst->writeback = false;
} }
void MCInst_clear(MCInst *inst) void MCInst_clear(MCInst *inst)

View File

@ -106,6 +106,7 @@ struct MCInst {
// This is copied from cs_x86 struct // This is copied from cs_x86 struct
uint8_t x86_prefix[4]; uint8_t x86_prefix[4];
uint8_t imm_size; // immediate size for X86_OP_IMM operand uint8_t imm_size; // immediate size for X86_OP_IMM operand
bool writeback; // writeback for ARM
}; };
void MCInst_Init(MCInst *inst); void MCInst_Init(MCInst *inst);

View File

@ -1772,6 +1772,7 @@ static DecodeStatus DecodeAddrMode3Instruction(MCInst *Inst, unsigned Insn,
} }
if (writeback) { // Writeback if (writeback) { // Writeback
Inst->writeback = true;
if (P) if (P)
U |= ARMII_IndexModePre << 9; U |= ARMII_IndexModePre << 9;
else else

View File

@ -248,8 +248,104 @@ void ARM_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
return; return;
// check if this insn requests write-back // check if this insn requests write-back
if (strrchr(insn_asm, '!') != NULL) { if (mci->writeback || (strrchr(insn_asm, '!')) != NULL) {
insn->detail->arm.writeback = true; insn->detail->arm.writeback = true;
} else if (MI->csh->mode & CS_MODE_THUMB) {
// handle some special instructions with writeback
switch(mci->Opcode) {
default:
break;
case ARM_t2LDC2L_PRE:
case ARM_t2LDC2_PRE:
case ARM_t2LDCL_PRE:
case ARM_t2LDC_PRE:
case ARM_t2LDRB_PRE:
case ARM_t2LDRD_PRE:
case ARM_t2LDRH_PRE:
case ARM_t2LDRSB_PRE:
case ARM_t2LDRSH_PRE:
case ARM_t2LDR_PRE:
case ARM_t2STC2L_PRE:
case ARM_t2STC2_PRE:
case ARM_t2STCL_PRE:
case ARM_t2STC_PRE:
case ARM_t2STRB_PRE:
case ARM_t2STRD_PRE:
case ARM_t2STRH_PRE:
case ARM_t2STR_PRE:
case ARM_t2LDC2L_POST:
case ARM_t2LDC2_POST:
case ARM_t2LDCL_POST:
case ARM_t2LDC_POST:
case ARM_t2LDRB_POST:
case ARM_t2LDRD_POST:
case ARM_t2LDRH_POST:
case ARM_t2LDRSB_POST:
case ARM_t2LDRSH_POST:
case ARM_t2LDR_POST:
case ARM_t2STC2L_POST:
case ARM_t2STC2_POST:
case ARM_t2STCL_POST:
case ARM_t2STC_POST:
case ARM_t2STRB_POST:
case ARM_t2STRD_POST:
case ARM_t2STRH_POST:
case ARM_t2STR_POST:
insn->detail->arm.writeback = true;
break;
}
} else { // ARM mode
// handle some special instructions with writeback
switch(mci->Opcode) {
default:
break;
case ARM_LDC2L_PRE:
case ARM_LDC2_PRE:
case ARM_LDCL_PRE:
case ARM_LDC_PRE:
case ARM_LDRD_PRE:
case ARM_LDRH_PRE:
case ARM_LDRSB_PRE:
case ARM_LDRSH_PRE:
case ARM_STC2L_PRE:
case ARM_STC2_PRE:
case ARM_STCL_PRE:
case ARM_STC_PRE:
case ARM_STRD_PRE:
case ARM_STRH_PRE:
case ARM_LDC2L_POST:
case ARM_LDC2_POST:
case ARM_LDCL_POST:
case ARM_LDC_POST:
case ARM_LDRBT_POST:
case ARM_LDRD_POST:
case ARM_LDRH_POST:
case ARM_LDRSB_POST:
case ARM_LDRSH_POST:
case ARM_STC2L_POST:
case ARM_STC2_POST:
case ARM_STCL_POST:
case ARM_STC_POST:
case ARM_STRBT_POST:
case ARM_STRD_POST:
case ARM_STRH_POST:
insn->detail->arm.writeback = true;
break;
}
} }
// check if this insn requests update flags // check if this insn requests update flags
@ -536,8 +632,10 @@ void ARM_printInst(MCInst *MI, SStream *O, void *Info)
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = BaseReg; MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = BaseReg;
MI->flat_insn->detail->arm.op_count++; MI->flat_insn->detail->arm.op_count++;
} }
if (Writeback) if (Writeback) {
MI->writeback = true;
SStream_concat0(O, "!"); SStream_concat0(O, "!");
}
SStream_concat0(O, ", "); SStream_concat0(O, ", ");
printRegisterList(MI, 3, O); printRegisterList(MI, 3, O);
return; return;
@ -1137,9 +1235,10 @@ static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O)
static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O) static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
{ {
MCOperand *MO = MCInst_getOperand(MI, OpNum); MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_getReg(MO) == 0) if (MCOperand_getReg(MO) == 0) {
MI->writeback = true;
SStream_concat0(O, "!"); SStream_concat0(O, "!");
else { } else {
SStream_concat0(O, ", "); SStream_concat0(O, ", ");
printRegName(MI->csh, O, MCOperand_getReg(MO)); printRegName(MI->csh, O, MCOperand_getReg(MO));
if (MI->csh->detail) { if (MI->csh->detail) {