decompiler
1.0.0
|
Lowest level operation of the p-code language. More...
#include <op.hh>
Public Types | |
enum | { startbasic = 1, branch = 2, call = 4, returns = 0x8, nocollapse = 0x10, dead = 0x20, marker = 0x40, booloutput = 0x80, boolean_flip = 0x100, fallthru_true = 0x200, indirect_source = 0x400, coderef = 0x800, startmark = 0x1000, mark = 0x2000, commutative = 0x4000, unary = 0x8000, binary = 0x10000, special = 0x20000, ternary = 0x40000, splittingbranch = 0x80000, nonprinting = 0x100000, halt = 0x200000, badinstruction = 0x400000, unimplemented = 0x800000, noreturn = 0x1000000, missing = 0x2000000, spacebase_ptr = 0x4000000, indirect_creation = 0x8000000, calculated_bool = 0x10000000, has_callspec = 0x20000000, ptrflow = 0x40000000, indirect_store = 0x80000000 } |
enum | { special_prop = 1, special_print = 2, modified = 4, warning = 8, incidental_copy = 0x10, is_cpool_transformed = 0x20 } |
Public Member Functions | |
PcodeOp (int4 s, const SeqNum &sq) | |
Construct an unattached PcodeOp. More... | |
~PcodeOp (void) | |
Destructor. | |
int4 | numInput (void) const |
Get the number of inputs to this op. | |
Varnode * | getOut (void) |
Get the output Varnode of this op or null. | |
const Varnode * | getOut (void) const |
Get the output Varnode of this op or null. | |
Varnode * | getIn (int4 slot) |
Get a specific input Varnode to this op. | |
const Varnode * | getIn (int4 slot) const |
Get a specific input Varnode to this op. | |
const BlockBasic * | getParent (void) const |
Get the parent basic block. | |
BlockBasic * | getParent (void) |
Get the parent basic block. | |
const Address & | getAddr (void) const |
Get the instruction address associated with this op. | |
uintm | getTime (void) const |
Get the time index indicating when this op was created. | |
const SeqNum & | getSeqNum (void) const |
Get the sequence number associated with this op. | |
list< PcodeOp * >::iterator | getInsertIter (void) const |
Get position within alive/dead list. | |
list< PcodeOp * >::iterator | getBasicIter (void) const |
int4 | getSlot (const Varnode *vn) const |
Get the slot number of the indicated input varnode. | |
int4 | getRepeatSlot (const Varnode *vn, int4 firstSlot, list< PcodeOp * >::const_iterator iter) const |
Find the slot for a given Varnode, which may be take up multiple input slots. More... | |
uint4 | getEvalType (void) const |
Get the evaluation type of this op. | |
uint4 | getHaltType (void) const |
Get type which indicates unusual halt in control-flow. | |
bool | isDead (void) const |
Return true if this op is dead. | |
bool | isAssignment (void) const |
Return true is this op has an output. | |
bool | isCall (void) const |
bool | isCallWithoutSpec (void) const |
Return true if this op acts as call but does not have a full specification. | |
bool | isMarker (void) const |
Return true is a special SSA form op. | |
bool | isIndirectCreation (void) const |
Return true if op creates a varnode indirectly. | |
bool | isIndirectStore (void) const |
bool | notPrinted (void) const |
Return true if this op is not directly represented in C output. | |
bool | isBoolOutput (void) const |
Return true if this op produces a boolean output. | |
bool | isBranch (void) const |
bool | isCallOrBranch (void) const |
Return true if this op is a call or branch. | |
bool | isFlowBreak (void) const |
Return true if this op breaks fall-thru flow. | |
bool | isBooleanFlip (void) const |
Return true if this op flips the true/false meaning of its control-flow branching. | |
bool | isFallthruTrue (void) const |
Return true if the fall-thru branch is taken when the boolean input is true. | |
bool | isCodeRef (void) const |
Return true if the first input is a code reference. | |
bool | isInstructionStart (void) const |
Return true if this starts an instruction. | |
bool | isBlockStart (void) const |
Return true if this starts a basic block. | |
bool | isModified (void) const |
Return true if this is modified by the current action. | |
bool | isMark (void) const |
Return true if this op has been marked. | |
void | setMark (void) const |
Set the mark on this op. | |
bool | isWarning (void) const |
Return true if a warning has been generated for this op. | |
void | clearMark (void) const |
Clear any mark on this op. | |
bool | isIndirectSource (void) const |
Return true if this causes an INDIRECT. | |
void | setIndirectSource (void) |
Mark this op as source of INDIRECT. | |
void | clearIndirectSource (void) |
Clear INDIRECT source flag. | |
bool | isPtrFlow (void) const |
Return true if this produces/consumes ptrs. | |
void | setPtrFlow (void) |
Mark this op as consuming/producing ptrs. | |
bool | isSplitting (void) const |
Return true if this branch splits. | |
bool | doesSpecialPropagation (void) const |
Return true if this does datatype propagation. | |
bool | doesSpecialPrinting (void) const |
Return true if this needs to special printing. | |
bool | isIncidentalCopy (void) const |
bool | isCalculatedBool (void) const |
Return true if output is 1-bit boolean. | |
bool | isCpoolTransformed (void) const |
Return true if we have already examined this cpool. | |
bool | isCollapsible (void) const |
bool | usesSpacebasePtr (void) const |
Return true if this LOADs or STOREs from a dynamic spacebase pointer. | |
uintm | getCseHash (void) const |
Return hash indicating possibility of common subexpression elimination. More... | |
bool | isCseMatch (const PcodeOp *op) const |
Return true if this and op represent common subexpressions. More... | |
TypeOp * | getOpcode (void) const |
Get the opcode for this op. | |
OpCode | code (void) const |
Get the opcode id (enum) for this op. | |
bool | isCommutative (void) const |
Return true if inputs commute. | |
uintb | collapse (bool &markedInput) const |
Calculate the constant output produced by this op. More... | |
void | collapseConstantSymbol (Varnode *newConst) const |
Propagate constant symbol from inputs to given output. More... | |
PcodeOp * | nextOp (void) const |
Return the next op in the control-flow from this or null. | |
PcodeOp * | previousOp (void) const |
Return the previous op within this op's basic block or null. More... | |
PcodeOp * | target (void) const |
Return starting op for instruction associated with this op. More... | |
uintb | getNZMaskLocal (bool cliploop) const |
Calculate known zero bits for output to this op. More... | |
int4 | compareOrder (const PcodeOp *bop) const |
Compare the control-flow order of this and bop. More... | |
void | printRaw (ostream &s) const |
Print raw info about this op to stream. | |
const string & | getOpName (void) const |
Return the name of this op. | |
void | printDebug (ostream &s) const |
Print debug description of this op to stream. More... | |
void | saveXml (ostream &s) const |
Datatype * | outputTypeLocal (void) const |
Calculate the local output type. | |
Datatype * | inputTypeLocal (int4 slot) const |
Calculate the local input type. | |
bool | markExplicitUnsigned (int4 slot) |
Decide on unsignedness printing. | |
bool | inheritsSign (void) const |
Does this token inherit its sign from operands. | |
Static Public Member Functions | |
static PcodeOp * | getOpFromConst (const Address &addr) |
Retrieve the PcodeOp encoded as the address addr. | |
Private Member Functions | |
void | setOpcode (TypeOp *t_op) |
Set the opcode for this PcodeOp. More... | |
void | setOutput (Varnode *vn) |
Set the output Varnode of this op. | |
void | clearInput (int4 slot) |
Clear a specific input Varnode to null. | |
void | setInput (Varnode *vn, int4 slot) |
Set a specific input Varnode. | |
void | setFlag (uint4 fl) |
Set specific boolean attribute(s) on this op. | |
void | clearFlag (uint4 fl) |
Clear specific boolean attribute(s) | |
void | setAdditionalFlag (uint4 fl) |
Set specific boolean attribute. | |
void | clearAdditionalFlag (uint4 fl) |
Clear specific boolean atribute. | |
void | flipFlag (uint4 fl) |
Flip the setting of specific boolean attribute(s) | |
void | setNumInputs (int4 num) |
Make sure this op has num inputs. More... | |
void | removeInput (int4 slot) |
Eliminate a specific input Varnode. More... | |
void | insertInput (int4 slot) |
Make room for a new input Varnode at a specific position. More... | |
void | setOrder (uintm ord) |
Order this op within the ops for a single instruction. | |
void | setParent (BlockBasic *p) |
Set the parent basic block of this op. | |
void | setBasicIter (list< PcodeOp * >::iterator iter) |
Store the iterator into this op's basic block. | |
Private Attributes | |
TypeOp * | opcode |
Pointer to class providing behavioral details of the operation. | |
uint4 | flags |
Collection of boolean attributes on this op. | |
uint4 | addlflags |
Additional boolean attributes for this op. | |
SeqNum | start |
What instruction address is this attached to. | |
BlockBasic * | parent |
Basic block in which this op is contained. | |
list< PcodeOp * >::iterator | basiciter |
Iterator within basic block. | |
list< PcodeOp * >::iterator | insertiter |
Position in alive/dead list. | |
list< PcodeOp * >::iterator | codeiter |
Position in opcode list. | |
Varnode * | output |
The one possible output Varnode of this op. | |
vector< Varnode * > | inrefs |
The ordered list of input Varnodes for this op. | |
Friends | |
class | BlockBasic |
class | Funcdata |
class | PcodeOpBank |
class | VarnodeBank |
Lowest level operation of the p-code language.
The philosophy here is to have only one version of any type of operation, and to be completely explicit about all effects. All operations except the control flow operations have exactly one explicit output. Any given operation can have multiple inputs, but all are listed explicitly.
Input and output size for an operation are specified explicitly. All inputs must be of the same size. Except for the above restrictions, input and output can be any size in bytes.
P-code can be either big or little endian, this is determined by the language being translated from
anonymous enum |
Boolean attributes (flags) that can be placed on a PcodeOp. Even though this enum is public, these are all set and read internally, although many are read publicly via get or is methods.
anonymous enum |
PcodeOp::PcodeOp | ( | int4 | s, |
const SeqNum & | sq | ||
) |
Construct an unattached PcodeOp.
Construct a completely unattached PcodeOp. Space is reserved for input and output Varnodes but all are set initially to null.
s | indicates the number of input slots reserved |
sq | is the sequence number to associate with the new PcodeOp |
References addlflags, flags, inrefs, opcode, output, and parent.
Referenced by PcodeOpBank::create().
uintb PcodeOp::collapse | ( | bool & | markedInput | ) | const |
Calculate the constant output produced by this op.
Assuming all the inputs to this op are constants, compute the constant result of evaluating this op on this inputs. If one if the inputs has attached symbol information, pass-back "the fact of" as we may want to propagate the info to the new constant. Throw an exception if a constant result cannot be produced.
markedInput | will pass-back whether or not one of the inputs is a marked constant |
References binary, TypeOp::evaluateBinary(), TypeOp::evaluateUnary(), getEvalType(), getIn(), Varnode::getOffset(), Varnode::getSize(), Varnode::getSymbolEntry(), opcode, output, and unary.
Referenced by RuleCollapseConstants::applyOp().
void PcodeOp::collapseConstantSymbol | ( | Varnode * | newConst | ) | const |
Propagate constant symbol from inputs to given output.
Knowing that this PcodeOp has collapsed its constant inputs, one of which has symbol content, figure out if the symbol should propagate to the new given output constant.
newConst | is the given output constant |
References code(), Varnode::copySymbolIfValid(), CPUI_COPY, CPUI_INT_2COMP, CPUI_INT_ADD, CPUI_INT_AND, CPUI_INT_LEFT, CPUI_INT_MULT, CPUI_INT_NEGATE, CPUI_INT_OR, CPUI_INT_RIGHT, CPUI_INT_SRIGHT, CPUI_INT_XOR, CPUI_INT_ZEXT, CPUI_SUBPIECE, getIn(), Varnode::getOffset(), and Varnode::getSymbolEntry().
Referenced by RuleCollapseConstants::applyOp().
int4 PcodeOp::compareOrder | ( | const PcodeOp * | bop | ) | const |
Compare the control-flow order of this and bop.
Compare the execution order of -this- and -bop-, if -this- executes earlier (dominates) return -1; if -bop- executes earlier return 1, otherwise return 0. Note that 0 is returned if there is no absolute execution order.
bop | is the PcodeOp to compare this to |
References FlowBlock::findCommonBlock(), SeqNum::getOrder(), parent, and start.
Referenced by RuleOrPredicate::applyOp().
|
inline |
Get position within basic block
Referenced by RuleDoubleIn::applyOp(), Heritage::concatPieces(), FuncCallSpecs::insertPcode(), Funcdata::opInsertAfter(), Funcdata::opInsertBefore(), Heritage::removeRevisitedMarkers(), ActionStackPtrFlow::repair(), and Heritage::splitPieces().
uintm PcodeOp::getCseHash | ( | void | ) | const |
Return hash indicating possibility of common subexpression elimination.
Produce a hash of the following attributes: output size, the opcode, and the identity of each input varnode. This is suitable for determining if two PcodeOps calculate identical values
References binary, code(), CPUI_COPY, Varnode::getCreateIndex(), getEvalType(), getIn(), Varnode::getOffset(), Varnode::getSize(), inrefs, Varnode::isConstant(), output, and unary.
Referenced by RuleSelectCse::applyOp().
uintb PcodeOp::getNZMaskLocal | ( | bool | cliploop | ) | const |
Calculate known zero bits for output to this op.
Compute nonzeromask assuming inputs to op have their masks properly defined. Assume the op has an output. For any inputs to this op, that have zero bits where their nzmasks have zero bits, then the output produced by this op is guaranteed to have zero bits at every location in the nzmask calculated by this function.
cliploop | indicates the calculation shouldn't include inputs from known looping edges |
References calc_mask(), coveringmask(), CPUI_BOOL_AND, CPUI_BOOL_NEGATE, CPUI_BOOL_OR, CPUI_BOOL_XOR, CPUI_CALL, CPUI_CALLIND, CPUI_COPY, CPUI_CPOOLREF, CPUI_FLOAT_EQUAL, CPUI_FLOAT_LESS, CPUI_FLOAT_LESSEQUAL, CPUI_FLOAT_NAN, CPUI_FLOAT_NOTEQUAL, CPUI_INT_ADD, CPUI_INT_AND, CPUI_INT_CARRY, CPUI_INT_DIV, CPUI_INT_EQUAL, CPUI_INT_LEFT, CPUI_INT_LESS, CPUI_INT_LESSEQUAL, CPUI_INT_MULT, CPUI_INT_NOTEQUAL, CPUI_INT_OR, CPUI_INT_REM, CPUI_INT_RIGHT, CPUI_INT_SBORROW, CPUI_INT_SCARRY, CPUI_INT_SEXT, CPUI_INT_SLESS, CPUI_INT_SLESSEQUAL, CPUI_INT_SRIGHT, CPUI_INT_XOR, CPUI_INT_ZEXT, CPUI_MULTIEQUAL, CPUI_PIECE, CPUI_POPCOUNT, CPUI_SUBPIECE, getIn(), Varnode::getNZMask(), Varnode::getOffset(), TypeOp::getOpcode(), Varnode::getSize(), inrefs, isCalculatedBool(), Varnode::isConstant(), FlowBlock::isLoopIn(), leastsigbit_set(), mostsigbit_set(), opcode, output, parent, pcode_left(), pcode_right(), popcount(), and sign_extend().
Referenced by Funcdata::calcNZMask().
int4 PcodeOp::getRepeatSlot | ( | const Varnode * | vn, |
int4 | firstSlot, | ||
list< PcodeOp * >::const_iterator | iter | ||
) | const |
Find the slot for a given Varnode, which may be take up multiple input slots.
In the rare case that this PcodeOp takes the same Varnode as input multiple times, use the specific descendant iterator producing this PcodeOp to work out the corresponding slot. Every slot containing the given Varnode will be produced exactly once over the course of iteration.
vn | is the given Varnode |
firstSlot | is the first instance of the Varnode in this input list |
iter | is the specific descendant iterator producing this |
References Varnode::beginDescend(), and inrefs.
Referenced by SubvariableFlow::traceForward(), SubfloatFlow::traceForward(), and SubvariableFlow::traceForwardSext().
|
private |
Make room for a new input Varnode at a specific position.
Insert space for a new Varnode before slot. The new space is filled with null.
slot | is index of the slot where the new space is inserted |
References inrefs.
Referenced by Funcdata::opInsertInput(), and Funcdata::spacebaseConstant().
|
inline |
Return true if this op is a branch
Referenced by PrintC::emitBlockBasic(), ConditionalExecution::execute(), BlockBasic::hasOnlyMarkers(), BlockBasic::insert(), Funcdata::nodeSplitCloneOp(), IopSpace::printRaw(), and Funcdata::spliceBlockBasic().
|
inline |
Return true if this op indicates call semantics
References call, and has_callspec.
Referenced by ActionDeadCode::apply(), RuleEarlyRemoval::applyOp(), RuleIndirectCollapse::applyOp(), RulePiecePathology::applyOp(), ActionMarkExplicit::baseExplicit(), Funcdata::blockRemoveInternal(), ActionMarkImplied::checkImpliedCover(), ActionMarkExplicit::checkNewToConstructor(), ValueSetSolver::constraintsFromCBranch(), ValueSetSolver::constraintsFromPath(), functionalEqualityLevel(), BlockBasic::isComplex(), RulePiecePathology::isPathology(), JumpBasic::isprune(), CastStrategyC::localExtensionType(), Merge::mergeAdjacent(), ActionDeadCode::neverConsumed(), Funcdata::nodeSplitInputPatch(), Heritage::normalizeWriteSize(), ActionStackPtrFlow::repair(), ConditionalExecution::testRemovability(), SubvariableFlow::traceForward(), and SubvariableFlow::traceForwardSext().
bool PcodeOp::isCollapsible | ( | void | ) | const |
Return true if this can be collapsed to a COPY of a constant
Can this be collapsed to a copy op, i.e. are all inputs constants
References code(), CPUI_COPY, flags, getIn(), getOut(), Varnode::getSize(), inrefs, isAssignment(), Varnode::isConstant(), and nocollapse.
Referenced by RuleCollapseConstants::applyOp().
bool PcodeOp::isCseMatch | ( | const PcodeOp * | op | ) | const |
Return true if this and op represent common subexpressions.
Do these two ops represent a common subexpression? This is the full test of matching indicated by getCseHash
op | is the PcodeOp to compare with this |
References binary, code(), CPUI_COPY, getEvalType(), getIn(), Varnode::getOffset(), Varnode::getSize(), inrefs, Varnode::isConstant(), output, and unary.
Referenced by RuleTrivialArith::applyOp(), and cseEliminateList().
|
inline |
Return true if this COPY is incidental
References booloutput, calculated_bool, and incidental_copy.
Referenced by Funcdata::ancestorOpUse(), and AncestorRealistic::enterNode().
|
inline |
Return true if this INDIRECT is caused by STORE
References indirect_store, marker, nonprinting, and noreturn.
Referenced by ActionDirectWrite::apply(), Funcdata::checkIndirectUse(), AncestorRealistic::enterNode(), ValueSetSolver::establishValueSets(), Heritage::findAddressForces(), and ActionLikelyTrash::traceTrash().
PcodeOp * PcodeOp::previousOp | ( | void | ) | const |
Return the previous op within this op's basic block or null.
Find the previous op that flowed uniquely into this op, if it exists. This routine will not search farther than the basic block containing this.
References basiciter, BlockBasic::beginOp(), and parent.
Referenced by ActionShadowVar::apply(), FuncCallSpecs::collectOutputTrialVarnodes(), Heritage::reprocessFreeStores(), and FuncCallSpecs::transferLockedOutputParam().
void PcodeOp::printDebug | ( | ostream & | s | ) | const |
Print debug description of this op to stream.
Print an address and a raw representation of this op to the stream, suitable for console debugging apps
s | is the stream to print to |
References isDead(), parent, printRaw(), and start.
Referenced by PcodeEmitFd::dump().
|
private |
Eliminate a specific input Varnode.
Remove the input Varnode in a specific slot. The slot is eliminated and all Varnodes beyond this slot are renumbered. All the other Varnodes are otherwise undisturbed.
slot | is the index of the Varnode to remove |
References inrefs.
Referenced by Funcdata::opRemoveInput().
void PcodeOp::saveXml | ( | ostream & | s | ) | const |
Write an XML description of this op to stream
Write a description including: the opcode name, the sequence number, and separate xml tags providing a reference number for each input and output Varnode
s | is the stream to write to |
References a_v_i(), a_v_u(), code(), CPUI_INDIRECT, CPUI_LOAD, CPUI_STORE, Varnode::getAddr(), Varnode::getCreateIndex(), getIn(), AddrSpace::getName(), getOpFromConst(), getSeqNum(), Varnode::getSpace(), Address::getSpaceFromConst(), SeqNum::getTime(), AddrSpace::getType(), inrefs, IPTR_CONSTANT, IPTR_IOP, output, SeqNum::saveXml(), and start.
Referenced by Funcdata::saveXmlTree().
|
private |
Make sure this op has num inputs.
Make sure there are exactly num input slots for this op. All slots, regardless of the total being increased or decreased, are set to null.
num | is the number of inputs to set |
References inrefs.
Referenced by Funcdata::nodeSplitInputPatch(), and Funcdata::opSetAllInput().
|
private |
Set the opcode for this PcodeOp.
Set the behavioral class (opcode) of this operation. For most applications this should only be called by the PcodeOpBank. This is fairly low-level but does cache various boolean flags associated with the opcode
t_op | is the behavioural class to set |
References binary, booloutput, branch, call, coderef, commutative, flags, TypeOp::getFlags(), marker, nocollapse, opcode, returns, special, and unary.
Referenced by PcodeOpBank::changeOpcode().
PcodeOp * PcodeOp::target | ( | void | ) | const |
Return starting op for instruction associated with this op.
Scan backward within the basic block containing this op and find the first op marked as the start of an instruction. This also works if basic blocks haven't been calculated yet, and all the ops are still in the dead list. The starting op may be from a different instruction if this op was from an instruction in a delay slot
References basiciter, flags, insertiter, isDead(), and startmark.
Referenced by PcodeOpBank::target().