Overlapping input fixes

This commit is contained in:
caheckman 2020-03-17 13:12:57 -04:00
parent a8f9d4f7ac
commit 2df81f803b
4 changed files with 33 additions and 9 deletions

View file

@ -1649,6 +1649,12 @@ int4 AncestorRealistic::enterNode(State &state)
multiDepth += 1; multiDepth += 1;
stateStack.push_back(State(op,0)); stateStack.push_back(State(op,0));
return enter_node; // Nothing to check, start traversing inputs of MULTIEQUAL return enter_node; // Nothing to check, start traversing inputs of MULTIEQUAL
case CPUI_PIECE:
// If the trial is getting pieced together and then truncated in a register,
// this is evidence of artificial data-flow.
if (state.vn->getSize() > trial->getSize() && state.vn->getSpace()->getType() != IPTR_SPACEBASE)
return pop_fail;
return pop_solid;
default: default:
return pop_solid; // Any other LOAD or arithmetic/logical operation is viewed as solid movement return pop_solid; // Any other LOAD or arithmetic/logical operation is viewed as solid movement
} }

View file

@ -7279,7 +7279,7 @@ int4 RuleSubvarAnd::applyOp(PcodeOp *op,Funcdata &data)
// if ((vn->getConsume() & 0xff)==0xff) return 0; // if ((vn->getConsume() & 0xff)==0xff) return 0;
// if (op->getIn(1)->getOffset() != (uintb)1) return 0; // if (op->getIn(1)->getOffset() != (uintb)1) return 0;
if (op->getOut()->hasNoDescend()) return 0; if (op->getOut()->hasNoDescend()) return 0;
SubvariableFlow subflow(&data,vn,cmask,false,false); SubvariableFlow subflow(&data,vn,cmask,false,false,false);
if (!subflow.doTrace()) return 0; if (!subflow.doTrace()) return 0;
subflow.doReplacement(); subflow.doReplacement();
return 1; return 1;
@ -7298,14 +7298,24 @@ int4 RuleSubvarSubpiece::applyOp(PcodeOp *op,Funcdata &data)
{ {
Varnode *vn = op->getIn(0); Varnode *vn = op->getIn(0);
Varnode *outvn = op->getOut(); Varnode *outvn = op->getOut();
uintb mask = calc_mask( outvn->getSize() ); int4 flowsize = outvn->getSize();
uintb mask = calc_mask( flowsize );
mask <<= 8*((int4)op->getIn(1)->getOffset()); mask <<= 8*((int4)op->getIn(1)->getOffset());
bool aggressive = outvn->isPtrFlow(); bool aggressive = outvn->isPtrFlow();
if (!aggressive) { if (!aggressive) {
if ((vn->getConsume() & mask) != vn->getConsume()) return 0; if ((vn->getConsume() & mask) != vn->getConsume()) return 0;
if (op->getOut()->hasNoDescend()) return 0; if (op->getOut()->hasNoDescend()) return 0;
} }
SubvariableFlow subflow(&data,vn,mask,aggressive,false); bool big = false;
if (flowsize >= 8 && vn->isInput()) {
// Vector register inputs getting truncated to what actually gets used
// happens occasionally. We let SubvariableFlow deal with this special case
// to avoid overlapping inputs
// TODO: ActionLaneDivide should be handling this
if (vn->loneDescend() == op)
big = true;
}
SubvariableFlow subflow(&data,vn,mask,aggressive,false,big);
if (!subflow.doTrace()) return 0; if (!subflow.doTrace()) return 0;
subflow.doReplacement(); subflow.doReplacement();
return 1; return 1;
@ -7624,7 +7634,7 @@ int4 RuleSubvarCompZero::applyOp(PcodeOp *op,Funcdata &data)
} }
} }
SubvariableFlow subflow(&data,vn,mask,false,false); SubvariableFlow subflow(&data,vn,mask,false,false,false);
if (!subflow.doTrace()) { if (!subflow.doTrace()) {
return 0; return 0;
} }
@ -7656,7 +7666,7 @@ int4 RuleSubvarShift::applyOp(PcodeOp *op,Funcdata &data)
mask = (mask >> sa) << sa; mask = (mask >> sa) << sa;
if (op->getOut()->hasNoDescend()) return 0; if (op->getOut()->hasNoDescend()) return 0;
SubvariableFlow subflow(&data,vn,mask,false,false); SubvariableFlow subflow(&data,vn,mask,false,false,false);
if (!subflow.doTrace()) return 0; if (!subflow.doTrace()) return 0;
subflow.doReplacement(); subflow.doReplacement();
return 1; return 1;
@ -7677,7 +7687,7 @@ int4 RuleSubvarZext::applyOp(PcodeOp *op,Funcdata &data)
Varnode *invn = op->getIn(0); Varnode *invn = op->getIn(0);
uintb mask = calc_mask(invn->getSize()); uintb mask = calc_mask(invn->getSize());
SubvariableFlow subflow(&data,vn,mask,invn->isPtrFlow(),false); SubvariableFlow subflow(&data,vn,mask,invn->isPtrFlow(),false,false);
if (!subflow.doTrace()) return 0; if (!subflow.doTrace()) return 0;
subflow.doReplacement(); subflow.doReplacement();
return 1; return 1;
@ -7698,7 +7708,7 @@ int4 RuleSubvarSext::applyOp(PcodeOp *op,Funcdata &data)
Varnode *invn = op->getIn(0); Varnode *invn = op->getIn(0);
uintb mask = calc_mask(invn->getSize()); uintb mask = calc_mask(invn->getSize());
SubvariableFlow subflow(&data,vn,mask,isaggressive,true); SubvariableFlow subflow(&data,vn,mask,isaggressive,true,false);
if (!subflow.doTrace()) return 0; if (!subflow.doTrace()) return 0;
subflow.doReplacement(); subflow.doReplacement();
return 1; return 1;

