mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-2957 Sub-flow through INT_DIV and INT_REM
This commit is contained in:
parent
16388dc261
commit
8847d2a6b9
4 changed files with 65 additions and 26 deletions
|
@ -4439,28 +4439,23 @@ bool RuleSubCommute::cancelExtensions(PcodeOp *longform,PcodeOp *subOp,Varnode *
|
||||||
int4 RuleSubCommute::applyOp(PcodeOp *op,Funcdata &data)
|
int4 RuleSubCommute::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
|
|
||||||
{
|
{
|
||||||
Varnode *base,*vn,*newvn,*outvn;
|
Varnode *base = op->getIn(0);
|
||||||
PcodeOp *longform,*newsub,*prevop;
|
|
||||||
int4 i,j,offset,insize;
|
|
||||||
|
|
||||||
base = op->getIn(0);
|
|
||||||
if (!base->isWritten()) return 0;
|
if (!base->isWritten()) return 0;
|
||||||
offset = op->getIn(1)->getOffset();
|
int4 offset = op->getIn(1)->getOffset();
|
||||||
outvn = op->getOut();
|
Varnode *outvn = op->getOut();
|
||||||
if (outvn->isPrecisLo()||outvn->isPrecisHi()) return 0;
|
if (outvn->isPrecisLo()||outvn->isPrecisHi()) return 0;
|
||||||
insize = base->getSize();
|
int4 insize = base->getSize();
|
||||||
longform = base->getDef();
|
PcodeOp *longform = base->getDef();
|
||||||
j = -1;
|
int4 j = -1;
|
||||||
switch( longform->code() ) { // Determine if this op commutes with SUBPIECE
|
switch( longform->code() ) { // Determine if this op commutes with SUBPIECE
|
||||||
// case CPUI_COPY:
|
// case CPUI_COPY:
|
||||||
case CPUI_INT_LEFT:
|
case CPUI_INT_LEFT:
|
||||||
j = 1; // Special processing for shift amount param
|
j = 1; // Special processing for shift amount param
|
||||||
if (offset != 0) return 0;
|
if (offset != 0) return 0;
|
||||||
if (!longform->getIn(0)->isWritten()) return 0;
|
if (longform->getIn(0)->isWritten()) {
|
||||||
prevop = longform->getIn(0)->getDef();
|
OpCode opc = longform->getIn(0)->getDef()->code();
|
||||||
if (prevop->code()==CPUI_INT_ZEXT) {
|
if (opc != CPUI_INT_ZEXT && opc != CPUI_PIECE)
|
||||||
}
|
return 0;
|
||||||
else if (prevop->code()==CPUI_PIECE) {
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4558,17 +4553,24 @@ int4 RuleSubCommute::applyOp(PcodeOp *op,Funcdata &data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i=0;i<longform->numInput();++i) {
|
Varnode *lastIn = (Varnode *)0;
|
||||||
vn = longform->getIn(i);
|
Varnode *newVn = (Varnode *)0;
|
||||||
|
for(int4 i=0;i<longform->numInput();++i) {
|
||||||
|
Varnode *vn = longform->getIn(i);
|
||||||
if (i!=j) {
|
if (i!=j) {
|
||||||
newsub = data.newOp(2,op->getAddr()); // Commuted SUBPIECE op
|
if (lastIn != vn || newVn == (Varnode *)0) { // Don't duplicate the SUBPIECE if inputs are the same
|
||||||
|
PcodeOp *newsub = data.newOp(2,op->getAddr()); // Commuted SUBPIECE op
|
||||||
data.opSetOpcode(newsub,CPUI_SUBPIECE);
|
data.opSetOpcode(newsub,CPUI_SUBPIECE);
|
||||||
newvn = data.newUniqueOut(outvn->getSize(),newsub); // New varnode is subpiece
|
newVn = data.newUniqueOut(outvn->getSize(),newsub); // New varnode is SUBPIECE of old varnode
|
||||||
data.opSetInput(longform,newvn,i);
|
data.opSetInput(longform,newVn,i);
|
||||||
data.opSetInput(newsub,vn,0); // of old varnode
|
data.opSetInput(newsub,vn,0); // vn may be free, so set as input after setting newVn
|
||||||
data.opSetInput(newsub,data.newConstant(4,offset),1);
|
data.opSetInput(newsub,data.newConstant(4,offset),1);
|
||||||
data.opInsertBefore(newsub,longform);
|
data.opInsertBefore(newsub,longform);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
data.opSetInput(longform,newVn,i);
|
||||||
|
}
|
||||||
|
lastIn = vn;
|
||||||
}
|
}
|
||||||
data.opSetOutput(longform,outvn);
|
data.opSetOutput(longform,outvn);
|
||||||
data.opDestroy(op); // Get rid of old SUBPIECE
|
data.opDestroy(op); // Get rid of old SUBPIECE
|
||||||
|
|
|
@ -443,6 +443,16 @@ bool SubvariableFlow::traceForward(ReplaceVarnode *rvn)
|
||||||
if (!createLink(rop,rvn->mask<<sa,-1,outvn)) return false;
|
if (!createLink(rop,rvn->mask<<sa,-1,outvn)) return false;
|
||||||
hcount += 1;
|
hcount += 1;
|
||||||
break;
|
break;
|
||||||
|
case CPUI_INT_DIV:
|
||||||
|
case CPUI_INT_REM:
|
||||||
|
if ((rvn->mask & 1)==0) return false; // Logical value must be least sig bits
|
||||||
|
if ((bitsize & 7)!=0) return false; // Must be a whole number of bytes
|
||||||
|
if (!op->getIn(0)->isZeroExtended(flowsize)) return false;
|
||||||
|
if (!op->getIn(1)->isZeroExtended(flowsize)) return false;
|
||||||
|
rop = createOpDown(op->code(),2,op,rvn,slot);
|
||||||
|
if (!createLink(rop,rvn->mask,-1,outvn)) return false;
|
||||||
|
hcount += 1;
|
||||||
|
break;
|
||||||
case CPUI_INT_ADD:
|
case CPUI_INT_ADD:
|
||||||
if ((rvn->mask & 1)==0)
|
if ((rvn->mask & 1)==0)
|
||||||
return false; // Cannot account for carry
|
return false; // Cannot account for carry
|
||||||
|
@ -768,6 +778,16 @@ bool SubvariableFlow::traceBackward(ReplaceVarnode *rvn)
|
||||||
if (!createLink(rop,rvn->mask,1,op->getIn(1))) return false;
|
if (!createLink(rop,rvn->mask,1,op->getIn(1))) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case CPUI_INT_DIV:
|
||||||
|
case CPUI_INT_REM:
|
||||||
|
if ((rvn->mask & 1) == 0) return false;
|
||||||
|
if ((bitsize & 7)!=0) return false; // Must be a whole number of bytes
|
||||||
|
if (!op->getIn(0)->isZeroExtended(flowsize)) return false;
|
||||||
|
if (!op->getIn(1)->isZeroExtended(flowsize)) return false;
|
||||||
|
rop = createOp(op->code(),2,rvn);
|
||||||
|
if (!createLink(rop,rvn->mask,0,op->getIn(0))) return false;
|
||||||
|
if (!createLink(rop,rvn->mask,1,op->getIn(1))) return false;
|
||||||
|
return true;
|
||||||
case CPUI_SUBPIECE:
|
case CPUI_SUBPIECE:
|
||||||
sa = (int4)op->getIn(1)->getOffset() * 8;
|
sa = (int4)op->getIn(1)->getOffset() * 8;
|
||||||
newmask = rvn->mask << sa;
|
newmask = rvn->mask << sa;
|
||||||
|
|
|
@ -940,6 +940,22 @@ bool Varnode::isBooleanValue(bool useAnnotation) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If we can prove that the upper bits of \b this are zero, return \b true.
|
||||||
|
/// \param baseSize is the maximum number of least significant bytes that are allowed to be non-zero
|
||||||
|
/// \return \b true if all the most significant bytes are zero
|
||||||
|
bool Varnode::isZeroExtended(int4 baseSize) const
|
||||||
|
|
||||||
|
{
|
||||||
|
if (baseSize >= size) return false;
|
||||||
|
if (size > sizeof(uintb)) {
|
||||||
|
if (!isWritten()) return false;
|
||||||
|
if (def->code() != CPUI_INT_ZEXT) return false;
|
||||||
|
if (def->getIn(0)->getSize() > baseSize) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
uintb mask = nzm >> 8*baseSize;
|
||||||
|
return (mask == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/// Make a local determination if \b this and \b op2 hold the same value. We check if
|
/// Make a local determination if \b this and \b op2 hold the same value. We check if
|
||||||
/// there is a common ancester for which both \b this and \b op2 are created from a direct
|
/// there is a common ancester for which both \b this and \b op2 are created from a direct
|
||||||
|
|
|
@ -340,6 +340,7 @@ public:
|
||||||
void copySymbolIfValid(const Varnode *vn); ///< Copy symbol info from \b vn if constant value matches
|
void copySymbolIfValid(const Varnode *vn); ///< Copy symbol info from \b vn if constant value matches
|
||||||
Datatype *getLocalType(bool &blockup) const; ///< Calculate type of Varnode based on local information
|
Datatype *getLocalType(bool &blockup) const; ///< Calculate type of Varnode based on local information
|
||||||
bool isBooleanValue(bool useAnnotation) const; ///< Does \b this Varnode hold a formal boolean value
|
bool isBooleanValue(bool useAnnotation) const; ///< Does \b this Varnode hold a formal boolean value
|
||||||
|
bool isZeroExtended(int4 baseSize) const; ///< Is \b this zero extended from something of the given size
|
||||||
bool copyShadow(const Varnode *op2) const; ///< Are \b this and \b op2 copied from the same source?
|
bool copyShadow(const Varnode *op2) const; ///< Are \b this and \b op2 copied from the same source?
|
||||||
bool findSubpieceShadow(int4 leastByte,const Varnode *whole,int4 recurse) const;
|
bool findSubpieceShadow(int4 leastByte,const Varnode *whole,int4 recurse) const;
|
||||||
bool findPieceShadow(int4 leastByte,const Varnode *piece) const;
|
bool findPieceShadow(int4 leastByte,const Varnode *piece) const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue