From 3c3244bd11743b49ca262caed70156ddba502bfc Mon Sep 17 00:00:00 2001 From: clc5q <clc5q@git.zephyr-software.com> Date: Tue, 5 May 2015 11:43:43 +0000 Subject: [PATCH] Move stack frame processing from SMPFunction to STARS_IDA_Function_t. Former-commit-id: bd0164d90ade36e7b03f75fc6f29525c35f7c924 --- include/base/SMPFunction.h | 14 +++- include/interfaces/SMPDBInterface.h | 14 +--- include/interfaces/abstract/STARSFunction.h | 19 +++-- include/interfaces/idapro/STARSFunction.h | 1 + src/base/SMPFunction.cpp | 92 ++++----------------- src/interfaces/idapro/STARSFunction.cpp | 71 ++++++++++++++++ src/interfaces/idapro/STARSIDAProgram.cpp | 4 +- 7 files changed, 114 insertions(+), 101 deletions(-) diff --git a/include/base/SMPFunction.h b/include/base/SMPFunction.h index 9c98acbd..719de1d9 100644 --- a/include/base/SMPFunction.h +++ b/include/base/SMPFunction.h @@ -53,6 +53,8 @@ class SMPProgram; // forward declaration so we can declare a pointer to an SMPProgram class STARS_IDA_Function_t; +#define SMP_DEBUG_STACK_GRANULARITY 0 + // What is the default change to the stack pointer for a function? // NOTE: When we start handling different calling conventions beyond // the gcc model, we will have to make this a variable that gets @@ -181,6 +183,7 @@ public: inline STARS_sval_t GetMaxDirectStackAccessDelta(void) const { return MaxDirectStackAccessDelta; }; inline STARS_ea_t GetFirstFrameAllocInstAddr(void) const { return LocalVarsAllocInstr; }; inline STARS_asize_t GetLocalVarsSize(void) const { return LocalVarsSize; }; + inline long GetLocalVarOffsetLimit(void) const { return LocalVarOffsetLimit; }; inline std::set<STARSOpndTypePtr, LessOp>::iterator GetFirstGlobalName(void) { return GlobalNames.begin(); }; inline std::set<STARSOpndTypePtr, LessOp>::iterator GetLastGlobalName(void) { return GlobalNames.end(); }; inline std::size_t NumGlobalNames(void) { return GlobalNames.size(); }; @@ -243,10 +246,13 @@ public: // Set methods void ResetJumpToFollowNodeCounter(STARS_ea_t InstAddr); // Set counter to zero, or insert zero counter if none found void IncrementJumpToFollowNodeCounter(STARS_ea_t InstAddr); // Increment counter, or insert count of 1 if none found - inline void IncTypedPhiDefs(void) { ++TypedPhiDefs; return; }; - inline void IncUntypedPhiDefs(void) { ++UntypedPhiDefs; return; }; - inline void DecTypedPhiDefs(void) { --TypedPhiDefs; return; }; - inline void DecUntypedPhiDefs(void) { --UntypedPhiDefs; return; }; + inline void IncTypedPhiDefs(void) { ++TypedPhiDefs; }; + inline void IncUntypedPhiDefs(void) { ++UntypedPhiDefs; }; + inline void DecTypedPhiDefs(void) { --TypedPhiDefs; }; + inline void DecUntypedPhiDefs(void) { --UntypedPhiDefs; }; + inline void SetIDAReturnAddressOffset(long NewOffset) { IDAReturnAddressOffset = NewOffset; }; + inline void SetLocalVarOffsetLimit(long NewLimit) { LocalVarOffsetLimit = NewLimit; }; + inline void PushBackLocalVarEntry(struct LocalVar TempLocal) { LocalVarTable.push_back(TempLocal); }; inline void SetReturnAddressStatus(FuncType funcType) { ReturnAddrStatus = funcType; } diff --git a/include/interfaces/SMPDBInterface.h b/include/interfaces/SMPDBInterface.h index dcbf46f8..d407879f 100644 --- a/include/interfaces/SMPDBInterface.h +++ b/include/interfaces/SMPDBInterface.h @@ -205,15 +205,15 @@ extern const char *CallTypeNames[4]; #ifdef STARS_IDA_INTERFACE -// #include <pro.h> // for qstr... functions +#include <pro.h> // for qstr... functions // #include <ua.hpp> // #include <fpro.h> // for qf... functions // #include <bytes.hpp> // for getFlags() -#include <frame.hpp> // for get_frame() +// #include <frame.hpp> // for get_frame() // #include <kernwin.hpp> // for msg() // #include <lines.hpp> // for tag_remove() -#include <name.hpp> // for get_true_name() -#include <struct.hpp> // for get_member_name() +// #include <name.hpp> // for get_true_name() +// #include <struct.hpp> // for get_member_name() #include <xref.hpp> // for add_cref(), xrefblk_t #include <interfaces/abstract/STARSInterface.h> @@ -224,12 +224,6 @@ extern const char *CallTypeNames[4]; // Globals, typedefs and macros for STARS_IDA_INTERFACE only -#if 0 -#define SMP_get_frame(ptr_to_func_t) get_frame((func_t*)(ptr_to_func_t)) -#else -#define SMP_get_frame(ptr_to_func_t) get_frame((func_t*)*dynamic_cast<STARS_IDA_Function_t*>(ptr_to_func_t)) -#endif -#define SMP_get_member_name(mid, buf, bufsize) get_member_name(mid, buf, bufsize) #define SMP_add_cref(from, to, type) add_cref(from, to, type) struct SMP_xref_t { diff --git a/include/interfaces/abstract/STARSFunction.h b/include/interfaces/abstract/STARSFunction.h index ad644785..f01c98dd 100644 --- a/include/interfaces/abstract/STARSFunction.h +++ b/include/interfaces/abstract/STARSFunction.h @@ -8,27 +8,28 @@ class SMPFunction; class STARS_Function_t { public: - virtual char* GetFunctionName(const char* name, const int len) const =0; - virtual STARS_ea_t get_startEA()=0; - virtual STARS_ea_t get_endEA()=0; + virtual char* GetFunctionName(const char* name, const int len) const =0; + virtual STARS_ea_t get_startEA()=0; + virtual STARS_ea_t get_endEA()=0; virtual std::size_t GetFrameSize()=0; virtual void SetFrameSize(std::size_t size) = 0; virtual std::size_t GetSavedRegSize() = 0; virtual std::size_t GetIncomingArgumentSize() = 0; virtual std::size_t GetFrameReturnAddressSize() = 0; - virtual bool FunctionUsesFP()=0; - virtual bool IsStaticFunction()=0; - virtual bool IsLibraryFunction()=0; - virtual bool IsStackPointerAnalyzed()=0; + virtual bool FunctionUsesFP()=0; + virtual bool IsStaticFunction()=0; + virtual bool IsLibraryFunction()=0; + virtual bool IsStackPointerAnalyzed()=0; virtual STARS_sval_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; - virtual void UpdateXrefs()=0; + virtual void UpdateXrefs()=0; virtual void BuildFuncIR(SMPFunction *func)=0; - virtual bool FindDistantCodeFragment(SMPFunction* func, STARS_ea_t TargetAddr)=0; + virtual bool FindDistantCodeFragment(SMPFunction* func, STARS_ea_t TargetAddr)=0; + virtual void FillInLocalVarTable(SMPFunction *CurrFunc) = 0; // get stack frame fine-grained info diff --git a/include/interfaces/idapro/STARSFunction.h b/include/interfaces/idapro/STARSFunction.h index 30c61766..1cfab61d 100644 --- a/include/interfaces/idapro/STARSFunction.h +++ b/include/interfaces/idapro/STARSFunction.h @@ -47,6 +47,7 @@ public: virtual void UpdateXrefs(); virtual void BuildFuncIR(SMPFunction *func); virtual bool FindDistantCodeFragment(SMPFunction* func, STARS_ea_t TargetAddr); + void FillInLocalVarTable(SMPFunction *CurrFunc); // get stack frame fine-grained info // temporary cast operator for testing operator func_t* () { return the_func; } diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp index 99493a7c..949129c6 100644 --- a/src/base/SMPFunction.cpp +++ b/src/base/SMPFunction.cpp @@ -79,7 +79,6 @@ using namespace std; #define SMP_DEBUG_DATAFLOW_VERBOSE 0 #define SMP_DEBUG_TYPE_INFERENCE 0 #define SMP_DEBUG_PROFILED_TYPE_INFERENCE 0 -#define SMP_DEBUG_STACK_GRANULARITY 0 #define SMP_DEBUG_FUNC 0 #define SMP_DEBUG_FUNC_SAFETY 1 #define SMP_VERBOSE_DEBUG_FUNC 0 @@ -235,7 +234,7 @@ SMPFunction::SMPFunction(STARS_Function_t *Info, SMPProgram* pgm) { this->PreAllocStackDelta = CALLING_CONVENTION_DEFAULT_PREFRAMEALLOC_STACK_DELTA; this->FramePointerStackDelta = 0; this->GlobalStackAdjustment = 0; - this->LocalVarOffsetLimit = 0; + this->SetLocalVarOffsetLimit(0); this->MaxDirectStackAccessDelta = 0; this->IDAReturnAddressOffset = 0; @@ -2523,9 +2522,6 @@ void SMPFunction::BuildLocalVarTable(void) { return; } // end of SMPFunction::BuildLocalVarTable() -// Limit damage from garbage stack offset values produced by IDA Pro. -#define IDAPRO_KLUDGE_STACK_FRAME_SIZE_LIMIT 5000000 - // Use the local variable offset list from IDA's stack frame structure to compute // the table of local variable boundaries. void SMPFunction::SemiNaiveLocalVarID(void) { @@ -2534,71 +2530,16 @@ void SMPFunction::SemiNaiveLocalVarID(void) { // read from the stack frame structure returned by get_frame() are consistent // with other IDA Pro values, not with our corrected values. list<SMPInstr *>::iterator InstIter; - bool DebugFlag = false; - bool FoundReturnAddress = false; - this->LocalVarOffsetLimit = -20000; -#if SMP_DEBUG_STACK_GRANULARITY - DebugFlag |= (0 == strcmp("qSort3", this->GetFuncName())); -#endif + this->SetLocalVarOffsetLimit(-20000); + STARS_Function_t *FuncPtr = SMP_get_func(this->FuncInfo->get_startEA()); if (NULL == FuncPtr) { - SMP_msg("ERROR in SMPFunction::SemiNaiveLocalVarID; no func ptr\n"); + SMP_msg("FATAL ERROR in SMPFunction::SemiNaiveLocalVarID; no func ptr\n"); } assert(NULL != FuncPtr); -#ifdef STARS_IDA_INTERFACE // Only get stack frame info from IDA Pro, not IRDB - - struc_t *StackFrame = SMP_get_frame(FuncPtr); - - if (NULL == StackFrame) { - SMP_msg("WARNING: No stack frame info from get_frame for %s\n", this->GetFuncName()); - return; - } - - member_t *Member = StackFrame->members; - for (std::size_t i = 0; i < StackFrame->memqty; ++i, ++Member) { - long offset; - char MemberName[MAXSMPVARSTR] = {'\0'}; - if (NULL == Member) { - SMP_msg("NULL stack frame member pointer in %s\n", this->GetFuncName()); - break; - } - SMP_get_member_name(Member->id, MemberName, MAXSMPVARSTR - 1); - if (MemberName == NULL) { -#if SMP_DEBUG_STACK_GRANULARITY - SMP_msg("NULL stack frame member in %s\n", this->GetFuncName()); -#endif - continue; - } - if (Member->unimem()) { - // Not a separate variable; name for member of a union. - // The union itself should have a separate entry, so we skip this. - SMP_msg("STACK INFO: Skipping union member %s frame member %zu in stack frame for %s\n", - MemberName, i, this->GetFuncName()); - continue; - } - offset = (long) Member->get_soff(); // Would be 0 for union member, so we skipped them above. - if (DebugFlag) { - SMP_msg("%s local var %s at offset %ld\n", this->GetFuncName(), MemberName, offset); - } - if (offset > IDAPRO_KLUDGE_STACK_FRAME_SIZE_LIMIT) { - SMP_msg("ERROR: Rejected enormous stack offset %ld for var %s in func %s\n", offset, MemberName, this->GetFuncName()); - continue; - } - if (!FoundReturnAddress && (2 == strlen(MemberName)) && (0 == strncmp(" r", MemberName, 2))) { - FoundReturnAddress = true; - this->IDAReturnAddressOffset = offset; - } - struct LocalVar TempLocal; - TempLocal.offset = offset; - TempLocal.size = Member->eoff - Member->soff; // audit later - SMP_strncpy(TempLocal.VarName, MemberName, sizeof(TempLocal.VarName) - 1); - this->LocalVarTable.push_back(TempLocal); - if ((offset + (long) TempLocal.size) >= this->LocalVarOffsetLimit) { - this->LocalVarOffsetLimit = (long) (TempLocal.offset + TempLocal.size); - } - } // end for all stack frame members -#endif // STARS_IDA_INTERFACE + // We only get stack frame info from IDA Pro, not IRDB + FuncPtr->FillInLocalVarTable(this); // If AnalyzedSP is false, that is all we can do. if (!this->AnalyzedSP) { @@ -2646,7 +2587,6 @@ void SMPFunction::SemiNaiveLocalVarID(void) { SMPInstr *CurrInst = (*InstIter); STARS_ea_t addr = CurrInst->GetAddr(); // Find the min and max stack offsets in DEFs and USEs. - STARSOpndTypePtr TempOp; if (CurrInst->HasDestMemoryOperand() || CurrInst->MDIsPushInstr() || CurrInst->MDIsEnterInstr()) { set<DefOrUse, LessDefUse>::iterator CurrDef; for (CurrDef = CurrInst->GetFirstDef(); CurrDef != CurrInst->GetLastDef(); ++CurrDef) { @@ -2777,8 +2717,8 @@ void SMPFunction::SemiNaiveLocalVarID(void) { this->LocalVarTable.back().size = this->FuncInfo->GetFrameSize() - SavedRegsSpace - this->LocalVarTable.back().offset; - this->LocalVarOffsetLimit = this->LocalVarTable.back().offset - + (adiff_t) this->LocalVarTable.back().size; + this->SetLocalVarOffsetLimit(this->LocalVarTable.back().offset + + (adiff_t) this->LocalVarTable.back().size); #endif } @@ -2786,14 +2726,14 @@ void SMPFunction::SemiNaiveLocalVarID(void) { // IDA Pro can have difficulty with some irregular functions such as are found // in the C startup code. The frsize value might be bogus. Just punt on the // local variable ID if that is the case. - if ((this->LocalVarOffsetLimit - AboveLocalsSize) > (adiff_t) this->FuncInfo->GetFrameSize()) { + if ((this->GetLocalVarOffsetLimit() - AboveLocalsSize) > (adiff_t) this->FuncInfo->GetFrameSize()) { this->LocalVarTable.clear(); this->GoodLocalVarTable = false; SMP_msg("WARNING: Bad frsize %d for %s OffsetLimit: %d AboveLocalsSize: %d LocalVarsSize: %d ; abandoning SemiNaiveLocalVarID.\n", - this->FuncInfo->GetFrameSize(), this->GetFuncName(), this->LocalVarOffsetLimit, AboveLocalsSize, this->LocalVarsSize); + this->FuncInfo->GetFrameSize(), this->GetFuncName(), this->GetLocalVarOffsetLimit(), AboveLocalsSize, this->LocalVarsSize); return; } - assert((this->LocalVarOffsetLimit - AboveLocalsSize) <= (adiff_t) this->FuncInfo->GetFrameSize()); + assert((this->GetLocalVarOffsetLimit() - AboveLocalsSize) <= (adiff_t) this->FuncInfo->GetFrameSize()); #endif // Find out how many of the locals are really outgoing args. @@ -2890,7 +2830,7 @@ bool SMPFunction::AuditLocalVarTable(void) { SMP_strncat(TempLocal.VarName, TempStr, sizeof(TempLocal.VarName) - 1); this->LocalVarTable.push_back(TempLocal); } while (((long)TotalFillerSize) < LocalVarIncrement); - this->LocalVarOffsetLimit += LocalVarIncrement; + this->SetLocalVarOffsetLimit(this->GetLocalVarOffsetLimit() + LocalVarIncrement); /* wtf? changing ida info? * from clc -- no, not updating idapro, just caching a change in stars. @@ -2909,11 +2849,11 @@ bool SMPFunction::AuditLocalVarTable(void) { // instructions to find the MaxStackAccessLimit. If LocalVarOffsetLimit // is not big enough to reach from AllocPointDelta to MaxStackAccessLimit, // then add 4-byte incoming arg entries until it reaches. - while (this->LocalVarOffsetLimit < (long) this->MaxStackAccessLimit) { + while (this->GetLocalVarOffsetLimit() < (long) this->MaxStackAccessLimit) { // Extend LocalVarTable. struct LocalVar TempLocal; char TempStr[20]; - TempLocal.offset = this->LocalVarOffsetLimit; + TempLocal.offset = this->GetLocalVarOffsetLimit(); TempLocal.size = global_STARS_program->GetSTARS_ISA_Bytewidth(); if ((TempLocal.size + TempLocal.offset) > ((long) this->MaxStackAccessLimit)) { TempLocal.size = ((long) this->MaxStackAccessLimit) - TempLocal.offset; @@ -2922,7 +2862,7 @@ bool SMPFunction::AuditLocalVarTable(void) { (void) SMP_snprintf(TempStr, 18, "%ld", TempLocal.offset); SMP_strncat(TempLocal.VarName, TempStr, sizeof(TempLocal.VarName) - 1); this->LocalVarTable.push_back(TempLocal); - this->LocalVarOffsetLimit += TempLocal.size; + this->SetLocalVarOffsetLimit(this->GetLocalVarOffsetLimit() + TempLocal.size); } // Fill in the gaps with new variables as well. SHOULD WE? WHY? @@ -2987,7 +2927,7 @@ void SMPFunction::FindOutgoingArgsSize(void) { this->FineGrainedStackTable.push_back(TempFineGrained); } #if 0 - for (int i = 0; i < this->LocalVarOffsetLimit; ++i) { + for (int i = 0; i < this->GetLocalVarOffsetLimit(); ++i) { struct FineGrainedInfo TempFineGrained; TempFineGrained.SignMiscInfo = 0; TempFineGrained.SizeInfo = 0; diff --git a/src/interfaces/idapro/STARSFunction.cpp b/src/interfaces/idapro/STARSFunction.cpp index 4a3d73b0..37fef52d 100644 --- a/src/interfaces/idapro/STARSFunction.cpp +++ b/src/interfaces/idapro/STARSFunction.cpp @@ -16,6 +16,12 @@ using namespace std; #define SMP_isCode(flags) isCode(flags) #define SMP_get_item_end(addr) get_item_end(addr) #define SMP_getFlags(addr) getFlags(addr) +// #if 1 +#define SMP_get_frame(ptr_to_func_t) get_frame(ptr_to_func_t) +// #else +// #define SMP_get_frame(ptr_to_func_t) get_frame((func_t*)*dynamic_cast<STARS_IDA_Function_t*>(ptr_to_func_t)) +// #endif +#define SMP_get_member_name(mid, buf, bufsize) get_member_name(mid, buf, bufsize) // Used for binary search by function number in SMPStaticAnalyzer.cpp // to trigger debugging output and find which instruction in which @@ -592,3 +598,68 @@ bool STARS_IDA_Function_t::FindDistantCodeFragment(SMPFunction* func, STARS_ea_t } // end if (!AlreadyFound && TargetFunc) return PrivateFragment; } // end of STARSFunction::FindDistantCodeFragment() + +// Limit damage from garbage stack offset values produced by IDA Pro. +#define IDAPRO_KLUDGE_STACK_FRAME_SIZE_LIMIT 5000000 + +void STARS_IDA_Function_t::FillInLocalVarTable(SMPFunction *CurrFunc) { + bool DebugFlag = false; + bool FoundReturnAddress = false; +#if SMP_DEBUG_STACK_GRANULARITY + DebugFlag |= (0 == strcmp("qSort3", this->GetFuncName())); +#endif + + struc_t *StackFrame = SMP_get_frame(this->the_func); + + if (NULL == StackFrame) { + SMP_msg("WARNING: No stack frame info from get_frame for %s\n", CurrFunc->GetFuncName()); + CurrFunc->SetLocalVarOffsetLimit(0); + // return; + } + else { + member_t *Member = StackFrame->members; + for (std::size_t i = 0; i < StackFrame->memqty; ++i, ++Member) { + long offset; + char MemberName[MAXSMPVARSTR] = { '\0' }; + if (NULL == Member) { + SMP_msg("NULL stack frame member pointer in %s\n", CurrFunc->GetFuncName()); + break; + } + SMP_get_member_name(Member->id, MemberName, MAXSMPVARSTR - 1); + if (MemberName == NULL) { +#if SMP_DEBUG_STACK_GRANULARITY + SMP_msg("NULL stack frame member in %s\n", CurrFunc->GetFuncName()); +#endif + continue; + } + if (Member->unimem()) { + // Not a separate variable; name for member of a union. + // The union itself should have a separate entry, so we skip this. + SMP_msg("STACK INFO: Skipping union member %s frame member %zu in stack frame for %s\n", + MemberName, i, CurrFunc->GetFuncName()); + continue; + } + offset = (long) Member->get_soff(); // Would be 0 for union member, so we skipped them above. + if (DebugFlag) { + SMP_msg("%s local var %s at offset %ld\n", CurrFunc->GetFuncName(), MemberName, offset); + } + if (offset > IDAPRO_KLUDGE_STACK_FRAME_SIZE_LIMIT) { + SMP_msg("ERROR: Rejected enormous stack offset %ld for var %s in func %s\n", offset, MemberName, CurrFunc->GetFuncName()); + continue; + } + if (!FoundReturnAddress && (2 == strlen(MemberName)) && (0 == strncmp(" r", MemberName, 2))) { + FoundReturnAddress = true; + CurrFunc->SetIDAReturnAddressOffset(offset); + } + struct LocalVar TempLocal; + TempLocal.offset = offset; + TempLocal.size = Member->eoff - Member->soff; // audit later + SMP_strncpy(TempLocal.VarName, MemberName, sizeof(TempLocal.VarName) - 1); + CurrFunc->PushBackLocalVarEntry(TempLocal); + if ((offset + (long) TempLocal.size) >= CurrFunc->GetLocalVarOffsetLimit()) { + CurrFunc->SetLocalVarOffsetLimit((long)(TempLocal.offset + TempLocal.size)); + } + } // end for all stack frame members + } + return; +} // end of STARS_IDA_Function_t::FillInLocalVarTable() diff --git a/src/interfaces/idapro/STARSIDAProgram.cpp b/src/interfaces/idapro/STARSIDAProgram.cpp index 4cee6ebe..0f1866d5 100644 --- a/src/interfaces/idapro/STARSIDAProgram.cpp +++ b/src/interfaces/idapro/STARSIDAProgram.cpp @@ -429,7 +429,7 @@ void STARS_IDA_Program_t::ComputeGlobalFieldOffsets(struct GlobalVar &CurrGlobal return; } // end of STARS_IDA_Program_t::ComputeGlobalFieldOffsets() - -// No need for IRDB version, as all fine-grained info computed in ComputeGlobalFieldOffsets() will +// No need for IRDB version for fine-grained global static data, as all fine-grained info computed in ComputeGlobalFieldOffsets() will // be written to the annotations file, read by the IRDB builder process, and then read back in // the IRDB version of InitStaticDataTable(). + -- GitLab