ghidra/Ghidra/Features/Decompiler/src/decompile/cpp/unify.hh

711 lines
31 KiB
C++

/* ###
* 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.
*/
#ifndef __UNIFY_HH__
#define __UNIFY_HH__
#include "funcdata.hh"
namespace ghidra {
class UnifyCPrinter;
class UnifyDatatype {
public:
enum {
op_type, var_type, const_type, block_type
};
private:
uint4 type;
union {
PcodeOp *op;
Varnode *vn;
uintb *cn;
BlockBasic *bl;
} storespot;
public:
UnifyDatatype(void) { type = op_type; }
UnifyDatatype(uint4 tp);
UnifyDatatype(const UnifyDatatype &op2);
UnifyDatatype &operator=(const UnifyDatatype &op2);
~UnifyDatatype(void);
uint4 getType(void) const { return type; }
void setOp(PcodeOp *o) { storespot.op = o; }
PcodeOp *getOp(void) const { return storespot.op; }
void setVarnode(Varnode *v) { storespot.vn = v; }
Varnode *getVarnode(void) const { return storespot.vn; }
void setBlock(BlockBasic *b) { storespot.bl = b; }
BlockBasic *getBlock(void) const { return storespot.bl; }
void setConstant(uintb val);
uintb getConstant(void) const { return *storespot.cn; }
void printVarDecl(ostream &s,int4 id,const UnifyCPrinter &cprinter) const;
string getBaseName(void) const;
};
class UnifyState;
class RHSConstant { // A construction that results in a constant on the right-hand side of an expression
public:
virtual ~RHSConstant(void) {}
virtual RHSConstant *clone(void)=0;
virtual uintb getConstant(UnifyState &state) const=0;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const=0;
};
class ConstantNamed : public RHSConstant {
int4 constindex;
public:
ConstantNamed(int4 id) { constindex = id; }
int4 getId(void) const { return constindex; }
virtual RHSConstant *clone(void) { return new ConstantNamed(constindex); }
virtual uintb getConstant(UnifyState &state) const;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstantAbsolute : public RHSConstant {
uintb val; // The absolute value
public:
ConstantAbsolute(uintb v) { val = v; }
uintb getVal(void) const { return val; }
virtual RHSConstant *clone(void) { return new ConstantAbsolute(val); }
virtual uintb getConstant(UnifyState &state) const;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstantNZMask : public RHSConstant { // A varnode's non-zero mask
int4 varindex;
public:
ConstantNZMask(int4 ind) { varindex = ind; }
virtual RHSConstant *clone(void) { return new ConstantNZMask(varindex); }
virtual uintb getConstant(UnifyState &state) const;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstantConsumed : public RHSConstant { // A varnode's consume mask
int4 varindex;
public:
ConstantConsumed(int4 ind) { varindex = ind; }
virtual RHSConstant *clone(void) { return new ConstantConsumed(varindex); }
virtual uintb getConstant(UnifyState &state) const;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstantOffset : public RHSConstant { // A varnode's offset
int4 varindex;
public:
ConstantOffset(int4 ind) { varindex = ind; }
virtual RHSConstant *clone(void) { return new ConstantOffset(varindex); }
virtual uintb getConstant(UnifyState &state) const;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstantIsConstant : public RHSConstant { // TRUE if the varnode is constant
int4 varindex;
public:
ConstantIsConstant(int4 ind) { varindex = ind; }
virtual RHSConstant *clone(void) { return new ConstantIsConstant(varindex); }
virtual uintb getConstant(UnifyState &state) const;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstantHeritageKnown : public RHSConstant { // A varnode's consume mask
int4 varindex;
public:
ConstantHeritageKnown(int4 ind) { varindex = ind; }
virtual RHSConstant *clone(void) { return new ConstantHeritageKnown(varindex); }
virtual uintb getConstant(UnifyState &state) const;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstantVarnodeSize : public RHSConstant { // A varnode's size as an actual constant
int4 varindex;
public:
ConstantVarnodeSize(int4 ind) { varindex = ind; }
virtual RHSConstant *clone(void) { return new ConstantVarnodeSize(varindex); }
virtual uintb getConstant(UnifyState &state) const;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstantExpression : public RHSConstant {
RHSConstant *expr1,*expr2;
OpCode opc;
public:
ConstantExpression(RHSConstant *e1,RHSConstant *e2,OpCode oc) { expr1 = e1; expr2 = e2; opc = oc; }
virtual ~ConstantExpression(void);
virtual RHSConstant *clone(void);
virtual uintb getConstant(UnifyState &state) const;
virtual void writeExpression(ostream &s,UnifyCPrinter &printstate) const;
};
class TraverseConstraint {
protected:
int4 uniqid;
public:
TraverseConstraint(int4 i) { uniqid = i; }
virtual ~TraverseConstraint(void) {}
// int4 getId(void) const { return uniqid; }
};
class TraverseDescendState : public TraverseConstraint {
bool onestep; // true if first step has occurred
list<PcodeOp *>::const_iterator iter; // Different forward branches we could traverse
list<PcodeOp *>::const_iterator enditer;
public:
TraverseDescendState(int4 i) : TraverseConstraint(i) {}
PcodeOp *getCurrentOp(void) const { return *iter; }
void initialize(Varnode *vn) { onestep = false; iter = vn->beginDescend(); enditer = vn->endDescend(); }
bool step(void) {
if (onestep)
++iter;
else
onestep = true;
return (iter!=enditer); }
};
class TraverseCountState : public TraverseConstraint {
int4 state;
int4 endstate;
public:
TraverseCountState(int4 i) : TraverseConstraint(i) {}
int4 getState(void) const { return state; }
void initialize(int4 end) { state = -1; endstate = end; }
bool step(void) { ++state; return (state != endstate); }
};
class TraverseGroupState : public TraverseConstraint {
vector<TraverseConstraint *> traverselist;
int4 currentconstraint;
int4 state;
public:
TraverseGroupState(int4 i) : TraverseConstraint(i) {}
void addTraverse(TraverseConstraint *tc) { traverselist.push_back(tc); }
TraverseConstraint *getSubTraverse(int4 slot) const { return traverselist[slot]; }
int4 getCurrentIndex(void) const { return currentconstraint; }
void setCurrentIndex(int4 val) { currentconstraint = val; }
int4 getState(void) const { return state; }
void setState(int4 val) { state = val; }
};
class UnifyConstraint {
friend class ConstraintGroup;
protected:
int4 uniqid; // Unique identifier for constraint for retrieving state
int4 maxnum;
UnifyConstraint *copyid(const UnifyConstraint *op) { uniqid = op->uniqid; maxnum = op->maxnum; return this; }
public:
virtual ~UnifyConstraint(void) {}
int4 getId(void) const { return uniqid; }
int4 getMaxNum(void) { return maxnum; }
virtual UnifyConstraint *clone(void) const=0;
virtual void initialize(UnifyState &state);
virtual bool step(UnifyState &state)=0;
virtual void buildTraverseState(UnifyState &state);
virtual void setId(int4 &id) { uniqid = id; id += 1; }
virtual void collectTypes(vector<UnifyDatatype> &typelist) const {}
virtual int4 getBaseIndex(void) const { return -1; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const=0;
virtual bool isDummy(void) const { return false; }
virtual void removeDummy(void) {}
};
class DummyOpConstraint : public UnifyConstraint {
int4 opindex;
public:
DummyOpConstraint(int4 ind) { maxnum = opindex = ind; }
virtual UnifyConstraint *clone(void) const { return (new DummyOpConstraint(opindex))->copyid(this); }
virtual bool step(UnifyState &state) { return true; }
virtual void collectTypes(vector<UnifyDatatype> &typelist) const { typelist[opindex] = UnifyDatatype(UnifyDatatype::op_type); }
virtual int4 getBaseIndex(void) const { return opindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const {}
virtual bool isDummy(void) const { return true; }
};
class DummyVarnodeConstraint : public UnifyConstraint {
int4 varindex;
public:
DummyVarnodeConstraint(int4 ind) { maxnum = varindex = ind; }
virtual UnifyConstraint *clone(void) const { return (new DummyVarnodeConstraint(varindex))->copyid(this); }
virtual bool step(UnifyState &state) { return true; }
virtual void collectTypes(vector<UnifyDatatype> &typelist) const { typelist[varindex] = UnifyDatatype(UnifyDatatype::var_type); }
virtual int4 getBaseIndex(void) const { return varindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const {}
virtual bool isDummy(void) const { return true; }
};
class DummyConstConstraint : public UnifyConstraint {
int4 constindex;
public:
DummyConstConstraint(int4 ind) { maxnum = constindex = ind; }
virtual UnifyConstraint *clone(void) const { return (new DummyConstConstraint(constindex))->copyid(this); }
virtual bool step(UnifyState &state) { return true; }
virtual void collectTypes(vector<UnifyDatatype> &typelist) const { typelist[constindex] = UnifyDatatype(UnifyDatatype::const_type); }
virtual int4 getBaseIndex(void) const { return constindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const {}
virtual bool isDummy(void) const { return true; }
};
class ConstraintBoolean : public UnifyConstraint { // Constant expression must evaluate to true (or false)
bool istrue;
RHSConstant *expr;
public:
ConstraintBoolean(bool ist,RHSConstant *ex) { istrue = ist; expr = ex; maxnum = -1; }
virtual ~ConstraintBoolean(void) { delete expr; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintBoolean(istrue,expr->clone()))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintVarConst : public UnifyConstraint { // Create a new varnode constant
int4 varindex;
RHSConstant *expr;
RHSConstant *exprsz;
public:
ConstraintVarConst(int4 ind,RHSConstant *ex,RHSConstant *sz) { varindex = ind; maxnum = ind; expr = ex; exprsz = sz; }
virtual ~ConstraintVarConst(void);
virtual UnifyConstraint *clone(void) const;
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return varindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintNamedExpression : public UnifyConstraint {
int4 constindex;
RHSConstant *expr;
public:
ConstraintNamedExpression(int4 ind,RHSConstant *ex) { constindex = ind, expr=ex; maxnum = constindex; }
virtual ~ConstraintNamedExpression(void) { delete expr; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintNamedExpression(constindex,expr->clone()))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return constindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintOpCopy : public UnifyConstraint {
int4 oldopindex;
int4 newopindex;
public:
ConstraintOpCopy(int4 oldind,int4 newind) { oldopindex = oldind; newopindex = newind; maxnum = (oldopindex > newopindex) ? oldopindex : newopindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintOpCopy(oldopindex,newopindex))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return oldopindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintOpcode : public UnifyConstraint {
int4 opindex;
vector<OpCode> opcodes; // Which opcodes match
public:
ConstraintOpcode(int4 ind,const vector<OpCode> &o) { maxnum = opindex = ind; opcodes = o; }
const vector<OpCode> &getOpCodes(void) const { return opcodes; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintOpcode(opindex,opcodes))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return opindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintOpCompare : public UnifyConstraint {
int4 op1index;
int4 op2index;
bool istrue;
public:
ConstraintOpCompare(int4 op1ind,int4 op2ind,bool val) { op1index = op1ind; op2index = op2ind; istrue = val; maxnum = (op1index > op2index) ? op1index : op2index; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintOpCompare(op1index,op2index,istrue))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return op1index; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintOpInput : public UnifyConstraint { // Move from op to one of its input varnodes
int4 opindex; // Which op
int4 varnodeindex; // Which input varnode
int4 slot; // Which slot to take
public:
ConstraintOpInput(int4 oind,int4 vind,int4 sl) { opindex = oind; varnodeindex = vind; slot = sl; maxnum = (opindex > varnodeindex) ? opindex : varnodeindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintOpInput(opindex,varnodeindex,slot))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return varnodeindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintOpInputAny : public UnifyConstraint { // Move from op to ANY of its input varnodes
int4 opindex; // Which op
int4 varnodeindex; // What to label input varnode
public:
ConstraintOpInputAny(int4 oind,int4 vind) { opindex = oind; varnodeindex = vind; maxnum = (opindex > varnodeindex) ? opindex : varnodeindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintOpInputAny(opindex,varnodeindex))->copyid(this); }
virtual void initialize(UnifyState &state);
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return varnodeindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintOpOutput : public UnifyConstraint { // Move from op to its output varnode
int4 opindex; // Which op
int4 varnodeindex; // Label of output varnode
public:
ConstraintOpOutput(int4 oind,int4 vind) { opindex = oind; varnodeindex = vind; maxnum = (opindex > varnodeindex) ? opindex : varnodeindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintOpOutput(opindex,varnodeindex))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return varnodeindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintParamConstVal : public UnifyConstraint {
int4 opindex; // Which opcode
int4 slot; // Which slot to examine for constant
uintb val; // What value parameter must match
public:
ConstraintParamConstVal(int4 oind,int4 sl,uintb v) { maxnum = opindex = oind; slot=sl; val = v; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintParamConstVal(opindex,slot,val))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintParamConst : public UnifyConstraint {
int4 opindex; // Which opcode
int4 slot; // Which slot to examine for constant
int4 constindex; // Which varnode is the constant
public:
ConstraintParamConst(int4 oind,int4 sl,int4 cind) { opindex = oind; slot=sl; constindex = cind; maxnum = (opindex > constindex) ? opindex : constindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintParamConst(opindex,slot,constindex))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return constindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintVarnodeCopy : public UnifyConstraint {
int4 oldvarindex;
int4 newvarindex;
public:
ConstraintVarnodeCopy(int4 oldind,int4 newind) { oldvarindex = oldind; newvarindex = newind; maxnum = (oldvarindex > newvarindex) ? oldvarindex : newvarindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintVarnodeCopy(oldvarindex,newvarindex))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return oldvarindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintVarCompare : public UnifyConstraint {
int4 var1index;
int4 var2index;
bool istrue;
public:
ConstraintVarCompare(int4 var1ind,int4 var2ind,bool val) { var1index = var1ind; var2index = var2ind; istrue = val; maxnum = (var1index > var2index) ? var1index : var2index; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintVarCompare(var1index,var2index,istrue))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return var1index; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintDef : public UnifyConstraint {
int4 opindex; // Where to store defining op
int4 varindex; // Which varnode to examine for def
public:
ConstraintDef(int4 oind,int4 vind) { opindex = oind; varindex = vind; maxnum = (opindex > varindex) ? opindex : varindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintDef(opindex,varindex))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return opindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintDescend : public UnifyConstraint {
int4 opindex;
int4 varindex;
public:
ConstraintDescend(int4 oind,int4 vind) { opindex = oind; varindex = vind; maxnum = (opindex > varindex) ? opindex : varindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintDescend(opindex,varindex))->copyid(this); }
virtual void buildTraverseState(UnifyState &state);
virtual void initialize(UnifyState &state);
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return opindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintLoneDescend : public UnifyConstraint {
int4 opindex;
int4 varindex;
public:
ConstraintLoneDescend(int4 oind,int4 vind) { opindex = oind; varindex = vind; maxnum = (opindex > varindex) ? opindex : varindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintLoneDescend(opindex,varindex))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return opindex; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintOtherInput : public UnifyConstraint {
int4 opindex; // For a particular binary op
int4 varindex_in; // Given one of its input varnodes
int4 varindex_out; // Label the other input to op
public:
ConstraintOtherInput(int4 oind,int4 v_in,int4 v_out) { maxnum = opindex = oind; varindex_in = v_in; varindex_out = v_out;
if (varindex_in > maxnum) maxnum = varindex_in; if (varindex_out > maxnum) maxnum = varindex_out; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintOtherInput(opindex,varindex_in,varindex_out))->copyid(this); }
virtual int4 getBaseIndex(void) const { return varindex_out; }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintConstCompare : public UnifyConstraint {
int4 const1index; // Compare two constants resulting in a boolean
int4 const2index;
OpCode opc;
public:
ConstraintConstCompare(int4 c1ind,int4 c2ind,OpCode oc) { const1index = c1ind; const2index = c2ind; opc = oc;
maxnum = (const1index > const2index) ? const1index : const2index; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintConstCompare(const1index,const2index,opc))->copyid(this); }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual int4 getBaseIndex(void) const { return const1index; }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
// For a ConstraintGroup, the list of subconstraints must all match for the whole constraint to match.
// Constraints are tested first to last, i.e. testing for constraint n can assume that 1 thru n-1 match.
class ConstraintGroup : public UnifyConstraint {
protected:
vector<UnifyConstraint *> constraintlist;
public:
ConstraintGroup(void);
virtual ~ConstraintGroup(void);
UnifyConstraint *getConstraint(int4 slot) const { return constraintlist[slot]; }
void addConstraint(UnifyConstraint *a);
int4 numConstraints(void) const { return constraintlist.size(); }
void deleteConstraint(int4 slot);
void mergeIn(ConstraintGroup *b);
virtual UnifyConstraint *clone(void) const;
virtual void initialize(UnifyState &state);
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual void buildTraverseState(UnifyState &state);
virtual void setId(int4 &id);
virtual int4 getBaseIndex(void) const { return constraintlist.back()->getBaseIndex(); }
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
virtual void removeDummy(void);
};
// For a ConstraintOr, exactly one subconstraint needs to be true, for the whole constraint to match
// The constraints are tested sequentially, but there can be no dependency between subconstraints
class ConstraintOr : public ConstraintGroup {
public:
virtual UnifyConstraint *clone(void) const;
virtual void initialize(UnifyState &state);
virtual bool step(UnifyState &state);
virtual void buildTraverseState(UnifyState &state);
virtual int4 getBaseIndex(void) const { return -1; } // Does not have a base
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
// Action constraints, these must always step exactly once (returning true), and do their action
class ConstraintNewOp : public UnifyConstraint {
int4 newopindex;
int4 oldopindex;
bool insertafter; // true if inserted AFTER oldop
OpCode opc; // new opcode
int4 numparams;
public:
ConstraintNewOp(int4 newind,int4 oldind,OpCode oc,bool iafter,int4 num);
virtual UnifyConstraint *clone(void) const { return (new ConstraintNewOp(newopindex,oldopindex,opc,insertafter,numparams))->copyid(this); }
virtual int4 getBaseIndex(void) const { return newopindex; }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintNewUniqueOut : public UnifyConstraint {
int4 opindex;
int4 newvarindex;
int4 sizevarindex; // Negative is specific size, Positive is varnode index (for size)
public:
ConstraintNewUniqueOut(int4 oind,int4 newvarind,int4 sizeind);
virtual UnifyConstraint *clone(void) const { return (new ConstraintNewUniqueOut(opindex,newvarindex,sizevarindex))->copyid(this); }
virtual int4 getBaseIndex(void) const { return newvarindex; }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintSetInput : public UnifyConstraint {
int4 opindex;
RHSConstant *slot;
int4 varindex;
public:
ConstraintSetInput(int4 oind,RHSConstant *sl,int4 varind) { opindex = oind; slot=sl; varindex = varind; maxnum = (opindex > varindex) ? opindex : varindex; }
virtual ~ConstraintSetInput(void) { delete slot; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintSetInput(opindex,slot->clone(),varindex))->copyid(this); }
virtual int4 getBaseIndex(void) const { return varindex; }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintSetInputConstVal : public UnifyConstraint {
int4 opindex;
RHSConstant *slot;
RHSConstant *val;
RHSConstant *exprsz;
public:
ConstraintSetInputConstVal(int4 oind,RHSConstant *sl,RHSConstant *v,RHSConstant *sz) { opindex=oind; slot=sl; val=v; exprsz = sz; maxnum = opindex; }
virtual ~ConstraintSetInputConstVal(void);
virtual UnifyConstraint *clone(void) const;
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintRemoveInput : public UnifyConstraint {
int4 opindex;
RHSConstant *slot;
public:
ConstraintRemoveInput(int4 oind,RHSConstant *sl) { opindex = oind; slot = sl; maxnum = opindex; }
virtual ~ConstraintRemoveInput(void) { delete slot; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintRemoveInput(opindex,slot->clone()))->copyid(this); }
virtual int4 getBaseIndex(void) const { return opindex; }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class ConstraintSetOpcode : public UnifyConstraint {
int4 opindex;
OpCode opc;
public:
ConstraintSetOpcode(int4 oind,OpCode oc) { opindex = oind; opc = oc; maxnum = opindex; }
virtual UnifyConstraint *clone(void) const { return (new ConstraintSetOpcode(opindex,opc))->copyid(this); }
virtual int4 getBaseIndex(void) const { return opindex; }
virtual bool step(UnifyState &state);
virtual void collectTypes(vector<UnifyDatatype> &typelist) const;
virtual void print(ostream &s,UnifyCPrinter &printstate) const;
};
class UnifyState {
ConstraintGroup *container; // containing unifyer
vector<UnifyDatatype> storemap;
vector<TraverseConstraint *> traverselist;
Funcdata *fd;
public:
UnifyState(ConstraintGroup *uni);
~UnifyState(void);
int4 numTraverse(void) const { return traverselist.size(); }
void registerTraverseConstraint(TraverseConstraint *t) { traverselist.push_back(t); }
UnifyDatatype &data(int4 slot) { return storemap[slot]; }
TraverseConstraint *getTraverse(int4 slot) const { return traverselist[slot]; }
Funcdata *getFunction(void) const { return fd; }
OpBehavior *getBehavior(OpCode opc);
void setFunction(Funcdata *f) { fd = f; }
void initialize(int4 id,Varnode *vn);
void initialize(int4 id,PcodeOp *op);
};
class UnifyCPrinter {
vector<UnifyDatatype> storemap;
vector<string> namemap;
int4 depth;
int4 printingtype; // 0 = standard rule
string classname; // Name of the printed class
int4 opparam;
vector<OpCode> opcodelist; // List of opcodes that are recognized by rule
void initializeBase(ConstraintGroup *g);
void printGetOpList(ostream &s);
void printRuleHeader(ostream &s);
ConstraintGroup *grp;
public:
UnifyCPrinter(void) { grp = (ConstraintGroup *)0; opparam = -1; printingtype=0; }
int4 getDepth(void) const { return depth; }
void incDepth(void) { depth += 1; }
void decDepth(void) { depth -= 1; }
void printIndent(ostream &s) const { for(int4 i=0;i<depth+1;++i) s << " "; }
void printAbort(ostream &s);
void popDepth(ostream &s,int4 newdepth);
const string &getName(int4 id) const { return namemap[id]; }
void initializeRuleAction(ConstraintGroup *g,int4 opparam,const vector<OpCode> &olist);
void initializeBasic(ConstraintGroup *g);
void setClassName(const string &nm) { classname = nm; }
void addNames(const map<string,int4> &nmmap);
void printVarDecls(ostream &s) const;
void print(ostream &s);
};
// Rule language
// Identifiers are strict C identifiers that start with either:
// 'o' for a pcode op
// 'v' for a varnode
// '#' for a constant
// 'b' for a basic block
//
// constraints
// oname ( "opname" ) constrain "oname" to a given opcode
// oname <-(1) vname define varnode "vname" as input 1 of "oname"
// oname <-(1) #45 make sure input 1 to "oname" is the constant value 45
// oname <-(1) #name define '#name' as the constant input 1 to "oname"
// oname -> vname define "vname" as the output varnode of op "oname"
// vname <- oname define op "oname" is the op which writes "vname"
// vname -> oname define op "oname" as (one of) ops that reads "vname"
// vname ->! oname define op "oname" as the lone ops that reads "vname"
// oname <- vname != vname1 define "vname" as other input to binary op "oname" besides "vname1"
// vname1( == vname2) verify that vname1 and vname2 are the same varnode
// vname1( != vname2) verify that vname1 and vname2 are not the same varnode
// oname1( == oname2) verify that ops are the same
// vname1 -> vname2 define vname2 as a copy of vname1
// oname <- vname vname is (one of) the inputs to oname
// statements end with ;
// Group construct
// ( statement
// statement ...
// }
// OR construct
// [ statement |
// statement ...
// ]
// vhi1 -> oadd1(+) ;
// [ ( oadd1 -> vadd1 ->! oadd2(+) -> vreshi;
// oadd1 <- vhizext1( != vhi1);
// oadd2 <- vhizext2( != vadd1); ) |
// ( oadd1 <- vtmpvn( != vhi1) <- oadd2(+) <-(0) vhizext1;
// oadd2 <-(1) vhizext2;
// oadd1 -> vreshi; ) ]
// [ ( vhizext1 <- ozext(ZEXT);
// vhizext2 -> vhi2; ) |
// ( vhizext2 <- ozext(ZEXT);
// vhizext1 -> vhi2; ) ]
// ozext <-(0) vzextin <- olesseq(<=) <-(0) vlessin <- oneg(*) <-(1) #-1
// [ (oneg <-(0) vtmp (== vlo1); olesseq <-(1) vlo2; ) |
// (oneg <-(1) vtmp (== vlo2); oneg <-(0) vlo2; ) ]
// vlo1 -> oloadd(+) <- vtmp( != vlo1)( == vlo2);
// oloadd -> vreslo;
} // End namespace ghidra
#endif