mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-12 23:23:17 +00:00
GP-4907 Multistage jumptable adjustment
This commit is contained in:
parent
86e77bd9ef
commit
691137abc1
@ -73,6 +73,8 @@ src/decompile/datatests/stackstring.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/statuscmp.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/switchhide.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/switchind.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/switchloop.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/switchmulti.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/switchreturn.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/threedim.xml||GHIDRA||||END|
|
||||
src/decompile/datatests/twodim.xml||GHIDRA||||END|
|
||||
|
@ -4410,12 +4410,8 @@ int4 ActionSwitchNorm::apply(Funcdata &data)
|
||||
for(int4 i=0;i<data.numJumpTables();++i) {
|
||||
JumpTable *jt = data.getJumpTable(i);
|
||||
if (!jt->isLabelled()) {
|
||||
if (jt->recoverLabels(&data)) { // Recover case statement labels
|
||||
// If this returns true, the jumptable was not fully recovered during flow analysis
|
||||
// So we need to issue a restart
|
||||
data.getOverride().insertMultistageJump(jt->getOpAddress());
|
||||
data.setRestartPending(true);
|
||||
}
|
||||
jt->matchModel(&data);
|
||||
jt->recoverLabels(&data); // Recover case statement labels
|
||||
jt->foldInNormalization(&data);
|
||||
count += 1;
|
||||
}
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -781,7 +781,6 @@ void FlowInfo::generateOps(void)
|
||||
if (hasInject())
|
||||
injectPcode();
|
||||
do {
|
||||
bool collapsed_jumptable = false;
|
||||
while(!tablelist.empty()) { // For each jumptable found
|
||||
vector<JumpTable *> newTables;
|
||||
recoverJumpTables(newTables, notreached);
|
||||
@ -793,16 +792,13 @@ void FlowInfo::generateOps(void)
|
||||
int4 num = jt->numEntries();
|
||||
for(int4 i=0;i<num;++i)
|
||||
newAddress(jt->getIndirectOp(),jt->getAddressByIndex(i));
|
||||
if (jt->isPossibleMultistage())
|
||||
collapsed_jumptable = true;
|
||||
while(!addrlist.empty()) // Try to fill in as much more as possible
|
||||
fallthru();
|
||||
}
|
||||
}
|
||||
|
||||
checkContainedCall(); // Check for PIC constructions
|
||||
if (collapsed_jumptable)
|
||||
checkMultistageJumptables();
|
||||
checkMultistageJumptables();
|
||||
while(notreachcnt < notreached.size()) {
|
||||
tablelist.push_back(notreached[notreachcnt]);
|
||||
notreachcnt += 1;
|
||||
@ -1435,14 +1431,18 @@ void FlowInfo::recoverJumpTables(vector<JumpTable *> &newTables,vector<PcodeOp *
|
||||
JumpTable::RecoveryMode mode;
|
||||
JumpTable *jt = data.recoverJumpTable(partial,op,this,mode); // Recover it
|
||||
if (jt == (JumpTable *)0) { // Could not recover jumptable
|
||||
if ((mode == JumpTable::fail_noflow) && (tablelist.size() > 1) && (!isInArray(notreached,op))) {
|
||||
// If the indirect op was not reachable with current flow AND there is more flow to generate,
|
||||
// AND we haven't tried to recover this table before
|
||||
notreached.push_back(op); // Save this op so we can try to recovery table again later
|
||||
}
|
||||
else if (!isFlowForInline()) // Unless this flow is being inlined for something else
|
||||
if (!isFlowForInline()) // Unless this flow is being inlined for something else
|
||||
truncateIndirectJump(op,mode); // Treat the indirect jump as a call
|
||||
}
|
||||
else if (jt->isPartial()) {
|
||||
if (tablelist.size() > 1 && !isInArray(notreached,op)) {
|
||||
// If the recovery is incomplete with current flow AND there is more flow to generate,
|
||||
// AND we haven't tried to recover this table before
|
||||
notreached.push_back(op); // Save this op so we can try to recover the table again later
|
||||
}
|
||||
else
|
||||
jt->markComplete(); // If we aren't revisiting, mark the table as complete
|
||||
}
|
||||
newTables.push_back(jt);
|
||||
}
|
||||
}
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -528,14 +528,11 @@ JumpTable::RecoveryMode Funcdata::stageJumpTable(Funcdata &partial,JumpTable *jt
|
||||
try {
|
||||
jt->setLoadCollect(flow->doesJumpRecord());
|
||||
jt->setIndirectOp(partop);
|
||||
if (jt->getStage()>0)
|
||||
if (jt->isPartial())
|
||||
jt->recoverMultistage(&partial);
|
||||
else
|
||||
jt->recoverAddresses(&partial); // Analyze partial to recover jumptable addresses
|
||||
}
|
||||
catch(JumptableNotReachableError &err) { // Thrown by recoverAddresses
|
||||
return JumpTable::fail_noflow;
|
||||
}
|
||||
catch(JumptableThunkError &err) { // Thrown by recoverAddresses
|
||||
return JumpTable::fail_thunk;
|
||||
}
|
||||
@ -645,7 +642,7 @@ JumpTable *Funcdata::recoverJumpTable(Funcdata &partial,PcodeOp *op,FlowInfo *fl
|
||||
jt = linkJumpTable(op); // Search for pre-existing jumptable
|
||||
if (jt != (JumpTable *)0) {
|
||||
if (!jt->isOverride()) {
|
||||
if (jt->getStage() != 1)
|
||||
if (!jt->isPartial())
|
||||
return jt; // Previously calculated jumptable (NOT an override and NOT incomplete)
|
||||
}
|
||||
mode = stageJumpTable(partial,jt,op,flow); // Recover based on override information
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -1049,7 +1049,7 @@ void JumpBasic::analyzeGuards(BlockBasic *bl,int4 pathout)
|
||||
int4 i,j,indpath;
|
||||
int4 maxbranch = 2; // Maximum number of CBRANCHs to consider
|
||||
int4 maxpullback = 2;
|
||||
bool usenzmask = (jumptable->getStage() == 0);
|
||||
bool usenzmask = !jumptable->isPartial();
|
||||
|
||||
selectguards.clear();
|
||||
BlockBasic *prevbl;
|
||||
@ -2205,6 +2205,33 @@ JumpModel *JumpAssisted::clone(JumpTable *jt) const
|
||||
return clone;
|
||||
}
|
||||
|
||||
void JumpTable::saveModel(void)
|
||||
|
||||
{
|
||||
if (origmodel != (JumpModel *)0)
|
||||
delete origmodel;
|
||||
origmodel = jmodel;
|
||||
jmodel = (JumpModel *)0;
|
||||
}
|
||||
|
||||
void JumpTable::restoreSavedModel(void)
|
||||
|
||||
{
|
||||
if (jmodel != (JumpModel *)0)
|
||||
delete jmodel;
|
||||
jmodel = origmodel;
|
||||
origmodel = (JumpModel *)0;
|
||||
}
|
||||
|
||||
void JumpTable::clearSavedModel(void)
|
||||
|
||||
{
|
||||
if (origmodel != (JumpModel *)0) {
|
||||
delete origmodel;
|
||||
origmodel = (JumpModel *)0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to recover each model in turn, until we find one that matches the specific BRANCHIND.
|
||||
/// \param fd is the function containing the switch
|
||||
void JumpTable::recoverModel(Funcdata *fd)
|
||||
@ -2252,12 +2279,12 @@ void JumpTable::sanityCheck(Funcdata *fd,vector<int4> *loadcounts)
|
||||
|
||||
{
|
||||
if (jmodel->isOverride())
|
||||
return; // Don't perform sanity check on an override
|
||||
return; // Don't perform sanity check on an override
|
||||
uint4 sz = addresstable.size();
|
||||
|
||||
if (!isReachable(indirect))
|
||||
throw JumptableNotReachableError("No legal flow");
|
||||
if (addresstable.size() == 1) { // One entry is likely some kind of thunk
|
||||
partialTable = true; // If the jumptable is not reachable, mark as incomplete
|
||||
if (addresstable.size() == 1) { // One entry is likely some kind of thunk
|
||||
bool isthunk = false;
|
||||
uintb diff;
|
||||
Address addr = addresstable[0];
|
||||
@ -2346,7 +2373,7 @@ JumpTable::JumpTable(Architecture *g,Address ad)
|
||||
maxaddsub = 1;
|
||||
maxleftright = 1;
|
||||
maxext = 1;
|
||||
recoverystage = 0;
|
||||
partialTable = false;
|
||||
collectloads = false;
|
||||
defaultIsFolded = false;
|
||||
}
|
||||
@ -2367,7 +2394,7 @@ JumpTable::JumpTable(const JumpTable *op2)
|
||||
maxaddsub = op2->maxaddsub;
|
||||
maxleftright = op2->maxleftright;
|
||||
maxext = op2->maxext;
|
||||
recoverystage = op2->recoverystage;
|
||||
partialTable = op2->partialTable;
|
||||
collectloads = op2->collectloads;
|
||||
defaultIsFolded = false;
|
||||
// We just clone the addresses themselves
|
||||
@ -2587,8 +2614,8 @@ void JumpTable::recoverAddresses(Funcdata *fd)
|
||||
}
|
||||
if (jmodel->getTableSize() == 0) {
|
||||
ostringstream err;
|
||||
err << "Impossible to reach jumptable at " << opaddress;
|
||||
throw JumptableNotReachableError(err.str());
|
||||
err << "Jumptable with 0 entries at " << opaddress;
|
||||
throw LowlevelError(err.str());
|
||||
}
|
||||
// if (sz < 2)
|
||||
// fd->warning("Jumptable has only one branch",opaddress);
|
||||
@ -2609,10 +2636,7 @@ void JumpTable::recoverAddresses(Funcdata *fd)
|
||||
void JumpTable::recoverMultistage(Funcdata *fd)
|
||||
|
||||
{
|
||||
if (origmodel != (JumpModel *)0)
|
||||
delete origmodel;
|
||||
origmodel = jmodel;
|
||||
jmodel = (JumpModel *)0;
|
||||
saveModel();
|
||||
|
||||
vector<Address> oldaddresstable = addresstable;
|
||||
addresstable.clear();
|
||||
@ -2621,36 +2645,25 @@ void JumpTable::recoverMultistage(Funcdata *fd)
|
||||
recoverAddresses(fd);
|
||||
}
|
||||
catch(JumptableThunkError &err) {
|
||||
if (jmodel != (JumpModel *)0)
|
||||
delete jmodel;
|
||||
jmodel = origmodel;
|
||||
origmodel = (JumpModel *)0;
|
||||
restoreSavedModel();
|
||||
addresstable = oldaddresstable;
|
||||
fd->warning("Second-stage recovery error",indirect->getAddr());
|
||||
}
|
||||
catch(LowlevelError &err) {
|
||||
if (jmodel != (JumpModel *)0)
|
||||
delete jmodel;
|
||||
jmodel = origmodel;
|
||||
origmodel = (JumpModel *)0;
|
||||
restoreSavedModel();
|
||||
addresstable = oldaddresstable;
|
||||
fd->warning("Second-stage recovery error",indirect->getAddr());
|
||||
}
|
||||
recoverystage = 2;
|
||||
if (origmodel != (JumpModel *)0) { // Keep the new model if it was created successfully
|
||||
delete origmodel;
|
||||
origmodel = (JumpModel *)0;
|
||||
}
|
||||
partialTable = false;
|
||||
clearSavedModel(); // Keep the new model if it was created successfully
|
||||
}
|
||||
|
||||
/// This is run assuming the address table has already been recovered, via recoverAddresses() in another
|
||||
/// Funcdata instance. So recoverModel() needs to be rerun on the instance passed in here.
|
||||
///
|
||||
/// The unnormalized switch variable is recovered, and for each possible address table entry, the variable
|
||||
/// value that produces it is calculated and stored as the formal \e case label for the associated code block.
|
||||
/// \param fd is the (final instance of the) function containing the switch
|
||||
/// \return \b true if it looks like a multi-stage restart is needed.
|
||||
bool JumpTable::recoverLabels(Funcdata *fd)
|
||||
/// This assumes the address table has already been recovered, via recoverAddresses() in another
|
||||
/// Funcdata instance. We rerun recoverModel() to match with the current Funcdata. If the recovered model
|
||||
/// does not match the original address table size, we may be missing control-flow. In this case,
|
||||
/// if it looks like we have a \e multistage jumptable, we generate a multistage restart, otherwise
|
||||
/// we generate a warning of the mismatch.
|
||||
void JumpTable::matchModel(Funcdata *fd)
|
||||
|
||||
{
|
||||
if (!isRecovered())
|
||||
@ -2658,24 +2671,33 @@ bool JumpTable::recoverLabels(Funcdata *fd)
|
||||
|
||||
// Unless the model is an override, move model (created on a flow copy) so we can create a current instance
|
||||
if (jmodel != (JumpModel *)0) {
|
||||
if (origmodel != (JumpModel *)0)
|
||||
delete origmodel;
|
||||
if (!jmodel->isOverride()) {
|
||||
origmodel = jmodel;
|
||||
jmodel = (JumpModel *)0;
|
||||
}
|
||||
else
|
||||
if (!jmodel->isOverride())
|
||||
saveModel();
|
||||
else {
|
||||
clearSavedModel();
|
||||
fd->warning("Switch is manually overridden",opaddress);
|
||||
}
|
||||
|
||||
bool multistagerestart = false;
|
||||
recoverModel(fd); // Create a current instance of the model
|
||||
if (jmodel != (JumpModel *)0) {
|
||||
if (jmodel->getTableSize() != addresstable.size()) {
|
||||
fd->warning("Could not find normalized switch variable to match jumptable",opaddress);
|
||||
if ((addresstable.size()==1)&&(jmodel->getTableSize() > 1))
|
||||
multistagerestart = true;
|
||||
}
|
||||
}
|
||||
recoverModel(fd); // Create a current instance of the model
|
||||
if (jmodel != (JumpModel *)0 && jmodel->getTableSize() != addresstable.size()) {
|
||||
if ((addresstable.size()==1)&&(jmodel->getTableSize() > 1)) {
|
||||
// The jumptable was not fully recovered during flow analysis, try to issue a restart
|
||||
fd->getOverride().insertMultistageJump(opaddress);
|
||||
fd->setRestartPending(true);
|
||||
return;
|
||||
}
|
||||
fd->warning("Could not find normalized switch variable to match jumptable",opaddress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// The unnormalized switch variable is recovered, and for each possible address table entry, the variable
|
||||
/// value that produces it is calculated and stored as the formal \e case label for the associated code block.
|
||||
/// \param fd is the (final instance of the) function containing the switch
|
||||
void JumpTable::recoverLabels(Funcdata *fd)
|
||||
|
||||
{
|
||||
if (jmodel != (JumpModel *)0) {
|
||||
if ((origmodel == (JumpModel *)0)||(origmodel->getTableSize()==0)) {
|
||||
jmodel->findUnnormalized(maxaddsub,maxleftright,maxext);
|
||||
jmodel->buildLabels(fd,addresstable,label,jmodel);
|
||||
@ -2692,11 +2714,7 @@ bool JumpTable::recoverLabels(Funcdata *fd)
|
||||
trivialSwitchOver();
|
||||
jmodel->buildLabels(fd,addresstable,label,origmodel);
|
||||
}
|
||||
if (origmodel != (JumpModel *)0) {
|
||||
delete origmodel;
|
||||
origmodel = (JumpModel *)0;
|
||||
}
|
||||
return multistagerestart;
|
||||
clearSavedModel();
|
||||
}
|
||||
|
||||
/// Clear out any data that is specific to a Funcdata instance.
|
||||
@ -2704,10 +2722,7 @@ bool JumpTable::recoverLabels(Funcdata *fd)
|
||||
void JumpTable::clear(void)
|
||||
|
||||
{
|
||||
if (origmodel != (JumpModel *)0) {
|
||||
delete origmodel;
|
||||
origmodel = (JumpModel *)0;
|
||||
}
|
||||
clearSavedModel();
|
||||
if (jmodel->isOverride())
|
||||
jmodel->clear();
|
||||
else {
|
||||
@ -2722,7 +2737,7 @@ void JumpTable::clear(void)
|
||||
indirect = (PcodeOp *)0;
|
||||
switchVarConsume = ~((uintb)0);
|
||||
defaultBlock = -1;
|
||||
recoverystage = 0;
|
||||
partialTable = false;
|
||||
// -opaddress- -maxtablesize- -maxaddsub- -maxleftright- -maxext- -collectloads- are permanent
|
||||
}
|
||||
|
||||
@ -2816,11 +2831,11 @@ bool JumpTable::checkForMultistage(Funcdata *fd)
|
||||
|
||||
{
|
||||
if (addresstable.size()!=1) return false;
|
||||
if (recoverystage != 0) return false;
|
||||
if (partialTable) return false;
|
||||
if (indirect == (PcodeOp *)0) return false;
|
||||
|
||||
if (fd->getOverride().queryMultistageJumptable(indirect->getAddr())) {
|
||||
recoverystage = 1; // Mark that we need additional recovery
|
||||
partialTable = true; // Mark that we need additional recovery
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -42,11 +42,6 @@ struct JumptableThunkError : public LowlevelError {
|
||||
JumptableThunkError(const string &s) : LowlevelError(s) {} ///< Construct with an explanatory string
|
||||
};
|
||||
|
||||
/// \brief Exception thrown is there are no legal flows to a switch
|
||||
struct JumptableNotReachableError : public LowlevelError {
|
||||
JumptableNotReachableError(const string &s) : LowlevelError(s) {} ///< Constructor
|
||||
};
|
||||
|
||||
/// \brief A description where and how data was loaded from memory
|
||||
///
|
||||
/// This is a generic table description, giving the starting address
|
||||
@ -547,9 +542,8 @@ public:
|
||||
success = 0, ///< JumpTable is fully recovered
|
||||
fail_normal = 1, ///< Normal failure to recover
|
||||
fail_thunk = 2, ///< Likely \b thunk
|
||||
fail_noflow = 3, ///< No legal flow to BRANCHIND
|
||||
fail_return = 4, ///< Likely \b return operation
|
||||
fail_callother = 5 ///< Address formed by CALLOTHER
|
||||
fail_return = 3, ///< Likely \b return operation
|
||||
fail_callother = 4 ///< Address formed by CALLOTHER
|
||||
};
|
||||
private:
|
||||
/// \brief An address table index and its corresponding out-edge
|
||||
@ -575,9 +569,12 @@ private:
|
||||
uint4 maxaddsub; ///< Maximum ADDs or SUBs to normalize
|
||||
uint4 maxleftright; ///< Maximum shifts to normalize
|
||||
uint4 maxext; ///< Maximum extensions to normalize
|
||||
int4 recoverystage; ///< 0=no stages recovered, 1=additional stage needed, 2=complete
|
||||
bool partialTable; ///< Set to \b true if \b this table is incomplete and needs additional recovery steps
|
||||
bool collectloads; ///< Set to \b true if information about in-memory model data is/should be collected
|
||||
bool defaultIsFolded; ///< The \e default block is the target of a folded CBRANCH (and cannot have a label)
|
||||
void saveModel(void); ///< Save off current model (if any) and prepare for instantiating a new model
|
||||
void restoreSavedModel(void); ///< Restore any saved model as the current model
|
||||
void clearSavedModel(void); ///< Clear any saved model
|
||||
void recoverModel(Funcdata *fd); ///< Attempt recovery of the jump-table model
|
||||
void trivialSwitchOver(void); ///< Switch \b this table over to a trivial model
|
||||
void sanityCheck(Funcdata *fd,vector<int4> *loadpoints); ///< Perform sanity check on recovered address targets
|
||||
@ -590,8 +587,8 @@ public:
|
||||
bool isRecovered(void) const { return !addresstable.empty(); } ///< Return \b true if a model has been recovered
|
||||
bool isLabelled(void) const { return !label.empty(); } ///< Return \b true if \e case labels are computed
|
||||
bool isOverride(void) const; ///< Return \b true if \b this table was manually overridden
|
||||
bool isPossibleMultistage(void) const { return (addresstable.size()==1); } ///< Return \b true if this could be multi-staged
|
||||
int4 getStage(void) const { return recoverystage; } ///< Return what stage of recovery this jump-table is in.
|
||||
bool isPartial(void) const { return partialTable; } ///< Return \b true if \b this is a partial table needing more recovery
|
||||
void markComplete(void) { partialTable = false; } ///< Mark whatever is recovered so far as the complete table
|
||||
int4 numEntries(void) const { return addresstable.size(); } ///< Return the size of the address table for \b this jump-table
|
||||
uintb getSwitchVarConsume(void) const { return switchVarConsume; } ///< Get bits of switch variable consumed by \b this table
|
||||
int4 getDefaultBlock(void) const { return defaultBlock; } ///< Get the out-edge corresponding to the \e default switch destination
|
||||
@ -616,7 +613,8 @@ public:
|
||||
bool foldInGuards(Funcdata *fd) { return jmodel->foldInGuards(fd,this); } ///< Hide any guard code for \b this switch
|
||||
void recoverAddresses(Funcdata *fd); ///< Recover the raw jump-table addresses (the address table)
|
||||
void recoverMultistage(Funcdata *fd); ///< Recover jump-table addresses keeping track of a possible previous stage
|
||||
bool recoverLabels(Funcdata *fd); ///< Recover the case labels for \b this jump-table
|
||||
void matchModel(Funcdata *fd); ///< Try to match JumpTable model to the existing function
|
||||
void recoverLabels(Funcdata *fd); ///< Recover the case labels for \b this jump-table
|
||||
bool checkForMultistage(Funcdata *fd); ///< Check if this jump-table requires an additional recovery stage
|
||||
void clear(void); ///< Clear instance specific data for \b this jump-table
|
||||
void encode(Encoder &encoder) const; ///< Encode \b this jump-table as a \<jumptable> element
|
||||
|
@ -0,0 +1,44 @@
|
||||
<decompilertest>
|
||||
<binaryimage arch="x86:LE:64:default:gcc">
|
||||
<!--
|
||||
Switch variable also a loop variable with increments in cases
|
||||
-->
|
||||
<bytechunk space="ram" offset="0x100000" readonly="true">
|
||||
f30f1efa4189f831c9488d35c0000000
|
||||
41b908000000bf0a00000041ba050000
|
||||
0041bb0300000083f90a0f849c000000
|
||||
8d41ff83f808770a486304864801f03e
|
||||
ffe0418d4001b901000000eb77418d40
|
||||
02b902000000eb6c438d040083f80b41
|
||||
0f4dcbeb5f418d4064b904000000eb54
|
||||
4489c099f7ff4181f895000000410f4e
|
||||
caeb41418d80e8030000b906000000eb
|
||||
33418d8010270000b907000000eb2544
|
||||
89c04489c9348789c283e20129d1eb14
|
||||
418d4008b909000000eb09418d4010b9
|
||||
0a0000004189c0e95bffffff4489c0c3
|
||||
7dffffff88ffffff95ffffffa0ffffff
|
||||
b3ffffffc1ffffffcfffffffe0ffffff
|
||||
ebffffff
|
||||
</bytechunk>
|
||||
<symbol space="ram" offset="0x100000" name="switchloop"/>
|
||||
</binaryimage>
|
||||
<script>
|
||||
<com>option readonly on</com>
|
||||
<com>parse line extern uint4 switchloop(uint4 startval);</com>
|
||||
<com>lo fu switchloop</com>
|
||||
<com>decompile</com>
|
||||
<com>print C</com>
|
||||
<com>quit</com>
|
||||
</script>
|
||||
<stringmatch name="Switch Loop #1" min="9" max="9">case .*:</stringmatch>
|
||||
<stringmatch name="Switch Loop #2" min="1" max="1">startval = startval \+ 2;</stringmatch>
|
||||
<stringmatch name="Switch Loop #3" min="1" max="1">startval = startval \* 2;</stringmatch>
|
||||
<stringmatch name="Switch Loop #4" min="1" max="1">startval = startval \+ 100;</stringmatch>
|
||||
<stringmatch name="Switch Loop #5" min="1" max="1">startval / 10;</stringmatch>
|
||||
<stringmatch name="Switch Loop #6" min="1" max="1">startval = startval \+ 1000;</stringmatch>
|
||||
<stringmatch name="Switch Loop #7" min="1" max="1">startval = startval \+ 10000;</stringmatch>
|
||||
<stringmatch name="Switch Loop #8" min="1" max="1">startval = startval \^ 0x87;</stringmatch>
|
||||
<stringmatch name="Switch Loop #9" min="1" max="1">startval = startval \+ 8;</stringmatch>
|
||||
<stringmatch name="Switch Loop #10" min="1" max="1">startval = startval \+ 1;</stringmatch>
|
||||
</decompilertest>
|
@ -0,0 +1,43 @@
|
||||
<decompilertest>
|
||||
<binaryimage arch="x86:LE:64:default:gcc">
|
||||
<!--
|
||||
Switch in a loop and also depending on a variable set to a constant locally and
|
||||
modified indirectly.
|
||||
-->
|
||||
<bytechunk space="ram" offset="0x100000" readonly="true">
|
||||
f30f1efa4883ec2848897c24084889e7
|
||||
488974241048c704240000000048c744
|
||||
241800000000e8d50f00004c8b14244c
|
||||
8b5c241031c9488d3583000000bf6500
|
||||
000041b9030000004d85d2745b4d8d04
|
||||
0b4883f90677574863048e4801f03eff
|
||||
e0498d480aeb39498d48f6eb33496bc8
|
||||
07eb2d4c89c0489949f7f94889c1eb20
|
||||
4c89c0489948f7ff4889d1eb134c89c1
|
||||
4881f1ba0a0000eb074c89c14883c920
|
||||
4883f9637ea2eb0d4983c8ffeb0749c7
|
||||
c0feffffff4c89c04883c428c3
|
||||
</bytechunk>
|
||||
<bytechunk space="ram" offset="0x1000c0" readonly="true">
|
||||
a1ffffffa7ffffffadffffffb3ffffff
|
||||
c0ffffffcdffffffd9ffffff
|
||||
</bytechunk>
|
||||
<symbol space="ram" offset="0x100000" name="switchmulti"/>
|
||||
</binaryimage>
|
||||
<script>
|
||||
<com>option readonly on</com>
|
||||
<com>lo fu switchmulti</com>
|
||||
<com>decompile</com>
|
||||
<com>print C</com>
|
||||
<com>quit</com>
|
||||
</script>
|
||||
<stringmatch name="Switch Multi #1" min="7" max="7">case .*:</stringmatch>
|
||||
<stringmatch name="Switch Multi #2" min="1" max="1">uVar1 \+ 10;</stringmatch>
|
||||
<stringmatch name="Switch Multi #3" min="1" max="1">uVar1 \- 10;</stringmatch>
|
||||
<stringmatch name="Switch Multi #4" min="1" max="1">uVar1 \* 7;</stringmatch>
|
||||
<stringmatch name="Switch Multi #5" min="1" max="1">uVar1 / 3;</stringmatch>
|
||||
<stringmatch name="Switch Multi #6" min="1" max="1">uVar1 % 0x65;</stringmatch>
|
||||
<stringmatch name="Switch Multi #7" min="1" max="1">uVar1 \^ 0xaba;</stringmatch>
|
||||
<stringmatch name="Switch Multi #8" min="1" max="1">uVar1 \| 0x20;</stringmatch>
|
||||
<stringmatch name="Switch Multi #9" min="1" max="1">return 0xfffffffffffffffe;</stringmatch>
|
||||
</decompilertest>
|
Loading…
Reference in New Issue
Block a user