mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GP-4214 Allow INT_ADD in the iblock
This commit is contained in:
parent
48a7542e47
commit
ce09332fcd
4 changed files with 45 additions and 20 deletions
|
@ -122,7 +122,12 @@ bool ConditionalExecution::testOpRead(Varnode *vn,PcodeOp *op)
|
|||
{
|
||||
if (op->getParent() == iblock) return true;
|
||||
PcodeOp *writeOp = vn->getDef();
|
||||
if (writeOp->code() == CPUI_COPY || writeOp->code() == CPUI_SUBPIECE) {
|
||||
OpCode opc = writeOp->code();
|
||||
if (opc == CPUI_COPY || opc == CPUI_SUBPIECE || opc == CPUI_INT_ADD || opc == CPUI_PTRSUB) {
|
||||
if (opc == CPUI_INT_ADD || opc == CPUI_PTRSUB) {
|
||||
if (!writeOp->getIn(1)->isConstant())
|
||||
return false;
|
||||
}
|
||||
Varnode *invn = writeOp->getIn(0);
|
||||
if (invn->isWritten()) {
|
||||
PcodeOp *upop = invn->getDef();
|
||||
|
@ -146,18 +151,19 @@ Varnode *ConditionalExecution::findPullback(int4 inbranch)
|
|||
return pullback[inbranch];
|
||||
}
|
||||
|
||||
/// Create a duplicate SUBPIECE outside the iblock. If the SUBPIECE input is defined by a MULTIEQUAL in the iblock,
|
||||
/// the duplicate's input will be selected from the MULTIEQUAL input.
|
||||
/// \param subOp is the SUBPIECE in the iblock being replaced
|
||||
/// Create a duplicate PcodeOp outside the iblock. The first input to the PcodeOp can
|
||||
/// be defined by a MULTIEQUAL in the iblock, in which case the duplicate's input will be
|
||||
/// selected from the MULTIEQUAL input. Any other inputs must be constants.
|
||||
/// \param op is the PcodeOp in the iblock being replaced
|
||||
/// \param inbranch is the direction to pullback from
|
||||
/// \return the output Varnode of the new SUBPIECE
|
||||
Varnode *ConditionalExecution::pullbackSubpiece(PcodeOp *subOp,int4 inbranch)
|
||||
/// \return the output Varnode of the new op
|
||||
Varnode *ConditionalExecution::pullbackOp(PcodeOp *op,int4 inbranch)
|
||||
|
||||
{
|
||||
Varnode *invn = findPullback(inbranch); // Look for pullback constructed for a previous read
|
||||
if (invn != (Varnode *)0)
|
||||
return invn;
|
||||
invn = subOp->getIn(0);
|
||||
invn = op->getIn(0);
|
||||
BlockBasic *bl;
|
||||
if (invn->isWritten()) {
|
||||
PcodeOp *defOp = invn->getDef();
|
||||
|
@ -166,17 +172,18 @@ Varnode *ConditionalExecution::pullbackSubpiece(PcodeOp *subOp,int4 inbranch)
|
|||
invn = defOp->getIn(inbranch); // defOp must by MULTIEQUAL
|
||||
}
|
||||
else
|
||||
bl = defOp->getParent();
|
||||
bl = (BlockBasic *)iblock->getImmedDom();
|
||||
}
|
||||
else {
|
||||
bl = (BlockBasic *)iblock->getImmedDom();
|
||||
}
|
||||
PcodeOp *newOp = fd->newOp(2,subOp->getAddr());
|
||||
Varnode *origOutVn = subOp->getOut();
|
||||
PcodeOp *newOp = fd->newOp(op->numInput(),op->getAddr());
|
||||
Varnode *origOutVn = op->getOut();
|
||||
Varnode *outVn = fd->newVarnodeOut(origOutVn->getSize(),origOutVn->getAddr(),newOp);
|
||||
fd->opSetOpcode(newOp,CPUI_SUBPIECE);
|
||||
fd->opSetOpcode(newOp,op->code());
|
||||
fd->opSetInput(newOp,invn,0);
|
||||
fd->opSetInput(newOp,subOp->getIn(1),1);
|
||||
for(int4 i=1;i<op->numInput();++i)
|
||||
fd->opSetInput(newOp,op->getIn(i),i);
|
||||
fd->opInsertEnd(newOp, bl);
|
||||
pullback[inbranch] = outVn; // Cache pullback in case there are other reads
|
||||
return outVn;
|
||||
|
@ -245,10 +252,11 @@ Varnode *ConditionalExecution::resolveIblockRead(PcodeOp *op,int4 inbranch)
|
|||
else
|
||||
return vn;
|
||||
}
|
||||
if (op->code() == CPUI_MULTIEQUAL)
|
||||
OpCode opc = op->code();
|
||||
if (opc == CPUI_MULTIEQUAL)
|
||||
return op->getIn(inbranch);
|
||||
else if (op->code() == CPUI_SUBPIECE) {
|
||||
return pullbackSubpiece(op, inbranch);
|
||||
else if (opc == CPUI_SUBPIECE || opc == CPUI_INT_ADD || opc == CPUI_PTRSUB) {
|
||||
return pullbackOp(op, inbranch);
|
||||
}
|
||||
throw LowlevelError("Conditional execution: Illegal op in iblock");
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ class ConditionalExecution {
|
|||
bool testMultiRead(Varnode *vn,PcodeOp *op); ///< Can we move the MULTIEQUAL defining p-code of the given Varnode
|
||||
bool testRemovability(PcodeOp *op); ///< Test if the given PcodeOp can be removed from \b iblock
|
||||
Varnode *findPullback(int4 inbranch); ///< Find previously constructed pull-back op
|
||||
Varnode *pullbackSubpiece(PcodeOp *subOp,int4 inbranch); ///< Pull-back SUBPIECE out of the iblock
|
||||
Varnode *pullbackOp(PcodeOp *op,int4 inbranch); ///< Pull-back PcodeOp out of the iblock
|
||||
Varnode *getNewMulti(PcodeOp *op,BlockBasic *bl);
|
||||
Varnode *resolveRead(PcodeOp *op,BlockBasic *bl); ///< Resolve a read op coming through an arbitrary block
|
||||
Varnode *resolveIblockRead(PcodeOp *op,int4 inbranch); ///< Resolve a read op coming through the \b iblock
|
||||
|
|
|
@ -413,8 +413,7 @@ static int4 functionalEqualityLevel0(Varnode *vn1,Varnode *vn2)
|
|||
return -1;
|
||||
}
|
||||
if (vn2->isConstant()) return -1;
|
||||
if (vn1->isWritten() && vn2->isWritten()) return 1;
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// \brief Try to determine if \b vn1 and \b vn2 contain the same value
|
||||
|
@ -434,7 +433,11 @@ int4 functionalEqualityLevel(Varnode *vn1,Varnode *vn2,Varnode **res1,Varnode **
|
|||
|
||||
{
|
||||
int4 testval = functionalEqualityLevel0(vn1,vn2);
|
||||
if (testval != 1) return testval;
|
||||
if (testval != 1)
|
||||
return testval;
|
||||
if (!vn1->isWritten() || !vn2->isWritten()) {
|
||||
return -1; // Did not find at least one level of match
|
||||
}
|
||||
PcodeOp *op1 = vn1->getDef();
|
||||
PcodeOp *op2 = vn2->getDef();
|
||||
OpCode opc = op1->code();
|
||||
|
|
|
@ -3,29 +3,43 @@
|
|||
<!--
|
||||
Example where a SUBPIECE gets placed in an iblock that should still be removed.
|
||||
The predicates should still all collapse to a single "if" body.
|
||||
Example with INT_ADD in the iblock that should be removed. Should collapse to single if/else.
|
||||
-->
|
||||
<bytechunk space="ram" offset="0x402d29a8" readonly="true">
|
||||
10402de9eaffffeb
|
||||
24309fe5003093e50120a0e31420c3e5
|
||||
000050e30030a0131730c0151630c015
|
||||
1530c0151040bde81eff2fe100003040
|
||||
0929d9bf026083604360c2607047
|
||||
</bytechunk>
|
||||
<symbol space="ram" offset="0x402d29a8" name="func"/>
|
||||
<symbol space="ram" offset="0x402d295c" name="other"/>
|
||||
<symbol space="ram" offset="0x402d29e0" name="iblockadd"/>
|
||||
</binaryimage>
|
||||
<script>
|
||||
<com>option readonly on</com>
|
||||
<com>set context TMode 1 [ram,0x402d29e0] [ram,0x402d29ef]</com>
|
||||
<com>parse line struct foo { char buf[0x14]; char w; char x; char y; char z; };</com>
|
||||
<com>parse line extern void iblockadd(int4 *iptr,int4 a,int4 b,int4 c);</com>
|
||||
<com>parse line extern foo *other(void);</com>
|
||||
<com>map addr r0x40300000 foo *glob1</com>
|
||||
<com>lo fu func</com>
|
||||
<com>decompile</com>
|
||||
<com>print C</com>
|
||||
<com>lo fu iblockadd</com>
|
||||
<com>decompile</com>
|
||||
<com>print C</com>
|
||||
</script>
|
||||
<stringmatch name="Conditional Subpiece #1" min="1" max="1">if</stringmatch>
|
||||
<stringmatch name="Conditional Subpiece #1" min="1" max="1">if \(pfVar</stringmatch>
|
||||
<stringmatch name="Conditional Subpiece #2" min="0" max="0">\(char\)</stringmatch>
|
||||
<stringmatch name="Conditional Subpiece #3" min="1" max="1">glob1->w = '\\x01';</stringmatch>
|
||||
<stringmatch name="Conditional Subpiece #4" min="1" max="1">pfVar1->x = '\\0';</stringmatch>
|
||||
<stringmatch name="Conditional Subpiece #5" min="1" max="1">pfVar1->y = '\\0';</stringmatch>
|
||||
<stringmatch name="Conditional Subpiece #6" min="1" max="1">pfVar1->z = '\\0';</stringmatch>
|
||||
<stringmatch name="Conditional Add #1" min="1" max="1">if \(a</stringmatch>
|
||||
<stringmatch name="Conditional Add #2" min="1" max="1">\*iptr = b;
|
||||
iptr\[2\] = c;</stringmatch>
|
||||
<stringmatch name="Conditional Add #3" min="1" max="1">else \{
|
||||
iptr\[1\] = c;
|
||||
iptr\[3\] = b;</stringmatch>
|
||||
</decompilertest>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue