New flag for dynamic STORE test

This commit is contained in:
caheckman 2019-06-25 14:23:05 -04:00
parent b6b9b27128
commit cb39d39a23
11 changed files with 67 additions and 88 deletions

View file

@ -2494,8 +2494,8 @@ void ActionMarkExplicit::checkNewToConstructor(Funcdata &data,Varnode *vn)
if (firstuse->numInput() < 2) return; // Must have at least 1 parameter (plus destination varnode)
if (firstuse->getIn(1) != vn) return; // First parameter must result of new
// if (!fc->isConstructor()) return; // Function must be a constructor
data.opSetFlag(firstuse,PcodeOp::special_print); // Mark call to print the new operator as well
data.opSetFlag(op,PcodeOp::nonprinting); // Don't print the new operator as stand-alone operation
data.opMarkSpecialPrint(firstuse); // Mark call to print the new operator as well
data.opMarkNonPrinting(op); // Don't print the new operator as stand-alone operation
}
int4 ActionMarkExplicit::apply(Funcdata &data)

View file

@ -212,7 +212,7 @@ void FlowInfo::newAddress(PcodeOp *from,const Address &to)
if (seenInstruction(to)) { // If we have seen this address before
PcodeOp *op = target(to);
data.opSetFlag(op,PcodeOp::startbasic);
data.opMarkStartBasic(op);
return;
}
addrlist.push_back(to);
@ -255,7 +255,7 @@ PcodeOp *FlowInfo::xrefControlFlow(list<PcodeOp *>::const_iterator oiter,bool &s
while(oiter != obank.endDead()) {
op = *oiter++;
if (startbasic) {
data.opSetFlag(op,PcodeOp::startbasic);
data.opMarkStartBasic(op);
startbasic = false;
}
switch(op->code()) {
@ -266,7 +266,7 @@ PcodeOp *FlowInfo::xrefControlFlow(list<PcodeOp *>::const_iterator oiter,bool &s
Address fallThruAddr;
PcodeOp *destop = findRelTarget(op,fallThruAddr);
if (destop != (PcodeOp *)0) {
data.opSetFlag(destop,PcodeOp::startbasic); // Make sure the target op is a basic block start
data.opMarkStartBasic(destop); // Make sure the target op is a basic block start
uintm newtime = destop->getTime();
if (newtime > maxtime)
maxtime = newtime;
@ -286,7 +286,7 @@ PcodeOp *FlowInfo::xrefControlFlow(list<PcodeOp *>::const_iterator oiter,bool &s
Address fallThruAddr;
PcodeOp *destop = findRelTarget(op,fallThruAddr);
if (destop != (PcodeOp *)0) {
data.opSetFlag(destop,PcodeOp::startbasic); // Make sure the target op is a basic block start
data.opMarkStartBasic(destop); // Make sure the target op is a basic block start
uintm newtime = destop->getTime();
if (newtime > maxtime)
maxtime = newtime;
@ -456,7 +456,7 @@ bool FlowInfo::processInstruction(const Address &curaddr,bool &startbasic)
if (oiter != obank.endDead()) {
stat.seqnum = (*oiter)->getSeqNum();
data.opSetFlag(*oiter,PcodeOp::startmark); // Mark the first op in the instruction
data.opMarkStartInstruction(*oiter); // Mark the first op in the instruction
if (flowoverride != Override::NONE)
data.overrideFlow(curaddr,flowoverride);
xrefControlFlow(oiter,startbasic,isfallthru,(FuncCallSpecs *)0);
@ -484,7 +484,7 @@ bool FlowInfo::setFallthruBound(Address &bound)
if (addr == (*iter).first) { // If we have already visited this address
addrlist.pop_back(); // Throw it away
PcodeOp *op = target(addr); // But make sure the address
data.opSetFlag(op,PcodeOp::startbasic); // starts a basic block
data.opMarkStartBasic(op); // starts a basic block
return false;
}
if (addr < (*iter).first + (*iter).second.size)
@ -555,7 +555,7 @@ void FlowInfo::fallthru(void)
if (bound == addrlist.back()) { // Hit the bound exactly
if (startbasic) {
PcodeOp *op = target(addrlist.back());
data.opSetFlag(op,PcodeOp::startbasic);
data.opMarkStartBasic(op);
}
addrlist.pop_back();
break;
@ -828,7 +828,7 @@ void FlowInfo::findUnprocessed(void)
for(iter=addrlist.begin();iter!=addrlist.end();++iter) {
if (seenInstruction(*iter)) {
PcodeOp *op = target(*iter);
data.opSetFlag(op,PcodeOp::startbasic);
data.opMarkStartBasic(op);
}
else
unprocessed.push_back(*iter);
@ -868,7 +868,8 @@ void FlowInfo::fillinBranchStubs(void)
dedupUnprocessed();
for(iter=unprocessed.begin();iter!=unprocessed.end();++iter) {
PcodeOp *op = artificialHalt(*iter,PcodeOp::missing);
data.opSetFlag(op,PcodeOp::startmark|PcodeOp::startbasic);
data.opMarkStartBasic(op);
data.opMarkStartInstruction(op);
}
}
@ -1125,7 +1126,7 @@ bool FlowInfo::testHardInlineRestrictions(Funcdata *inlinefd,PcodeOp *op,Address
return false;
}
// If the inlining "jumps back" this starts a new basic block
data.opSetFlag(nextop,PcodeOp::startbasic);
data.opMarkStartBasic(nextop);
}
inline_recursion->insert(inlinefd->getAddress());
@ -1173,7 +1174,7 @@ void FlowInfo::doInjection(InjectPayload *payload,InjectContext &icontext,PcodeO
iter = op->getInsertIter();
++iter; // Mark next op after the call
if (iter != obank.endDead())
data.opSetFlag(*iter,PcodeOp::startbasic); // as start of basic block
data.opMarkStartBasic(*iter); // as start of basic block
}
obank.moveSequenceDead(firstop,lastop,op); // Move the injection to right after the call
@ -1356,12 +1357,12 @@ void FlowInfo::checkContainedCall(void)
data.opSetOpcode(op,CPUI_BRANCH);
// Make sure target of new goto starts a basic block
PcodeOp *targ = target(addr);
data.opSetFlag(targ,PcodeOp::startbasic);
data.opMarkStartBasic(targ);
// Make sure the following op starts a basic block
list<PcodeOp *>::const_iterator oiter = op->getInsertIter();
++oiter;
if (oiter != obank.endDead())
data.opSetFlag(*oiter,PcodeOp::startbasic);
data.opMarkStartBasic(*oiter);
// Restore original address
data.opSetInput(op,data.newCodeRef(addr),0);
iter = qlst.erase(iter); // Delete the call

View file

@ -413,9 +413,14 @@ public:
void opSetAllInput(PcodeOp *op,const vector<Varnode *> &vvec); ///< Set all input Varnodes for the given PcodeOp simultaneously
void opRemoveInput(PcodeOp *op,int4 slot); ///< Remove a specific input slot for the given PcodeOp
void opInsertInput(PcodeOp *op,Varnode *vn,int4 slot); ///< Insert a new Varnode into the operand list for the given PcodeOp
void opSetFlag(PcodeOp *op,uint4 fl) { op->setFlag(fl); } ///< Set a boolean property on the given PcodeOp
void opClearFlag(PcodeOp *op,uint4 fl) { op->clearFlag(fl); } ///< Clear a boolean property on the given PcodeOp
void opFlipFlag(PcodeOp *op,uint4 fl) { op->flipFlag(fl); } ///< Flip a boolean property on the given PcodeOp
void opMarkStartBasic(PcodeOp *op) { op->setFlag(PcodeOp::startbasic); } ///< Mark PcodeOp as starting a basic block
void opMarkStartInstruction(PcodeOp *op) { op->setFlag(PcodeOp::startmark); } ///< Mark PcodeOp as starting its instruction
void opMarkNonPrinting(PcodeOp *op) { op->setFlag(PcodeOp::nonprinting); } ///< Mark PcodeOp as not being printed
void opMarkSpecialPrint(PcodeOp *op) { op->setAdditionalFlag(PcodeOp::special_print); } ///< Mark PcodeOp as needing special printing
void opMarkNoCollapse(PcodeOp *op) { op->setFlag(PcodeOp::nocollapse); } ///< Mark PcodeOp as not collapsible
void opMarkCpoolTransformed(PcodeOp *op) { op->setFlag(PcodeOp::is_cpool_transformed); } ///< Mark cpool record was visited
void opMarkCalculatedBool(PcodeOp *op) { op->setFlag(PcodeOp::calculated_bool); } ///< Mark PcodeOp as having boolean output
void opFlipCondition(PcodeOp *op) { op->flipFlag(PcodeOp::boolean_flip); } ///< Flip output condition of given CBRANCH
PcodeOp *target(const Address &addr) const { return obank.target(addr); } ///< Look up a PcodeOp by an instruction Address
Varnode *createStackRef(AddrSpace *spc,uintb off,PcodeOp *op,Varnode *stackptr,bool insertafter);
Varnode *opStackLoad(AddrSpace *spc,uintb off,uint4 sz,PcodeOp *op,Varnode *stackptr,bool insertafter);

View file

@ -762,7 +762,7 @@ PcodeOp *Funcdata::nodeSplitCloneOp(PcodeOp *op)
opSetOpcode(dup,op->code());
uint4 flags = op->flags & (PcodeOp::startbasic | PcodeOp::nocollapse |
PcodeOp::startmark);
opSetFlag(dup,flags);
dup->setFlag(flags);
return dup;
}

View file

@ -532,7 +532,7 @@ PcodeOp *Funcdata::cloneOp(const PcodeOp *op,const SeqNum &seq)
PcodeOp *newop = newOp(op->numInput(),seq);
opSetOpcode(newop,op->code());
uint4 flags = op->flags & (PcodeOp::startmark | PcodeOp::startbasic);
opSetFlag(newop,flags);
newop->setFlag(flags);
if (op->getOut() != (Varnode *)0)
opSetOutput(newop,cloneVarnode(op->getOut()));
for(int4 i=0;i<op->numInput();++i)

View file

@ -519,9 +519,9 @@ bool Funcdata::fillinReadOnly(Varnode *vn)
if (vn->isWritten()) { // Can't replace output with constant
PcodeOp *defop = vn->getDef();
if (defop->isMarker())
defop->setFlag(PcodeOp::warning); // Not a true write, ignore it
defop->setAdditionalFlag(PcodeOp::warning); // Not a true write, ignore it
else if (!defop->isWarning()) { // No warning generated before
defop->setFlag(PcodeOp::warning);
defop->setAdditionalFlag(PcodeOp::warning);
ostringstream s;
if ((!vn->isAddrForce())||(!vn->hasNoDescend())) {
s << "Read-only address (";

View file

@ -1072,7 +1072,7 @@ void Merge::markRedundantCopies(HighVariable *high,vector<PcodeOp *> &copy,int4
PcodeOp *domOp = copy[pos + j];
if (domOp->isDead()) continue;
if (checkCopyPair(high, domOp, subOp)) {
data.opSetFlag(subOp, PcodeOp::nonprinting);
data.opMarkNonPrinting(subOp);
break;
}
}
@ -1233,7 +1233,7 @@ void Merge::markInternalCopies(void)
v1 = op->getOut();
h1 = v1->getHigh();
if (h1 == op->getIn(0)->getHigh()) {
data.opSetFlag(op, PcodeOp::nonprinting);
data.opMarkNonPrinting(op);
}
else { // COPY between different HighVariables
if (!h1->hasCopyIn1()) { // If this is the first COPY we've seen for this high
@ -1244,7 +1244,7 @@ void Merge::markInternalCopies(void)
h1->setCopyIn2(); // This is at least the second COPY we've seen
if (v1->hasNoDescend()) { // Don't print shadow assignments
if (shadowedVarnode(v1)) {
data.opSetFlag(op, PcodeOp::nonprinting);
data.opMarkNonPrinting(op);
}
}
}
@ -1261,7 +1261,7 @@ void Merge::markInternalCopies(void)
v3 = h3->getTiedVarnode();
if (v3->overlap(*v1) != 0) break;
if (v2->overlap(*v1) != v3->getSize()) break;
data.opSetFlag(op,PcodeOp::nonprinting);
data.opMarkNonPrinting(op);
break;
case CPUI_SUBPIECE:
h1 = op->getOut()->getHigh();
@ -1272,7 +1272,7 @@ void Merge::markInternalCopies(void)
v2 = h2->getTiedVarnode();
val = op->getIn(1)->getOffset();
if (v1->overlap(*v2) != val) break;
data.opSetFlag(op,PcodeOp::nonprinting);
data.opMarkNonPrinting(op);
break;
default:
break;

View file

@ -62,7 +62,7 @@ class PcodeOp {
friend class VarnodeBank; // Only uses setInput
public:
/// Boolean attributes (flags) that can be placed on a PcodeOp. Even though this enum is public, these are
/// all set and read internally, although many are read publically via \e get or \e is methods.
/// all set and read internally, although many are read publicly via \e get or \e is methods.
enum {
startbasic = 1, ///< This instruction starts a basic block
branch = 2, ///< This instruction is a branch
@ -73,38 +73,39 @@ public:
marker = 0x40, ///< special placeholder op (multiequal or indirect)
///< or CPUI_COPY between different copies
///< of same variable
booloutput = 0x80, ///< Boolean operation
boolean_flip = 0x100, ///< Set if condition must be false to take branch
fallthru_true = 0x200, ///< Set if fallthru happens on true condition
indirect_source = 0x400, ///< Op is source of (one or more) CPUI_INDIRECTs
coderef = 0x800, ///< The first parameter to this op is a coderef
startmark = 0x1000, ///< This op is the first in its instruction
mark = 0x2000, ///< Used by many algorithms that need to detect loops or avoid repeats
commutative = 0x4000, ///< Order of input parameters does not matter
unary = 0x8000, ///< Evaluate as unary expression
binary = 0x10000, ///< Evaluate as binary expression
special = 0x20000, ///< Cannot be evaluated (without special processing)
floatingpoint = 0x40000, ///< A floating point operation
splittingbranch = 0x80000, ///< Dead edge cannot be removed as it splits
nonprinting = 0x100000, ///< Op should not be directly printed as source
halt = 0x200000, ///< instruction causes processor or process to halt
badinstruction = 0x400000, ///< placeholder for bad instruction data
unimplemented = 0x800000, ///< placeholder for unimplemented instruction
noreturn = 0x1000000, ///< placeholder for previous call that doesn't exit
missing = 0x2000000, ///< ops at this address were not generated
warning = 0x4000000, ///< Warning has been generated for this op
booloutput = 0x80, ///< Boolean operation
boolean_flip = 0x100, ///< Set if condition must be false to take branch
fallthru_true = 0x200, ///< Set if fallthru happens on true condition
indirect_source = 0x400, ///< Op is source of (one or more) CPUI_INDIRECTs
coderef = 0x800, ///< The first parameter to this op is a coderef
startmark = 0x1000, ///< This op is the first in its instruction
mark = 0x2000, ///< Used by many algorithms that need to detect loops or avoid repeats
commutative = 0x4000, ///< Order of input parameters does not matter
unary = 0x8000, ///< Evaluate as unary expression
binary = 0x10000, ///< Evaluate as binary expression
special = 0x20000, ///< Cannot be evaluated (without special processing)
floatingpoint = 0x40000, ///< A floating point operation
splittingbranch = 0x80000, ///< Dead edge cannot be removed as it splits
nonprinting = 0x100000, ///< Op should not be directly printed as source
halt = 0x200000, ///< instruction causes processor or process to halt
badinstruction = 0x400000, ///< placeholder for bad instruction data
unimplemented = 0x800000, ///< placeholder for unimplemented instruction
noreturn = 0x1000000, ///< placeholder for previous call that doesn't exit
missing = 0x2000000, ///< ops at this address were not generated
spacebase_ptr = 0x4000000, ///< Loads or stores from a dynamic pointer into a spacebase
indirect_creation = 0x8000000, ///< Output varnode is created by indirect effect
calculated_bool = 0x10000000, ///< Output has been determined to be a 1-bit boolean value
is_cpool_transformed = 0x20000000, ///< Have we checked for cpool transforms
ptrflow = 0x40000000, ///< Op consumes or produces a ptr
special_print = 0x80000000 ///< Op is marked for special printing
ptrflow = 0x40000000 ///< Op consumes or produces a ptr
};
enum {
has_thisptr = 0x1, ///< First parameter ( getIn(1) ) is a this pointer
is_constructor = 0x2, ///< Op is call to a constructor
is_destructor = 0x4, ///< Op is call to a destructor
special_prop = 0x8, ///< Does some special form of datatype propagation
modified = 0x10 ///< This op has been modified by the current action
special_print = 0x10, ///< Op is marked for special printing
modified = 0x20, ///< This op has been modified by the current action
warning = 0x40 ///< Warning has been generated for this op
};
private:
TypeOp *opcode; ///< Pointer to class providing behavioral details of the operation
@ -119,6 +120,7 @@ private:
vector<Varnode *> inrefs; ///< The ordered list of input Varnodes for this op
// Only used by Funcdata
void setOpcode(TypeOp *t_op); ///< Set the opcode for this PcodeOp
void setOutput(Varnode *vn) { output = vn; } ///< Set the output Varnode of this op
void clearInput(int4 slot) { inrefs[slot] = (Varnode *)0; } ///< Clear a specific input Varnode to \e null
void setInput(Varnode *vn,int4 slot) { inrefs[slot] = vn; } ///< Set a specific input Varnode
@ -180,7 +182,7 @@ public:
bool isModified(void) const { return ((addlflags&PcodeOp::modified)!=0); } ///< Return \b true if this is modified by the current action
bool isMark(void) const { return ((flags&PcodeOp::mark)!=0); } ///< Return \b true if this op has been marked
void setMark(void) const { flags |= PcodeOp::mark; } ///< Set the mark on this op
bool isWarning(void) const { return ((flags&PcodeOp::warning)!=0); } ///< Return \b true if a warning has been generated for this op
bool isWarning(void) const { return ((addlflags&PcodeOp::warning)!=0); } ///< Return \b true if a warning has been generated for this op
void clearMark(void) const { flags &= ~PcodeOp::mark; } ///< Clear any mark on this op
bool isIndirectSource(void) const { return ((flags&PcodeOp::indirect_source)!=0); } ///< Return \b true if this causes an INDIRECT
void setIndirectSource(void) { flags |= PcodeOp::indirect_source; } ///< Mark this op as source of INDIRECT
@ -189,7 +191,7 @@ public:
void setPtrFlow(void) { flags |= PcodeOp::ptrflow; } ///< Mark this op as consuming/producing ptrs
bool isSplitting(void) const { return ((flags&PcodeOp::splittingbranch)!=0); } ///< Return \b true if this branch splits
bool doesSpecialPropagation(void) const { return ((addlflags&PcodeOp::special_prop)!=0); } ///< Return \b true if this does datatype propagation
bool doesSpecialPrinting(void) const { return ((flags&PcodeOp::special_print)!=0); } ///< Return \b true if this needs to special printing
bool doesSpecialPrinting(void) const { return ((addlflags&PcodeOp::special_print)!=0); } ///< Return \b true if this needs to special printing
bool hasThisPointer(void) const { return ((addlflags&PcodeOp::has_thisptr)!=0); } ///< Return \b true if this is a call taking 'this' parameter
bool isConstructor(void) const { return ((addlflags&PcodeOp::is_constructor)!=0); } ///< Return \b true if this is call to a constructor
bool isDestructor(void) const { return ((addlflags&PcodeOp::is_destructor)!=0); } ///< Return \b true if this is call to a destructor
@ -198,9 +200,10 @@ public:
/// \brief Return \b true if we have already examined this cpool
bool isCpoolTransformed(void) const { return ((flags&PcodeOp::is_cpool_transformed)!=0); }
bool isCollapsible(void) const; ///< Return \b true if this can be collapsed to a COPY of a constant
/// \brief Return \b true if this LOADs or STOREs from a dynamic \e spacebase pointer
bool usesSpacebasePtr(void) const { return ((flags&PcodeOp::spacebase_ptr)!=0); }
uintm getCseHash(void) const; ///< Return hash indicating possibility of common subexpression elimination
bool isCseMatch(const PcodeOp *op) const; ///< Return \b true if this and \e op represent common subexpressions
void setOpcode(TypeOp *t_op); ///< Set the opcode for this PcodeOp
TypeOp *getOpcode(void) const { return opcode; } ///< Get the opcode for this op
OpCode code(void) const { return opcode->getOpcode(); } ///< Get the opcode id (enum) for this op
bool isCommutative(void) const { return ((flags & PcodeOp::commutative)!=0); } ///< Return \b true if inputs commute

View file

@ -3263,7 +3263,7 @@ int4 RuleCollapseConstants::applyOp(PcodeOp *op,Funcdata &data)
newval = data.getArch()->getConstant(op->collapse(markedInput));
}
catch(LowlevelError &err) {
data.opSetFlag(op,PcodeOp::nocollapse); // Dont know how or dont want to collapse further
data.opMarkNoCollapse(op); // Dont know how or dont want to collapse further
return 0;
}
@ -3294,14 +3294,14 @@ int4 RuleTransformCpool::applyOp(PcodeOp *op,Funcdata &data)
{
if (op->isCpoolTransformed()) return 0; // Already visited
data.opSetFlag(op,PcodeOp::is_cpool_transformed); // Mark our visit
data.opMarkCpoolTransformed(op); // Mark our visit
vector<uintb> refs;
for(int4 i=1;i<op->numInput();++i)
refs.push_back(op->getIn(i)->getOffset());
const CPoolRecord *rec = data.getArch()->cpool->getRecord(refs); // Recover the record
if (rec != (const CPoolRecord *)0) {
if (rec->getTag() == CPoolRecord::instance_of) {
data.opSetFlag(op,PcodeOp::calculated_bool);
data.opMarkCalculatedBool(op);
}
else if (rec->getTag() == CPoolRecord::primitive) {
int4 sz = op->getOut()->getSize();
@ -4883,7 +4883,7 @@ int4 RuleCondNegate::applyOp(PcodeOp *op,Funcdata &data)
data.opSetInput(newop,vn,0);
data.opSetInput(op,outvn,1);
data.opInsertBefore(newop,op);
data.opFlipFlag(op,PcodeOp::boolean_flip); // Flip meaning of condition
data.opFlipCondition(op); // Flip meaning of condition
// NOTE fallthru block is still same status
return 1;
}

View file

@ -126,35 +126,6 @@ bool AddrSpace::contain(AddrSpace *id2) const
return true;
}
/// Convert an array of bytes, which we assume are contained in
/// the space, into an integer value. The conversion depends
/// on the endian property of the space
/// \param ptr is the array of bytes
/// \param size is the size of the array to convert
/// \return the converted integer value
uintm AddrSpace::data2Uintm(const uint1 *ptr,int4 size) const
{
uintm res;
int4 i;
if ((flags&big_endian)!=0) {
res = 0;
for(i=0;i<size;++i) {
res <<= 8;
res |= ptr[i];
}
}
else {
res = 0;
for(i=size-1;i>=0;--i) {
res <<= 8;
res |= ptr[i];
}
}
return res;
}
/// Write the main XML attributes for an address within this space
/// The caller provides only the \e offset, and this routine fills
/// in other details pertaining to this particular space.

View file

@ -130,7 +130,6 @@ public:
bool isOverlay(void) const; ///< Return \b true if this is an overlay space
bool isOverlayBase(void) const; ///< Return \b true if other spaces overlay this space
bool isTruncated(void) const; ///< Return \b true if this space is truncated from its original size
uintm data2Uintm(const uint1 *ptr,int4 size) const; ///< Convert a sequence of bytes into an integer value
void printOffset(ostream &s,uintb offset) const; ///< Write an address offset to a stream
virtual int4 numSpacebase(void) const; ///< Number of base registers associated with this space