/* ### * IP: GHIDRA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef CPUI_RULECOMPILE #include "unify.hh" UnifyDatatype::UnifyDatatype(uint4 tp) { type = tp; switch(type) { case op_type: case var_type: case block_type: break; case const_type: storespot.cn = new uintb; break; default: throw LowlevelError("Bad unify datatype"); } } UnifyDatatype::UnifyDatatype(const UnifyDatatype &op2) { type = op2.type; switch(type) { case op_type: case var_type: case block_type: break; case const_type: storespot.cn = new uintb; // Copy needs its own memory break; default: throw LowlevelError("Bad unify datatype"); } } UnifyDatatype &UnifyDatatype::operator=(const UnifyDatatype &op2) { switch(type) { case op_type: case var_type: case block_type: break; case const_type: delete storespot.cn; break; default: throw LowlevelError("Bad unify datatype"); } type = op2.type; switch(type) { case op_type: case var_type: case block_type: break; case const_type: storespot.cn = new uintb; // Copy needs its own memory break; default: throw LowlevelError("Bad unify datatype"); } return *this; } UnifyDatatype::~UnifyDatatype(void) { switch(type) { case op_type: case var_type: case block_type: break; case const_type: delete storespot.cn; break; default: break; } } void UnifyDatatype::setConstant(uintb val) { *storespot.cn = val; } void UnifyDatatype::printVarDecl(ostream &s,int4 id,const UnifyCPrinter &cprinter) const { cprinter.printIndent(s); switch(type) { case op_type: s << "PcodeOp *" << cprinter.getName(id) << ';' << endl; break; case var_type: s << "Varnode *" << cprinter.getName(id) << ';' << endl; break; case block_type: s << "BlockBasic *" << cprinter.getName(id) << ';' << endl; break; case const_type: s << "uintb " << cprinter.getName(id) << ';' << endl; break; default: throw LowlevelError("Bad unify datatype"); } } string UnifyDatatype::getBaseName(void) const { switch(type) { case op_type: return "op"; case var_type: return "vn"; case block_type: return "bl"; case const_type: return "cn"; default: throw LowlevelError("Bad unify datatype"); } } uintb ConstantNamed::getConstant(UnifyState &state) const { return state.data(constindex).getConstant(); } void ConstantNamed::writeExpression(ostream &s,UnifyCPrinter &printstate) const { s << printstate.getName(constindex); } uintb ConstantAbsolute::getConstant(UnifyState &state) const { return val; } void ConstantAbsolute::writeExpression(ostream &s,UnifyCPrinter &printstate) const { s << "(uintb)0x" << hex << val; } uintb ConstantNZMask::getConstant(UnifyState &state) const { Varnode *vn = state.data(varindex).getVarnode(); return vn->getNZMask(); } void ConstantNZMask::writeExpression(ostream &s,UnifyCPrinter &printstate) const { s << printstate.getName(varindex) << "->getNZMask()"; } uintb ConstantConsumed::getConstant(UnifyState &state) const { Varnode *vn = state.data(varindex).getVarnode(); return vn->getConsume(); } void ConstantConsumed::writeExpression(ostream &s,UnifyCPrinter &printstate) const { s << printstate.getName(varindex) << "->getConsume()"; } uintb ConstantOffset::getConstant(UnifyState &state) const { Varnode *vn = state.data(varindex).getVarnode(); return vn->getOffset(); } void ConstantOffset::writeExpression(ostream &s,UnifyCPrinter &printstate) const { s << printstate.getName(varindex) << "->getOffset()"; } uintb ConstantIsConstant::getConstant(UnifyState &state) const { Varnode *vn = state.data(varindex).getVarnode(); return vn->isConstant() ? (uintb)1 : (uintb)0; } void ConstantIsConstant::writeExpression(ostream &s,UnifyCPrinter &printstate) const { s << "(uintb)" << printstate.getName(varindex) << "->isConstant()"; } uintb ConstantHeritageKnown::getConstant(UnifyState &state) const { Varnode *vn = state.data(varindex).getVarnode(); return (uintb)(vn->isHeritageKnown() ? 1 : 0); } void ConstantHeritageKnown::writeExpression(ostream &s,UnifyCPrinter &printstate) const { s << "(uintb)" << printstate.getName(varindex) << "->isHeritageKnown()"; } uintb ConstantVarnodeSize::getConstant(UnifyState &state) const { Varnode *vn = state.data(varindex).getVarnode(); return (uintb)vn->getSize(); // The size is the actual value } void ConstantVarnodeSize::writeExpression(ostream &s,UnifyCPrinter &printstate) const { s << "(uintb)" << printstate.getName(varindex) << "->getSize()"; } ConstantExpression::~ConstantExpression(void) { delete expr1; if (expr2 != (RHSConstant *)0) delete expr2; } RHSConstant *ConstantExpression::clone(void) { RHSConstant *ecopy1 = expr1->clone(); RHSConstant *ecopy2 = (RHSConstant *)0; if (expr2 != (RHSConstant *)0) ecopy2 = expr2->clone(); return new ConstantExpression(ecopy1,ecopy2,opc); } uintb ConstantExpression::getConstant(UnifyState &state) const { OpBehavior *behavior = state.getBehavior(opc); if (behavior->isSpecial()) throw LowlevelError("Cannot evaluate special operator in constant expression"); uintb res; if (behavior->isUnary()) { uintb ourconst1 = expr1->getConstant(state); res = behavior->evaluateUnary(sizeof(uintb),sizeof(uintb),ourconst1); } else { uintb ourconst1 = expr1->getConstant(state); uintb ourconst2 = expr2->getConstant(state); res = behavior->evaluateBinary(sizeof(uintb),sizeof(uintb),ourconst1,ourconst2); } return res; } void ConstantExpression::writeExpression(ostream &s,UnifyCPrinter &printstate) const { int4 type; // 0=binary 1=unarypre 2=unarypost 3=func string name; // name of operator switch(opc) { case CPUI_INT_ADD: type=0; name = " + "; break; case CPUI_INT_SUB: type=0; name = " - "; break; case CPUI_INT_AND: type=0; name = " & "; break; case CPUI_INT_OR: type=0; name = " | "; break; case CPUI_INT_XOR: type=0; name = " ^ "; break; case CPUI_INT_MULT: type = 0; name = " * "; break; case CPUI_INT_DIV: type = 0; name = " / "; break; case CPUI_INT_EQUAL: type = 0; name = " == "; break; case CPUI_INT_NOTEQUAL: type = 0; name = " != "; break; // case CPUI_INT_SLESS: // case CPUI_INT_SLESSEQUAL: case CPUI_INT_LESS: type = 0; name = " < "; break; case CPUI_INT_LESSEQUAL: type = 0; name = " <= "; break; // case CPUI_INT_ZEXT: // case CPUI_INT_SEXT: // case CPUI_INT_CARRY: // case CPUI_INT_SCARRY: // case CPUI_INT_SBORROW: case CPUI_INT_LEFT: type = 0; name = " << "; break; case CPUI_INT_RIGHT: type = 0; name = " >> "; break; // case CPUI_INT_SRIGHT: default: throw LowlevelError("Unable to generate C for this expression element"); } if (type==0) { s << '('; expr1->writeExpression(s,printstate); s << name; expr2->writeExpression(s,printstate); s << ')'; } else if (type==1) { s << '(' << name; expr1->writeExpression(s,printstate); s << ')'; } else if (type==2) { s << '('; expr1->writeExpression(s,printstate); s << name << ')'; } else { s << name << '('; expr1->writeExpression(s,printstate); s << ')'; } } void UnifyConstraint::initialize(UnifyState &state) { // Default initialization (with only 1 state) TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); traverse->initialize(1); // Initialize with only one state } void UnifyConstraint::buildTraverseState(UnifyState &state) { // Build the default boolean traversal state if (uniqid != state.numTraverse()) throw LowlevelError("Traverse id does not match index"); TraverseConstraint *newt = new TraverseCountState(uniqid); state.registerTraverseConstraint(newt); } bool ConstraintBoolean::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; uintb ourconst = expr->getConstant(state); if (istrue) return (ourconst != 0); return (ourconst == 0); } void ConstraintBoolean::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "if ("; expr->writeExpression(s,printstate); if (istrue) s << "== 0)"; // If false abort else s << "!= 0)"; // If true abort s << endl; printstate.printAbort(s); } ConstraintVarConst::~ConstraintVarConst(void) { delete expr; if (exprsz != (RHSConstant *)0) delete exprsz; } UnifyConstraint *ConstraintVarConst::clone(void) const { UnifyConstraint *res; RHSConstant *newexprsz = (RHSConstant *)0; if (exprsz != (RHSConstant *)0) newexprsz = exprsz->clone(); res = (new ConstraintVarConst(varindex,expr->clone(),newexprsz))->copyid(this); return res; } bool ConstraintVarConst::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; uintb ourconst = expr->getConstant(state); Funcdata *fd = state.getFunction(); int4 sz; if (exprsz != (RHSConstant *)0) sz = (int4)exprsz->getConstant(state); else sz = (int4)sizeof(uintb); ourconst &= calc_mask(sz); Varnode *vn = fd->newConstant( sz, ourconst ); state.data(varindex).setVarnode(vn); return true; } void ConstraintVarConst::collectTypes(vector &typelist) const { typelist[varindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintVarConst::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(varindex) << " = data.newConstant("; if (exprsz != (RHSConstant *)0) exprsz->writeExpression(s,printstate); else s << dec << (int4)sizeof(uintb); s << ','; expr->writeExpression(s,printstate); s << " & calc_mask("; exprsz->writeExpression(s,printstate); s << "));" << endl; } bool ConstraintNamedExpression::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; uintb ourconst = expr->getConstant(state); state.data(constindex).setConstant(ourconst); return true; } void ConstraintNamedExpression::collectTypes(vector &typelist) const { typelist[constindex] = UnifyDatatype(UnifyDatatype::const_type); } void ConstraintNamedExpression::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(constindex) << " = "; expr->writeExpression(s,printstate); s << ';' << endl; } bool ConstraintOpCopy::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op = state.data(oldopindex).getOp(); state.data(newopindex).setOp(op); return true; } void ConstraintOpCopy::collectTypes(vector &typelist) const { typelist[oldopindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[newopindex] = UnifyDatatype(UnifyDatatype::op_type); } void ConstraintOpCopy::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(newopindex) << " = " << printstate.getName(oldopindex) << ';' << endl; } bool ConstraintOpcode::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op = state.data(opindex).getOp(); for(int4 i=0;icode() == opcodes[i]) return true; return false; } void ConstraintOpcode::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); } void ConstraintOpcode::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "if ("; if (opcodes.size()==1) { s << printstate.getName(opindex) << "->code() != CPUI_" << get_opname(opcodes[0]); } else { s << '(' << printstate.getName(opindex) << "->code() != CPUI_" << get_opname(opcodes[0]) << ')'; for(int4 i=1;icode() != CPUI_" << get_opname(opcodes[i]) << ')'; } } s << ')' << endl; printstate.printAbort(s); } bool ConstraintOpCompare::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op1 = state.data(op1index).getOp(); PcodeOp *op2 = state.data(op2index).getOp(); return ((op1==op2) == istrue); } void ConstraintOpCompare::collectTypes(vector &typelist) const { typelist[op1index] = UnifyDatatype(UnifyDatatype::op_type); typelist[op2index] = UnifyDatatype(UnifyDatatype::op_type); } void ConstraintOpCompare::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "if (" << printstate.getName(op1index); if (istrue) s << " != "; else s << " == "; s << printstate.getName(op2index) << ')' << endl; printstate.printAbort(s); } bool ConstraintOpInput::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op = state.data(opindex).getOp(); Varnode *vn = op->getIn(slot); state.data(varnodeindex).setVarnode(vn); return true; } void ConstraintOpInput::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[varnodeindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintOpInput::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(varnodeindex) << " = " << printstate.getName(opindex); s << "->getIn(" << dec << slot << ");" << endl; } void ConstraintOpInputAny::initialize(UnifyState &state) { // Default initialization (with only 1 state) TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); PcodeOp *op = state.data(opindex).getOp(); traverse->initialize(op->numInput()); // Initialize total number of inputs } bool ConstraintOpInputAny::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op = state.data(opindex).getOp(); Varnode *vn = op->getIn(traverse->getState()); state.data(varnodeindex).setVarnode(vn); return true; } void ConstraintOpInputAny::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[varnodeindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintOpInputAny::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "for(int4 i" << dec << printstate.getDepth() << "=0;i"<numInput();++i" << printstate.getDepth() << ") {" << endl; printstate.incDepth(); // A permanent increase in depth printstate.printIndent(s); s << printstate.getName(varnodeindex) << " = " << printstate.getName(opindex) << "->getIn(i"; s << (printstate.getDepth()-1) << ");" << endl; } bool ConstraintOpOutput::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op = state.data(opindex).getOp(); Varnode *vn = op->getOut(); state.data(varnodeindex).setVarnode(vn); return true; } void ConstraintOpOutput::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[varnodeindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintOpOutput::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(varnodeindex) << " = " << printstate.getName(opindex) << "->getOut();" << endl; } bool ConstraintParamConstVal::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op = state.data(opindex).getOp(); Varnode *vn = op->getIn(slot); if (!vn->isConstant()) return false; if (vn->getOffset() != (val&calc_mask(vn->getSize()))) return false; return true; } void ConstraintParamConstVal::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); } void ConstraintParamConstVal::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "if (!" << printstate.getName(opindex) << "->getIn(" << dec << slot << ")->isConstant())" << endl; printstate.printAbort(s); printstate.printIndent(s); s << "if (" << printstate.getName(opindex) << "->getIn(" << dec << slot << ")->getOffset() != 0x"; s << hex << val << " & calc_mask(" << printstate.getName(opindex) << "->getIn(" << dec; s << slot << ")->getSize()))" << endl; printstate.printAbort(s); } bool ConstraintParamConst::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op = state.data(opindex).getOp(); Varnode *vn = op->getIn(slot); if (!vn->isConstant()) return false; state.data(constindex).setConstant(vn->getOffset()); return true; } void ConstraintParamConst::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[constindex] = UnifyDatatype(UnifyDatatype::const_type); } void ConstraintParamConst::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "if (!" << printstate.getName(opindex) << "->getIn(" << dec << slot << ")->isConstant())" << endl; printstate.printAbort(s); printstate.printIndent(s); s << printstate.getName(constindex) << " = "; s << printstate.getName(opindex) << "->getIn(" << dec << slot << ")->getOffset();" << endl; } bool ConstraintVarnodeCopy::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Varnode *vn = state.data(oldvarindex).getVarnode(); state.data(newvarindex).setVarnode(vn); return true; } void ConstraintVarnodeCopy::collectTypes(vector &typelist) const { typelist[oldvarindex] = UnifyDatatype(UnifyDatatype::var_type); typelist[newvarindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintVarnodeCopy::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(newvarindex) << " = " << printstate.getName(oldvarindex) << ';' << endl; } bool ConstraintVarCompare::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Varnode *vn1 = state.data(var1index).getVarnode(); Varnode *vn2 = state.data(var2index).getVarnode(); return ((vn1 == vn2)==istrue); } void ConstraintVarCompare::collectTypes(vector &typelist) const { typelist[var1index] = UnifyDatatype(UnifyDatatype::var_type); typelist[var2index] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintVarCompare::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "if (" << printstate.getName(var1index); if (istrue) s << " != "; else s << " == "; s << printstate.getName(var2index) << ')' << endl; printstate.printAbort(s); } bool ConstraintDef::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Varnode *vn = state.data(varindex).getVarnode(); if (!vn->isWritten()) return false; PcodeOp *op = vn->getDef(); state.data(opindex).setOp(op); return true; } void ConstraintDef::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[varindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintDef::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "if (!" << printstate.getName(varindex) << "->isWritten())" << endl; printstate.printAbort(s); printstate.printIndent(s); s << printstate.getName(opindex) << " = " << printstate.getName(varindex) << "->getDef();" << endl; } void ConstraintDescend::buildTraverseState(UnifyState &state) { if (uniqid != state.numTraverse()) throw LowlevelError("Traverse id does not match index"); TraverseConstraint *newt = new TraverseDescendState(uniqid); state.registerTraverseConstraint(newt); } void ConstraintDescend::initialize(UnifyState &state) { TraverseDescendState *traverse = (TraverseDescendState *)state.getTraverse(uniqid); Varnode *vn = state.data(varindex).getVarnode(); traverse->initialize(vn); } bool ConstraintDescend::step(UnifyState &state) { TraverseDescendState *traverse = (TraverseDescendState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op = traverse->getCurrentOp(); state.data(opindex).setOp(op); return true; } void ConstraintDescend::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[varindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintDescend::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "list::const_iterator iter" << dec << printstate.getDepth() << ",enditer" << printstate.getDepth() << ';' << endl; printstate.printIndent(s); s << "iter" << printstate.getDepth() << " = " << printstate.getName(varindex) << "->beginDescend();" << endl; printstate.printIndent(s); s << "enditer" << printstate.getDepth() << " = " << printstate.getName(varindex) << "->endDescend();" << endl; printstate.printIndent(s); s << "while(iter" << printstate.getDepth() << " != enditer" << printstate.getDepth() << ") {" << endl; printstate.incDepth(); // permanent increase in depth printstate.printIndent(s); s << printstate.getName(opindex) << " = *iter" << (printstate.getDepth()-1) << ';' << endl; printstate.printIndent(s); s << "++iter" << (printstate.getDepth()-1) << endl; } bool ConstraintLoneDescend::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Varnode *vn = state.data(varindex).getVarnode(); PcodeOp *res = vn->loneDescend(); if (res == (PcodeOp *)0) return false; state.data(opindex).setOp(res); return true; } void ConstraintLoneDescend::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[varindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintLoneDescend::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(opindex) << " = " << printstate.getName(varindex) << "->loneDescend();" << endl; printstate.printIndent(s); s << "if (" << printstate.getName(opindex) << " == (PcodeOp *)0)" << endl; printstate.printAbort(s); } bool ConstraintOtherInput::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; PcodeOp *op = state.data(opindex).getOp(); Varnode *vn = state.data(varindex_in).getVarnode(); Varnode *res = op->getIn(1-op->getSlot(vn)); // Get the "other" input state.data(varindex_out).setVarnode(res); return true; } void ConstraintOtherInput::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[varindex_in] = UnifyDatatype(UnifyDatatype::var_type); typelist[varindex_out] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintOtherInput::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(varindex_out) << " = " << printstate.getName(opindex) << "->getIn(1 - "; s << printstate.getName(opindex) << "->getSlot(" << printstate.getName(varindex_in) << "));" << endl; } bool ConstraintConstCompare::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; uintb c1 = state.data(const1index).getConstant(); uintb c2 = state.data(const2index).getConstant(); // This only does operations with boolean result OpBehavior *behavior = state.getBehavior(opc); uintb res = behavior->evaluateBinary(1,sizeof(uintb),c1,c2); return (res != 0); } void ConstraintConstCompare::collectTypes(vector &typelist) const { typelist[const1index] = UnifyDatatype(UnifyDatatype::const_type); typelist[const2index] = UnifyDatatype(UnifyDatatype::const_type); } void ConstraintConstCompare::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "if ("; switch(opc) { case CPUI_INT_EQUAL: s << printstate.getName(const1index) << " != " << printstate.getName(const2index); break; case CPUI_INT_NOTEQUAL: s << printstate.getName(const1index) << " == " << printstate.getName(const2index); break; default: s << "/* unimplemented constant operation */" ; break; } s << ')' << endl; printstate.printAbort(s); } ConstraintGroup::ConstraintGroup(void) { maxnum = -1; } ConstraintGroup::~ConstraintGroup(void) { for(uint4 i=0;igetMaxNum() > maxnum) maxnum = c->getMaxNum(); } void ConstraintGroup::deleteConstraint(int4 slot) { vector::iterator iter = constraintlist.begin(); iter = iter + slot; UnifyConstraint *mydel = *iter; constraintlist.erase(iter); delete mydel; } void ConstraintGroup::mergeIn(ConstraintGroup *b) { // Merge all the subconstraints from -b- into this for(int4 i=0;iconstraintlist.size();++i) addConstraint(b->constraintlist[i]); b->constraintlist.clear(); // Constraints are no longer controlled by -b- delete b; } UnifyConstraint *ConstraintGroup::clone(void) const { ConstraintGroup *res = new ConstraintGroup(); for(int4 i=0;iclone(); res->constraintlist.push_back(subconst); } res->copyid(this); return res; } void ConstraintGroup::initialize(UnifyState &state) { TraverseGroupState *traverse = (TraverseGroupState *)state.getTraverse(uniqid); traverse->setState(-1); } bool ConstraintGroup::step(UnifyState &state) { TraverseGroupState *traverse = (TraverseGroupState *)state.getTraverse(uniqid); UnifyConstraint *subconstraint; TraverseConstraint *subtraverse; int4 subindex; int4 stateint; int4 max = constraintlist.size(); do { stateint = traverse->getState(); if (stateint == 0) { // Attempt a step at current constraint subindex = traverse->getCurrentIndex(); subtraverse = traverse->getSubTraverse(subindex); subconstraint = constraintlist[subindex]; if (subconstraint->step(state)) { traverse->setState(1); // Now try a push subindex += 1; traverse->setCurrentIndex(subindex); } else { subindex -= 1; if (subindex < 0) return false; // Popped off the top traverse->setCurrentIndex(subindex); traverse->setState(0); // Try a step next } } else if (stateint == 1) { // Push subindex = traverse->getCurrentIndex(); subtraverse = traverse->getSubTraverse(subindex); subconstraint = constraintlist[subindex]; subconstraint->initialize(state); traverse->setState(0); // Try a step next } else { // Very first time through traverse->setCurrentIndex(0); subindex = 0; subtraverse = traverse->getSubTraverse(subindex); subconstraint = constraintlist[subindex]; subconstraint->initialize(state); // Initialize the very first subcontraint traverse->setState(0); // Now try a step } } while(subindex < max); subindex -= 1; traverse->setCurrentIndex(subindex); traverse->setState(0); // Have full solution, do step next, to get to next solution return true; } void ConstraintGroup::collectTypes(vector &typelist) const { for(int4 i=0;icollectTypes(typelist); } void ConstraintGroup::buildTraverseState(UnifyState &state) { if (uniqid != state.numTraverse()) throw LowlevelError("Traverse id does not match index"); TraverseGroupState *basetrav = new TraverseGroupState(uniqid); state.registerTraverseConstraint(basetrav); for(int4 i=0;ibuildTraverseState(state); TraverseConstraint *subtraverse = state.getTraverse(subconstraint->getId()); basetrav->addTraverse(subtraverse); } } void ConstraintGroup::setId(int4 &id) { UnifyConstraint::setId(id); for(int4 i=0;isetId(id); } void ConstraintGroup::print(ostream &s,UnifyCPrinter &printstate) const { for(int4 i=0;iprint(s,printstate); } void ConstraintGroup::removeDummy(void) { // Remove any dummy constraints within us vector newlist; for(int4 i=0;iisDummy()) { delete cur; } else { cur->removeDummy(); newlist.push_back(cur); } } constraintlist = newlist; } UnifyConstraint *ConstraintOr::clone(void) const { ConstraintOr *res = new ConstraintOr(); for(int4 i=0;iclone(); res->constraintlist.push_back(subconst); } res->copyid(this); return res; } void ConstraintOr::initialize(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); traverse->initialize(constraintlist.size()); } bool ConstraintOr::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); int4 stateind = traverse->getState(); UnifyConstraint *cur; if (stateind == -1) { // First time through if (!traverse->step()) return false; stateind = traverse->getState(); cur = getConstraint(stateind); cur->initialize(state); } else cur = getConstraint(stateind); for(;;) { if (cur->step(state)) return true; if (!traverse->step()) break; stateind = traverse->getState(); cur = getConstraint(stateind); cur->initialize(state); } return false; } void ConstraintOr::buildTraverseState(UnifyState &state) { if (uniqid != state.numTraverse()) throw LowlevelError("Traverse id does not match index in or"); TraverseCountState *trav = new TraverseCountState(uniqid); state.registerTraverseConstraint(trav); for(int4 i=0;ibuildTraverseState(state); } } void ConstraintOr::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "for(i" << dec << printstate.getDepth() << "=0;i" << printstate.getDepth() << '<'; s << (int4)constraintlist.size() << ";++i" << printstate.getDepth() << ") {" << endl; printstate.incDepth(); // permanent increase in depth for(int4 i=0;iprint(s,printstate); printstate.popDepth(s,olddepth); } } ConstraintNewOp::ConstraintNewOp(int4 newind,int4 oldind,OpCode oc,bool iafter,int4 num) { newopindex = newind; oldopindex = oldind; opc = oc; insertafter = iafter; numparams = num; maxnum = (newind > oldind) ? newind : oldind; } bool ConstraintNewOp::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Funcdata *fd = state.getFunction(); PcodeOp *op = state.data(oldopindex).getOp(); PcodeOp *newop = fd->newOp(numparams,op->getAddr()); fd->opSetOpcode(newop,opc); if (insertafter) fd->opInsertAfter(newop,op); else fd->opInsertBefore(newop,op); return true; } void ConstraintNewOp::collectTypes(vector &typelist) const { typelist[newopindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[oldopindex] = UnifyDatatype(UnifyDatatype::op_type); } void ConstraintNewOp::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(newopindex) << " = data.newOp(" << dec << numparams; s << ',' << printstate.getName(oldopindex) << "->getAddr());" << endl; printstate.printIndent(s); s << "data.opSetOpcode(" << printstate.getName(newopindex) << ",CPUI_" << get_opname(opc) << ");" << endl; s << "data.opInsert"; if (insertafter) s << "After("; else s << "Before("; s << printstate.getName(newopindex) << ',' << printstate.getName(oldopindex) << ");" << endl; } ConstraintNewUniqueOut::ConstraintNewUniqueOut(int4 oind,int4 newvarind,int4 sizeind) { opindex = oind; newvarindex = newvarind; sizevarindex = sizeind; maxnum = (opindex > newvarindex) ? opindex : newvarindex; if (sizevarindex > maxnum) maxnum = sizevarindex; } bool ConstraintNewUniqueOut::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Funcdata *fd = state.getFunction(); PcodeOp *op = state.data(opindex).getOp(); int4 sz; if (sizevarindex < 0) sz = -sizevarindex; // A specific size else { Varnode *sizevn = state.data(sizevarindex).getVarnode(); sz = sizevn->getSize(); } Varnode *newvn = fd->newUniqueOut(sz,op); state.data(newvarindex).setVarnode(newvn); return true; } void ConstraintNewUniqueOut::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[newvarindex] = UnifyDatatype(UnifyDatatype::var_type); if (sizevarindex >= 0) typelist[sizevarindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintNewUniqueOut::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << printstate.getName(newvarindex) << " = data.newUniqueOut("; if (sizevarindex < 0) s << dec << -sizevarindex; else s << printstate.getName(sizevarindex) << "->getSize()"; s << ',' << printstate.getName(opindex) << ");" << endl; } bool ConstraintSetInput::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Funcdata *fd = state.getFunction(); PcodeOp *op = state.data(opindex).getOp(); Varnode *vn = state.data(varindex).getVarnode(); int4 slt = (int4)slot->getConstant(state); fd->opSetInput(op,vn,slt); return true; } void ConstraintSetInput::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); typelist[varindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintSetInput::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "data.opSetInput(" << printstate.getName(opindex) << ',' << printstate.getName(varindex); s << ','; slot->writeExpression(s,printstate); s << ");" << endl; } ConstraintSetInputConstVal::~ConstraintSetInputConstVal(void) { delete val; delete slot; if (exprsz != (RHSConstant *)0) delete exprsz; } UnifyConstraint *ConstraintSetInputConstVal::clone(void) const { RHSConstant *newexprsz = (RHSConstant *)0; if (exprsz != (RHSConstant *)0) newexprsz = exprsz->clone(); UnifyConstraint *res; res = (new ConstraintSetInputConstVal(opindex,slot->clone(),val->clone(),newexprsz))->copyid(this); return res; } bool ConstraintSetInputConstVal::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Funcdata *fd = state.getFunction(); PcodeOp *op = state.data(opindex).getOp(); uintb ourconst = val->getConstant(state); int4 sz; if (exprsz != (RHSConstant *)0) sz = (int4)exprsz->getConstant(state); else sz = (int4)sizeof(uintb); int4 slt = (int4)slot->getConstant(state); fd->opSetInput(op,fd->newConstant(sz,ourconst&calc_mask(sz)),slt); return true; } void ConstraintSetInputConstVal::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); // typelist[varindex] = UnifyDatatype(UnifyDatatype::var_type); } void ConstraintSetInputConstVal::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "data.opSetInput(" << printstate.getName(opindex) << ",data.newConstant("; if (exprsz != (RHSConstant *)0) exprsz->writeExpression(s,printstate); else s << dec << (int4)sizeof(uintb); s << ",calc_mask("; if (exprsz != (RHSConstant *)0) exprsz->writeExpression(s,printstate); else s << dec << (int4)sizeof(uintb); s << ")&"; val->writeExpression(s,printstate); s << "),"; slot->writeExpression(s,printstate); s << ");" << endl; } bool ConstraintRemoveInput::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Funcdata *fd = state.getFunction(); PcodeOp *op = state.data(opindex).getOp(); int4 slt = (int4)slot->getConstant(state); fd->opRemoveInput(op,slt); return true; } void ConstraintRemoveInput::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); } void ConstraintRemoveInput::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "data.opRemoveInput(" << printstate.getName(opindex) << ','; slot->writeExpression(s,printstate); s << ");" << endl; } bool ConstraintSetOpcode::step(UnifyState &state) { TraverseCountState *traverse = (TraverseCountState *)state.getTraverse(uniqid); if (!traverse->step()) return false; Funcdata *fd = state.getFunction(); PcodeOp *op = state.data(opindex).getOp(); fd->opSetOpcode(op,opc); return true; } void ConstraintSetOpcode::collectTypes(vector &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); } void ConstraintSetOpcode::print(ostream &s,UnifyCPrinter &printstate) const { printstate.printIndent(s); s << "data.opSetOpcode(" << printstate.getName(opindex) << ",CPUI_" << get_opname(opc) << ");" << endl; } UnifyState::UnifyState(ConstraintGroup *uni) { container = uni; storemap.resize(container->getMaxNum()+1,UnifyDatatype()); container->collectTypes(storemap); container->buildTraverseState(*this); } UnifyState::~UnifyState(void) { for(int4 i=0;igetArch(); return glb->inst[opc]->getBehavior(); } void UnifyState::initialize(int4 id,Varnode *vn) { // Enter an initial varnode (root) starting point storemap[id].setVarnode(vn); } void UnifyState::initialize(int4 id,PcodeOp *op) { // Enter an initial op (root) starting point storemap[id].setOp(op); } void UnifyCPrinter::initializeBase(ConstraintGroup *g) { grp = g; depth = 0; namemap.clear(); storemap.clear(); opparam = -1; opcodelist.clear(); int4 maxop = g->getMaxNum(); storemap.resize(maxop+1,UnifyDatatype()); g->collectTypes(storemap); for(int4 i=0;i<=maxop;++i) { ostringstream s; s << storemap[i].getBaseName() << dec << i; namemap.push_back(s.str()); } } void UnifyCPrinter::printGetOpList(ostream &s) { // Print the getOpList method of the new rule s << "void " << classname << "::getOpList(vector &oplist) const" << endl; s << endl; s << '{' << endl; for(int4 i=0;i1) s << "continue;"; else { if (printingtype == 0) s << "return 0;"; else s << "return false;"; } depth -= 1; s << endl; } void UnifyCPrinter::popDepth(ostream &s,int4 newdepth) { while(depth != newdepth) { depth -= 1; printIndent(s); s << '}' << endl; } } void UnifyCPrinter::printVarDecls(ostream &s) const { // Print the variables declarations for(int4 i=0;i &oplist) { initializeBase(g); printingtype = 0; classname = "DummyRule"; opparam = opp; opcodelist = oplist; } void UnifyCPrinter::initializeBasic(ConstraintGroup *g) { initializeBase(g); printingtype = 1; opparam = -1; } void UnifyCPrinter::addNames(const map &nmmap) { map::const_iterator iter; for(iter=nmmap.begin();iter!=nmmap.end();++iter) { int4 slot = (*iter).second; if (namemap.size() <= slot) throw LowlevelError("Name indices do not match constraint"); namemap[slot] = (*iter).first; } } void UnifyCPrinter::print(ostream &s) { if (printingtype == 0) { printGetOpList(s); s << endl; printRuleHeader(s); printVarDecls(s); grp->print(s,*this); printIndent(s); s << "return 1;" << endl; // Found a complete match if (depth != 0) { popDepth(s,0); printIndent(s); s << "return 0;" << endl; // Could never find a complete match } s << '}' << endl; } else if (printingtype == 1) { printVarDecls(s); grp->print(s,*this); printIndent(s); s << "return true;" << endl; if (depth != 0) { popDepth(s,0); printIndent(s); s << "return false;" << endl; } s << '}' << endl; } } #endif