From 27a22f8633178df25120782c936dceb5f08d4fd5 Mon Sep 17 00:00:00 2001 From: NighterMan Date: Fri, 10 Apr 2015 04:47:42 +0200 Subject: [PATCH] Sparc conditional branches displacement fix --- arch/Sparc/SparcInstPrinter.c | 36 ++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/arch/Sparc/SparcInstPrinter.c b/arch/Sparc/SparcInstPrinter.c index cd8979ce..edc1971b 100644 --- a/arch/Sparc/SparcInstPrinter.c +++ b/arch/Sparc/SparcInstPrinter.c @@ -160,7 +160,7 @@ static bool printSparcAliasInstr(MCInst *MI, SStream *O) static void printOperand(MCInst *MI, int opNum, SStream *O) { - int Imm; + int Imm, len; unsigned reg; MCOperand *MO = MCInst_getOperand(MI, opNum); @@ -189,11 +189,37 @@ static void printOperand(MCInst *MI, int opNum, SStream *O) Imm = (int)MCOperand_getImm(MO); // get absolute address for CALL/Bxx - if (MI->Opcode == SP_CALL) + if (MI->Opcode == SP_CALL) { + Imm = SignExtend32(Imm, 30); Imm += (uint32_t)MI->address; - else if (MI->flat_insn->id == SPARC_INS_B) - // pc + (disp30 * 4) - Imm = (uint32_t)MI->address + Imm * 4; + } + + // Conditional branches displacements needs to be signextended to be + // able to jump backwards. + // + // Displacements are measured as the number of instructions forward or + // backward, so they need to be multiplied by 4 + switch (MI->flat_insn->id) { + case SPARC_INS_B: + case SPARC_INS_FB: + len = 19; + + if (MI->csh->detail) + len = (MI->flat_insn->detail->sparc.op_count)? 19 : 22; + + Imm = SignExtend32(Imm, len); + Imm = (uint32_t)MI->address + Imm * 4; + break; + case SPARC_INS_BRZ: + case SPARC_INS_BRNZ: + case SPARC_INS_BRLZ: + case SPARC_INS_BRLEZ: + case SPARC_INS_BRGEZ: + case SPARC_INS_BRGZ: + Imm = SignExtend32(Imm, 16); + Imm = (uint32_t)MI->address + Imm * 4; + break; + } if (Imm >= 0) { if (Imm > HEX_THRESHOLD)