mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-1683 Extensions to SUBPIECE/shift rules
This commit is contained in:
parent
d0a8291e93
commit
aa85bba5d7
3 changed files with 70 additions and 11 deletions
|
@ -32,6 +32,7 @@ src/decompile/datatests/noforloop_alias.xml||GHIDRA||||END|
|
|||
src/decompile/datatests/noforloop_globcall.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/noforloop_iterused.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/offsetarray.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/packstructaccess.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/pointercmp.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/pointerrel.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/pointersub.xml||GHIDRA||||END|
|
||||
|
|
|
@ -4736,7 +4736,7 @@ int4 RuleSubCancel::applyOp(PcodeOp *op,Funcdata &data)
|
|||
}
|
||||
|
||||
/// \class RuleShiftSub
|
||||
/// \brief Simplify SUBPIECE applied to INT_LEFT: `sub( V << 8*c, c) => sub(V,0)`
|
||||
/// \brief Simplify SUBPIECE applied to INT_LEFT: `sub( V << 8*k, c) => sub(V,c-k)`
|
||||
void RuleShiftSub::getOpList(vector<uint4> &oplist) const
|
||||
|
||||
{
|
||||
|
@ -4749,13 +4749,20 @@ int4 RuleShiftSub::applyOp(PcodeOp *op,Funcdata &data)
|
|||
if (!op->getIn(0)->isWritten()) return 0;
|
||||
PcodeOp *shiftop = op->getIn(0)->getDef();
|
||||
if (shiftop->code() != CPUI_INT_LEFT) return 0;
|
||||
if (!shiftop->getIn(1)->isConstant()) return 0;
|
||||
if (8*op->getIn(1)->getOffset() != shiftop->getIn(1)->getOffset())
|
||||
return 0;
|
||||
Varnode *sa = shiftop->getIn(1);
|
||||
if (!sa->isConstant()) return 0;
|
||||
int4 n = sa->getOffset();
|
||||
if ((n & 7) != 0) return 0; // Must shift by a multiple of 8 bits
|
||||
int4 c = op->getIn(1)->getOffset();
|
||||
Varnode *vn = shiftop->getIn(0);
|
||||
if (vn->isFree()) return 0;
|
||||
int4 insize = vn->getSize();
|
||||
int4 outsize = op->getOut()->getSize();
|
||||
c -= n/8;
|
||||
if (c < 0 || c + outsize > insize) // Check if this is a natural truncation
|
||||
return 0;
|
||||
data.opSetInput(op,vn,0);
|
||||
data.opSetInput(op,data.newConstant(op->getIn(1)->getSize(),0),1);
|
||||
data.opSetInput(op,data.newConstant(op->getIn(1)->getSize(),c),1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -6879,7 +6886,8 @@ int4 RuleExtensionPush::applyOp(PcodeOp *op,Funcdata &data)
|
|||
/// \brief Pull-back SUBPIECE through INT_RIGHT and INT_SRIGHT
|
||||
///
|
||||
/// The form looks like:
|
||||
/// - `sub( V>>c ,d ) => sub( V, d+k/8 ) >> (c-k) where k = (c/8)*8`
|
||||
/// - `sub( V>>n ,c ) => sub( V, c+k/8 ) >> (n-k) where k = (n/8)*8` or
|
||||
/// - `sub( V>>n, c ) => ext( sub( V, c+k/8 ) ) if n is big`
|
||||
void RuleSubNormal::getOpList(vector<uint4> &oplist) const
|
||||
|
||||
{
|
||||
|
@ -6901,13 +6909,35 @@ int4 RuleSubNormal::applyOp(PcodeOp *op,Funcdata &data)
|
|||
int4 n = shiftop->getIn(1)->getOffset();
|
||||
int4 c = op->getIn(1)->getOffset();
|
||||
int4 k = (n/8);
|
||||
int4 insize = a->getSize();
|
||||
int4 outsize = op->getOut()->getSize();
|
||||
// If totalcut + remain > original input, shrink cut
|
||||
if (k+c+outsize > shiftout->getSize())
|
||||
k = shiftout->getSize()-c-outsize;
|
||||
|
||||
// Total shift + outsize must be greater equal to size of input
|
||||
if ((n+8*c+8*outsize < 8*a->getSize())&&(n != k*8)) return 0;
|
||||
if ((n+8*c+8*outsize < 8*insize)&&(n != k*8)) return 0;
|
||||
|
||||
// If totalcut + remain > original input
|
||||
if (k+c+outsize > insize) {
|
||||
int4 truncSize = insize - c - k;
|
||||
if (n == k*8 && truncSize > 0 && popcount(truncSize)==1) {
|
||||
// We need an additional extension
|
||||
c += k;
|
||||
PcodeOp *newop = data.newOp(2,op->getAddr());
|
||||
opc = (opc == CPUI_INT_SRIGHT) ? CPUI_INT_SEXT : CPUI_INT_ZEXT;
|
||||
data.opSetOpcode(newop,CPUI_SUBPIECE);
|
||||
data.newUniqueOut(truncSize,newop);
|
||||
data.opSetInput(newop,a,0);
|
||||
data.opSetInput(newop,data.newConstant(4,c),1);
|
||||
data.opInsertBefore(newop,op);
|
||||
|
||||
data.opSetInput(op,newop->getOut(),0);
|
||||
data.opRemoveInput(op,1);
|
||||
data.opSetOpcode(op,opc);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
k = insize-c-outsize; // Or we can shrunk the cut
|
||||
}
|
||||
|
||||
// if n == k*8, then a shift is unnecessary
|
||||
c += k;
|
||||
n -= k*8;
|
||||
|
@ -6919,7 +6949,7 @@ int4 RuleSubNormal::applyOp(PcodeOp *op,Funcdata &data)
|
|||
|
||||
PcodeOp *newop = data.newOp(2,op->getAddr());
|
||||
data.opSetOpcode(newop,CPUI_SUBPIECE);
|
||||
data.newUniqueOut(op->getOut()->getSize(),newop);
|
||||
data.newUniqueOut(outsize,newop);
|
||||
data.opSetInput(newop,a,0);
|
||||
data.opSetInput(newop,data.newConstant(4,c),1);
|
||||
data.opInsertBefore(newop,op);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<decompilertest>
|
||||
<binaryimage arch="x86:LE:64:default:gcc">
|
||||
<!--
|
||||
Access fields of a packed structure. Should see field accesses, not shifts and truncations.
|
||||
Accesses are from beginning, middle, and end of the register holding the structure.
|
||||
-->
|
||||
<bytechunk space="ram" offset="0x100705" readonly="true">
|
||||
e8d0ffffff4889c248c1e2
|
||||
1048c1fa3001c248c1f83001d0c3
|
||||
</bytechunk>
|
||||
<symbol space="ram" offset="0x100705" name="access"/>
|
||||
<symbol space="ram" offset="0x1006da" name="getstruct"/>
|
||||
</binaryimage>
|
||||
<script>
|
||||
<com>option structalign 1</com>
|
||||
<com>parse line struct tinystruct { int4 a; int2 b; int2 c; };</com>
|
||||
<com>parse line extern tinystruct getstruct(int4 i);</com>
|
||||
<com>parse line extern int4 access(int4 i);</com>
|
||||
<com>lo fu access</com>
|
||||
<com>dec</com>
|
||||
<com>print C</com>
|
||||
<com>quit</com>
|
||||
</script>
|
||||
<stringmatch name="Access packed fields #1" min="1" max="1">tVar1 = getstruct\(i\);</stringmatch>
|
||||
<stringmatch name="Access packed fields #2" min="1" max="1">tVar1\.a</stringmatch>
|
||||
<stringmatch name="Access packed fields #3" min="1" max="1">\(int4\)tVar1\.b</stringmatch>
|
||||
<stringmatch name="Access packed fields #4" min="1" max="1">\(int4\)tVar1\.c</stringmatch>
|
||||
</decompilertest>
|
Loading…
Add table
Add a link
Reference in a new issue