From 27a22f8633178df25120782c936dceb5f08d4fd5 Mon Sep 17 00:00:00 2001 From: NighterMan Date: Fri, 10 Apr 2015 04:47:42 +0200 Subject: [PATCH 1/2] 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) From 40e6a999f0cfbcc381b061c90cf658e958348dd4 Mon Sep 17 00:00:00 2001 From: NighterMan Date: Sat, 11 Apr 2015 04:55:16 +0200 Subject: [PATCH 2/2] Improved displacement decoding for sparc banching instructions --- arch/Sparc/SparcInstPrinter.c | 79 +++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/arch/Sparc/SparcInstPrinter.c b/arch/Sparc/SparcInstPrinter.c index edc1971b..c44c0faf 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, len; + int Imm; unsigned reg; MCOperand *MO = MCInst_getOperand(MI, opNum); @@ -188,34 +188,71 @@ static void printOperand(MCInst *MI, int opNum, SStream *O) if (MCOperand_isImm(MO)) { Imm = (int)MCOperand_getImm(MO); - // get absolute address for CALL/Bxx - if (MI->Opcode == SP_CALL) { - Imm = SignExtend32(Imm, 30); - Imm += (uint32_t)MI->address; - } - // 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; + switch (MI->Opcode) { + case SP_CALL: + Imm = SignExtend32(Imm, 30); + Imm += (uint32_t)MI->address; + break; - if (MI->csh->detail) - len = (MI->flat_insn->detail->sparc.op_count)? 19 : 22; - - Imm = SignExtend32(Imm, len); + // Branch on integer condition with prediction (BPcc) + // Branch on floating point condition with prediction (FBPfcc) + case SP_BPICC: + case SP_BPICCA: + case SP_BPICCANT: + case SP_BPICCNT: + case SP_BPXCC: + case SP_BPXCCA: + case SP_BPXCCANT: + case SP_BPXCCNT: + case SP_BPFCC: + case SP_BPFCCA: + case SP_BPFCCANT: + case SP_BPFCCNT: + Imm = SignExtend32(Imm, 19); 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: + + // Branch on integer condition (Bicc) + // Branch on floating point condition (FBfcc) + case SP_BA: + case SP_BCOND: + case SP_BCONDA: + case SP_FBCOND: + case SP_FBCONDA: + Imm = SignExtend32(Imm, 22); + Imm = (uint32_t)MI->address + Imm * 4; + break; + + // Branch on integer register with prediction (BPr) + case SP_BPGEZapn: + case SP_BPGEZapt: + case SP_BPGEZnapn: + case SP_BPGEZnapt: + case SP_BPGZapn: + case SP_BPGZapt: + case SP_BPGZnapn: + case SP_BPGZnapt: + case SP_BPLEZapn: + case SP_BPLEZapt: + case SP_BPLEZnapn: + case SP_BPLEZnapt: + case SP_BPLZapn: + case SP_BPLZapt: + case SP_BPLZnapn: + case SP_BPLZnapt: + case SP_BPNZapn: + case SP_BPNZapt: + case SP_BPNZnapn: + case SP_BPNZnapt: + case SP_BPZapn: + case SP_BPZapt: + case SP_BPZnapn: + case SP_BPZnapt: Imm = SignExtend32(Imm, 16); Imm = (uint32_t)MI->address + Imm * 4; break;