View file

@ -1260,7 +1260,8 @@ bool SubvariableFlow::processNextWork(void)
/// \param mask is a mask where 1 bits indicate the position of the logical value within the \e root Varnode /// \param mask is a mask where 1 bits indicate the position of the logical value within the \e root Varnode
/// \param aggr is \b true if we should use aggressive (less restrictive) tests during the trace /// \param aggr is \b true if we should use aggressive (less restrictive) tests during the trace
/// \param sext is \b true if we should assume sign extensions from the logical value into its container /// \param sext is \b true if we should assume sign extensions from the logical value into its container
SubvariableFlow::SubvariableFlow(Funcdata *f,Varnode *root,uintb mask,bool aggr,bool sext) /// \param big is \b true if we look for subvariable flow for \e big (8-byte) logical values
SubvariableFlow::SubvariableFlow(Funcdata *f,Varnode *root,uintb mask,bool aggr,bool sext,bool big)
{ {
fd = f; fd = f;
@ -1280,6 +1281,13 @@ SubvariableFlow::SubvariableFlow(Funcdata *f,Varnode *root,uintb mask,bool aggr,
flowsize = 3; flowsize = 3;
else if (bitsize <= 32) else if (bitsize <= 32)
flowsize = 4; flowsize = 4;
else if (bitsize <= 64) {
if (!big) {
fd = (Funcdata *)0;
return;
}
flowsize = 8;
}
else { else {
fd = (Funcdata *)0; fd = (Funcdata *)0;
return; return;

View file

@ -118,7 +118,7 @@ class SubvariableFlow {
Varnode *getReplaceVarnode(ReplaceVarnode *rvn); Varnode *getReplaceVarnode(ReplaceVarnode *rvn);
bool processNextWork(void); ///< Extend the subgraph from the next node in the worklist bool processNextWork(void); ///< Extend the subgraph from the next node in the worklist
public: public:
SubvariableFlow(Funcdata *f,Varnode *root,uintb mask,bool aggr,bool sext); ///< Constructor SubvariableFlow(Funcdata *f,Varnode *root,uintb mask,bool aggr,bool sext,bool big); ///< Constructor
bool doTrace(void); ///< Trace logical value through data-flow, constructing transform bool doTrace(void); ///< Trace logical value through data-flow, constructing transform
void doReplacement(void); ///< Perform the discovered transform, making logical values explicit void doReplacement(void); ///< Perform the discovered transform, making logical values explicit
}; };