From 8d0ad8e7f4a544e2d6289a21ea366df952f2d3ff Mon Sep 17 00:00:00 2001 From: jdh8d <jdh8d@git.zephyr-software.com> Date: Mon, 13 Jul 2015 02:39:17 +0000 Subject: [PATCH] BuildFuncIR draft, untested, but builds. Former-commit-id: de39c9aba850a9ce19fb7a54c0706b8b155f299b --- .gitattributes | 2 + SConscript | 7 +- SConscript.irdb | 4 +- include/base/SMPFunction.h | 2 + include/interfaces/irdb/STARSFunction.h | 47 +++- include/interfaces/irdb/STARSInstruction.h | 81 +++++++ include/interfaces/irdb/STARSInterface.h | 19 +- include/interfaces/irdb/STARSSegment.h | 2 +- src/interfaces/idapro/STARSFunction.cpp | 2 +- src/interfaces/irdb/STARSFunction.cpp | 258 +++++++++++++++++++++ 10 files changed, 401 insertions(+), 23 deletions(-) create mode 100644 include/interfaces/irdb/STARSInstruction.h create mode 100644 src/interfaces/irdb/STARSFunction.cpp diff --git a/.gitattributes b/.gitattributes index 85aace05..88e0c1a8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -37,6 +37,7 @@ include/interfaces/idapro/STARSProgram.h -text include/interfaces/idapro/STARSSegment.h -text include/interfaces/idapro/all.h -text include/interfaces/irdb/STARSFunction.h -text +include/interfaces/irdb/STARSInstruction.h -text include/interfaces/irdb/STARSInterface.h -text include/interfaces/irdb/STARSProgram.h -text include/interfaces/irdb/STARSSegment.h -text @@ -76,6 +77,7 @@ src/interfaces/idapro/STARSIDAOp.cpp -text src/interfaces/idapro/STARSIDAProgram.cpp -text src/interfaces/idapro/STARSInterface.cpp -text src/interfaces/irdb/Makefile.in -text +src/interfaces/irdb/STARSFunction.cpp -text src/interfaces/irdb/STARSIRDBProgram.cpp -text tests/commit/busybox.psexe -text tests/commit/bzip2.psexe -text diff --git a/SConscript b/SConscript index 673e30fb..739f8f4f 100644 --- a/SConscript +++ b/SConscript @@ -31,18 +31,17 @@ if argenv['IDAROOT'] is None: if int(argenv['debug']) == 1: print "Setting debug mode" - STARS_CCFLAGS=" -g" + STARS_CCFLAGS=" -g " else: print "Setting release mode" - STARS_CCFLAGS=" -O3" + STARS_CCFLAGS=" -O3 " if int(argenv['do_64bit_analysis']) == 1: - STARS_CCFLAGS+=" -D__EA64__" + STARS_CCFLAGS+=" -D__EA64__ " Export('argenv', 'STARS_CCFLAGS') - if int(argenv['build_ida']) == 1: lib=SConscript('SConscript.ida', variant_dir='build_ida') if int(argenv['build_irdb']) == 1: diff --git a/SConscript.irdb b/SConscript.irdb index 30a1a6dd..e850c84a 100644 --- a/SConscript.irdb +++ b/SConscript.irdb @@ -29,10 +29,10 @@ cpppath=''' IRDB_CCFLAGS=''' -std=c++0x \ -w \ -DSTARS_IRDB_INTERFACE \ - '''+STARS_CCFLAGS + '''+STARS_CCFLAGS+" " IRDB_LIBPATH="$SECURITY_TRANSFORMS_HOME/lib $SECURITY_TRANSFORMS_HOME/beaengine/lib/Linux.gnu.Debug " -LIBS="IRDB-core IRDB-cfg pqxx BeaEngine_s_d MEDSannotation pq" +LIBS="IRDB-core IRDB-cfg pqxx BeaEngine_s_d MEDSannotation pq IRDB-util" IRDB_LDFLAGS=" " diff --git a/include/base/SMPFunction.h b/include/base/SMPFunction.h index f93c28b9..0f1c9d12 100644 --- a/include/base/SMPFunction.h +++ b/include/base/SMPFunction.h @@ -52,6 +52,7 @@ class SMPProgram; // forward declaration so we can declare a pointer to an SMPProgram class STARS_IDA_Function_t; +class STARS_IRDB_Function_t; #define SMP_DEBUG_STACK_GRANULARITY 0 @@ -603,6 +604,7 @@ private: bool IsCallerReturnAddressReadOrWritten(void); // Can the return address of any caller be read or written directly from this function? friend class STARS_IDA_Function_t; + friend class STARS_IRDB_Function_t; }; // end class SMPFunction #endif diff --git a/include/interfaces/irdb/STARSFunction.h b/include/interfaces/irdb/STARSFunction.h index 2a4fe221..02428fe5 100644 --- a/include/interfaces/irdb/STARSFunction.h +++ b/include/interfaces/irdb/STARSFunction.h @@ -5,6 +5,7 @@ #include <libIRDB-core.hpp> class SMPFunction; +class SMPInstr; class STARS_IRDB_Function_t : public STARS_Function_t { @@ -18,26 +19,32 @@ public: virtual char* GetFunctionName(const char* name, const int len) const { assert(0); } // get entry point of function - virtual STARS_ea_t get_startEA(){ return the_func->GetEntryPoint()->GetBaseID(); } + virtual STARS_ea_t get_startEA() { return the_func->GetEntryPoint()->GetBaseID(); } // clc needs to review and get back to me. - virtual STARS_ea_t get_endEA(){ assert(0); } + virtual STARS_ea_t get_endEA() { assert(0); } - virtual std::size_t GetFuncSize() { assert(false); } // TODO + // return # of instructions. + virtual std::size_t GetFuncSize() { return the_func->GetInstructions().size(); } + +#if 1 +//This chunk of things is going away? // init class-local variable with IRDB value // and these are accessors to that. virtual std::size_t GetFrameSize(){ return the_func -> GetStackFrameSize(); } + + + // should go away. virtual void SetFrameSize(std::size_t size) { assert(0); } // todo for clc: audit these functions and see if they are really getting info from idapro // or if these can be removed from the interface because they are calculated by STARS // interface-independent routines. + // eventually going away. virtual std::size_t GetSavedRegSize() { assert(0); } virtual std::size_t GetIncomingArgumentSize() { assert(0); } - virtual std::size_t GetFrameReturnAddressSize() { assert(0); } - - + virtual std::size_t GetFrameReturnAddressSize() {assert(0); } virtual bool FunctionUsesFP(){ return the_func->GetUseFramePointer(); } virtual bool IsStaticFunction(){ return false; } @@ -52,17 +59,37 @@ public: virtual bool HasSharedChunks() const { assert(0); } virtual void SetSharedChunks(bool v) { assert(0); } virtual void UpdateXrefs(){ assert(0); } - virtual void BuildFuncIR(SMPFunction *func){ assert(0); } - virtual bool FindDistantCodeFragment(SMPFunction* func, STARS_ea_t TargetAddr){ assert(0); } virtual void FillInLocalVarTable(SMPFunction *CurrFunc) { assert(0); } - virtual bool AnalyzeInstAsCallTarget(SMPFunction *CurrFunc, bool &IsIndirectCallTarget, bool &IsTailCallTarget) { assert(0); } virtual bool IsChunkUnshared(STARS_ea_t ChunkAddr, STARS_ea_t FuncHeadStart, STARS_ea_t FuncHeadEnd) { assert(0); } - virtual bool IsInstIDInFunc(STARS_ea_t InstID) {assert(0); } +#endif + + virtual void BuildFuncIR(SMPFunction *func); + + + virtual bool FindDistantCodeFragment(SMPFunction* func, STARS_ea_t TargetAddr) + { return false; } + + + // see src/ file. + virtual bool AnalyzeInstAsCallTarget(SMPFunction *CurrFunc, + bool &IsIndirectCallTarget, + bool &IsTailCallTarget) ; + + // see src/ dir. + virtual bool IsInstIDInFunc(STARS_ea_t InstID); private: libIRDB::Function_t* the_func; + // disallow access to class members. + static void IRDB_IR_Build_helper + ( + SMPFunction *func, + SMPInstr *CurrInst + ); + + }; #endif diff --git a/include/interfaces/irdb/STARSInstruction.h b/include/interfaces/irdb/STARSInstruction.h new file mode 100644 index 00000000..7807ad34 --- /dev/null +++ b/include/interfaces/irdb/STARSInstruction.h @@ -0,0 +1,81 @@ +#ifndef STARS_IRDB_Instruction_h +#define STARS_IRDB_Instruction_h + +#include <assert.h> + +#include "interfaces/abstract/STARSInstruction.h" +#include "interfaces/abstract/STARSInstructionID.h" +#include <libIRDB-core.hpp> + +class SMPInstr; + +class STARS_IRDB_Instruction_t : public STARS_Instruction_t +{ + public: + + // Constructors and destructors + STARS_IRDB_Instruction_t(const libIRDB::Instruction_t *insn) + : STARS_Instruction_t(insn->GetBaseID()), irdb_insn(insn) + { } + + STARS_InstructionID_t GetID() { return irdb_insn->GetBaseID(); } + + // Data initialization methods + virtual bool STARS_GetCmd(void) { assert(0); } + + // Get (accessor) methods + virtual inline uint16_t GetSize(void) const { assert(0); } + virtual inline uint16_t GetIDAOpcode(void) const { assert(0); } + virtual STARS_InstructionID_t GetNextInstructionID(void) { assert(0); } + virtual STARS_InstructionID_t GetTargetInstructionID(void) { assert(0); } + virtual inline uint32_t GetInstFeatures(void) const { assert(0); } + virtual STARSOpndTypePtr GetOpnd(std::size_t OpndNum) const { assert(0); } + + // Set (mutator) methods + virtual void SetOpUsed(std::size_t OpndNum) {assert(0); } // set the USE bit + virtual void SetOpNotUsed(std::size_t OpndNum) {assert(0); } // reset the USE bit + virtual void SetOpDefed(std::size_t OpndNum) {assert(0); } // set the DEF bit + virtual void SetOpNotDefed(std::size_t OpndNum) {assert(0); } // reset the DEF bit + virtual void RemoveIDAOp1ForIMUL(void) {assert(0); } // Fix up IDA Pro IMUL instruction by removing operand 1 + + // Query methods + virtual inline bool HasRepeatIfEqualPrefix(void) const {assert(0); } + virtual inline bool HasRepeatIfNotEqualPrefix(void) const {assert(0); } + virtual inline bool HasAnyRepeatPrefix(void) const {assert(0); } + virtual bool OpcodeDefaultsTo64BitOperands(void) const {assert(0); } + virtual bool Has64BitOperands(void) const {assert(0); } + virtual inline bool Uses64BitAddressing(void) const {assert(0); } + virtual bool Uses32BitAddressing(void) const {assert(0); } + virtual inline bool IsRegOpnd(std::size_t OpndNum) const {assert(0); } + virtual inline bool IsImmedOpnd(std::size_t OpndNum) const {assert(0); } + virtual inline bool RegOpndMatches(std::size_t OpndNum, uint16_t RegNum) const {assert(0); } + virtual bool IsUseOpnd(std::size_t OpndNum) const {assert(0); } + virtual bool IsDefOpnd(std::size_t OpndNum) const {assert(0); } + virtual bool IsBranchToFarChunk(SMPInstr *CurrInst, STARS_ea_t &TargetAddr) {assert(0); } + + // Operand creation methods + virtual STARSOpndTypePtr MakeVoidOpnd(void) const {assert(0); } + virtual STARSOpndTypePtr MakeImmediateOpnd(STARS_uval_t value) const {assert(0); } + virtual STARSOpndTypePtr MakeRegOpnd(uint16_t RegNum) const {assert(0); } + virtual STARSOpndTypePtr MakeFloatingPointRegOpnd(uint16_t RegNum) const {assert(0); } + virtual STARSOpndTypePtr MakeMMXRegOpnd(uint16_t RegNum) const {assert(0); } + virtual STARSOpndTypePtr MakeXMMRegOpnd(uint16_t RegNum) const {assert(0); } + virtual STARSOpndTypePtr MakeYMMRegOpnd(uint16_t RegNum) const {assert(0); } + virtual STARSOpndTypePtr MakeMemDisplacementOpnd(uint16_t BaseRegNum, uint16_t IndexRegNum, uint16_t ScaleFactor, STARS_ea_t offset) const {assert(0); } + virtual STARSOpndTypePtr MakeMemPhraseOpnd(uint16_t BaseRegNum, uint16_t IndexRegNum, uint16_t ScaleFactor) const {assert(0); } + + // Analysis methods + + + virtual const libIRDB::Instruction_t* GetIRDBInstruction() const { return irdb_insn;} + + private: + + const libIRDB::Instruction_t* irdb_insn; + +}; + +#endif + + + diff --git a/include/interfaces/irdb/STARSInterface.h b/include/interfaces/irdb/STARSInterface.h index 4e8bf028..4323e94a 100644 --- a/include/interfaces/irdb/STARSInterface.h +++ b/include/interfaces/irdb/STARSInterface.h @@ -9,21 +9,26 @@ #include <elfio/elfio_dump.hpp> #include <libIRDB-core.hpp> +#include <libIRDB-util.hpp> #include <assert.h> #include <stdarg.h> #include <stdio.h> #include <pqxx/pqxx> +class STARS_IRDB_Function_t; + class STARS_IRDB_Interface_t: public STARS_Interface_t { public: // Constructors - STARS_IRDB_Interface_t(FileIR_t* p_firp, libIRDB::pqxxDB_t &p_pqxx_interface) : + STARS_IRDB_Interface_t(libIRDB::FileIR_t* p_firp, libIRDB::pqxxDB_t &p_pqxx_interface) : firp(p_firp), pqxx_interface(p_pqxx_interface) { InitSegments(); InitFunctions(); + // init instruction predecessors. + instruction_preds.AddFile(p_firp); } ~STARS_IRDB_Interface_t() @@ -197,8 +202,8 @@ private: elfiop=new ELFIO::elfio; elfiop->load("readeh_tmp_file.exe"); - ELFIO::dump::header(cout,*elfiop); - ELFIO::dump::section_headers(cout,*elfiop); + ELFIO::dump::header(std::cout,*elfiop); + ELFIO::dump::section_headers(std::cout,*elfiop); segments.resize(elfiop->sections.size()); int j=0; @@ -206,8 +211,8 @@ private: { if((elfiop->sections[i]->get_flags() & SHF_ALLOC) == SHF_ALLOC) { - cout<<"Found 'segment'["<<dec<<i<<"] named "<<elfiop->sections[i]->get_name(); - cout<<" start: "<<hex<<elfiop->sections[i]->get_address()<<endl; + std::cout<<"Found 'segment'["<<std::dec<<i<<"] named "<<elfiop->sections[i]->get_name(); + std::cout<<" start: "<<std::hex<<elfiop->sections[i]->get_address()<<std::endl; segments[j]=new STARS_IRDB_Segment_t(elfiop->sections[i],j); j++; } @@ -244,6 +249,10 @@ private: libIRDB::FileIR_t *firp; libIRDB::pqxxDB_t &pqxx_interface; + + libIRDB::InstructionPredecessors_t instruction_preds; + + friend class STARS_IRDB_Function_t; }; diff --git a/include/interfaces/irdb/STARSSegment.h b/include/interfaces/irdb/STARSSegment.h index 8750d677..238ecfbd 100644 --- a/include/interfaces/irdb/STARSSegment.h +++ b/include/interfaces/irdb/STARSSegment.h @@ -24,7 +24,7 @@ class STARS_IRDB_Segment_t : public STARS_Segment_t virtual STARS_ea_t get_endEA() { return the_seg->get_address()+the_seg->get_size(); } // Get the segment size in bytes. - virtual std::size_t get_seg_size() { the_seg->get_size(); } + virtual std::size_t get_seg_size() { return (std::size_t) the_seg->get_size(); } // return if the EXE bit is set. virtual bool IsCodeSegment() diff --git a/src/interfaces/idapro/STARSFunction.cpp b/src/interfaces/idapro/STARSFunction.cpp index f0448e46..586c6af3 100644 --- a/src/interfaces/idapro/STARSFunction.cpp +++ b/src/interfaces/idapro/STARSFunction.cpp @@ -321,7 +321,7 @@ void STARS_IDA_Function_t::BuildFuncIR(SMPFunction *func) CurrInst->AnalyzeCallInst(func->GetFirstFuncAddr()); #endif STARS_ea_t TargetAddr = CurrInst->GetCallTarget(); - bool LinkedToTarget = (BADADDR != TargetAddr); + bool LinkedToTarget = (STARS_BADADDR != TargetAddr); if (LinkedToTarget) { if (0 == TargetAddr) { SMP_msg("WARNING: Ignoring NULL call target (unreachable) at %lx\n", diff --git a/src/interfaces/irdb/STARSFunction.cpp b/src/interfaces/irdb/STARSFunction.cpp new file mode 100644 index 00000000..17d3e9dc --- /dev/null +++ b/src/interfaces/irdb/STARSFunction.cpp @@ -0,0 +1,258 @@ + +#include <SMPFunction.h> +#include <SMPInstr.h> +#include <interfaces/abstract/STARSFunction.h> +#include <interfaces/irdb/STARSFunction.h> +#include <interfaces/irdb/STARSInstruction.h> +#include <interfaces/irdb/STARSInterface.h> +#include <libIRDB-core.hpp> +#include <libIRDB-cfg.hpp> + +#include <list> + +using namespace std; +using namespace libIRDB; + +void STARS_IRDB_Function_t::IRDB_IR_Build_helper + ( + SMPFunction *func, + SMPInstr *CurrInst + ) +{ +#if 1 + SMPitype DataFlowType = CurrInst->GetDataFlowType(); + if ((DataFlowType == INDIR_CALL) || (DataFlowType == CALL)) { + // See if IDA has determined the target of the call. +#if 0 // Phase ordering: Do this later. + CurrInst->AnalyzeCallInst(func->GetFirstFuncAddr()); +#endif + STARS_ea_t TargetAddr = CurrInst->GetCallTarget(); + bool LinkedToTarget = (STARS_BADADDR != TargetAddr); + if (LinkedToTarget) { + if (0 == TargetAddr) { + SMP_msg("WARNING: Ignoring NULL call target (unreachable) at %lx\n", + (unsigned long) CurrInst->GetAddr()); + } + else { + if (INDIR_CALL == DataFlowType) { + pair<set<STARS_ea_t>::iterator, bool> InsertResult = func->IndirectCallTargets.insert(TargetAddr); + if (InsertResult.second) { + func->AllCallTargets.push_back(TargetAddr); + } + } + else { + (void) func->AddDirectCallTarget(TargetAddr); + } + } + } + if (DataFlowType == INDIR_CALL) { + func->IndirectCalls = true; + func->UnresolvedIndirectCalls = (!LinkedToTarget); + } + } // end if INDIR_CALL or CALL + else if (DataFlowType == INDIR_JUMP) { + func->IndirectJumps = true; +// was if STARS_AUDIT_INDIR_JUMP_XREFS +#if 0 + PreviousIndirJumpAddr = addr; +#endif + } + else if (DataFlowType == RETURN) { + func->HasReturnInst = true; + } +/* + else if (CurrInst->IsBranchToFarChunk()) { + probably doesn't apply to IRDB. + } +*/ + + + +#endif +} + +void STARS_IRDB_Function_t::BuildFuncIR(SMPFunction *func) +{ + +typedef list<SMPInstr*> SMPInstrList_t; + + SMPInstrList_t::iterator FirstInBlock = func->Instrs.end(); + SMPInstrList_t::iterator LastInBlock = func->Instrs.end(); + bool GoodRTL=false; + + // build cfg + ControlFlowGraph_t cfg(the_func); + + // sort the blocks into any order where the entry block is first. + vector<BasicBlock_t*> sorted_blocks; + + sorted_blocks.push_back(cfg.GetEntry()); + for(BasicBlockSet_t::iterator it=cfg.GetBlocks().begin(); + it!=cfg.GetBlocks().end(); ++it) + { + BasicBlock_t* block=*it; + if(cfg.GetEntry() == block) // we did the entry block first. + continue; + sorted_blocks.push_back(block); + } + + + + + bool first_in_func=true; + for(vector<BasicBlock_t*>::iterator block_it=sorted_blocks.begin(); + block_it!=sorted_blocks.end(); ++block_it) + { + list<SMPInstr*> block_id_map; + block_id_map.clear(); + BasicBlock_t* block=*block_it; + for(InstructionVector_t::iterator insn_it=block->GetInstructions().begin(); + insn_it!=block->GetInstructions().end(); ++insn_it) + { + Instruction_t* irdb_insn=*insn_it; + STARS_IRDB_Instruction_t* interface_insn=new STARS_IRDB_Instruction_t(irdb_insn); + STARS_InstructionID_t instruction_id=interface_insn->GetID(); + // create instruction + SMPInstr *CurrInst = new SMPInstr(interface_insn->GetID().GetIDWithinFile()); + CurrInst->Analyze(); + + block_id_map.push_back(CurrInst); + + if(first_in_func) + { + first_in_func=false; + + // create SSA marker instruction + SMPInstr *MarkerInst = new SMPInstr(STARS_SSA_MARKER_PSEUDO_ID); + + MarkerInst->AnalyzeMarker(); + assert(STARS_NN_fnop == MarkerInst->GetIDAOpcode()); + GoodRTL = MarkerInst->BuildRTL(); + func->BuiltRTLs = (func->BuiltRTLs && GoodRTL); + if (GoodRTL) { + MarkerInst->SetGoodRTL(); + } + assert(FirstInBlock == func->Instrs.end()); + func->Instrs.push_back(MarkerInst); + + + // find all callers. + //for each instruction id, FromAddr, that might jump + // (but not fallthrough): + STARS_IRDB_Interface_t *sGi=dynamic_cast<STARS_IRDB_Interface_t*> + (global_stars_interface); + assert(sGi); + Instruction_t* entry=the_func->GetEntryPoint(); + for(InstructionSet_t::iterator tmp_it=sGi->instruction_preds[entry].begin(); + tmp_it!=sGi->instruction_preds[entry].end(); ++tmp_it) + { + Instruction_t* tmp=*tmp_it; + if(tmp->GetFunction()!=the_func && tmp->GetFallthrough()!=entry) + // tell stars about the jump + func->AddCallSource(tmp->GetBaseID()); + } + + if(the_func->GetEntryPoint()->GetIndirectBranchTargetAddress()) + func->PossibleIndirectCallTarget = true; + + + } + + // do a bunch of stuff that is based on the currently built IR. why + // this needs to be specific to IRDB I don't know. Ask clc. + IRDB_IR_Build_helper(func,CurrInst); + + // Build tree RTLs for the instruction. + GoodRTL = CurrInst->BuildRTL(); + func->BuiltRTLs = (func->BuiltRTLs && GoodRTL); + if (GoodRTL) { + CurrInst->SetGoodRTL(); + } + + // Insert instruction at end of list. + func->Instrs.push_back(CurrInst); + + } + + // find start/end of block + + // get first and last insn in the block. + FirstInBlock=find( func->Instrs.begin(), func->Instrs.end(), *(block_id_map.begin())); + LastInBlock =find( func->Instrs.begin(), func->Instrs.end(), *(--block_id_map.end())); + SMPBasicBlock *NewBlock = new SMPBasicBlock(func, FirstInBlock, LastInBlock); + + } + +} + + + + +bool STARS_IRDB_Function_t::IsInstIDInFunc(STARS_ea_t InstID) +{ + STARS_InstructionID_t id(InstID); + const STARS_Instruction_t *stars_insn=id.GetInstruction(); + const STARS_IRDB_Instruction_t* interface_insn=dynamic_cast<const STARS_IRDB_Instruction_t*>(stars_insn); + assert(interface_insn); + libIRDB::Instruction_t* irdb_insn=(libIRDB::Instruction_t*)interface_insn->GetIRDBInstruction(); + InstructionSet_t::iterator it=the_func->GetInstructions().find(irdb_insn); + if(it==the_func->GetInstructions().end()) + return false; + return true; +} + + +// assert this represents the same function as CurrFunc +// IsIndirectCallTarget if some instruction (might) indirectly +// branch to this function's entry. +// IsTailCallTarget if some function has a jump to this function's entry +// use IRDB-util::preds class to check that all predecessors are +// call instructions. How to deal with push/jmp pairs? ignore for now? +bool STARS_IRDB_Function_t::AnalyzeInstAsCallTarget(SMPFunction *CurrFunc, + bool &IsIndirectCallTarget, + bool &IsTailCallTarget) +{ + // Init. + IsIndirectCallTarget=false; + IsTailCallTarget=false; + + // Sanity + assert(the_func); + + // Get Entry. + Instruction_t* entry=the_func->GetEntryPoint(); + assert(entry); + + // Check if entry is an IBT + if(entry->GetIndirectBranchTargetAddress()) + // report appropriately. + IsIndirectCallTarget=true; + + extern STARS_Interface_t* global_stars_interface; + // safe convert. + STARS_IRDB_Interface_t *sGi=dynamic_cast<STARS_IRDB_Interface_t*>( global_stars_interface); + assert(sGi); + + + for(InstructionSet_t::iterator it=sGi->instruction_preds[entry].begin(); + it!=sGi->instruction_preds[entry].end(); ++it) + { + Instruction_t* pred=*it; + + // skip any fallthroughs to the entry (weird, but could happen) + if(pred->GetFallthrough()==entry) + continue; + + // skip any call instructions that target the branch + DISASM d; + pred->Disassemble(d); + if(d.Instruction.BranchType==CallType) + continue; + + IsTailCallTarget=true; + } + + return true; + +} + -- GitLab