From 8f4e62e31858dbb9e64ba91def902ea3f32b9b28 Mon Sep 17 00:00:00 2001 From: clc5q <clc5q@git.zephyr-software.com> Date: Tue, 5 Jan 2016 22:30:06 +0000 Subject: [PATCH] Handle fixed indirect calls that become a push followed by an indirect jump. Former-commit-id: d53527fc9169f7ebe06d988d23251d6bb5ebd84d --- include/base/SMPFunction.h | 3 ++ src/base/SMPFunction.cpp | 20 +++++++++- src/base/SMPInstr.cpp | 15 +++++++- src/interfaces/idapro/STARSFunction.cpp | 10 ++++- src/interfaces/irdb/STARS_IRDB_Function.cpp | 41 +++++++++++++-------- 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/include/base/SMPFunction.h b/include/base/SMPFunction.h index 35355772..5b293a5a 100644 --- a/include/base/SMPFunction.h +++ b/include/base/SMPFunction.h @@ -285,6 +285,8 @@ public: ReturnAddrStatus = funcType; } inline void SetFuncProcessed(bool Status) { FuncProcessed = Status; return; }; + inline void SetHasIndirectCalls(void) { IndirectCalls = true; }; + inline void SetHasUnresolvedIndirectCalls(void) { UnresolvedIndirectCalls = true; }; inline void SetFuncSafe(bool Status) { SafeFunc = Status; return; }; inline void SetSpecFuncSafe(bool Status) { SpecSafeFunc = Status; return; }; inline void SetNeedsFrame(bool Status) { NeedsStackReferent = Status; return; }; @@ -295,6 +297,7 @@ public: inline void SetHasHashingCode(bool Hashes) { HasHashingCode = Hashes; }; void AddCallSource(STARS_ea_t addr); // Add a caller to the list of all callers of this function. bool AddDirectCallTarget(STARS_ea_t addr); // Add a direct call target; return true if new target, false if target already added + bool AddIndirectCallTarget(STARS_ea_t addr); // Add an indirect call target; return true if new target, false if target already added std::set<STARS_ea_t>::iterator RemoveDirectCallTarget(STARS_ea_t TargetAddr); // Remove TargetAddr from DirectCallTargets and AllCallTargets. bool RemoveIndirectCallTarget(STARS_ea_t TargetAddr); // Remove TargetAddr from IndirectCallTargets and AllCallTargets. inline void SetMaxStackSSANum(int NewMaxSSANum) { MaxDirectStackAccessSSANum = NewMaxSSANum; }; diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp index 868ae987..ed9cd53b 100644 --- a/src/base/SMPFunction.cpp +++ b/src/base/SMPFunction.cpp @@ -526,7 +526,17 @@ void SMPFunction::AddCallSource(STARS_ea_t addr) { // Add a direct call target; return true if new target, false if target already added bool SMPFunction::AddDirectCallTarget(STARS_ea_t addr) { pair<set<STARS_ea_t>::iterator, bool> InsertResult = this->DirectCallTargets.insert(addr); - if (InsertResult.second) { // new call target + if (InsertResult.second) { // new direct call target + this->AllCallTargets.push_back(addr); + } + return InsertResult.second; +} + +// Add an indirect call target; return true if new target, false if target already added +bool SMPFunction::AddIndirectCallTarget(STARS_ea_t addr) { + this->SetHasIndirectCalls(); + pair<set<STARS_ea_t>::iterator, bool> InsertResult = this->IndirectCallTargets.insert(addr); + if (InsertResult.second) { // new indirect call target this->AllCallTargets.push_back(addr); } return InsertResult.second; @@ -3825,6 +3835,14 @@ void SMPFunction::AnalyzeFunc(void) { CurrBlock->SetUnreachableBlock(true); SMP_msg("INFO: Marking basic block unreachable due to call 0 instruction at %llx\n", (unsigned long long) InstAddr); } + else if (STARS_BADADDR != CallTarget) { + if (INDIR_CALL == InstDataFlowType) { + this->SetHasIndirectCalls(); + } + } + else { // STARS_BADADDR == CallTarget + + } } } // end for each inst CurrBlock->Analyze(); diff --git a/src/base/SMPInstr.cpp b/src/base/SMPInstr.cpp index 32cf78db..d708d8de 100644 --- a/src/base/SMPInstr.cpp +++ b/src/base/SMPInstr.cpp @@ -5362,11 +5362,22 @@ void SMPInstr::SetLeaMemUseOp(STARSOpndTypePtr NewLeaOperand) { void SMPInstr::SetFixedCallJump(void) { this->booleans5 |= INSTR_SET_FIXED_CALL_JUMP; this->CallTarget = this->GetJumpTarget(); - this->type = CALL; // Important: Change type to CALL only after calling GetJumpTarget() this->RTL.GetRT(0)->SetOperator(SMP_CALL); this->RTL.GetRT(0)->SetLeftOperand(this->STARSInstPtr->MakeVoidOpnd()); + if (this->type == JUMP) { + this->type = CALL; // Important: Change type to CALL only after calling GetJumpTarget() + bool NewDirectTarget = this->GetBlock()->GetFunc()->AddDirectCallTarget(this->CallTarget); + } + else { + assert(this->type == INDIR_JUMP); + this->type = INDIR_CALL; + bool NewIndirectTarget = this->GetBlock()->GetFunc()->AddIndirectCallTarget(this->CallTarget); + if (STARS_BADADDR == this->CallTarget) { + this->GetBlock()->GetFunc()->SetHasUnresolvedIndirectCalls(); + } + } return; -} +} // end of SMPInstr::SetFixedCallJump() // If DefReg is not already in the DEF list, add a DEF for it. void SMPInstr::MDAddRegDef(uint16_t DefReg, bool Shown, SMPOperandType Type) { diff --git a/src/interfaces/idapro/STARSFunction.cpp b/src/interfaces/idapro/STARSFunction.cpp index 431a4e0f..21edda8f 100644 --- a/src/interfaces/idapro/STARSFunction.cpp +++ b/src/interfaces/idapro/STARSFunction.cpp @@ -375,6 +375,10 @@ void STARS_IDA_Function_t::BuildFuncIR(SMPFunction *func) // Found a caller, with its call address in CurrXrefs.from func->AddCallSource(FromAddr); } + else { + SMP_msg("ERROR: Bad CallInst.Analyze() at %llx to %llx with xref type %d\n", + (unsigned long long) FromAddr, (unsigned long long) addr, CurrXrefs.GetType()); + } } else { // Data xref global_STARS_program->PrintDataToCodeXref(FromAddr, addr, 0); @@ -417,8 +421,10 @@ void STARS_IDA_Function_t::BuildFuncIR(SMPFunction *func) } } if (DataFlowType == INDIR_CALL) { - func->IndirectCalls = true; - func->UnresolvedIndirectCalls = (!LinkedToTarget); + func->SetHasIndirectCalls(); + if (!LinkedToTarget) { + func->SetHasUnresolvedIndirectCalls(); + } } } // end if INDIR_CALL or CALL else if (DataFlowType == INDIR_JUMP) { diff --git a/src/interfaces/irdb/STARS_IRDB_Function.cpp b/src/interfaces/irdb/STARS_IRDB_Function.cpp index bbf99e28..4f77a969 100644 --- a/src/interfaces/irdb/STARS_IRDB_Function.cpp +++ b/src/interfaces/irdb/STARS_IRDB_Function.cpp @@ -49,8 +49,10 @@ void STARS_IRDB_Function_t::IRDB_IR_Build_helper } } if (DataFlowType == INDIR_CALL) { - func->IndirectCalls = true; - func->UnresolvedIndirectCalls = (!LinkedToTarget); + func->SetHasIndirectCalls(); + if (!LinkedToTarget) { + func->SetHasUnresolvedIndirectCalls(); + } } } // end if INDIR_CALL or CALL else if (DataFlowType == INDIR_JUMP) { @@ -243,21 +245,30 @@ void STARS_IRDB_Function_t::FindFixedCalls(SMPFunction *CurrFunc) { } } } - if ((CurrInst->GetDataFlowType() == JUMP) && FixedCallPushSeen && (STARS_BADADDR != FixedCallPushTargetID)) { - // If the current instruction has a jump target outside of the current func, it could be the fixed call jump - // that matches the fixed call push. We really should do more analysis to be sure. - bool success = false; - STARS_InstructionID_Set_t TargetIDSet = CurrInst->GetReferencedIDs(success); - if (success && (!TargetIDSet.empty())) { - assert(1 == TargetIDSet.size()); - STARS_ea_t JumpTargetID = TargetIDSet.begin()->GetIDWithinFile(); - if ((STARS_BADADDR != JumpTargetID) && (!this->IsInstIDInFunc(JumpTargetID))) { - // Valid jump target outside of current function. - CurrInst->SetFixedCallJump(); - cout << "Found fixed call jump to ID " << JumpTargetID << " from ID " << CurrInst->GetAddr() << endl; - FixedCallPushSeen = false; // reset for detection of next occurrence + if (FixedCallPushSeen && (STARS_BADADDR != FixedCallPushTargetID)) { + SMPitype FlowType = CurrInst->GetDataFlowType(); + if (FlowType == JUMP) { + // If the current instruction has a jump target outside of the current func, it could be the fixed call jump + // that matches the fixed call push. We really should do more analysis to be sure. + bool success = false; + STARS_InstructionID_Set_t TargetIDSet = CurrInst->GetReferencedIDs(success); + if (success && (!TargetIDSet.empty())) { + assert(1 == TargetIDSet.size()); + STARS_ea_t JumpTargetID = TargetIDSet.begin()->GetIDWithinFile(); + if ((STARS_BADADDR != JumpTargetID) && (!this->IsInstIDInFunc(JumpTargetID))) { + // Valid jump target outside of current function. + CurrInst->SetFixedCallJump(); + cout << "Found fixed call jump to ID " << JumpTargetID << " from ID " << CurrInst->GetAddr() << endl; + FixedCallPushSeen = false; // reset for detection of next occurrence + } } } + else if (FlowType == INDIR_JUMP) { + // Could be a fixed indirect call. + CurrInst->SetFixedCallJump(); + cout << "Found fixed call indirect jump from ID " << CurrInst->GetAddr() << endl; + FixedCallPushSeen = false; // reset for detection of next occurrence + } } } // end for all instructions #endif -- GitLab