decompiler
1.0.0
|
The basic switch model. More...
#include <jumptable.hh>
Public Member Functions | |
JumpBasic (JumpTable *jt) | |
Construct given a parent JumpTable. | |
const PathMeld & | getPathMeld (void) const |
Get the possible of paths to the switch. | |
const JumpValuesRange * | getValueRange (void) const |
Get the normalized value iterator. | |
virtual bool | isOverride (void) const |
Return true if this model was manually overridden. | |
virtual int4 | getTableSize (void) const |
Return the number of entries in the address table. | |
virtual bool | recoverModel (Funcdata *fd, PcodeOp *indop, uint4 matchsize, uint4 maxtablesize) |
Attempt to recover details of the model, given a specific BRANCHIND. More... | |
virtual void | buildAddresses (Funcdata *fd, PcodeOp *indop, vector< Address > &addresstable, vector< LoadTable > *loadpoints) const |
Construct the explicit list of target addresses (the Address Table) from this model. More... | |
virtual void | findUnnormalized (uint4 maxaddsub, uint4 maxleftright, uint4 maxext) |
Recover the unnormalized switch variable. More... | |
virtual void | buildLabels (Funcdata *fd, vector< Address > &addresstable, vector< uintb > &label, const JumpModel *orig) const |
Recover case labels associated with the Address table. More... | |
virtual Varnode * | foldInNormalization (Funcdata *fd, PcodeOp *indop) |
Do normalization of the given switch specific to this model. More... | |
virtual bool | foldInGuards (Funcdata *fd, JumpTable *jump) |
Eliminate any guard code involved in computing the switch destination. More... | |
virtual bool | sanityCheck (Funcdata *fd, PcodeOp *indop, vector< Address > &addresstable) |
Perform a sanity check on recovered addresses. More... | |
virtual JumpModel * | clone (JumpTable *jt) const |
Clone this model. | |
virtual void | clear (void) |
Clear any non-permanent aspects of the model. | |
Public Member Functions inherited from JumpModel | |
JumpModel (JumpTable *jt) | |
Construct given a parent jump-table. | |
virtual | ~JumpModel (void) |
Destructor. | |
virtual void | saveXml (ostream &s) const |
Save this model as an XML tag. | |
virtual void | restoreXml (const Element *el, Architecture *glb) |
Restore this model from an XML tag. | |
Protected Member Functions | |
void | findDeterminingVarnodes (PcodeOp *op, int4 slot) |
Calculate the initial set of Varnodes that might be switch variables. More... | |
void | analyzeGuards (BlockBasic *bl, int4 pathout) |
Analyze CBRANCHs leading up to the given basic-block as a potential switch guard. More... | |
void | calcRange (Varnode *vn, CircleRange &rng) const |
Calculate the range of values in the given Varnode that direct control-flow to the switch. More... | |
void | findSmallestNormal (uint4 matchsize) |
Find the putative switch variable with the smallest range of values reaching the switch. More... | |
void | findNormalized (Funcdata *fd, BlockBasic *rootbl, int4 pathout, uint4 matchsize, uint4 maxtablesize) |
Do all the work necessary to recover the normalized switch variable. More... | |
void | markFoldableGuards () |
Mark the guard CBRANCHs that are truly part of the model. More... | |
void | markModel (bool val) |
Mark (or unmark) all PcodeOps involved in the model. More... | |
bool | flowsOnlyToModel (Varnode *vn, PcodeOp *trailOp) |
Check if the given Varnode flows to anything other than this model. More... | |
virtual bool | foldInOneGuard (Funcdata *fd, GuardRecord &guard, JumpTable *jump) |
Eliminate the given guard to this switch. More... | |
Static Protected Member Functions | |
static bool | isprune (Varnode *vn) |
Do we prune in here in our depth-first search for the normalized switch variable. More... | |
static bool | ispoint (Varnode *vn) |
Is it possible for the given Varnode to be a switch variable? More... | |
static int4 | getStride (Varnode *vn) |
Get the step/stride associated with the Varnode. More... | |
static uintb | backup2Switch (Funcdata *fd, uintb output, Varnode *outvn, Varnode *invn) |
Back up the constant value in the output Varnode to the value in the input Varnode. More... | |
Protected Attributes | |
JumpValuesRange * | jrange |
Range of values for the (normalized) switch variable. | |
PathMeld | pathMeld |
Set of PcodeOps and Varnodes producing the final target addresses. | |
vector< GuardRecord > | selectguards |
Any guards associated with model. | |
int4 | varnodeIndex |
Position of the normalized switch Varnode within PathMeld. | |
Varnode * | normalvn |
Normalized switch Varnode. | |
Varnode * | switchvn |
Unnormalized switch Varnode. | |
Protected Attributes inherited from JumpModel | |
JumpTable * | jumptable |
The jump-table that is building this model. | |
The basic switch model.
This is the most common model:
|
protected |
Analyze CBRANCHs leading up to the given basic-block as a potential switch guard.
In general there is only one path to the switch, and the given basic-block will hold the BRANCHIND. In some models, there is more than one path to the switch block, and a path must be specified. In this case, the given basic-block will be a block that flows into the switch block, and the pathout parameter describes which path leads to the switch block.
For each CBRANCH, range restrictions on the various variables which allow control flow to pass through the CBRANCH to the switch are analyzed. A GuardRecord is created for each of these restrictions.
bl | is the given basic-block |
pathout | is an optional path from the basic-block to the switch or -1 |
References PcodeOp::code(), CPUI_BRANCHIND, CPUI_CBRANCH, Varnode::getDef(), FlowBlock::getFlipPath(), PcodeOp::getIn(), FlowBlock::getIn(), FlowBlock::getInRevIndex(), FlowBlock::getOut(), PcodeOp::isBooleanFlip(), CircleRange::isEmpty(), Varnode::isWritten(), BlockBasic::lastOp(), CircleRange::pullBack(), FlowBlock::sizeIn(), and FlowBlock::sizeOut().
|
staticprotected |
Back up the constant value in the output Varnode to the value in the input Varnode.
This does the work of going from a normalized switch value to the unnormalized value. PcodeOps between the output and input Varnodes must be reversible or an exception is thrown.
fd | is the function containing the switch |
output | is the constant value to back up |
outvn | is the output Varnode of the data-flow |
invn | is the input Varnode to back up to |
References PcodeOp::binary, Varnode::getAddr(), Funcdata::getArch(), Varnode::getDef(), PcodeOp::getEvalType(), PcodeOp::getIn(), PcodeOp::getOpcode(), PcodeOp::getOut(), Varnode::getSize(), MemoryBank::getValue(), Varnode::isConstant(), Architecture::loader, PcodeOp::numInput(), TypeOp::recoverInputBinary(), TypeOp::recoverInputUnary(), and PcodeOp::unary.
Referenced by JumpBasicOverride::buildLabels().
|
virtual |
Construct the explicit list of target addresses (the Address Table) from this model.
The addresses produced all come from the BRANCHIND and may not be deduped. Alternate guard destinations are not yet included.
fd | is the function containing the switch |
indop | is the root BRANCHIND of the switch |
addresstable | will hold the list of Addresses |
loadpoints | if non-null will hold LOAD table information used by the model |
Implements JumpModel.
Reimplemented in JumpBasicOverride.
References AddrSpace::addressToByte(), EmulateFunction::collectLoadPoints(), EmulateFunction::emulatePath(), PcodeOp::getAddr(), Address::getSpace(), AddrSpace::getWordSize(), and EmulateFunction::setLoadCollect().
|
virtual |
Recover case labels associated with the Address table.
The unnormalized switch variable must already be recovered. Values that the normalized switch value can hold or walked back to obtain the value that the unnormalized switch variable would hold. Labels are returned in the order provided by normalized switch variable iterator JumpValues.
fd | is the function containing the switch |
addresstable | is the address table (used to label code blocks with bad or missing labels) |
label | will hold recovered labels in JumpValues order |
orig | is the JumpModel to use for the JumpValues iterator |
Implements JumpModel.
Reimplemented in JumpBasicOverride.
References JumpValuesRange::getValue(), JumpValuesRange::initializeForReading(), JumpValuesRange::isReversible(), JumpValuesRange::next(), and Funcdata::warning().
|
protected |
Calculate the range of values in the given Varnode that direct control-flow to the switch.
The Varnode is evaluated against each GuardRecord to determine if its range of values can be restricted. Multiple guards may provide different restrictions.
vn | is the given Varnode |
rng | will hold resulting range of values the Varnode can hold at the switch |
References calc_mask(), PcodeOp::code(), coveringmask(), CPUI_INT_AND, Varnode::getDef(), PcodeOp::getIn(), CircleRange::getMask(), Varnode::getOffset(), GuardRecord::getRange(), CircleRange::getSize(), Varnode::getSize(), CircleRange::intersect(), PcodeOp::isBoolOutput(), Varnode::isConstant(), Varnode::isWritten(), GuardRecord::quasiCopy(), and GuardRecord::valueMatch().
|
protected |
Calculate the initial set of Varnodes that might be switch variables.
Paths that terminate at the given PcodeOp are calculated and organized in a PathMeld object that determines Varnodes that are common to all the paths.
References Varnode::getDef(), PcodeOp::getIn(), Varnode::getOffset(), and Varnode::isConstant().
Referenced by JumpBasicOverride::recoverModel().
|
protected |
Do all the work necessary to recover the normalized switch variable.
The switch can be specified as the basic-block containing the BRANCHIND, or as a block that flows to the BRANCHIND block by following the specified path out.
fd | is the function containing the switch |
rootbl | is the basic-block |
pathout | is the (optional) path to the BRANCHIND or -1 |
matchsize | is an (optional) size to expect for the normalized switch variable range |
maxtablesize | is the maximum size expected for the normalized switch variable range |
References Funcdata::getArch(), Varnode::getOffset(), Varnode::getSize(), Varnode::getSpace(), MemoryBank::getValue(), EmulatePcodeOp::glb, Varnode::isReadOnly(), and Architecture::loader.
|
protected |
Find the putative switch variable with the smallest range of values reaching the switch.
The Varnode with the smallest range and closest to the BRANCHIND is assumed to be the normalized switch variable. If an expected range size is provided, it is used to prefer a particular Varnode as the switch variable. Whatever Varnode is selected, the JumpValue object is set up to iterator over its range.
matchsize | optionally gives an expected size of the range, or it can be 0 |
References CircleRange::getSize(), and CircleRange::setRange().
|
virtual |
Recover the unnormalized switch variable.
The normalized switch variable must already be recovered. The amount of normalization between the two switch variables can be restricted.
maxaddsub | is a restriction on arithmetic operations |
maxleftright | is a restriction on shift operations |
maxext | is a restriction on extension operations |
Implements JumpModel.
Reimplemented in JumpBasic2.
References PcodeOp::code(), CPUI_INT_ADD, CPUI_INT_SEXT, CPUI_INT_SUB, CPUI_INT_ZEXT, PcodeOp::getIn(), Varnode::isConstant(), and PcodeOp::numInput().
Referenced by JumpBasic2::findUnnormalized().
Check if the given Varnode flows to anything other than this model.
The PcodeOps in this model must have been previously marked with markModel(). Run through the descendants of the given Varnode and look for this mark.
References Varnode::beginDescend(), Varnode::endDescend(), and PcodeOp::isMark().
Eliminate any guard code involved in computing the switch destination.
We now think of the BRANCHIND as encompassing any guard function.
fd | is the function containing the switch |
jump | is the JumpTable owning this model. |
Implements JumpModel.
Reimplemented in JumpBasicOverride.
References PcodeOp::isDead().
Do normalization of the given switch specific to this model.
The PcodeOp machinery is removed so it looks like the CPUI_BRANCHIND simply takes the switch variable as an input Varnode and automatically interprets its values to reach the correct destination.
fd | is the function containing the switch |
indop | is the given switch as a CPUI_BRANCHIND |
Implements JumpModel.
References Funcdata::opSetInput().
|
protectedvirtual |
Eliminate the given guard to this switch.
We disarm the guard instructions by making the guard condition always false. If the simplification removes the unusable branches, we are left with only one path through the switch.
fd | is the function containing the switch |
guard | is a description of the particular guard mechanism |
jump | is the JumpTable owning this model |
Reimplemented in JumpBasic2.
References JumpTable::addBlockToSwitch(), GuardRecord::clear(), GuardRecord::getBranch(), FlowBlock::getFlipPath(), PcodeOp::getIn(), JumpTable::getIndirectOp(), FlowBlock::getOut(), PcodeOp::getParent(), GuardRecord::getPath(), Varnode::getSize(), PcodeOp::isBooleanFlip(), BlockBasic::lastOp(), Funcdata::newConstant(), BlockBasic::noInterveningStatement(), Funcdata::opSetInput(), Funcdata::pushBranch(), JumpTable::setDefaultBlock(), JumpTable::setLastAsMostCommon(), and FlowBlock::sizeOut().
|
staticprotected |
Get the step/stride associated with the Varnode.
If the some of the least significant bits of the given Varnode are known to be zero, translate this into a stride for the jumptable range.
vn | is the given Varnode |
References Varnode::getNZMask().
|
staticprotected |
Is it possible for the given Varnode to be a switch variable?
vn | is the given Varnode to test |
References Varnode::isAnnotation(), Varnode::isConstant(), and Varnode::isReadOnly().
|
staticprotected |
Do we prune in here in our depth-first search for the normalized switch variable.
vn | is the Varnode we are testing for pruning |
References Varnode::getDef(), PcodeOp::isCall(), PcodeOp::isMarker(), Varnode::isWritten(), and PcodeOp::numInput().
|
protected |
Mark the guard CBRANCHs that are truly part of the model.
These CBRANCHs will be removed from the active control-flow graph, their function folded into the action of the model, as represented by BRANCHIND.
References GuardRecord::quasiCopy().
|
protected |
Mark (or unmark) all PcodeOps involved in the model.
val | is true to set marks, false to clear marks |
References PcodeOp::clearMark(), and PcodeOp::setMark().
|
virtual |
Attempt to recover details of the model, given a specific BRANCHIND.
This generally recovers the normalized switch variable and any guards.
fd | is the function containing the switch |
indop | is the given BRANCHIND |
matchsize | is the expected number of address table entries to recover, or 0 for no expectation |
maxtablesize | is maximum number of address table entries to allow in the model |
Implements JumpModel.
Reimplemented in JumpBasicOverride, and JumpBasic2.
References PcodeOp::getParent().
|
virtual |
Perform a sanity check on recovered addresses.
Individual addresses are checked against the function or its program to determine if they are reasonable. This method can optionally remove addresses from the table. If it does so, the underlying model is changed to reflect the removal.
fd | is the function containing the switch |
indop | is the root BRANCHIND of the switch |
addresstable | is the list of recovered Addresses, which may be modified |
Implements JumpModel.
Reimplemented in JumpBasicOverride.
References Funcdata::getArch(), Address::getOffset(), Architecture::loader, and LoadImage::loadFill().