mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
Merge remote-tracking branch 'origin/GP-2866_SwitchAnalysisFilter' into patch
This commit is contained in:
commit
1e8c575671
2 changed files with 80 additions and 0 deletions
|
@ -511,6 +511,7 @@ public:
|
||||||
JumpTable *linkJumpTable(PcodeOp *op); ///< Link jump-table with a given BRANCHIND
|
JumpTable *linkJumpTable(PcodeOp *op); ///< Link jump-table with a given BRANCHIND
|
||||||
JumpTable *findJumpTable(const PcodeOp *op) const; ///< Find a jump-table associated with a given BRANCHIND
|
JumpTable *findJumpTable(const PcodeOp *op) const; ///< Find a jump-table associated with a given BRANCHIND
|
||||||
JumpTable *installJumpTable(const Address &addr); ///< Install a new jump-table for the given Address
|
JumpTable *installJumpTable(const Address &addr); ///< Install a new jump-table for the given Address
|
||||||
|
bool earlyJumpTableFail(PcodeOp *op); ///< Try to determine, early, if jump-table analysis will fail
|
||||||
JumpTable *recoverJumpTable(PcodeOp *op,FlowInfo *flow,int4 &failuremode);
|
JumpTable *recoverJumpTable(PcodeOp *op,FlowInfo *flow,int4 &failuremode);
|
||||||
int4 numJumpTables(void) const { return jumpvec.size(); } ///< Get the number of jump-tables for \b this function
|
int4 numJumpTables(void) const { return jumpvec.size(); } ///< Get the number of jump-tables for \b this function
|
||||||
JumpTable *getJumpTable(int4 i) { return jumpvec[i]; } ///< Get the i-th jump-table
|
JumpTable *getJumpTable(int4 i) { return jumpvec[i]; } ///< Get the i-th jump-table
|
||||||
|
|
|
@ -545,6 +545,83 @@ int4 Funcdata::stageJumpTable(JumpTable *jt,PcodeOp *op,FlowInfo *flow)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Backtrack from the BRANCHIND, looking for ops that might affect the destination.
|
||||||
|
/// If a CALLOTHER, which is not injected/inlined in some way, is in the flow path of
|
||||||
|
/// the destination calculation, we know the jump-table analysis will fail and return \b true.
|
||||||
|
/// \param op is the BRANCHIND op
|
||||||
|
/// \return \b true if jump-table analysis is guaranteed to fail
|
||||||
|
bool Funcdata::earlyJumpTableFail(PcodeOp *op)
|
||||||
|
|
||||||
|
{
|
||||||
|
Varnode *vn = op->getIn(0);
|
||||||
|
list<PcodeOp *>::const_iterator iter = op->insertiter;
|
||||||
|
list<PcodeOp *>::const_iterator startiter = beginOpDead();
|
||||||
|
int4 countMax = 8;
|
||||||
|
while(iter != startiter) {
|
||||||
|
if (vn->getSize() == 1) return false;
|
||||||
|
countMax -= 1;
|
||||||
|
if (countMax < 0) return false; // Don't iterate too many times
|
||||||
|
--iter;
|
||||||
|
op = *iter;
|
||||||
|
Varnode *outvn = op->getOut();
|
||||||
|
bool outhit = false;
|
||||||
|
if (outvn != (Varnode *)0)
|
||||||
|
outhit = vn->intersects(*outvn);
|
||||||
|
if (op->getEvalType() == PcodeOp::special) {
|
||||||
|
if (op->isCall()) {
|
||||||
|
OpCode opc = op->code();
|
||||||
|
if (opc == CPUI_CALLOTHER) {
|
||||||
|
int4 id = (int4)op->getIn(0)->getOffset();
|
||||||
|
InjectedUserOp *userOp = dynamic_cast<InjectedUserOp *>(glb->userops.getOp(id));
|
||||||
|
if (userOp != (InjectedUserOp *)0) {
|
||||||
|
return false; // Don't try to back track through injection
|
||||||
|
}
|
||||||
|
if (outhit)
|
||||||
|
return true; // Address formed via uninjected CALLOTHER, analysis will fail
|
||||||
|
// Assume CALLOTHER will not interfere with address and continue backtracking
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// CALL or CALLIND - Output has not been established yet
|
||||||
|
return false; // Don't try to back track through CALL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (op->isBranch())
|
||||||
|
return false; // Don't try to back track further
|
||||||
|
else {
|
||||||
|
if (op->code() == CPUI_STORE) return false; // Don't try to back track through STORE
|
||||||
|
if (outhit)
|
||||||
|
return false; // Some special op (CPOOLREF, NEW, etc) generates address, don't assume failure
|
||||||
|
// Assume special will not interfere with address and continue backtracking
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (op->getEvalType() == PcodeOp::unary) {
|
||||||
|
if (outhit) {
|
||||||
|
Varnode *invn = op->getIn(0);
|
||||||
|
if (invn->getSize() != vn->getSize()) return false;
|
||||||
|
vn = invn; // Treat input as address
|
||||||
|
}
|
||||||
|
// Continue backtracking
|
||||||
|
}
|
||||||
|
else if (op->getEvalType() == PcodeOp::binary) {
|
||||||
|
if (outhit) {
|
||||||
|
OpCode opc = op->code();
|
||||||
|
if (opc != CPUI_INT_ADD && opc != CPUI_INT_SUB && opc != CPUI_INT_XOR)
|
||||||
|
return false;
|
||||||
|
if (!op->getIn(1)->isConstant()) return false; // Don't back-track thru binary op, don't assume failure
|
||||||
|
Varnode *invn = op->getIn(0);
|
||||||
|
if (invn->getSize() != vn->getSize()) return false;
|
||||||
|
vn = invn; // Treat input as address
|
||||||
|
}
|
||||||
|
// Continue backtracking
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (outhit)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Recover destinations for a BRANCHIND by analyzing nearby data and control-flow
|
/// \brief Recover destinations for a BRANCHIND by analyzing nearby data and control-flow
|
||||||
///
|
///
|
||||||
/// This is the high-level entry point for jump-table/switch recovery. In short, a
|
/// This is the high-level entry point for jump-table/switch recovery. In short, a
|
||||||
|
@ -577,6 +654,8 @@ JumpTable *Funcdata::recoverJumpTable(PcodeOp *op,FlowInfo *flow,int4 &failuremo
|
||||||
|
|
||||||
if ((flags & jumptablerecovery_dont)!=0)
|
if ((flags & jumptablerecovery_dont)!=0)
|
||||||
return (JumpTable *)0; // Explicitly told not to recover jumptables
|
return (JumpTable *)0; // Explicitly told not to recover jumptables
|
||||||
|
if (earlyJumpTableFail(op))
|
||||||
|
return (JumpTable *)0;
|
||||||
JumpTable trialjt(glb);
|
JumpTable trialjt(glb);
|
||||||
failuremode = stageJumpTable(&trialjt,op,flow);
|
failuremode = stageJumpTable(&trialjt,op,flow);
|
||||||
if (failuremode != 0)
|
if (failuremode != 0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue