From a7a94176f49c6ef437abc812dc918f8aa948b8e1 Mon Sep 17 00:00:00 2001 From: clc5q <clc5q@git.zephyr-software.com> Date: Thu, 24 Sep 2015 15:19:46 +0000 Subject: [PATCH] Continue SPARK Ada translation improvements at package and procedure level. Former-commit-id: 2735035e70eea9a8cedc0dfc0ee4f332035e16e9 --- include/base/SMPDataFlowAnalysis.h | 3 ++ include/base/SMPFunction.h | 1 + include/base/SMPProgram.h | 4 +++ src/base/SMPDataFlowAnalysis.cpp | 36 ++++++++++++++++++++++++ src/base/SMPFunction.cpp | 26 +++++++++++++++-- src/base/SMPProgram.cpp | 33 +++++++++++++++++++++- src/drivers/idapro/SMPStaticAnalyzer.cpp | 2 +- 7 files changed, 101 insertions(+), 4 deletions(-) diff --git a/include/base/SMPDataFlowAnalysis.h b/include/base/SMPDataFlowAnalysis.h index da891dd1..001ecefe 100644 --- a/include/base/SMPDataFlowAnalysis.h +++ b/include/base/SMPDataFlowAnalysis.h @@ -973,4 +973,7 @@ void GetPointerArgPositionsForCallName(std::string CalleeName, unsigned int &Arg // Utility to count bits set in an unsigned int, e.g. ArgPosBits. unsigned int CountBitsSet(unsigned int ArgPosBits); +// Is FuncName a standard library function name? +bool IsLibFuncName(std::string CalleeName); + #endif diff --git a/include/base/SMPFunction.h b/include/base/SMPFunction.h index 1c48d026..c359f5ad 100644 --- a/include/base/SMPFunction.h +++ b/include/base/SMPFunction.h @@ -378,6 +378,7 @@ public: bool FindReachingStackDelta(STARS_sval_t &StackDelta); // Find maximum stack delta in TempStackDeltaReachesList; return true if one consistent delta is in the list void GatherIncomingArgTypes(void); // Use the SSA marker inst to record incoming arg types in member InArgTypes. void EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile); + void PreProcessForSPARKAdaTranslation(void); // Perform look-ahead steps needed before translation to SPARK Ada. void EmitFuncSPARKAda(void); // Emit SPARK Ada translation of function void LiveVariableAnalysis(bool Recomputing); // Perform Live Variable Analysis across all blocks void RecomputeSSA(void); // Recompute LVA and SSA and all dependent data structures now that unreachable blocks have been removed. diff --git a/include/base/SMPProgram.h b/include/base/SMPProgram.h index fbece3c4..a2feacf3 100644 --- a/include/base/SMPProgram.h +++ b/include/base/SMPProgram.h @@ -119,6 +119,8 @@ public: inline ProfilerInformation *GetProfInfo(void) { return ProfInfo; }; SMPFunction* FindFunction(STARS_ea_t FirstAddr); // get function from first addr in function inline std::size_t GetFuncCount(void) const { return FuncMap.size(); }; + inline std::set<std::string>::iterator GetFirstLibraryFuncName(void) { return LibraryCallTargetNames.begin(); }; + inline std::set<std::string>::iterator GetLastLibraryFuncName(void) { return LibraryCallTargetNames.end(); }; // Set methods void ProfGranularityFinished(FILE *AnnotFile, FILE *InfoAnnotFile); // notification from ProfilerInformation @@ -129,6 +131,7 @@ public: void AddBlockToRemovalList(SMPBasicBlock *UnreachableBlock); // Add block, e.g. with "call 0" instruction, to later removal list. std::pair<std::map<std::string, STARS_ea_t>::iterator, bool> InsertGlobalNameAddrMapEntry(std::pair<std::string, STARS_ea_t> TempPair) { return GlobalNameMap.insert(TempPair); }; void InsertGlobalVarTableEntry(std::pair<STARS_ea_t, struct GlobalVar> VarItem) { GlobalVarTable.insert(VarItem); }; + inline std::pair<std::set<std::string>::iterator, bool> InsertLibraryFuncName(std::string FuncName) { return LibraryCallTargetNames.insert(FuncName); }; // Query methods bool IsUnsharedFragment(STARS_ea_t InstAddr); // Does InstAddr begin an unshared function fragment? @@ -169,6 +172,7 @@ private: std::list<SMPInstr *> UnreachableInstList; // unreachable instructions, removed from their functions std::list<SMPBasicBlock *> BlocksPendingRemoval; // blocks that need to be removed later as unreachable std::set<SMPFunction *> FuncsWithBlocksRemoved; + std::set<std::string> LibraryCallTargetNames; // Standard library functions called by program; used in SPARK Ada translation // Methods void InitStaticDataTable(void); // Gather info about global static data locations diff --git a/src/base/SMPDataFlowAnalysis.cpp b/src/base/SMPDataFlowAnalysis.cpp index cfc7dc75..7f913ed0 100644 --- a/src/base/SMPDataFlowAnalysis.cpp +++ b/src/base/SMPDataFlowAnalysis.cpp @@ -4189,3 +4189,39 @@ void GetLibFuncFGInfo(string FuncName, struct FineGrainedInfo &InitFGInfo) { } // end of GetLibFuncFGInfo() +// Is FuncName a standard library function name? +bool IsLibFuncName(std::string CalleeName) { + // Return true if we find the name in any of our function type maps. + + map<string, struct FineGrainedInfo>::iterator RetTypeIter = ReturnRegisterTypeMap.find(CalleeName); + if (RetTypeIter != ReturnRegisterTypeMap.end()) { // found + return true; + } + + map<string, unsigned int>::iterator PtrArgIter = PointerArgPositionMap.find(CalleeName); + if (PtrArgIter != PointerArgPositionMap.end()) { // found it + return true; + } + + map<string, unsigned int>::iterator TaintIter = TaintWarningArgPositionMap.find(CalleeName); + if (TaintIter != TaintWarningArgPositionMap.end()) { // found it + return true; + } + + map<string, unsigned int>::iterator UnsignedIter = UnsignedArgPositionMap.find(CalleeName); + if (UnsignedIter != UnsignedArgPositionMap.end()) { // found it + return true; + } + + map<string, string>::iterator SinkIter = IntegerErrorCallSinkMap.find(CalleeName); + if (SinkIter != IntegerErrorCallSinkMap.end()) { // found it + return true; + } + + // Put searches for additional library function names here. + if (0 == CalleeName.compare("setuid")) { + return true; + } + + return false; +} // end of IsLibFuncName() diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp index 6a21dadf..ea5a97ef 100644 --- a/src/base/SMPFunction.cpp +++ b/src/base/SMPFunction.cpp @@ -8677,6 +8677,26 @@ void SMPFunction::MarkFunctionSafe() { return; } // end of SMPFunction::MarkFunctionSafe() +// Perform look-ahead steps needed before translation to SPARK Ada. +void SMPFunction::PreProcessForSPARKAdaTranslation(void) { + for (vector<SMPBasicBlock *>::iterator BlockIter = this->RPOBlocks.begin(); BlockIter != this->RPOBlocks.end(); ++BlockIter) { + SMPBasicBlock *CurrBlock = (*BlockIter); + if (CurrBlock->HasCallInstruction()) { + for (vector<SMPInstr *>::iterator InstIter = CurrBlock->GetFirstInst(); InstIter != CurrBlock->GetLastInst(); ++InstIter) { + SMPInstr *CurrInst = (*InstIter); + if (CurrInst->GetDataFlowType() == CALL) { + string CalledFuncName = CurrInst->GetTrimmedCalledFunctionName(); + if (IsLibFuncName(CalledFuncName)) { + pair<set<string>::iterator, bool> InsertResult = this->Program->InsertLibraryFuncName(CalledFuncName); + } + } + } + } + } + + return; +} // end of SMPFunction::PreProcessForSPARKAdaTranslation() + // For debugging purposes, only emit SPARK Ada for main(). #define STARS_EMIT_ADA_FOR_MAIN_ONLY 1 @@ -8685,6 +8705,7 @@ void SMPFunction::EmitFuncSPARKAda(void) { if (this->IsLinkerStub()) { return; } + string AdaFuncName(this->GetFuncName()); #if STARS_EMIT_ADA_FOR_MAIN_ONLY if (0 != strcmp("main", AdaFuncName.c_str())) { @@ -8701,9 +8722,10 @@ void SMPFunction::EmitFuncSPARKAda(void) { // Emit beginning of function body. SMP_fprintf(BodyFile, "procedure %s\nis\n", AdaFuncName.c_str()); - SMP_fprintf(BodyFile, "\tra0 : Unsigned8 := X86.ReadMem8(X86.RSP);\n"); + SMP_fprintf(BodyFile, "\tSaveStackPtr : Unsigned64 := X86.RSP with Ghost;\n"); + SMP_fprintf(BodyFile, "\tra0 : Unsigned8 := X86.ReadMem8(X86.RSP) with Ghost;\n"); for (unsigned short i = 1; i < ByteWidth; ++i) { - SMP_fprintf(BodyFile, "\tra%u : Unsigned8 := X86.ReadMem8(X86.RSP + %u);\n", i, i); + SMP_fprintf(BodyFile, "\tra%u : Unsigned8 := X86.ReadMem8(X86.RSP + %u) with Ghost;\n", i, i); } SMP_fprintf(BodyFile, "\nbegin\n"); diff --git a/src/base/SMPProgram.cpp b/src/base/SMPProgram.cpp index b343346a..4074c361 100644 --- a/src/base/SMPProgram.cpp +++ b/src/base/SMPProgram.cpp @@ -788,6 +788,7 @@ bool SMPProgram::EmitProgramSPARKAda(void) { FILE *BodyFile = global_STARS_program->GetSPARKSourceFile(); // SPARK Ada *.adb implementation FILE *SpecFile = global_STARS_program->GetSPARKHeaderFile(); // SPARK Ada *.ads specification string RootName(global_STARS_program->GetRootFileName()); // original file name without path, e.g. foo.exe + size_t ByteWidth = global_STARS_program->GetSTARS_ISA_Bytewidth(); // Extract "foo" from "foo.exe" to get the Ada package name string PackageName; @@ -815,8 +816,38 @@ bool SMPProgram::EmitProgramSPARKAda(void) { SMP_fprintf(SpecFile, "\tsubtype Unsigned16 is X86.Unsigned16;\n"); SMP_fprintf(SpecFile, "\tsubtype Unsigned8 is X86.Unsigned8;\n\n"); - // Loop through all functions and emit annotations for each. + // Loop through all functions and perform look-ahead pre-processing needed for later annotation emission. map<STARS_ea_t, SMPFunction *>::iterator FuncIter; + for (FuncIter = this->FuncMap.begin(); FuncIter != this->FuncMap.end(); ++FuncIter) { + SMPFunction *TempFunc = FuncIter->second; + if (TempFunc == NULL) continue; + if (TempFunc->HasReducibleControlFlow()) { + TempFunc->PreProcessForSPARKAdaTranslation(); + } + } // end for all functions + + // Emit procedure specifications and bodies for library functions + for (set<string>::iterator NameIter = this->LibraryCallTargetNames.begin(); NameIter != this->LibraryCallTargetNames.end(); ++NameIter) { + string LibFuncName = (*NameIter); + SMP_fprintf(SpecFile, "procedure %s with\n", LibFuncName.c_str()); + SMP_fprintf(BodyFile, "procedure %s is\nbegin\n\tX86.RSP := X86.RSP + %u;\n", LibFuncName.c_str(), ByteWidth); + if (0 != LibFuncName.compare("setuid")) { + // Emit minimal stub + SMP_fprintf(SpecFile, "\tGlobal => (In_Out => X86.RSP),\n"); + SMP_fprintf(SpecFile, "\tPost => (X86.RSP = X86.RSP'Old + 8);\n\n"); + } + else { // emit setuid stub + SMP_fprintf(SpecFile, "\tGlobal => (Input => (X86.RDI),\n"); + SMP_fprintf(SpecFile, "\t\tIn_Out => (Dummy_Var, X86.RSP)),\n"); + SMP_fprintf(SpecFile, "\tPre => (X86.RDI /= 0),\n"); + SMP_fprintf(SpecFile, "\tPost => ((Dummy_Var = Dummy_Var'Old + Unsigned64(X86.EDI)) and\n"); + SMP_fprintf(SpecFile, "\t\t(X86.RSP = X86.RSP'Old + 8));\n\n"); + SMP_fprintf(BodyFile, "\tDummy_Var := Dummy_Var + Unsigned64(X86.EDI);\n"); + } + SMP_fprintf(BodyFile, "end %s;\n\n", LibFuncName.c_str()); + } + + // Loop through all functions and emit annotations for each. for (FuncIter = this->FuncMap.begin(); FuncIter != this->FuncMap.end(); ++FuncIter) { SMPFunction *TempFunc = FuncIter->second; if (TempFunc == NULL) continue; diff --git a/src/drivers/idapro/SMPStaticAnalyzer.cpp b/src/drivers/idapro/SMPStaticAnalyzer.cpp index 6e3bf2ff..a8c55b1c 100644 --- a/src/drivers/idapro/SMPStaticAnalyzer.cpp +++ b/src/drivers/idapro/SMPStaticAnalyzer.cpp @@ -62,7 +62,7 @@ using namespace std; -#define SMP_DEBUG_DELAY 1 // for setting an early breakpoint +#define SMP_DEBUG_DELAY 0 // for setting an early breakpoint // Set to 1 for debugging output #define SMP_DEBUG 1 -- GitLab