diff --git a/.gitattributes b/.gitattributes index 15171e6d6a07f10ebe1036ad600258ecc2f8e0db..c5754d8efbae109f9bd2e9443eb547286ac1f94e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -42,5 +42,6 @@ src/base/SMPProgram.cpp -text src/base/SMPStaticAnalyzer.cpp -text src/interfaces/Makefile.in -text src/interfaces/idapro/Makefile.in -text +src/interfaces/idapro/STARSFunction.cpp -text src/interfaces/idapro64/Makefile.in -text src/interfaces/irdb/Makefile.in -text diff --git a/include/base/SMPFunction.h b/include/base/SMPFunction.h index 8415b0a7b6320b483e424aeac374e57d783909e9..325d14d9703b306cf43720581b2d9ec83a8a5c82 100644 --- a/include/base/SMPFunction.h +++ b/include/base/SMPFunction.h @@ -163,7 +163,7 @@ public: // Get methods inline SMPProgram *GetProg(void) const { return Program; }; inline const char *GetFuncName(void) const { SMP_get_func_name(FirstEA, StaticFuncName, MAXSMPSTR-1); return StaticFuncName; }; - STARS_Function_t *GetFuncInfo(void); + STARS_Function_t *GetFuncInfo(void) const; inline ea_t GetFirstFuncAddr(void) const { return FirstEA; }; ushort GetJumpToFollowNodeCounter(ea_t InstAddr) const; inline long GetTypedDefs(void) const { return TypedDefs; }; @@ -292,7 +292,10 @@ public: inline bool HasIndirectJumps(void) const { return IndirectJumps; }; inline bool HasUnresolvedIndirectJumps(void) const { return UnresolvedIndirectJumps; }; inline bool IsDirectlyRecursive(void) const { return DirectlyRecursive; }; - inline bool HasSharedChunks(void) const { return SharedChunks; }; + inline bool HasSharedChunks(void) const { return GetFuncInfo()->HasSharedChunks(); }; +// inline bool HasSharedChunks(void) const { return SharedChunks; }; + inline void SetSharedChunks(bool v) { GetFuncInfo()->SetSharedChunks(v); }; +// inline void SetSharedChunks(bool v) { SharedChunks=v; }; inline bool HasGoodRTLs(void) const { return BuiltRTLs; }; inline bool HasGoodSSAForm(void) const { return HasGoodSSA; }; inline bool HasReducibleControlFlow(void) const { return HasReducibleCFG; }; @@ -399,7 +402,7 @@ private: bool IndirectJumps; // Does function make indirect jumps? bool UnresolvedIndirectJumps; // Jumps could not all be linked to targets bool DirectlyRecursive; // Calls itself - bool SharedChunks; // Does function share a tail chunk with other functions? +// bool SharedChunks; // Does function share a tail chunk with other functions? bool UnsharedChunks; // Does function have noncontiguous fragments that are not shared with other funcs? bool MultipleEntryPoints; // Does function have multiple entry points from other functions? bool CallsAlloca; // Does function allocate stack space after initial allocation? NOTE:SMPInstr::IsAllocaCall() excludes immediate value alloca calls diff --git a/include/interfaces/abstract/STARSFunction.h b/include/interfaces/abstract/STARSFunction.h index b3f1f77e99ce9fddcd6787013aa348791260bc8e..e165b104dff7f6a1d0ba33f09919937dcface270 100644 --- a/include/interfaces/abstract/STARSFunction.h +++ b/include/interfaces/abstract/STARSFunction.h @@ -18,7 +18,10 @@ class STARS_Function_t virtual bool IsStackPointerAnalyzed()=0; virtual uint64_t get_spd(STARS_ea_t ea)=0; virtual bool HasReturnPoints()=0; - + virtual bool IsMultiEntry()=0; + virtual void MarkSharedChunks()=0; + virtual bool HasSharedChunks() const =0; + virtual void SetSharedChunks(bool v) =0; }; #endif diff --git a/include/interfaces/idapro/STARSFunction.h b/include/interfaces/idapro/STARSFunction.h index e49a774eb6ad1fb87bd84375a0dcb75858b4dc97..31d05c2144213d8de9a2ddc8bbf9c2b4d1dd3295 100644 --- a/include/interfaces/idapro/STARSFunction.h +++ b/include/interfaces/idapro/STARSFunction.h @@ -5,12 +5,18 @@ class STARS_IDA_Function_t : public STARS_Function_t { public: - virtual STARS_ea_t get_startEA() { return the_func->startEA; } - virtual STARS_ea_t get_endEA() { return the_func->endEA; } - STARS_IDA_Function_t(func_t* func) : the_func(func), frsize(the_func->frsize) {} + STARS_IDA_Function_t(func_t* func) : + the_func(func), + frsize(the_func->frsize), + SharedChunks(false), + UnsharedChunks(false) + {} + + virtual STARS_ea_t get_startEA() { return the_func->startEA; } + virtual STARS_ea_t get_endEA() { return the_func->endEA; } virtual char* GetFunctionName(const char* name, const int len) const { return ::get_func_name(the_func->startEA,(char*)name,len); } virtual size_t GetFrameSize() { return frsize; } @@ -24,6 +30,13 @@ class STARS_IDA_Function_t : public STARS_Function_t virtual bool IsStackPointerAnalyzed() { return the_func->analyzed_sp(); } virtual uint64_t get_spd(STARS_ea_t ea) { return ::get_spd(the_func,ea); } virtual bool HasReturnPoints() { return the_func->does_return(); } + virtual bool IsMultiEntry(); + virtual void MarkSharedChunks(); + virtual bool HasSharedChunks() const {return SharedChunks; } + virtual void SetSharedChunks(bool v) { SharedChunks=v; } + + + /* temporary cast operator for testing */ operator func_t* () { return the_func; } @@ -31,6 +44,8 @@ class STARS_IDA_Function_t : public STARS_Function_t private: func_t* the_func; + bool SharedChunks; + bool UnsharedChunks; size_t frsize; }; diff --git a/src/Makefile.in b/src/Makefile.in index 411220403a8c7f55ab0d6355760405dacfb5c39f..bf441decacced35c05cf74113a85ff1cfc735b39 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,10 +1,10 @@ .SUFFIXES: -dirs="base interfaces" +dirs=base interfaces all: .PHONY - for i in ${dirs}; do cd $$i; make || exit 1; cd ..; done + for i in ${dirs}; do echo ${PWD}; cd $$i; make || exit 1; cd ..; done clean: .PHONY for i in ${dirs}; do cd $$i; make clean; cd ..; done diff --git a/src/base/Makefile.in b/src/base/Makefile.in index 792b6f21d21a62e3cdb0f956aa005eb850125bd4..55bcd08b6fe071f1ef7407d02cce38420987ef04 100644 --- a/src/base/Makefile.in +++ b/src/base/Makefile.in @@ -23,7 +23,7 @@ all: $(OBJS) @rm -f $*.d.tmp clean: - rm -f $(OBJS) + rm -f $(OBJS) *.d .PHONY: @if [ "${IDAROOT}"X = "X" ]; then echo Please set IDAROOT; exit 1; fi diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp index aed395a0ed26d9c9c7f0fdd08444acd2712f504e..74881290514d3487f547561d11ffd7aa36d02a78 100644 --- a/src/base/SMPFunction.cpp +++ b/src/base/SMPFunction.cpp @@ -158,7 +158,7 @@ SMPFunction::SMPFunction(STARS_Function_t *Info, SMPProgram* pgm) { this->IndirectJumps = false; this->UnresolvedIndirectJumps = false; this->DirectlyRecursive = false; - this->SharedChunks = false; + this->SetSharedChunks(false); this->UnsharedChunks = false; this->MultipleEntryPoints = false; this->CallsAlloca = false; @@ -282,7 +282,7 @@ SMPFunction::~SMPFunction() { } // Get a non-stale pointer to the STARS_Function_t info for the current function. -STARS_Function_t *SMPFunction::GetFuncInfo(void) { +STARS_Function_t *SMPFunction::GetFuncInfo(void) const { STARS_Function_t *myPtr = SMP_get_func(this->FirstEA); assert(NULL != myPtr); return myPtr; @@ -3852,6 +3852,11 @@ void SMPFunction::EmitStackFrameAnnotations(FILE *AnnotFile, SMPInstr *Instr) { // are probably IDA Pro disassembly problems rather than true multi-entry functions. void SMPFunction::DetectMultiEntryFunction(void) { +#if 0 + this->MultipleEntryPoints = GetFuncInfo()->IsMultiEntry(); +#else + + /* convert to something like: * this->IsMultiEntry = GetFuncInfo()->IsMultiEntry(); */ @@ -3885,6 +3890,7 @@ void SMPFunction::DetectMultiEntryFunction(void) { this->MultipleEntryPoints = true; } return; +#endif } // end of SMPFunction::DetectMultiEntryFunction() // Audit and fix the IDA Pro code cross references for jumps and jump targets. @@ -4034,12 +4040,16 @@ void SMPFunction::AnalyzeFunc(void) { this->GetProg()->SetProgramThrowsExceptions(); } - // Determine if we are dealing with shared chunks. + size_t ChunkCounter = 0; + // Determine if we are dealing with shared chunks. +#if 1 + GetFuncInfo()->MarkSharedChunks(); func_tail_iterator_t FuncTail((func_t*)*dynamic_cast<STARS_IDA_Function_t*>(this->GetFuncInfo())); +#else + // Determine if we are dealing with shared chunks. ea_t FuncHeadLastAddr = 0; - -/* convert to GetFuncInfo()->MarkSharedChunks() */ + func_tail_iterator_t FuncTail((func_t*)*dynamic_cast<STARS_IDA_Function_t*>(this->GetFuncInfo())); for (bool ChunkOK = FuncTail.main(); ChunkOK; ChunkOK = FuncTail.next()) { const area_t &CurrChunk = FuncTail.chunk(); ++ChunkCounter; @@ -4067,6 +4077,7 @@ void SMPFunction::AnalyzeFunc(void) { #endif // STARS_FIND_UNSHARED_CHUNKS } } +#endif #if STARS_AUDIT_JUMP_XREFS this->MDAuditJumpXrefs(); @@ -4384,15 +4395,15 @@ void SMPFunction::AnalyzeFunc(void) { } // end for (bool ChunkOK = ...) #if KLUDGE_VFPRINTF_FAMILY - if (!this->SharedChunks && (0 != strstr(this->GetFuncName(), "printf"))) { - this->SharedChunks = true; + if (!this->HasSharedChunks() && (0 != strstr(this->GetFuncName(), "printf"))) { + GetFuncInfo()->SetSharedChunks(true); SMP_msg("INFO: Kludging function %s\n", this->GetFuncName()); } #endif #if SMP_IDAPRO52_WORKAROUND - if (!this->SharedChunks && (0 == strcmp(this->GetFuncName(), "error_for_asm"))) { - this->SharedChunks = true; + if (!this->HasSharedChunks() && (0 == strcmp(this->GetFuncName(), "error_for_asm"))) { + GetFuncInfo()->SetSharedChunks(true); SMP_msg("Kludging function %s\n", this->GetFuncName()); } #endif @@ -9230,7 +9241,7 @@ void SMPFunction::MarkFunctionSafe() { // For mmStrata bounds checking of the stack frame, we don't care // about indirect writes unless they are to the stack. bool SpecUnsafe = (HasStackPointerCopy || HasStackPointerPush - || HasIndexedStackWrite || this->SharedChunks + || HasIndexedStackWrite || this->HasSharedChunks() || this->HasUnresolvedIndirectJumps()); bool Unsafe = SpecUnsafe || this->UnresolvedIndirectCalls; @@ -9307,7 +9318,7 @@ void SMPFunction::MarkFunctionSafe() { WritesAboveLocalFrame, AccessesReturnAddress, HasIndexedStackWrite, HasIndirectWrite); SMP_msg("AnalyzedSP: %d UnresolvedCalls: %d UnresolvedJumps: %d SharedChunks: %d IsLeaf: %d ", this->AnalyzedSP, this->UnresolvedIndirectCalls, this->HasUnresolvedIndirectJumps(), - this->SharedChunks, this->IsLeaf()); + this->HasSharedChunks(), this->IsLeaf()); SMP_msg("IndirCallTarget: %d TailCallTarget: %d HasNoCallers: %d MultiEntry: %d\n", this->PossibleIndirectCallTarget, this->PossibleTailCallTarget, HasNoCallers, this->MultipleEntryPoints); #endif diff --git a/src/interfaces/Makefile.in b/src/interfaces/Makefile.in index e1f803cf07a64b03a4440bf17ccbdd15e5878386..7ab75433c1617b62a6fe81ed926fcf3c899042dd 100644 --- a/src/interfaces/Makefile.in +++ b/src/interfaces/Makefile.in @@ -1,10 +1,10 @@ .SUFFIXES: -dirs=base interfaces +dirs=idapro all: .PHONY - for i in ${dirs}; do cd $$i; make; cd ..; done + for i in ${dirs}; do cd $$i; make; cd ..; done clean: .PHONY for i in ${dirs}; do cd $$i; make clean; cd ..; done diff --git a/src/interfaces/idapro/Makefile.in b/src/interfaces/idapro/Makefile.in index 946ee59479f12d4be3076c1e649907a1b0f93af8..d6aecaa9886f57218abeb4c88715adfd3800b0b6 100644 --- a/src/interfaces/idapro/Makefile.in +++ b/src/interfaces/idapro/Makefile.in @@ -1,19 +1,28 @@ -OBJS=SMPStaticAnalyzer.o SMPDataFlowAnalysis.o SMPInstr.o SMPBasicBlock.o \ - SMPFunction.o SMPProgram.o SMPDBInterface.o ProfilerInformation.o +OBJS=STARSFunction.o CXX=@CXX@ LD=@LD@ +EXTRA_CXXFLAGS=@EXTRA_CXXFLAGS@ +LIB=${SMPSA_HOME}/lib/libbase.a all: $(OBJS) -$(OBJS): $(INCLUDE)/base/*.h # *.cpp depends on *.h +# pull in dependency info for *existing* .o files +-include $(OBJS:.o=.d) -.cpp.o: - $(CXX) $(EXTRA_CXXFLAGS) -c $< - $(AR) -r $(LIB) $(OBJS) +%.o: %.cpp + $(CXX) -c $(EXTRA_CXXFLAGS) $*.cpp + $(AR) -r $(LIB) $*.o + @# + @# build dependencies -- http://scottmcpeak.com/autodepend/autodepend.html + @# + $(CXX) -MM $(EXTRA_CXXFLAGS) $*.cpp > $*.d + @cp -f $*.d $*.d.tmp + @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d + @rm -f $*.d.tmp clean: - rm -f $(OBJS) + rm -f $(OBJS) *.d .PHONY: @if [ "${IDAROOT}"X = "X" ]; then echo Please set IDAROOT; exit 1; fi diff --git a/src/interfaces/idapro/STARSFunction.cpp b/src/interfaces/idapro/STARSFunction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db9fb52a9f2b7d31694f0e493420bac0c50403da --- /dev/null +++ b/src/interfaces/idapro/STARSFunction.cpp @@ -0,0 +1,97 @@ + +#include "interfaces/SMPDBInterface.h" +#include "interfaces/abstract/all.h" +#include "interfaces/idapro/all.h" + + +static bool IsChunkUnshared(ea_t ChunkAddr, ea_t FuncHeadStart, ea_t FuncHeadEnd) +{ + bool Unshared = true; + SMP_xref_t CurrXrefs; + + // See if any xref reaches this ChunkAddr from outside the FuncHead range. + for (bool ok = CurrXrefs.SMP_first_to(ChunkAddr, XREF_ALL); ok; ok = CurrXrefs.SMP_next_to()) { + ea_t FromAddr = CurrXrefs.GetFrom(); + if ((FromAddr != 0) && (CurrXrefs.GetIscode())) { + // We found a code xref that comes to the ChunkAddr. Whether it is a fall-through or + // a jump/call, it is unshared only if it comes from within the FuncHead address range. + if ((FromAddr < FuncHeadStart) || (FromAddr >= FuncHeadEnd)) { + Unshared = false; + break; + } + } + } + + return Unshared; +} // end of SMPProgram::IsChunkUnshared() + + + +void STARS_IDA_Function_t::MarkSharedChunks() +{ + + char name[1000]; + ea_t FirstEA=this->get_startEA(); + ::get_func_name(FirstEA,name,sizeof(name)); + // Determine if we are dealing with shared chunks. + ea_t FuncHeadLastAddr = 0; + size_t ChunkCounter = 0; + //func_tail_iterator_t FuncTail((func_t*)*dynamic_cast<STARS_IDA_Function_t*>(this->GetFuncInfo())); + func_tail_iterator_t FuncTail(the_func);// (func_t*)*(dynamic_cast<STARS_IDA_Function_t*>(this->GetFuncInfo()))); + for (bool ChunkOK = FuncTail.main(); ChunkOK; ChunkOK = FuncTail.next()) + { + const area_t &CurrChunk = FuncTail.chunk(); + ++ChunkCounter; + if (1 == ChunkCounter) { // head chunk + FuncHeadLastAddr = CurrChunk.endEA; + } + else { // a tail chunk + if (IsChunkUnshared(CurrChunk.startEA, FirstEA, FuncHeadLastAddr)) + { +// this->UnsharedChunks = true; +// SMP_msg("INFO: Interface Found unshared tail chunk for %s at %lx\n", +// name, (unsigned long) CurrChunk.startEA); + } + else + { + this->SharedChunks = true; +// SMP_msg("INFO: Interface Found tail chunk for %s at %lx\n", +// name, (unsigned long) CurrChunk.startEA); + } + } + } + +} + +bool STARS_IDA_Function_t::IsMultiEntry() +{ + ea_t FirstEA=this->get_startEA(); + func_tail_iterator_t FuncTail(the_func);// (func_t*)*(dynamic_cast<STARS_IDA_Function_t*>(this->GetFuncInfo()))); + size_t CallTargetCount = 0; // how many addresses in this function are called? + + if (this->HasSharedChunks() || this->UnsharedChunks) { + for (bool ChunkOK = FuncTail.main(); ChunkOK; ChunkOK = FuncTail.next()) { + const area_t &CurrChunk = FuncTail.chunk(); + ea_t addr = CurrChunk.startEA; // Start with just the beginning addrs of chunks. + // Determine whether the instruction is a call target by looking + // at its cross references and seeing if it has "TO" code xrefs. + SMP_xref_t xrefs, Distant_xrefs; + for (bool ok = xrefs.SMP_first_to(addr, XREF_FAR); ok; ok = xrefs.SMP_next_to()) { + ea_t DistantAddr = xrefs.GetFrom(); + if ((DistantAddr != 0) && (xrefs.GetIscode())) { + // Now we see if the distant instruction is in another function. + STARS_Function_t *SourceFunc = SMP_get_func(DistantAddr); + if (NULL != SourceFunc) { + if (SourceFunc->get_startEA() != FirstEA) { + ++CallTargetCount; + break; + } + } + } + } // end for all xrefs + } // end for all chunks + } + + return CallTargetCount > 1; +} +