Move JMP processing from Function class
Add MarkAsSwitchCase command
This commit is contained in:
parent
ae27258e3c
commit
9c6dfd676e
@ -232,7 +232,6 @@ public:
|
|||||||
void markImpure();
|
void markImpure();
|
||||||
void findImmedDom();
|
void findImmedDom();
|
||||||
void process_operands(ICODE &pIcode, STATE *pstate);
|
void process_operands(ICODE &pIcode, STATE *pstate);
|
||||||
bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
|
||||||
bool process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
bool process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||||
void freeCFG();
|
void freeCFG();
|
||||||
void codeGen(QIODevice & fs);
|
void codeGen(QIODevice & fs);
|
||||||
@ -285,10 +284,6 @@ protected:
|
|||||||
bool findDerivedSeq(derSeq &derivedGi);
|
bool findDerivedSeq(derSeq &derivedGi);
|
||||||
bool nextOrderGraph(derSeq &derivedGi);
|
bool nextOrderGraph(derSeq &derivedGi);
|
||||||
void addOutEdgesForConditionalJump(BB* pBB, int next_ip, LLInst *ll);
|
void addOutEdgesForConditionalJump(BB* pBB, int next_ip, LLInst *ll);
|
||||||
|
|
||||||
private:
|
|
||||||
bool decodeIndirectJMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
|
||||||
bool decodeIndirectJMP2(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<PtrFunction> FunctionListType;
|
typedef std::list<PtrFunction> FunctionListType;
|
||||||
|
|||||||
@ -16,3 +16,34 @@ bool FollowControlFlow::execute(CommandContext *ctx)
|
|||||||
FollowCtrl(*scanned_func,proj.callGraph, &m_start_state);
|
FollowCtrl(*scanned_func,proj.callGraph, &m_start_state);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString MarkAsSwitchCase::instanceDescription() const
|
||||||
|
{
|
||||||
|
return name() + QString(" 0x%1 -> 0x%2 ; case %3")
|
||||||
|
.arg(m_src_addr,8,16,QChar('0'))
|
||||||
|
.arg(m_dst_addr,8,16,QChar('0'))
|
||||||
|
.arg(m_case_label);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MarkAsSwitchCase::execute(CommandContext * ctx)
|
||||||
|
{
|
||||||
|
//TODO: record code/data referneces in project for navigation UI purposes ?
|
||||||
|
auto switch_insn = ctx->m_func->Icode.labelSrch(m_src_addr);
|
||||||
|
if(switch_insn==ctx->m_func->Icode.end()) {
|
||||||
|
ctx->recordFailure(this,QString("switch instruction @ 0x%1 not found in procedure's instructions ?")
|
||||||
|
.arg(m_src_addr,8,16,QChar('0')));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto insn = ctx->m_func->Icode.labelSrch(m_dst_addr);
|
||||||
|
if(insn==ctx->m_func->Icode.end()) {
|
||||||
|
ctx->recordFailure(this,QString("switch target instruction 0x%1 not found in procedure's instructions ?")
|
||||||
|
.arg(m_dst_addr,8,16,QChar('0')));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
insn->ll()->caseEntry = m_case_label;
|
||||||
|
insn->ll()->setFlags(CASE);
|
||||||
|
switch_insn->ll()->caseTbl2.push_back( m_dst_addr );
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -16,5 +16,24 @@ public:
|
|||||||
QString instanceDescription() const override;
|
QString instanceDescription() const override;
|
||||||
bool execute(CommandContext *ctx) override;
|
bool execute(CommandContext *ctx) override;
|
||||||
};
|
};
|
||||||
|
// mark instruction at address m_dst_addr as a case m_case_label of switch located at m_src_addr
|
||||||
|
class MarkAsSwitchCase : public Command
|
||||||
|
{
|
||||||
|
uint32_t m_src_addr;
|
||||||
|
uint32_t m_dst_addr;
|
||||||
|
int m_case_label;
|
||||||
|
public:
|
||||||
|
MarkAsSwitchCase(uint32_t src_addr,uint32_t dst_addr,int lab) :
|
||||||
|
Command("Mark as switch case",eFunction),
|
||||||
|
m_src_addr(src_addr),
|
||||||
|
m_dst_addr(dst_addr),
|
||||||
|
m_case_label(lab)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Command interface
|
||||||
|
public:
|
||||||
|
QString instanceDescription() const override;
|
||||||
|
bool execute(CommandContext *ctx) override;
|
||||||
|
|
||||||
|
};
|
||||||
#endif // FOLLOWCONTROLFLOW_H
|
#endif // FOLLOWCONTROLFLOW_H
|
||||||
|
|||||||
132
src/parser.cpp
132
src/parser.cpp
@ -32,7 +32,8 @@ using namespace std;
|
|||||||
//static void FollowCtrl (Function * pProc, CALL_GRAPH * pcallGraph, STATE * pstate);
|
//static void FollowCtrl (Function * pProc, CALL_GRAPH * pcallGraph, STATE * pstate);
|
||||||
static void setBits(int16_t type, uint32_t start, uint32_t len);
|
static void setBits(int16_t type, uint32_t start, uint32_t len);
|
||||||
static void process_MOV(LLInst &ll, STATE * pstate);
|
static void process_MOV(LLInst &ll, STATE * pstate);
|
||||||
static SYM * lookupAddr (LLOperand *pm, STATE * pstate, int size, uint16_t duFlag);
|
static bool process_JMP(const PtrFunction &func,ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph);
|
||||||
|
static SYM * lookupAddr (LLOperand *pm, STATE * pstate, int size, uint16_t duFlag);
|
||||||
//void interactDis(Function * initProc, int ic);
|
//void interactDis(Function * initProc, int ic);
|
||||||
|
|
||||||
/* Returns the size of the string pointed by sym and delimited by delim.
|
/* Returns the size of the string pointed by sym and delimited by delim.
|
||||||
@ -277,13 +278,13 @@ void FollowCtrl(Function &func,CALL_GRAPH * pcallGraph, STATE *pstate)
|
|||||||
/* Next icode. Note: not the same as GetLastIcode() because of the call to FollowCtrl() */
|
/* Next icode. Note: not the same as GetLastIcode() because of the call to FollowCtrl() */
|
||||||
pIcode = func.Icode.GetIcode(ip);
|
pIcode = func.Icode.GetIcode(ip);
|
||||||
/* do the jump path */
|
/* do the jump path */
|
||||||
done = func.process_JMP (*pIcode, pstate, pcallGraph);
|
done = process_JMP(func.shared_from_this(),*pIcode, pstate, pcallGraph);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*** Jumps ***/
|
/*** Jumps ***/
|
||||||
case iJMP:
|
case iJMP:
|
||||||
case iJMPF: /* Returns true if we've run into a loop */
|
case iJMPF: /* Returns true if we've run into a loop */
|
||||||
done = func.process_JMP (*pIcode, pstate, pcallGraph);
|
done = process_JMP (func.shared_from_this(),*pIcode, pstate, pcallGraph);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*** Calls ***/
|
/*** Calls ***/
|
||||||
@ -401,7 +402,7 @@ bool Function::followAllTableEntries(JumpTable &table, uint32_t cs, ICODE& pIcod
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Function::decodeIndirectJMP(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph)
|
static bool decodeIndirectJMP(const PtrFunction &func,ICODE & pIcode, STATE *pstate)
|
||||||
{
|
{
|
||||||
PROG &prog(Project::get()->prog);
|
PROG &prog(Project::get()->prog);
|
||||||
// mov cx,NUM_CASES
|
// mov cx,NUM_CASES
|
||||||
@ -418,9 +419,9 @@ bool Function::decodeIndirectJMP(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pca
|
|||||||
// jmp word ptr [bx+2*NUM_CASES]
|
// jmp word ptr [bx+2*NUM_CASES]
|
||||||
static const llIcode match_seq[] = {iMOV,iMOV,iMOV,iCMP,iJE,iADD,iLOOP,iJMP,iJMP};
|
static const llIcode match_seq[] = {iMOV,iMOV,iMOV,iCMP,iJE,iADD,iLOOP,iJMP,iJMP};
|
||||||
|
|
||||||
if(Icode.size()<8)
|
if(func->Icode.size()<8)
|
||||||
return false;
|
return false;
|
||||||
if(&Icode.back()!=&pIcode) // not the last insn in the list skip it
|
if(&func->Icode.back()!=&pIcode) // not the last insn in the list skip it
|
||||||
return false;
|
return false;
|
||||||
if(pIcode.ll()->src().regi != INDEX_BX) {
|
if(pIcode.ll()->src().regi != INDEX_BX) {
|
||||||
return false;
|
return false;
|
||||||
@ -428,7 +429,7 @@ bool Function::decodeIndirectJMP(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pca
|
|||||||
// find address-wise predecessors of the icode
|
// find address-wise predecessors of the icode
|
||||||
std::deque<ICODE *> matched;
|
std::deque<ICODE *> matched;
|
||||||
QMap<uint32_t,ICODE *> addrmap;
|
QMap<uint32_t,ICODE *> addrmap;
|
||||||
for(ICODE & ic : Icode) {
|
for(ICODE & ic : func->Icode) {
|
||||||
addrmap[ic.ll()->GetLlLabel()] = ⁣
|
addrmap[ic.ll()->GetLlLabel()] = ⁣
|
||||||
}
|
}
|
||||||
auto iter = addrmap.find(pIcode.ll()->GetLlLabel());
|
auto iter = addrmap.find(pIcode.ll()->GetLlLabel());
|
||||||
@ -478,16 +479,12 @@ bool Function::decodeIndirectJMP(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pca
|
|||||||
STATE StCopy = *pstate;
|
STATE StCopy = *pstate;
|
||||||
uint32_t jump_target_location = table_addr + num_cases*2 + i*2;
|
uint32_t jump_target_location = table_addr + num_cases*2 + i*2;
|
||||||
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
||||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
Project::get()->addCommand(func,new FollowControlFlow(StCopy));
|
||||||
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
Project::get()->addCommand(func,new MarkAsSwitchCase(pIcode.ll()->label,StCopy.IP,i));
|
||||||
++last_current_insn;
|
|
||||||
last_current_insn->ll()->caseEntry = i;
|
|
||||||
last_current_insn->ll()->setFlags(CASE);
|
|
||||||
pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() );
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Function::decodeIndirectJMP2(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph)
|
static bool decodeIndirectJMP2(const PtrFunction &func,ICODE & pIcode, STATE *pstate)
|
||||||
{
|
{
|
||||||
PROG &prog(Project::get()->prog);
|
PROG &prog(Project::get()->prog);
|
||||||
// mov cx,NUM_CASES
|
// mov cx,NUM_CASES
|
||||||
@ -508,9 +505,9 @@ bool Function::decodeIndirectJMP2(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pc
|
|||||||
// jmp word ptr [bx+2*NUM_CASES]
|
// jmp word ptr [bx+2*NUM_CASES]
|
||||||
static const llIcode match_seq[] = {iMOV,iMOV,iMOV,iCMP,iJNE,iMOV,iCMP,iJE,iADD,iLOOP,iJMP,iJMP};
|
static const llIcode match_seq[] = {iMOV,iMOV,iMOV,iCMP,iJNE,iMOV,iCMP,iJE,iADD,iLOOP,iJMP,iJMP};
|
||||||
|
|
||||||
if(Icode.size()<12)
|
if(func->Icode.size()<12)
|
||||||
return false;
|
return false;
|
||||||
if(&Icode.back() != &pIcode) // not the last insn in the list skip it
|
if(&func->Icode.back() != &pIcode) // not the last insn in the list skip it
|
||||||
return false;
|
return false;
|
||||||
if(pIcode.ll()->src().regi != INDEX_BX) {
|
if(pIcode.ll()->src().regi != INDEX_BX) {
|
||||||
return false;
|
return false;
|
||||||
@ -518,7 +515,7 @@ bool Function::decodeIndirectJMP2(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pc
|
|||||||
// find address-wise predecessors of the icode
|
// find address-wise predecessors of the icode
|
||||||
std::deque<ICODE *> matched;
|
std::deque<ICODE *> matched;
|
||||||
QMap<uint32_t,ICODE *> addrmap;
|
QMap<uint32_t,ICODE *> addrmap;
|
||||||
for(ICODE & ic : Icode) {
|
for(ICODE & ic : func->Icode) {
|
||||||
addrmap[ic.ll()->GetLlLabel()] = ⁣
|
addrmap[ic.ll()->GetLlLabel()] = ⁣
|
||||||
}
|
}
|
||||||
auto iter = addrmap.find(pIcode.ll()->GetLlLabel());
|
auto iter = addrmap.find(pIcode.ll()->GetLlLabel());
|
||||||
@ -564,41 +561,19 @@ bool Function::decodeIndirectJMP2(ICODE & pIcode, STATE *pstate, CALL_GRAPH * pc
|
|||||||
STATE StCopy = *pstate;
|
STATE StCopy = *pstate;
|
||||||
uint32_t jump_target_location = table_addr + num_cases*4 + i*2;
|
uint32_t jump_target_location = table_addr + num_cases*4 + i*2;
|
||||||
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
StCopy.IP = cs + *(uint16_t *)(prog.image()+jump_target_location);
|
||||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
Project::get()->addCommand(func,new FollowControlFlow(StCopy));
|
||||||
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
Project::get()->addCommand(func,new MarkAsSwitchCase(pIcode.ll()->label,StCopy.IP,i));
|
||||||
++last_current_insn;
|
|
||||||
last_current_insn->ll()->caseEntry = i;
|
|
||||||
last_current_insn->ll()->setFlags(CASE);
|
|
||||||
pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() );
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph)
|
/* Look for switch() stmt. idiom of the form
|
||||||
{
|
* JMP uint16_t ptr word_offset[rBX | rSI | rDI] */
|
||||||
|
static bool decodeIndirectJMP0(const PtrFunction &func,ICODE & pIcode, STATE *pstate) {
|
||||||
|
const static uint8_t i2r[4] = {rSI, rDI, rBP, rBX};
|
||||||
|
|
||||||
|
uint32_t seg = (pIcode.ll()->src().seg)? pIcode.ll()->src().seg: rDS;
|
||||||
PROG &prog(Project::get()->prog);
|
PROG &prog(Project::get()->prog);
|
||||||
static uint8_t i2r[4] = {rSI, rDI, rBP, rBX};
|
|
||||||
ICODE _Icode;
|
|
||||||
uint32_t cs, offTable, endTable;
|
|
||||||
uint32_t i, k, seg, target;
|
|
||||||
|
|
||||||
if (pIcode.ll()->testFlags(I))
|
|
||||||
{
|
|
||||||
if (pIcode.ll()->getOpcode() == iJMPF)
|
|
||||||
pstate->setState( rCS, LH(prog.image() + pIcode.ll()->label + 3));
|
|
||||||
pstate->IP = pIcode.ll()->src().getImm2();
|
|
||||||
int64_t i = pIcode.ll()->src().getImm2();
|
|
||||||
if (i < 0)
|
|
||||||
{
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return true if jump target is already parsed */
|
|
||||||
return Icode.alreadyDecoded(i);
|
|
||||||
}
|
|
||||||
/* We've got an indirect JMP - look for switch() stmt. idiom of the form
|
|
||||||
* JMP uint16_t ptr word_offset[rBX | rSI | rDI] */
|
|
||||||
seg = (pIcode.ll()->src().seg)? pIcode.ll()->src().seg: rDS;
|
|
||||||
|
|
||||||
/* Ensure we have a uint16_t offset & valid seg */
|
/* Ensure we have a uint16_t offset & valid seg */
|
||||||
if (pIcode.ll()->match(iJMP) and (pIcode.ll()->testFlags(WORD_OFF)) and
|
if (pIcode.ll()->match(iJMP) and (pIcode.ll()->testFlags(WORD_OFF)) and
|
||||||
@ -608,8 +583,9 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
|||||||
pIcode.ll()->src().regi == INDEX_BX))
|
pIcode.ll()->src().regi == INDEX_BX))
|
||||||
{
|
{
|
||||||
|
|
||||||
offTable = ((uint32_t)(uint16_t)pstate->r[seg] << 4) + pIcode.ll()->src().off;
|
uint32_t offTable = ((uint32_t)(uint16_t)pstate->r[seg] << 4) + pIcode.ll()->src().off;
|
||||||
|
uint32_t endTable;
|
||||||
|
uint32_t i;
|
||||||
/* Firstly look for a leading range check of the form:-
|
/* Firstly look for a leading range check of the form:-
|
||||||
* CMP {BX | SI | DI}, immed
|
* CMP {BX | SI | DI}, immed
|
||||||
* JA | JAE | JB | JBE
|
* JA | JAE | JB | JBE
|
||||||
@ -630,10 +606,10 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
|||||||
/* Now do some heuristic pruning. Look for ptrs. into the table
|
/* Now do some heuristic pruning. Look for ptrs. into the table
|
||||||
* and for addresses that don't appear to point to valid code.
|
* and for addresses that don't appear to point to valid code.
|
||||||
*/
|
*/
|
||||||
cs = (uint32_t)(uint16_t)pstate->r[rCS] << 4;
|
uint32_t cs = (uint32_t)(uint16_t)pstate->r[rCS] << 4;
|
||||||
for (i = offTable; i < endTable; i += 2)
|
for (i = offTable; i < endTable; i += 2)
|
||||||
{
|
{
|
||||||
target = cs + LH(&prog.image()[i]);
|
uint32_t target = cs + LH(&prog.image()[i]);
|
||||||
if (target < endTable and target >= offTable)
|
if (target < endTable and target >= offTable)
|
||||||
endTable = target;
|
endTable = target;
|
||||||
else if (target >= (uint32_t)prog.cbImage)
|
else if (target >= (uint32_t)prog.cbImage)
|
||||||
@ -642,10 +618,10 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
|||||||
|
|
||||||
for (i = offTable; i < endTable; i += 2)
|
for (i = offTable; i < endTable; i += 2)
|
||||||
{
|
{
|
||||||
target = cs + LH(&prog.image()[i]);
|
uint32_t target = cs + LH(&prog.image()[i]);
|
||||||
/* Be wary of 00 00 as code - it's probably data */
|
/* Be wary of 00 00 as code - it's probably data */
|
||||||
if (not (prog.image()[target] or prog.image()[target+1]) or
|
ICODE _Icode;
|
||||||
scan(target, _Icode))
|
if (not (prog.image()[target] or prog.image()[target+1]) or scan(target, _Icode)!=NO_ERR)
|
||||||
endTable = i;
|
endTable = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -661,39 +637,55 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra
|
|||||||
setBits(BM_DATA, offTable, endTable - offTable);
|
setBits(BM_DATA, offTable, endTable - offTable);
|
||||||
|
|
||||||
pIcode.ll()->setFlags(SWITCH);
|
pIcode.ll()->setFlags(SWITCH);
|
||||||
//pIcode.ll()->caseTbl2.numEntries = (endTable - offTable) / 2;
|
|
||||||
|
|
||||||
|
uint32_t k;
|
||||||
for (i = offTable, k = 0; i < endTable; i += 2)
|
for (i = offTable, k = 0; i < endTable; i += 2)
|
||||||
{
|
{
|
||||||
StCopy = *pstate;
|
StCopy = *pstate;
|
||||||
StCopy.IP = cs + LH(&prog.image()[i]);
|
StCopy.IP = cs + LH(&prog.image()[i]);
|
||||||
iICODE last_current_insn = (++Icode.rbegin()).base();
|
Project::get()->addCommand(func,new FollowControlFlow(StCopy));
|
||||||
//ip = Icode.size();
|
Project::get()->addCommand(func,new MarkAsSwitchCase(pIcode.ll()->label,StCopy.IP,k++));
|
||||||
|
|
||||||
Project::get()->addCommand(shared_from_this(),new FollowControlFlow(StCopy));
|
|
||||||
|
|
||||||
++last_current_insn;
|
|
||||||
last_current_insn->ll()->caseEntry = k++;
|
|
||||||
last_current_insn->ll()->setFlags(CASE);
|
|
||||||
pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(decodeIndirectJMP(pIcode,pstate,pcallGraph)) {
|
return false;
|
||||||
|
}
|
||||||
|
static bool process_JMP(const PtrFunction &func,ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph)
|
||||||
|
{
|
||||||
|
PROG &prog(Project::get()->prog);
|
||||||
|
|
||||||
|
if (pIcode.ll()->testFlags(I))
|
||||||
|
{
|
||||||
|
if (pIcode.ll()->getOpcode() == iJMPF)
|
||||||
|
pstate->setState( rCS, LH(prog.image() + pIcode.ll()->label + 3));
|
||||||
|
pstate->IP = pIcode.ll()->src().getImm2();
|
||||||
|
int64_t i = pIcode.ll()->src().getImm2();
|
||||||
|
if (i < 0)
|
||||||
|
{
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if jump target is already parsed */
|
||||||
|
return func->Icode.alreadyDecoded(i);
|
||||||
|
}
|
||||||
|
/* We've got an indirect JMP */
|
||||||
|
if(decodeIndirectJMP0(func,pIcode,pstate)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(decodeIndirectJMP2(pIcode,pstate,pcallGraph)) {
|
if(decodeIndirectJMP(func,pIcode,pstate)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(decodeIndirectJMP2(func,pIcode,pstate)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can't do anything with this jump */
|
/* Can't do anything with this jump */
|
||||||
|
|
||||||
flg |= PROC_IJMP;
|
func->flg |= PROC_IJMP;
|
||||||
flg &= ~TERMINATES;
|
func->flg &= ~TERMINATES;
|
||||||
// TODO: consider adding a new user-interactive command ResolveControlFlowFailure ?
|
// TODO: consider adding a new user-interactive command ResolveControlFlowFailure ?
|
||||||
interactDis(shared_from_this(), Icode.size()-1);
|
interactDis(func, func->Icode.size()-1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user