From 3a8715b225efa4d2d9d685cd52ed4385d7817320 Mon Sep 17 00:00:00 2001 From: Xiaozhu Meng Date: Tue, 4 Oct 2016 10:55:46 -0500 Subject: [PATCH] 1. Add an architecture-independent interface to check whether a register represents a flag 2. In jump table analysis, perform shift-left operations if both operands are constant and use architecture-independent interface --- common/h/dyn_regs.h | 1 + common/src/dyn_regs.C | 17 +++++++++++++++++ parseAPI/src/BoundFactCalculator.C | 1 + parseAPI/src/BoundFactData.C | 16 +++++++++++----- parseAPI/src/IndirectASTVisitor.C | 8 ++++++++ parseAPI/src/JumpTablePred.C | 11 ++++++----- 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/common/h/dyn_regs.h b/common/h/dyn_regs.h index 6e78661407..3eff120b2d 100644 --- a/common/h/dyn_regs.h +++ b/common/h/dyn_regs.h @@ -106,6 +106,7 @@ namespace Dyninst bool isStackPointer() const; bool isSyscallNumberReg() const; bool isSyscallReturnValueReg() const; + bool isFlag() const; void getROSERegister(int &c, int &n, int &p); diff --git a/common/src/dyn_regs.C b/common/src/dyn_regs.C index 8f02d7ac96..ab0cc1a7d7 100644 --- a/common/src/dyn_regs.C +++ b/common/src/dyn_regs.C @@ -478,6 +478,23 @@ bool MachRegister::isSyscallReturnValueReg() const ); } +bool MachRegister::isFlag() const +{ + int regC = regClass(); + switch (getArchitecture()) + { + case Arch_x86: + return regC == x86::FLAG; + case Arch_x86_64: + return regC == x86_64::FLAG; + case Arch_aarch64: + return regC == aarch64::FLAG; + default: + assert(!"Not implemented!"); + } + return false; +} + COMMON_EXPORT bool Dyninst::isSegmentRegister(int regClass) { return 0 != (regClass & x86::SEG); diff --git a/parseAPI/src/BoundFactCalculator.C b/parseAPI/src/BoundFactCalculator.C index a2d7ed8ae6..82d507175c 100644 --- a/parseAPI/src/BoundFactCalculator.C +++ b/parseAPI/src/BoundFactCalculator.C @@ -320,6 +320,7 @@ static bool IsConditionalJump(Instruction::Ptr insn) { id == e_jb_jnaej_j || id == e_jnb_jae_j || id == e_jle || id == e_jl || id == e_jnl || id == e_jnle) return true; + if (id == aarch64_op_b_cond) return true; return false; } diff --git a/parseAPI/src/BoundFactData.C b/parseAPI/src/BoundFactData.C index b787ff12ca..2be606bd7f 100644 --- a/parseAPI/src/BoundFactData.C +++ b/parseAPI/src/BoundFactData.C @@ -1146,6 +1146,7 @@ bool BoundFact::ConditionalJumpBound(Instruction::Ptr insn, EdgeTypeEnum type) { } break; } + case aarch64_op_b_cond: case e_jnbe: { if (pred.e1->getID() == AST::V_ConstantAST) { if (pred.e2->getID() == AST::V_ConstantAST) { @@ -1315,14 +1316,19 @@ void BoundFact::SetPredicate(Assignment::Ptr assign,std::pair ex } AST::Ptr simplifiedAST = expandRet.first; parsing_printf("\t\t semanic expansions: %s\n", simplifiedAST->format().c_str()); + + ComparisonVisitor cv; + expandRet.first->accept(&cv); + pred.e1 = cv.subtrahend; + pred.e2 = cv.minuend; + pred.id = id; + if (pred.e1 != AST::Ptr() && pred.e2 != AST::Ptr()) { + return; + } + switch (id) { case e_cmp: case e_sub: { - ComparisonVisitor cv; - expandRet.first->accept(&cv); - pred.e1 = cv.subtrahend; - pred.e2 = cv.minuend; - pred.id = id; // The effect of the subtraction can only // be evaluated when there is a conditional jump // after it. Currently, we do not know anything. diff --git a/parseAPI/src/IndirectASTVisitor.C b/parseAPI/src/IndirectASTVisitor.C index 28acf33a05..7c76a18533 100644 --- a/parseAPI/src/IndirectASTVisitor.C +++ b/parseAPI/src/IndirectASTVisitor.C @@ -113,6 +113,14 @@ AST::Ptr SimplifyRoot(AST::Ptr ast, uint64_t insnSize) { else return RoseAST::create(ROSEOperation(ROSEOperation::derefOp), ast->child(0)); break; + case ROSEOperation::shiftLOp: + if (roseAST->child(0)->getID() == AST::V_ConstantAST && roseAST->child(1)->getID() == AST::V_ConstantAST) { + ConstantAST::Ptr child0 = boost::static_pointer_cast(roseAST->child(0)); + ConstantAST::Ptr child1 = boost::static_pointer_cast(roseAST->child(1)); + return ConstantAST::create(Constant(child0->val().val << child1->val().val, 64)); + } + break; + default: break; diff --git a/parseAPI/src/JumpTablePred.C b/parseAPI/src/JumpTablePred.C index 6c07eff1bd..18efa9a31e 100644 --- a/parseAPI/src/JumpTablePred.C +++ b/parseAPI/src/JumpTablePred.C @@ -91,7 +91,7 @@ static void BuildEdges(SliceNode::Ptr curNode, static bool AssignIsZF(Assignment::Ptr a) { return a->out().absloc().type() == Absloc::Register && - (a->out().absloc().reg() == x86::zf || a->out().absloc().reg() == x86_64::zf); + (a->out().absloc().reg() == MachRegister::getZeroFlag(a->out().absloc().reg().getArchitecture())); } static bool IsPushAndChangeSP(Assignment::Ptr a) { @@ -184,11 +184,12 @@ bool JumpTablePred::addNodeCallback(AssignmentPtr ap, set &visi if (currentAssigns.find(ap) != currentAssigns.end()) return true; if (currentAssigns.size() > 50) return false; // For flags, we only analyze zf - if (ap->out().absloc().type() == Absloc::Register && ap->out().absloc().reg().regClass() == (unsigned int)x86::FLAG && - ap->out().absloc().reg() != x86::zf && ap->out().absloc().reg() != x86_64::zf) { - return true; + if (ap->out().absloc().type() == Absloc::Register) { + MachRegister reg = ap->out().absloc().reg(); + if (reg.isFlag() && reg != MachRegister::getZeroFlag(reg.getArchitecture())) { + return true; + } } - pair expandRet = ExpandAssignment(ap); currentAssigns.insert(ap);