/* * SMPProgram.h - <see below>. * * Copyright (c) 2000, 2001, 2010 - University of Virginia * * This file is part of the Memory Error Detection System (MEDS) infrastructure. * This file may be used and modified for non-commercial purposes as long as * all copyright, permission, and nonwarranty notices are preserved. * Redistribution is prohibited without prior written consent from the University * of Virginia. * * Please contact the authors for restrictions applying to commercial use. * * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Author: University of Virginia * e-mail: jwd@virginia.com * URL : http://www.cs.virginia.edu/ * * Additional copyrights 2010, 2011 by Zephyr Software LLC * e-mail: {clc,jwd}@zephyr-software.com * URL : http://www.zephyr-software.com/ * */ #ifndef SMPPROGRAM_H #define SMPPROGRAM_H 1 // SMPProgram.h // // This header defines the interfaces needed for analyzing whole programs. #include <string> #include <utility> #include <list> #include <vector> #include <map> #include <set> #include <cstddef> #include "SMPDBInterface.h" #include "SMPDataFlowAnalysis.h" #include "SMPInstr.h" #include "SMPBasicBlock.h" #include "SMPFunction.h" using namespace std; class ProfilerInformation; extern ea_t LowestGlobalVarAddress; extern ea_t HighestGlobalVarAddress; extern ea_t LowestCodeAddress; extern ea_t HighestCodeAddress; inline bool IsImmedGlobalAddress(ea_t ImmedValue) { return ((ImmedValue >= LowestGlobalVarAddress) && (ImmedValue <= HighestGlobalVarAddress)); } // NOTE: Change this when we do targets with data (other than switch tables) in code. // Call IsDataAddress() first to weed out data items in the code range. inline bool IsImmedCodeAddress(ea_t ImmedValue) { return ((ImmedValue >= LowestCodeAddress) && (ImmedValue <= HighestCodeAddress)); } #if 0 // Is the address in a data segment? // NOTE: If we do targets with interleaved code and data, we must change the implementation. bool IsDataAddress(ea_t Address); #endif inline bool IsImmedNumeric(ea_t ImmedValue) { return (!(IsImmedGlobalAddress(ImmedValue) || IsImmedCodeAddress(ImmedValue))); } class LessOff { public: bool operator()(const pair<size_t, bool> &Off1, const pair<size_t, bool> &Off2) const { return (Off1.first < Off2.first); } // end operator }; // end class LessOff struct GlobalVar { ea_t addr; size_t size; char name[MAXSMPGLOBALVARSTR]; bool ReadOnly; // came from read-only data segment type bool IndexedAccess; flags_t flags; set<pair<size_t, bool>, LessOff> FieldOffsets; // bool = accessed through index register by any instruction? }; class LtStr { public: bool operator() (const char* c1, const char* c2) const { return strcmp(c1, c2) < 0; } }; // Class encapsulating all that the SMP static analyzer cares to know // about a whole program. class SMPProgram { public: // Constructors SMPProgram(void); // Default constructor ~SMPProgram(void); // Destructor // Get methods inline map<string, ea_t>::iterator FindGlobalName(string Name) { return GlobalNameMap.find(Name); } inline map<string, ea_t>::iterator GetLastGlobalName(void) { return GlobalNameMap.end(); } inline ProfilerInformation *GetProfInfo(void) { return ProfInfo; }; SMPFunction* FindFunction(ea_t FirstAddr); // get function from first addr in function inline size_t GetFuncCount(void) const { return FuncMap.size(); }; // Set methods void ProfGranularityFinished(FILE *AnnotFile, FILE *InfoAnnotFile); // notification from ProfilerInformation bool InsertUnsharedFragment(ea_t TargetAddr); // Add code fragment starting address to set; return false if already in set, true otherwise bool InsertDataToCodeXref(ea_t TargetAddr); // Data xref to code TargetAddr has been found; record it void AddUnreachableBlock(SMPBasicBlock *DeadBlock); // Add unreachable block and its instructions to containers void SetProgramThrowsExceptions(void); // Record detection of __cxa_throw in the binary void AddBlockToRemovalList(SMPBasicBlock *UnreachableBlock); // Add block, e.g. with "call 0" instruction, to later removal list. // Query methods bool IsUnsharedFragment(ea_t InstAddr); // Does InstAddr begin an unshared function fragment? bool IsCodeXrefFromData(ea_t InstAddr) const; // Does InstAddr have a data xref to it? inline bool ProgramThrowsExceptions(void) const { return ThrowsExceptions; }; // Printing methods void Dump(void); // debug dump // Analysis methods void AnalyzeData(void); // Analyze static data in the program. void Analyze(ProfilerInformation* pi, FILE *AnnotFile, FILE *InfoAnnotFile); // Analyze all functions in the program void EmitDataAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile); // Emit annotations for global data void EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile); // Emit annotations for all functions bool IsInstAddrStillInFunction(ea_t InstAddr, ea_t &FirstAddrInFunc); // is InstAddr still an SMPInstr inside an SMPFunction object? (not orphaned, not dead-code-removed) bool IsChunkUnshared(ea_t ChunkAddr, ea_t FuncHeadStart, ea_t FuncHeadEnd); // Does chunk at ChunkAddr belong exclusively to FuncHead? // If so, return true and add ChunkAddr to ProcessedFragments set. private: // Data bool ProfilerGranularityComplete; // Profiler-based granularity inference complete bool ThrowsExceptions; // Program throws exceptions in at least one location ProfilerInformation *ProfInfo; FILE *AnnotationFile; // need to store temporarily to pass to EmitDataAnnotations FILE *InfoAnnotationFile; // need to store temporarily to pass to EmitDataAnnotations map<ea_t, SMPFunction *> FuncMap; // all functions in the program indexed by starting address map<ea_t, SMPFunction *> TempFuncMap; // Copy of FuncMap that can be reduced as entries are processed list<SMPFunction *> PrioritizedFuncList; // Functions in bottom-up call-graph analysis order map<ea_t, struct GlobalVar> GlobalVarTable; // all global static variables map<string, ea_t> GlobalNameMap; // map global name to address list<pair<ea_t, SMPFunction *> > FuncList; // FuncMap entries prioritized in desired order for analysis set<ea_t> UnsharedFragments; // Code fragments incorporated into their callers; remove from FuncMaps set<ea_t> DataToCodeXrefTargets; // Code targets of data xrefs; probably will be called indirectly map<ea_t, SMPBasicBlock *> UnreachableInstBlockMap; // unreachable instructions, removed from their functions, mapped to blocks vector<SMPBasicBlock *> UnreachableBlocks; // unreachable blocks, removed from their functions list<SMPInstr *> UnreachableInstList; // unreachable instructions, removed from their functions list<SMPBasicBlock *> BlocksPendingRemoval; // blocks that need to be removed later as unreachable set<SMPFunction *> FuncsWithBlocksRemoved; // Methods void InitStaticDataTable(void); // Gather info about global static data locations void ComputeGlobalFieldOffsets(struct GlobalVar &CurrGlobal); FuncType RecurseAndMarkRetAdd(SMPFunction *); void ProcessExceptionHandlingFileSections(void); // If exception throwing code is detected, mark exception-handling functions as unsafe for fast returns. void ResetFuncsProcessed(void); // set all funcs to not processed before a whole program analysis void PrioritizeCallGraph(void); // Extract TempFuncMap entries into FuncList in a good order for whole program analyses. void ProcessBlocksPendingRemoval(void); // Remove unreachable blocks in BlocksPendingRemoval, handle calls to empty functions that result. }; // end class SMPProgram #endif