GP-6946 Refactor JumpTable thunk check

This commit is contained in:
caheckman
2026-06-12 15:22:23 +00:00
parent 4982080ee7
commit ff4f0ed1f6
2 changed files with 23 additions and 18 deletions

View File

@@ -2302,6 +2302,26 @@ void JumpTable::recoverModel(Funcdata *fd)
jmodel = (JumpModel *)0;
}
/// If the function is just a sequence of absolute jumps ending in an indirect jump that recovers
/// to a single address, return \b true.
/// \param fd is the function to test
/// \return \b true if the function looks like a thunk
bool JumpTable::isThunk(Funcdata *fd) const
{
if (addresstable.size() != 1) return false;
Address addr = addresstable[0];
if (addr.getOffset()==0)
return true;
list<PcodeOp *>::const_iterator iter;
for(iter = fd->beginOpAlive(); iter != fd->endOpAlive(); ++iter) {
OpCode opc = (*iter)->code();
if (opc != CPUI_BRANCHIND && opc != CPUI_BRANCH)
return false;
}
return true;
}
/// Check that the BRANCHIND is still reachable, if not throw JumptableNotReachableError.
/// Check pathological cases when there is only one address in the table, if we find
/// this, throw the JumptableThunkError. Let the model run its sanity check.
@@ -2319,24 +2339,8 @@ void JumpTable::sanityCheck(Funcdata *fd,vector<int4> *loadcounts)
if (!isReachable(indirect))
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];
if (addr.getOffset()==0)
isthunk = true;
else {
Address addr2 = indirect->getAddr();
diff = (addr.getOffset() < addr2.getOffset()) ?
(addr2.getOffset() - addr.getOffset()) :
(addr.getOffset() - addr2.getOffset());
if (diff > 0xffff)
isthunk = true;
}
if (isthunk) {
throw JumptableThunkError("Likely thunk");
}
}
if (isThunk(fd))
throw JumptableThunkError("Likely thunk");
if (!jmodel->sanityCheck(fd,indirect,addresstable,loadpoints,loadcounts)) {
ostringstream err;
err << "Jumptable at " << opaddress << " did not pass sanity check.";

View File

@@ -581,6 +581,7 @@ private:
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
bool isThunk(Funcdata *fd) const; ///< Return \b true if the function looks like a thunk
void sanityCheck(Funcdata *fd,vector<int4> *loadpoints); ///< Perform sanity check on recovered address targets
int4 block2Position(const FlowBlock *bl) const; ///< Convert a basic-block to an out-edge index from the switch.
static bool isReachable(PcodeOp *op); ///< Check if the given PcodeOp still seems reachable in its function