mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +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;
|
if (op->getParent() == iblock) return true;
|
||||||
PcodeOp *writeOp = vn->getDef();
|
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);
|
Varnode *invn = writeOp->getIn(0);
|
||||||
if (invn->isWritten()) {
|
if (invn->isWritten()) {
|
||||||
PcodeOp *upop = invn->getDef();
|
PcodeOp *upop = invn->getDef();
|
||||||
|
@ -146,18 +151,19 @@ Varnode *ConditionalExecution::findPullback(int4 inbranch)
|
||||||
return pullback[inbranch];
|
return pullback[inbranch];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a duplicate SUBPIECE outside the iblock. If the SUBPIECE input is defined by a MULTIEQUAL in the iblock,
|
/// Create a duplicate PcodeOp outside the iblock. The first input to the PcodeOp can
|
||||||
/// the duplicate's input will be selected from the MULTIEQUAL input.
|
/// be defined by a MULTIEQUAL in the iblock, in which case the duplicate's input will be
|
||||||
/// \param subOp is the SUBPIECE in the iblock being replaced
|
/// 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
|
/// \param inbranch is the direction to pullback from
|
||||||
/// \return the output Varnode of the new SUBPIECE
|
/// \return the output Varnode of the new op
|
||||||
Varnode *ConditionalExecution::pullbackSubpiece(PcodeOp *subOp,int4 inbranch)
|
Varnode *ConditionalExecution::pullbackOp(PcodeOp *op,int4 inbranch)
|
||||||
|
|
||||||
{
|
{
|
||||||
Varnode *invn = findPullback(inbranch); // Look for pullback constructed for a previous read
|
Varnode *invn = findPullback(inbranch); // Look for pullback constructed for a previous read
|
||||||
if (invn != (Varnode *)0)
|
if (invn != (Varnode *)0)
|
||||||
return invn;
|
return invn;
|
||||||
invn = subOp->getIn(0);
|
invn = op->getIn(0);
|
||||||
BlockBasic *bl;
|
BlockBasic *bl;
|
||||||
if (invn->isWritten()) {
|
if (invn->isWritten()) {
|
||||||
PcodeOp *defOp = invn->getDef();
|
PcodeOp *defOp = invn->getDef();
|
||||||
|
@ -166,17 +172,18 @@ Varnode *ConditionalExecution::pullbackSubpiece(PcodeOp *subOp,int4 inbranch)
|
||||||
invn = defOp->getIn(inbranch); // defOp must by MULTIEQUAL
|
invn = defOp->getIn(inbranch); // defOp must by MULTIEQUAL
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
bl = defOp->getParent();
|
bl = (BlockBasic *)iblock->getImmedDom();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
bl = (BlockBasic *)iblock->getImmedDom();
|
bl = (BlockBasic *)iblock->getImmedDom();
|
||||||
}
|
}
|
||||||
PcodeOp *newOp = fd->newOp(2,subOp->getAddr());
|
PcodeOp *newOp = fd->newOp(op->numInput(),op->getAddr());
|
||||||
Varnode *origOutVn = subOp->getOut();
|
Varnode *origOutVn = op->getOut();
|
||||||
Varnode *outVn = fd->newVarnodeOut(origOutVn->getSize(),origOutVn->getAddr(),newOp);
|
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,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);
|
fd->opInsertEnd(newOp, bl);
|
||||||
pullback[inbranch] = outVn; // Cache pullback in case there are other reads
|
pullback[inbranch] = outVn; // Cache pullback in case there are other reads
|
||||||
return outVn;
|
return outVn;
|
||||||
|
@ -245,10 +252,11 @@ Varnode *ConditionalExecution::resolveIblockRead(PcodeOp *op,int4 inbranch)
|
||||||
else
|
else
|
||||||
return vn;
|
return vn;
|
||||||
}
|
}
|
||||||
if (op->code() == CPUI_MULTIEQUAL)
|
OpCode opc = op->code();
|
||||||
|
if (opc == CPUI_MULTIEQUAL)
|
||||||
return op->getIn(inbranch);
|
return op->getIn(inbranch);
|
||||||
else if (op->code() == CPUI_SUBPIECE) {
|
else if (opc == CPUI_SUBPIECE || opc == CPUI_INT_ADD || opc == CPUI_PTRSUB) {
|
||||||
return pullbackSubpiece(op, inbranch);
|
return pullbackOp(op, inbranch);
|
||||||
}
|
}
|
||||||
throw LowlevelError("Conditional execution: Illegal op in iblock");
|
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 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
|
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 *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 *getNewMulti(PcodeOp *op,BlockBasic *bl);
|
||||||
Varnode *resolveRead(PcodeOp *op,BlockBasic *bl); ///< Resolve a read op coming through an arbitrary block
|
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
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
if (vn2->isConstant()) 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
|
/// \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);
|
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 *op1 = vn1->getDef();
|
||||||
PcodeOp *op2 = vn2->getDef();
|
PcodeOp *op2 = vn2->getDef();
|
||||||
OpCode opc = op1->code();
|
OpCode opc = op1->code();
|
||||||
|
|
|
@ -3,29 +3,43 @@
|
||||||
<!--
|
<!--
|
||||||
Example where a SUBPIECE gets placed in an iblock that should still be removed.
|
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.
|
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">
|
<bytechunk space="ram" offset="0x402d29a8" readonly="true">
|
||||||
10402de9eaffffeb
|
10402de9eaffffeb
|
||||||
24309fe5003093e50120a0e31420c3e5
|
24309fe5003093e50120a0e31420c3e5
|
||||||
000050e30030a0131730c0151630c015
|
000050e30030a0131730c0151630c015
|
||||||
1530c0151040bde81eff2fe100003040
|
1530c0151040bde81eff2fe100003040
|
||||||
|
0929d9bf026083604360c2607047
|
||||||
</bytechunk>
|
</bytechunk>
|
||||||
<symbol space="ram" offset="0x402d29a8" name="func"/>
|
<symbol space="ram" offset="0x402d29a8" name="func"/>
|
||||||
<symbol space="ram" offset="0x402d295c" name="other"/>
|
<symbol space="ram" offset="0x402d295c" name="other"/>
|
||||||
|
<symbol space="ram" offset="0x402d29e0" name="iblockadd"/>
|
||||||
</binaryimage>
|
</binaryimage>
|
||||||
<script>
|
<script>
|
||||||
<com>option readonly on</com>
|
<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 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>parse line extern foo *other(void);</com>
|
||||||
<com>map addr r0x40300000 foo *glob1</com>
|
<com>map addr r0x40300000 foo *glob1</com>
|
||||||
<com>lo fu func</com>
|
<com>lo fu func</com>
|
||||||
<com>decompile</com>
|
<com>decompile</com>
|
||||||
<com>print C</com>
|
<com>print C</com>
|
||||||
|
<com>lo fu iblockadd</com>
|
||||||
|
<com>decompile</com>
|
||||||
|
<com>print C</com>
|
||||||
</script>
|
</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 #2" min="0" max="0">\(char\)</stringmatch>
|
||||||
<stringmatch name="Conditional Subpiece #3" min="1" max="1">glob1->w = '\\x01';</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 #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 #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 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>
|
</decompilertest>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue