bool SgAsmMipsInstruction::get_branch_target(rose_addr_t *target) { SgAsmExpressionPtrList &args = get_operandList()->get_operands(); switch (get_kind()) { case mips_j: case mips_jal: case mips_jalx: { // target address stored in first argument assert(args.size()>=1); if (target) { SgAsmIntegerValueExpression *ival = isSgAsmIntegerValueExpression(args[0]); assert(ival!=NULL); *target = ival->get_absolute_value(); } return true; } case mips_bgez: case mips_bgezal: case mips_bgezall: case mips_bgezl: case mips_bgtz: case mips_bgtzl: case mips_blez: case mips_blezl: case mips_bltz: case mips_bltzal: case mips_bltzall: case mips_bltzl: { // target address stored in the second argument assert(args.size()>=2); if (target) { SgAsmIntegerValueExpression *ival = isSgAsmIntegerValueExpression(args[1]); assert(ival!=NULL); *target = ival->get_absolute_value(); } return true; } case mips_beq: case mips_beql: case mips_bne: case mips_bnel: { // target address stored in the third argument assert(args.size()>=3); if (target) { SgAsmIntegerValueExpression *ival = isSgAsmIntegerValueExpression(args[2]); assert(ival!=NULL); *target = ival->get_absolute_value(); } return true; } default: // no known target; do not modify *target return false; } }
/** Return control flow successors. See base class for full documentation. */ Disassembler::AddressSet SgAsmArmInstruction::get_successors(bool *complete) { Disassembler::AddressSet retval; const std::vector<SgAsmExpression*> &exprs = get_operandList()->get_operands(); *complete = true; /*assume retval is the complete set of successors for now*/ switch (get_kind()) { case arm_b: case arm_bl: case arm_blx: case arm_bx: { /* Branch target */ ROSE_ASSERT(exprs.size()==1); SgAsmExpression *dest = exprs[0]; if (isSgAsmValueExpression(dest)) { rose_addr_t target_va = SageInterface::getAsmConstant(isSgAsmValueExpression(dest)); retval.insert(target_va); } else { /* Could also be a register reference expression, but we don't know the successor in that case. */ *complete = false; } /* Fall-through address */ if (get_condition()!=arm_cond_al) retval.insert(get_address()+4); break; } case arm_bxj: { /* First argument is the register that holds the next instruction pointer value to use in the case that Jazelle is * not available. We only know the successor if the register is the instruction pointer, in which case the * successor is the fall-through address. */ ROSE_ASSERT(exprs.size()==1); SgAsmArmRegisterReferenceExpression *rre = isSgAsmArmRegisterReferenceExpression(exprs[0]); ROSE_ASSERT(rre); if (rre->get_descriptor().get_major()==arm_regclass_gpr && rre->get_descriptor().get_minor()==15) { retval.insert(get_address()+4); } else { *complete = false; } break; } case arm_cmn: case arm_cmp: case arm_teq: case arm_tst: /* Comparison and test instructions don't ever affect the instruction pointer; they only fall through */ retval.insert(get_address()+4); break; case arm_bkpt: case arm_swi: case arm_undefined: case arm_unknown_instruction: /* No known successors for interrupt-generating instructions */ break; default: if (!modifies_ip(this) || get_condition()!=arm_cond_al) { retval.insert(get_address()+4); } else { *complete = false; } break; } return retval; }