Ghidra 11.3.2
Ghidra internal decompiler documentation.
|
A logical value whose storage is split between two Varnodes. More...
#include <double.hh>
Public Member Functions | |
SplitVarnode (void) | |
Construct an uninitialized SplitVarnode. | |
SplitVarnode (int4 sz, uintb v) | |
Construct a double precision constant. | |
SplitVarnode (Varnode *l, Varnode *h) | |
Construct from lo and hi piece. | |
void | initAll (Varnode *w, Varnode *l, Varnode *h) |
Construct given Varnode pieces and a known whole Varnode. | |
void | initPartial (int4 sz, uintb v) |
(Re)initialize this SplitVarnode as a constant | |
void | initPartial (int4 sz, Varnode *l, Varnode *h) |
(Re)initialize this SplitVarnode given Varnode pieces | |
bool | inHandHi (Varnode *h) |
Try to initialize given just the most significant piece split from whole. | |
bool | inHandLo (Varnode *l) |
Try to initialize given just the least significant piece split from whole. | |
bool | inHandLoNoHi (Varnode *l) |
Try to initialize given just the least significant piece (other piece may be zero) | |
bool | inHandHiOut (Varnode *h) |
Try to initialize given just the most significant piece concatenated into whole. | |
bool | inHandLoOut (Varnode *l) |
Try to initialize given just the least significant piece concatenated into whole. | |
bool | isConstant (void) const |
Return true if this is a constant. | |
bool | hasBothPieces (void) const |
Return true if both pieces are initialized. | |
int4 | getSize (void) const |
Get the size of this SplitVarnode as a whole in bytes. | |
Varnode * | getLo (void) const |
Get the least significant Varnode piece. | |
Varnode * | getHi (void) const |
Get the most significant Varnode piece. | |
Varnode * | getWhole (void) const |
Get the Varnode representing this as a whole. | |
PcodeOp * | getDefPoint (void) const |
Get the(final) defining PcodeOp of this. | |
BlockBasic * | getDefBlock (void) const |
Get the defining basic block of this. | |
uintb | getValue (void) const |
Get the value of this, assuming it is a constant. | |
bool | isWholeFeasible (PcodeOp *existop) |
Does a whole Varnode already exist or can it be created before the given PcodeOp. | |
bool | isWholePhiFeasible (FlowBlock *bl) |
Does a whole Varnode already exist or can it be created before the given basic block. | |
void | findCreateWhole (Funcdata &data) |
Create a whole Varnode for this, if it doesn't already exist. | |
void | findCreateOutputWhole (Funcdata &data) |
Create a whole Varnode that will be a PcodeOp output. | |
void | createJoinedWhole (Funcdata &data) |
Create a whole Varnode from pieces, respecting piece storage. | |
void | buildLoFromWhole (Funcdata &data) |
Rebuild the least significant piece as a CPUI_SUBPIECE of the whole. | |
void | buildHiFromWhole (Funcdata &data) |
Rebuild the most significant piece as a CPUI_SUBPIECE of the whole. | |
PcodeOp * | findEarliestSplitPoint (void) |
Find the earliest definition point of the lo and hi pieces. | |
PcodeOp * | findOutExist (void) |
Find the point at which the output whole must exist. | |
bool | exceedsConstPrecision (void) const |
Check if this is a constant that exceeds precision limits. | |
Static Public Member Functions | |
static bool | adjacentOffsets (Varnode *vn1, Varnode *vn2, uintb size1) |
Check if the values in the given Varnodes differ by the given size. | |
static bool | testContiguousPointers (PcodeOp *most, PcodeOp *least, PcodeOp *&first, PcodeOp *&second, AddrSpace *&spc) |
Verify that the pointers into the given LOAD/STORE PcodeOps address contiguous memory. | |
static bool | isAddrTiedContiguous (Varnode *lo, Varnode *hi, Address &res) |
Return true if the given pieces can be melded into a contiguous storage location. | |
static void | wholeList (Varnode *w, vector< SplitVarnode > &splitvec) |
Create a list of all the possible pairs that contain the same logical value as the given Varnode. | |
static void | findCopies (const SplitVarnode &in, vector< SplitVarnode > &splitvec) |
Find copies from (the pieces of) the given SplitVarnode. | |
static void | getTrueFalse (PcodeOp *boolop, bool flip, BlockBasic *&trueout, BlockBasic *&falseout) |
For the given CBRANCH PcodeOp, pass back the true and false basic blocks. | |
static bool | otherwiseEmpty (PcodeOp *branchop) |
Return true if the basic block containing the given CBRANCH PcodeOp performs no other operation. | |
static bool | verifyMultNegOne (PcodeOp *op) |
Verify that the given PcodeOp is a CPUI_INT_MULT by -1. | |
static PcodeOp * | prepareBinaryOp (SplitVarnode &out, SplitVarnode &in1, SplitVarnode &in2) |
Check that the logical version of a (generic) binary double-precision operation can be created. | |
static void | createBinaryOp (Funcdata &data, SplitVarnode &out, SplitVarnode &in1, SplitVarnode &in2, PcodeOp *existop, OpCode opc) |
Rewrite a double precision binary operation by replacing the pieces with unified Varnodes. | |
static PcodeOp * | prepareShiftOp (SplitVarnode &out, SplitVarnode &in) |
Make sure input and output operands of a double precision shift operation are compatible. | |
static void | createShiftOp (Funcdata &data, SplitVarnode &out, SplitVarnode &in, Varnode *sa, PcodeOp *existop, OpCode opc) |
Rewrite a double precision shift by replacing hi/lo pieces with unified Varnodes. | |
static void | replaceBoolOp (Funcdata &data, PcodeOp *boolop, SplitVarnode &in1, SplitVarnode &in2, OpCode opc) |
Rewrite a double precision boolean operation by replacing the input pieces with unified Varnodes. | |
static bool | prepareBoolOp (SplitVarnode &in1, SplitVarnode &in2, PcodeOp *testop) |
Make sure input operands of a double precision compare operation are compatible. | |
static void | createBoolOp (Funcdata &data, PcodeOp *cbranch, SplitVarnode &in1, SplitVarnode &in2, OpCode opc) |
Create a new compare PcodeOp, replacing the boolean Varnode taken as input by the given CBRANCH. | |
static PcodeOp * | preparePhiOp (SplitVarnode &out, vector< SplitVarnode > &inlist) |
Check that the logical version of a CPUI_MULTIEQUAL operation can be created. | |
static void | createPhiOp (Funcdata &data, SplitVarnode &out, vector< SplitVarnode > &inlist, PcodeOp *existop) |
Rewrite a double precision MULTIEQUAL operation by replacing the pieces with unified Varnodes. | |
static bool | prepareIndirectOp (SplitVarnode &in, PcodeOp *affector) |
Check that the logical version of a CPUI_INDIRECT operation can be created. | |
static void | replaceIndirectOp (Funcdata &data, SplitVarnode &out, SplitVarnode &in, PcodeOp *affector) |
Rewrite a double precision INDIRECT operation by replacing the pieces with unified Varnodes. | |
static void | replaceCopyForce (Funcdata &data, const Address &addr, SplitVarnode &in, PcodeOp *copylo, PcodeOp *copyhi) |
Rewrite the double precision version of a COPY to an address forced Varnode. | |
static int4 | applyRuleIn (SplitVarnode &in, Funcdata &data) |
Try to perform one transform on a logical double precision operation given a specific input. | |
Private Member Functions | |
bool | findWholeSplitToPieces (void) |
Find whole out of which hi and lo are split. | |
bool | findDefinitionPoint (void) |
Find the earliest PcodeOp where both lo and hi are defined. | |
bool | findWholeBuiltFromPieces (void) |
Find whole Varnode formed as a CPUI_PIECE of hi and lo. | |
Private Attributes | |
Varnode * | lo |
Least significant piece of the double precision object. | |
Varnode * | hi |
Most significant piece of the double precision object. | |
Varnode * | whole |
A representative of the whole object. | |
PcodeOp * | defpoint |
Operation at which both lo and hi are defined. | |
BlockBasic * | defblock |
Block in which both lo and hi are defined. | |
uintb | val |
Value of a double precision constant. | |
int4 | wholesize |
Size in bytes of the (virtual) whole. | |
A logical value whose storage is split between two Varnodes.
This is usually a pair of Varnodes lo and hi holding the least and most significant part of the logical value respectively. Its possible for the logical value to be a constant, in which case lo and hi are set to null and val holds the actual constant. Its also possible for hi to be null by itself, indicating that most signficant part of the variable is zero, and the logical variable is the zero extension of lo.
ghidra::SplitVarnode::SplitVarnode | ( | int4 | sz, |
uintb | v | ||
) |
Check if the values in the given Varnodes differ by the given size.
Return true, if the (possibly dynamic) value represented by the given vn1 plus size1 produces the value in the given vn2. For constants, the values can be computed directly, but otherwise vn1 and vn2 must be defined by INT_ADD operations from a common ancestor.
vn1 | is the first given Varnode |
vn2 | is the second given Varnode |
size1 | is the given size to add to vn1 |
References ghidra::PcodeOp::code(), ghidra::CPUI_INT_ADD, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::Varnode::isConstant(), and ghidra::Varnode::isWritten().
Referenced by testContiguousPointers().
|
static |
Try to perform one transform on a logical double precision operation given a specific input.
All the various double precision forms are lined up against the input. The first one that matches has its associated transform performed and then 1 is returned. If no form matches, 0 is returned.
in | is the given double precision input |
data | is the function owning the Varnodes |
References ghidra::CopyForceForm::applyRule(), ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::CPUI_INDIRECT, ghidra::CPUI_INT_ADD, ghidra::CPUI_INT_AND, ghidra::CPUI_INT_EQUAL, ghidra::CPUI_INT_LEFT, ghidra::CPUI_INT_LESS, ghidra::CPUI_INT_LESSEQUAL, ghidra::CPUI_INT_MULT, ghidra::CPUI_INT_NOTEQUAL, ghidra::CPUI_INT_OR, ghidra::CPUI_INT_RIGHT, ghidra::CPUI_INT_SLESS, ghidra::CPUI_INT_SLESSEQUAL, ghidra::CPUI_INT_SRIGHT, ghidra::CPUI_INT_XOR, ghidra::CPUI_MULTIEQUAL, ghidra::Varnode::endDescend(), getHi(), getLo(), ghidra::PcodeOp::getOut(), and ghidra::Varnode::isAddrForce().
Referenced by ghidra::RuleDoubleIn::applyOp().
void ghidra::SplitVarnode::buildHiFromWhole | ( | Funcdata & | data | ) |
Rebuild the most significant piece as a CPUI_SUBPIECE of the whole.
Assume hi was initially defined in some other way but now needs to be defined as a split from a new whole Varnode. The original PcodeOp defining hi is transformed into a CPUI_SUBPIECE. The method findCreateOutputWhole() must already have been called on this.
References ghidra::PcodeOp::code(), ghidra::CPUI_INDIRECT, ghidra::CPUI_MULTIEQUAL, ghidra::CPUI_SUBPIECE, ghidra::Varnode::getAddr(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::PcodeOp::getOpFromConst(), ghidra::PcodeOp::getParent(), ghidra::Varnode::getSize(), hi, ghidra::PcodeOp::isDead(), lo, ghidra::Funcdata::newConstant(), ghidra::Funcdata::opInsertAfter(), ghidra::Funcdata::opInsertBegin(), ghidra::Funcdata::opSetAllInput(), ghidra::Funcdata::opSetOpcode(), ghidra::Funcdata::opUninsert(), and whole.
Referenced by createBinaryOp(), createPhiOp(), createShiftOp(), and replaceIndirectOp().
void ghidra::SplitVarnode::buildLoFromWhole | ( | Funcdata & | data | ) |
Rebuild the least significant piece as a CPUI_SUBPIECE of the whole.
Assume lo was initially defined in some other way but now needs to be defined as a split from a new whole Varnode. The original PcodeOp defining lo is transformed into a CPUI_SUBPIECE. The method findCreateOutputWhole() must already have been called on this.
References ghidra::PcodeOp::code(), ghidra::CPUI_INDIRECT, ghidra::CPUI_MULTIEQUAL, ghidra::CPUI_SUBPIECE, ghidra::Varnode::getAddr(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::PcodeOp::getOpFromConst(), ghidra::PcodeOp::getParent(), ghidra::PcodeOp::isDead(), lo, ghidra::Funcdata::newConstant(), ghidra::Funcdata::opInsertAfter(), ghidra::Funcdata::opInsertBegin(), ghidra::Funcdata::opSetAllInput(), ghidra::Funcdata::opSetOpcode(), ghidra::Funcdata::opUninsert(), and whole.
Referenced by createBinaryOp(), createPhiOp(), createShiftOp(), and replaceIndirectOp().
|
static |
Rewrite a double precision binary operation by replacing the pieces with unified Varnodes.
This assumes that we have checked that the transformation is possible via the various verify and prepare methods. After this method is called, the logical inputs and output of the calculation will exist as real Varnodes.
data | is the function owning the operation |
out | is the output of the binary operation |
in1 | is the first input to the binary operation |
in2 | is the second input to the binary operation |
existop | is the precalculated PcodeOp where the output whole Varnode must exist |
opc | is the opcode of the operation |
References buildHiFromWhole(), buildLoFromWhole(), ghidra::PcodeOp::code(), ghidra::CPUI_PIECE, findCreateOutputWhole(), findCreateWhole(), ghidra::PcodeOp::getAddr(), getWhole(), ghidra::Funcdata::newOp(), ghidra::Funcdata::opInsertBefore(), ghidra::Funcdata::opSetInput(), ghidra::Funcdata::opSetOpcode(), and ghidra::Funcdata::opSetOutput().
|
static |
Create a new compare PcodeOp, replacing the boolean Varnode taken as input by the given CBRANCH.
The inputs to the new compare operation are Varnodes representing the logical whole of the double precision pieces.
data | is the function owning the operation |
cbranch | is the given CBRANCH PcodeOp |
in1 | is the first input to the compare operation |
in2 | is the second input to the compare operation |
opc | is the opcode of the compare operation |
References findCreateWhole(), ghidra::PcodeOp::getAddr(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), getWhole(), ghidra::Varnode::isWritten(), ghidra::Funcdata::newOp(), ghidra::Funcdata::newUniqueOut(), ghidra::Funcdata::opInsertBefore(), ghidra::Funcdata::opSetInput(), and ghidra::Funcdata::opSetOpcode().
void ghidra::SplitVarnode::createJoinedWhole | ( | Funcdata & | data | ) |
Create a whole Varnode from pieces, respecting piece storage.
If the pieces can be treated as a contiguous whole, use the same storage location to construct the whole, otherwise use a join address for storage.
data | is the function owning the pieces |
References ghidra::AddrSpaceManager::constructJoinAddress(), ghidra::Varnode::getAddr(), ghidra::Funcdata::getArch(), ghidra::Varnode::getSize(), hi, isAddrTiedContiguous(), lo, ghidra::Funcdata::newVarnode(), ghidra::Varnode::setPrecisHi(), ghidra::Varnode::setPrecisLo(), ghidra::Varnode::setWriteMask(), ghidra::Architecture::translate, whole, and wholesize.
Referenced by replaceIndirectOp().
|
static |
Rewrite a double precision MULTIEQUAL operation by replacing the pieces with unified Varnodes.
This assumes that we have checked that the transformation is possible via the various verify and prepare methods. After this method is called, the logical inputs and output of the calculation will exist as real Varnodes.
data | is the function owning the operation |
out | is the output of the MULTIEQUAL operation |
inlist | is the list of input operands to the MULTIEQUAL |
existop | is the precalculated PcodeOp where the output whole Varnode must exist |
References buildHiFromWhole(), buildLoFromWhole(), ghidra::CPUI_MULTIEQUAL, findCreateOutputWhole(), findCreateWhole(), ghidra::PcodeOp::getAddr(), getWhole(), ghidra::Funcdata::newOp(), ghidra::Funcdata::opInsertBefore(), ghidra::Funcdata::opSetInput(), ghidra::Funcdata::opSetOpcode(), and ghidra::Funcdata::opSetOutput().
|
static |
Rewrite a double precision shift by replacing hi/lo pieces with unified Varnodes.
This assumes that we have checked that the transformation is possible by calling the appropriate verify and prepare methods. After this method is called, the logical inputs and output of the calculation will exist as real Varnodes. The shift amount is not treated as a double precision variable.
data | is the function owning the operation |
out | is the output of the double precision operation |
in | is the first input of the operation |
sa | is the Varnode indicating the shift amount for the operation |
existop | is the first PcodeOp where the output whole needs to exist |
opc | is the opcode of the particular shift operation |
References buildHiFromWhole(), buildLoFromWhole(), ghidra::PcodeOp::code(), ghidra::CPUI_PIECE, findCreateOutputWhole(), findCreateWhole(), ghidra::PcodeOp::getAddr(), ghidra::Varnode::getOffset(), ghidra::Varnode::getSize(), getWhole(), ghidra::Varnode::isConstant(), ghidra::Funcdata::newConstant(), ghidra::Funcdata::newOp(), ghidra::Funcdata::opInsertBefore(), ghidra::Funcdata::opSetInput(), ghidra::Funcdata::opSetOpcode(), and ghidra::Funcdata::opSetOutput().
bool ghidra::SplitVarnode::exceedsConstPrecision | ( | void | ) | const |
Check if this is a constant that exceeds precision limits.
If the logical whole is a constant and is too big to be represented internally return true.
References isConstant(), and wholesize.
|
static |
Find copies from (the pieces of) the given SplitVarnode.
Scan for each piece being used as input to COPY operations. If the each piece is copied within the same basic block to contiguous storage locations, create a new SplitVarnode from COPY outputs and add it to the list.
in | is the given SplitVarnode |
splitvec | is the container for holding SplitVarnode copies |
References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::Varnode::endDescend(), ghidra::Varnode::getAddr(), getHi(), getLo(), ghidra::PcodeOp::getOut(), ghidra::PcodeOp::getParent(), ghidra::Varnode::getSize(), getWhole(), hasBothPieces(), initAll(), and ghidra::Address::isBigEndian().
Referenced by wholeList().
void ghidra::SplitVarnode::findCreateOutputWhole | ( | Funcdata & | data | ) |
Create a whole Varnode that will be a PcodeOp output.
If the whole does not already exist, it is created as a unique register. The new Varnode must later be set explicitly as the output of some PcodeOp.
data | is the function owning the Varnode pieces |
References hi, lo, ghidra::Funcdata::newUnique(), ghidra::Varnode::setPrecisHi(), ghidra::Varnode::setPrecisLo(), whole, and wholesize.
Referenced by createBinaryOp(), createPhiOp(), and createShiftOp().
void ghidra::SplitVarnode::findCreateWhole | ( | Funcdata & | data | ) |
Create a whole Varnode for this, if it doesn't already exist.
This method assumes isWholeFeasible has been called and returned true. If the whole didn't already exist, it is created as the concatenation of its two pieces. If the pieces were constant, a constant whole Varnode is created. If the hi piece was null, the whole is created as a CPUI_ZEXT of the lo.
data | is the function owning the Varnode pieces |
References ghidra::CPUI_INT_ZEXT, ghidra::CPUI_PIECE, defblock, defpoint, ghidra::PcodeOp::getAddr(), ghidra::Funcdata::getBasicBlocks(), ghidra::PcodeOp::getParent(), ghidra::BlockBasic::getStart(), ghidra::BlockGraph::getStartBlock(), hi, isConstant(), lo, ghidra::Funcdata::newConstant(), ghidra::Funcdata::newOp(), ghidra::Funcdata::newUniqueOut(), ghidra::Funcdata::opInsertAfter(), ghidra::Funcdata::opInsertBegin(), ghidra::Funcdata::opSetInput(), ghidra::Funcdata::opSetOpcode(), ghidra::Funcdata::opSetOutput(), ghidra::Varnode::setPrecisHi(), ghidra::Varnode::setPrecisLo(), val, whole, and wholesize.
Referenced by createBinaryOp(), createBoolOp(), createPhiOp(), createShiftOp(), replaceBoolOp(), and replaceIndirectOp().
|
private |
Find the earliest PcodeOp where both lo and hi are defined.
Set the basic block, defblock, and PcodeOp, defpoint, where they are defined. Its possible that lo and hi are input Varnodes with no natural defining PcodeOp, in which case defpoint is set to null and defblock is set to the function entry block. The method returns true, if the definition point is found, which amounts to returning false if the SplitVarnode is only half constant or half input.
References defblock, defpoint, ghidra::Varnode::getDef(), ghidra::FlowBlock::getImmedDom(), ghidra::SeqNum::getOrder(), ghidra::PcodeOp::getParent(), ghidra::PcodeOp::getSeqNum(), hi, ghidra::Varnode::isConstant(), ghidra::Varnode::isInput(), ghidra::Varnode::isWritten(), and lo.
Referenced by isWholeFeasible(), and isWholePhiFeasible().
PcodeOp * ghidra::SplitVarnode::findEarliestSplitPoint | ( | void | ) |
Find the earliest definition point of the lo and hi pieces.
If both lo and hi pieces are written, the earlier of the two defining PcodeOps is returned. Otherwise null is returned.
References ghidra::Varnode::getDef(), ghidra::SeqNum::getOrder(), ghidra::PcodeOp::getParent(), ghidra::PcodeOp::getSeqNum(), hi, ghidra::Varnode::isWritten(), and lo.
Referenced by findOutExist(), and preparePhiOp().
PcodeOp * ghidra::SplitVarnode::findOutExist | ( | void | ) |
Find the point at which the output whole must exist.
Its assumed that this is the output of the double precision operation being performed. The whole Varnode may not yet exist. This method returns the first PcodeOp where the whole needs to exist. If no such PcodeOp exists, null is returned.
References defpoint, findEarliestSplitPoint(), and findWholeBuiltFromPieces().
Referenced by prepareBinaryOp(), and prepareShiftOp().
|
private |
Find whole Varnode formed as a CPUI_PIECE of hi and lo.
We scan for concatenations formed out of hi and lo, in the correct significance order. We assume hi and lo are defined in the same basic block (or are both inputs) and that the concatenation is also in this block. If such a concatenation is found, whole is set to the concatenated Varnode, the defining block and PcodeOp is filled in, and true is returned.
References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_PIECE, defblock, defpoint, ghidra::Varnode::endDescend(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::SeqNum::getOrder(), ghidra::PcodeOp::getOut(), ghidra::PcodeOp::getParent(), ghidra::PcodeOp::getSeqNum(), hi, ghidra::FlowBlock::isEntryPoint(), ghidra::Varnode::isInput(), ghidra::Varnode::isWritten(), lo, and whole.
Referenced by findOutExist(), isWholeFeasible(), and isWholePhiFeasible().
|
private |
Find whole out of which hi and lo are split.
Look for CPUI_SUBPIECE operations off of a common Varnode. The whole field is set to this Varnode if found; the definition point and block are filled in and true is returned. Otherwise false is returned.
References ghidra::PcodeOp::code(), ghidra::CPUI_COPY, ghidra::CPUI_SUBPIECE, defblock, defpoint, ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getParent(), ghidra::Varnode::getSize(), hi, ghidra::Varnode::isInput(), ghidra::Varnode::isWritten(), lo, whole, and wholesize.
Referenced by isWholeFeasible(), and isWholePhiFeasible().
|
static |
For the given CBRANCH PcodeOp, pass back the true and false basic blocks.
The result depends on the boolean flip property of the CBRANCH, and the user can also flip the meaning of the branches.
boolop | is the given CBRANCH PcodeOp |
flip | is true if the caller wants to flip the meaning of the blocks |
trueout | is used to pass back the true fall-through block |
falseout | is used to pass back the false fall-through block |
References ghidra::FlowBlock::getFalseOut(), ghidra::PcodeOp::getParent(), ghidra::FlowBlock::getTrueOut(), and ghidra::PcodeOp::isBooleanFlip().
bool ghidra::SplitVarnode::inHandHi | ( | Varnode * | h | ) |
Try to initialize given just the most significant piece split from whole.
Verify that the given most significant piece is formed via CPUI_SUBPIECE and search for the least significant piece being formed as a CPUI_SUBPIECE of the same whole.
h | is the given (most significant) Varnode piece |
References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_SUBPIECE, ghidra::Varnode::endDescend(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getOut(), ghidra::Varnode::getSize(), initAll(), ghidra::Varnode::isPrecisHi(), ghidra::Varnode::isPrecisLo(), and ghidra::Varnode::isWritten().
Referenced by ghidra::ActionParamDouble::apply().
bool ghidra::SplitVarnode::inHandHiOut | ( | Varnode * | h | ) |
Try to initialize given just the most significant piece concatenated into whole.
Initialize the SplitVarnode given the most significant piece, if it is concatenated together immediately with is least significant piece. The CPUI_PIECE and the matching least significant piece must be unique. If these are found, hi, lo, and whole are all filled in.
h | is the given (most significant) piece |
References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_PIECE, ghidra::Varnode::endDescend(), ghidra::PcodeOp::getIn(), ghidra::PcodeOp::getOut(), initAll(), and ghidra::Varnode::isPrecisLo().
bool ghidra::SplitVarnode::inHandLo | ( | Varnode * | l | ) |
Try to initialize given just the least significant piece split from whole.
Verify that the given least significant piece is formed via CPUI_SUBPIECE and search for the most significant piece being formed as a CPUI_SUBPIECE of the same whole.
l | is the given (least significant) Varnode piece |
References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_SUBPIECE, ghidra::Varnode::endDescend(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getOut(), ghidra::Varnode::getSize(), initAll(), ghidra::Varnode::isPrecisHi(), ghidra::Varnode::isPrecisLo(), and ghidra::Varnode::isWritten().
Referenced by ghidra::ActionParamDouble::apply().
bool ghidra::SplitVarnode::inHandLoNoHi | ( | Varnode * | l | ) |
Try to initialize given just the least significant piece (other piece may be zero)
The given least significant Varnode must already be marked as a piece. Initialize the SplitVarnode with the given piece and the whole that it came from. If a matching most significant piece can be found, as another CPUI_SUBPIECE off of the same whole, initialize that as well. Otherwise leave the most significant piece as null.
l | is the given (least significant) Varnode piece |
References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_SUBPIECE, ghidra::Varnode::endDescend(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getOut(), ghidra::Varnode::getSize(), initAll(), ghidra::Varnode::isPrecisHi(), ghidra::Varnode::isPrecisLo(), and ghidra::Varnode::isWritten().
bool ghidra::SplitVarnode::inHandLoOut | ( | Varnode * | l | ) |
Try to initialize given just the least significant piece concatenated into whole.
Initialize the SplitVarnode given the least significant piece, if it is concatenated together immediately with is nost significant piece. The CPUI_PIECE and the matching most significant piece must be unique. If these are found, hi, lo, and whole are all filled in.
l | is the given (least significant) piece |
References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_PIECE, ghidra::Varnode::endDescend(), ghidra::PcodeOp::getIn(), ghidra::PcodeOp::getOut(), initAll(), and ghidra::Varnode::isPrecisHi().
Construct given Varnode pieces and a known whole Varnode.
The lo, hi, and whole fields are filled in. The definition point remains uninitialized.
w | is the given whole Varnode |
l | is the given (least significant) Varnode piece |
h | is the given (most significant) Varnode piece |
References defblock, defpoint, ghidra::Varnode::getSize(), hi, lo, whole, and wholesize.
Referenced by findCopies(), inHandHi(), inHandHiOut(), inHandLo(), inHandLoNoHi(), and inHandLoOut().
void ghidra::SplitVarnode::initPartial | ( | int4 | sz, |
uintb | v | ||
) |
(Re)initialize this SplitVarnode as a constant
sz | is the size of the constant in bytes |
v | is the constant value |
References defblock, defpoint, hi, lo, val, whole, and wholesize.
Referenced by SplitVarnode().
(Re)initialize this SplitVarnode given Varnode pieces
The Varnode pieces can be constant, in which case a constant SplitVarnode is initialized and a constant value is built from the pieces. The given most significant piece can be null, indicating that the most significant piece of the whole is an implied zero.
sz | is the size of the logical whole in bytes |
l | is the given (least significant) Varnode piece |
h | is the given (most significant) Varnode piece |
References defblock, defpoint, ghidra::Varnode::getOffset(), ghidra::Varnode::getSize(), hi, ghidra::Varnode::isConstant(), lo, val, whole, and wholesize.
|
static |
Return true if the given pieces can be melded into a contiguous storage location.
The given Varnodes must be address tied, and their storage must line up, respecting their significance as pieces.
lo | is the given least significant piece |
hi | is the given most significant piece |
res | is used to pass back the starting address of the contigous range |
References ghidra::Varnode::getAddr(), ghidra::Varnode::getOffset(), ghidra::Varnode::getSize(), ghidra::Varnode::getSpace(), ghidra::SymbolEntry::getSymbol(), ghidra::Varnode::getSymbolEntry(), hi, ghidra::Varnode::isAddrTied(), ghidra::AddrSpace::isBigEndian(), and lo.
Referenced by ghidra::RuleDoubleOut::applyOp(), createJoinedWhole(), and ghidra::CopyForceForm::verify().
bool ghidra::SplitVarnode::isWholeFeasible | ( | PcodeOp * | existop | ) |
Does a whole Varnode already exist or can it be created before the given PcodeOp.
The whole Varnode must be defined or definable before the given PcodeOp. This is checked by comparing the given PcodeOp to the defining PcodeOp and block for this, which are filled in if they weren't before.
existop | is the given PcodeOp |
References defblock, defpoint, findDefinitionPoint(), findWholeBuiltFromPieces(), findWholeSplitToPieces(), ghidra::FlowBlock::getImmedDom(), ghidra::SeqNum::getOrder(), ghidra::PcodeOp::getParent(), ghidra::PcodeOp::getSeqNum(), hi, isConstant(), ghidra::Varnode::isConstant(), and lo.
Referenced by prepareBinaryOp(), prepareBoolOp(), prepareIndirectOp(), and prepareShiftOp().
bool ghidra::SplitVarnode::isWholePhiFeasible | ( | FlowBlock * | bl | ) |
Does a whole Varnode already exist or can it be created before the given basic block.
This is similar to isWholeFeasible(), but the whole must be defined before the end of the given basic block.
bl | is the given basic block |
References defblock, findDefinitionPoint(), findWholeBuiltFromPieces(), findWholeSplitToPieces(), ghidra::FlowBlock::getImmedDom(), and isConstant().
Referenced by preparePhiOp().
|
static |
Return true if the basic block containing the given CBRANCH PcodeOp performs no other operation.
The basic block can contain the CBRANCH and the one PcodeOp producing the boolean value. Otherwise false is returned.
branchop | is the given CBRANCH |
References ghidra::BlockBasic::beginOp(), ghidra::BlockBasic::endOp(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::PcodeOp::getParent(), ghidra::Varnode::isWritten(), and ghidra::FlowBlock::sizeIn().
|
static |
Check that the logical version of a (generic) binary double-precision operation can be created.
This checks only the most generic aspects of the calculation. The input and output whole Varnodes must already exist or be creatable. The point where the output Varnode must exist is identified and returned. If the binary operation cannot be created, null is returned.
out | is the output of the binary operation |
in1 | is the first input of the binary operation |
in2 | is the second input of the binary operation |
References findOutExist(), and isWholeFeasible().
|
static |
Make sure input operands of a double precision compare operation are compatible.
Do generic testing that the input whole Varnodes can be created. If they can be created, return true.
in1 | is the first input operand of the double precision compare operation |
in2 | is the second input operand of the double precision compare operation |
References isWholeFeasible().
|
static |
Check that the logical version of a CPUI_INDIRECT operation can be created.
This checks only the most generic aspects of the calculation. The input whole Varnode must already exist or be creatable. If the INDIRECT operation cannot be created, false is returned.
in | is the (first) input operand of the INDIRECT |
References isWholeFeasible().
|
static |
Check that the logical version of a CPUI_MULTIEQUAL operation can be created.
This checks only the most generic aspects of the calculation. The input and output whole Varnodes must already exist or be creatable. The point where the output Varnode must exist is identified and returned. If the MULTIEQUAL operation cannot be created, null is returned.
out | is the output of the MULTIEQUAL operation |
inlist | is a vector of the input operands to the MULTIEQUAL |
References ghidra::PcodeOp::code(), ghidra::CPUI_MULTIEQUAL, findEarliestSplitPoint(), ghidra::FlowBlock::getIn(), ghidra::PcodeOp::getParent(), and isWholePhiFeasible().
|
static |
Make sure input and output operands of a double precision shift operation are compatible.
Do generic testing that the input and output whole Varnodes can be created. Calculate the PcodeOp where the output whole must exist and return it. If logical operation cannot be created, return null.
out | is the output of the double precision shift operation |
in | is the (first) input operand of the double precision shift operation |
References findOutExist(), and isWholeFeasible().
|
static |
Rewrite a double precision boolean operation by replacing the input pieces with unified Varnodes.
This assumes we checked that the transformation is possible by calling the various verify and prepare methods. The inputs to the given PcodeOp producing the final boolean value are replaced with new logical Varnodes, and the opcode is updated. The output Varnode is not affected.
data | is the function owning the operation |
boolop | is the given PcodeOp producing the final boolean value |
in1 | is the first input to the operation |
in2 | is the second input to the operation |
opc | is the opcode of the operation |
References findCreateWhole(), getWhole(), ghidra::Funcdata::opSetInput(), and ghidra::Funcdata::opSetOpcode().
|
static |
Rewrite the double precision version of a COPY to an address forced Varnode.
This assumes that we have checked that the transformation is possible. The logical input must already exist, and after this method is called, the logical output will also exist. The original COPY pieces are explicitly destroyed.
data | is the function owning the COPYs |
addr | is the storage address being COPYed |
in | is the input to the COPYs |
copylo | is the original least significant COPY |
copyhi | is the original most significant COPY |
References ghidra::CPUI_COPY, ghidra::PcodeOp::getAddr(), ghidra::Varnode::getAddr(), ghidra::Varnode::getDef(), ghidra::PcodeOp::getIn(), ghidra::SeqNum::getOrder(), ghidra::PcodeOp::getSeqNum(), getSize(), getWhole(), ghidra::PcodeOp::isReturnCopy(), ghidra::Funcdata::markReturnCopy(), ghidra::Funcdata::newOp(), ghidra::Funcdata::newVarnodeOut(), ghidra::Funcdata::opDestroy(), ghidra::Funcdata::opInsertBefore(), ghidra::Funcdata::opSetInput(), ghidra::Funcdata::opSetOpcode(), and ghidra::Varnode::setAddrForce().
Referenced by ghidra::CopyForceForm::applyRule().
|
static |
Rewrite a double precision INDIRECT operation by replacing the pieces with unified Varnodes.
This assumes that we have checked that the transformation is possible via the various verify and prepare methods. After this method is called, the logical input and output of the calculation will exist as real Varnodes.
data | is the function owning the operation |
out | is the output of the INDIRECT operation |
in | is the (first) operand of the INDIRECT |
affector | is the second operand to the indirect, the PcodeOp producing the indirect affect |
References buildHiFromWhole(), buildLoFromWhole(), ghidra::CPUI_INDIRECT, createJoinedWhole(), findCreateWhole(), ghidra::PcodeOp::getAddr(), getWhole(), ghidra::Funcdata::newOp(), ghidra::Funcdata::newVarnodeIop(), ghidra::Funcdata::opInsertBefore(), ghidra::Funcdata::opSetInput(), ghidra::Funcdata::opSetOpcode(), and ghidra::Funcdata::opSetOutput().
|
static |
Verify that the pointers into the given LOAD/STORE PcodeOps address contiguous memory.
The two given PcodeOps must either both be LOADs or both be STOREs. The pointer for the first PcodeOp is labeled as the most significant piece of the contiguous whole, the second PcodeOp is labeled as the least significant piece. The p-code defining the pointers is examined to determine if the two memory regions being pointed at really form one contiguous region. If the regions are contiguous and the pointer labeling is valid, true is returned, the PcodeOps are sorted into first and second based on Address, and the address space of the memory region is passed back.
most | is the given LOAD/STORE PcodeOp referring to the most significant region |
least | is the given LOAD/STORE PcodeOp referring to the least significant region |
first | is used to pass back the earliest of the address sorted PcodeOps |
second | is used to pass back the latest of the address sorted PcodeOps |
spc | is used to pass back the LOAD address space |
sizeres | is used to pass back the combined LOAD size |
References adjacentOffsets(), ghidra::PcodeOp::code(), ghidra::CPUI_LOAD, ghidra::PcodeOp::getIn(), ghidra::PcodeOp::getOut(), ghidra::Varnode::getSize(), ghidra::Varnode::getSpaceFromConst(), ghidra::AddrSpace::isBigEndian(), and ghidra::Varnode::isFree().
Referenced by ghidra::RuleDoubleLoad::applyOp(), and ghidra::RuleDoubleStore::applyOp().
|
static |
Verify that the given PcodeOp is a CPUI_INT_MULT by -1.
The PcodeOp must be a CPUI_INT_MULT and the second operand must be a constant -1.
op | is the given PcodeOp |
References ghidra::calc_mask(), ghidra::PcodeOp::code(), ghidra::CPUI_INT_MULT, ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::Varnode::getSize(), and ghidra::Varnode::isConstant().
|
static |
Create a list of all the possible pairs that contain the same logical value as the given Varnode.
The given Varnode is assumed to be the logical whole that is being used in a double precision calculation. At least one of the most or least significant pieces must be extracted from the whole and must be marked as a double precision piece.
w | is the given Varnode whole |
splitvec | is the container for holding any discovered SplitVarnodes |
References ghidra::Varnode::beginDescend(), ghidra::PcodeOp::code(), ghidra::CPUI_SUBPIECE, ghidra::Varnode::endDescend(), findCopies(), ghidra::PcodeOp::getIn(), ghidra::Varnode::getOffset(), ghidra::PcodeOp::getOut(), ghidra::Varnode::getSize(), hi, ghidra::Varnode::isPrecisHi(), ghidra::Varnode::isPrecisLo(), lo, whole, and wholesize.
Referenced by ghidra::RuleDoubleIn::applyOp().