Newer
Older
/*
* SMPFunction.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, 2012, 2013, 2014, 2015 by Zephyr Software LLC
* e-mail: {clc,jwd}@zephyr-software.com
* URL : http://www.zephyr-software.com/
*
#ifndef SMPFUNCTION_H
#define SMPFUNCTION_H 1
// SMPFunction.h
//
// This header defines the interfaces needed for analyzing functions, performing live variable analysis,
// putting code into SSA form, etc.
#include <utility>
#include <list>
#include <vector>
#include <map>
#include <set>
#include <cstddef>
#include <stdio.h>
class SMPProgram; // forward declaration so we can declare a pointer to an SMPProgram
class STARS_IDA_Function_t;
class STARS_IRDB_Function_t;
#include "interfaces/STARSTypes.h"
#include "interfaces/SMPDBInterface.h"
clc5q
committed
#include "base/SMPDataFlowAnalysis.h"
#include "base/SMPInstr.h"
#include "base/SMPBasicBlock.h"
#include "base/ProfilerInformation.h"
#define SMP_DEBUG_STACK_GRANULARITY 0
clc5q
committed
// 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
// initialized.
#define CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA global_STARS_program->GetSTARS_ISA_Bytewidth()
clc5q
committed
// What is the default stack delta from function entry to stack frame allocation?
// This would only be used in resolving phase-ordering problems, and should be
// eliminated if possible.
#define CALLING_CONVENTION_DEFAULT_PREFRAMEALLOC_STACK_DELTA (-(global_STARS_program->GetSTARS_ISA_Bytewidth()))
clc5q
committed
// What default value should we assign to alloca stack frame allocations?
#define STARS_DEFAULT_ALLOCA_SIZE -32
// Use IDA info for switch tables to link indirect jumps to successor blocks?
#define SMP_USE_SWITCH_TABLE_INFO 1
// Detect function code fragments that are not shared with another function.
#define STARS_FIND_UNSHARED_CHUNKS 1
// Find and fix missing IDA Pro code xrefs.
#define STARS_AUDIT_JUMP_XREFS 0
#define STARS_AUDIT_INDIR_JUMP_XREFS 1
// We can decide if conservative analysis of memory writes will cause us to avoid fast returns,
// or merely shadow the return address.
clc5q
committed
#define STARS_CONSERVATIVE_FAST_RETURNS 0
// Emit CS: or FS: or GS: etc. segment reg prefix if found in operand
#define STARS_SPARK_EMIT_SEGMENT_REGS 0
struct LocalVar {
long offset;
std::size_t size;
// Comparison function for sorting.
bool LocalVarCompare(const LocalVar &LV1, const LocalVar &LV2);
enum StackAccessType {
STARS_STACK_UNKNOWN = 0,
STARS_STACK_INARG = 1,
STARS_STACK_RETURN_ADDRESS = 2,
STARS_STACK_CALLEE_SAVED_REG = 3,
STARS_STACK_LOCAL_FRAME = 4,
STARS_STACK_OUTARG = 5 // could be part of LOCAL_FRAME initially, then changed when we detect usage as OUTARG
};
// Entry for each byte address in the stack frame
struct StackFrameEntry {
struct LocalVar *VarPtr; // LocalVar that includes this offset
long offset; // offset relative to incoming stack pointer
bool Read; // was this entry ever read by an instruction?
bool Written; // was this entry ever written by an instruction?
bool AddressTaken; // did this entry have its address taken?
bool ESPRelativeAccess; // ever accessed by ESP+const?
bool EBPRelativeAccess; // ever accessed by EBP-const? (only if UseFP)
bool IndexedAccess; // index reg of unknown value added to the base address
StackAccessType EntryType; // inference based on location and accessing instructions
enum FuncType {
FUNC_UNKNOWN = 0,
FUNC_SAFE = 1,
FUNC_UNSAFE = 2,
FUNC_SAFE_IF_CALLEES_ARE_SAFE = 3
enum UnsafeFastReturnReason {
SAFE_FAST_RETURN = 0,
UNSAFE_RETURN_ADDRESS = 1,
RETURN_ADDRESS_WRITE = 2,
RETURN_ADDRESS_READ = 4,
INDIRECTLY_CALLED = 8,
NO_CALLERS = 16,
TAIL_CALL_TARGET = 32,
MAKES_TAIL_CALL = 128,
MULTIPLE_ENTRY_POINTS = 256,
UNRESOLVED_INDIR_JUMP = 512,
EH_FRAME_ENTRY = 1024
};
// For queries about the type of sink that a DEF eventually flows into.
enum SinkSearchType {
STARS_SINK_NONE = 0,
STARS_SINK_MEMWRITE = 1,
STARS_SINK_LOOP_CONDITION = 2,
STARS_SINK_CALL = 4,
STARS_SINK_RETURN = 8
};
// SPARK Ada recursive descent translation stack type; what we are currently translating
// is on top.
enum SPARKTranslationCFType {
SPARK_INITIAL_BLOCK = 0,
SPARK_THEN_CLAUSE = 1,
SPARK_ELSE_CLAUSE = 2,
SPARK_SWITCH = 3,
SPARK_LOOP = 4
// Loop types for structuring and decompilation
#define STARS_LOOP_TYPE_UNKNOWN 0
#define STARS_TOP_TESTING_LOOP 1
#define STARS_BOTTOM_TESTING_LOOP 2
#define STARS_INFINITE_OR_MIDDLE_TESTING_LOOP 3
#define STARS_CONSTANT_ITERATIONS_TOP_TESTING_LOOP 4
// A struct used to describe the comparison used to exit a loop or loop back.
// For loops that could not be analyzed, CompareOperator is SMP_NULL_OPERATOR.
struct LoopComparison {
DefOrUse Operand1;
DefOrUse Operand2;
STARS_ea_t CompareAddr; // could be address of a decrement inst, for the decrement+COND_BRANCH type of loop
SMPoperator CompareOperator;
bool ExitsLoop; // comparison could be used to loop back, in which case invert to exit loop.
};
// A struct to describe the triple (Multiplier * BasicInductionVar + Addend) that can be
// used to define any induction variable. The basic induction variable of a family can
// be represented with a Multiplier of one and an Addend of zero.
struct InductionVarTriple {
DefOrUse InductionVar;
DefOrUse Multiplier;
DefOrUse Addend;
bool SubtractAddend; // Multiplier * BasicInductionVar - Addend
};
// Are the operands, SSA numbers, and SubtractAddend fields identical?
bool EqualInductionVars(const InductionVarTriple &IV1, const InductionVarTriple &IV2);
// Dependent induction variable: At DIVDefAddr, DIV is defined by an operation IVExpr performed upon an earlier IV in the family.
struct DependentInductionVar {
struct InductionVarTriple IVExpr;
DefOrUse DIV;
STARS_ea_t DIVDefAddr;
Clark Coleman
committed
STARSExpression *DIVInitExpr;
STARSExpression *DIVLimitExpr;
// An induction variable family is composed of a basic induction variable and
// zero or more dependent induction variables, where each dependent induction
// variable can be represented as a linear function m*i+a of the basic induction variable i.
typedef std::vector<struct DependentInductionVar> STARSDepIndVarVector;
Clark Coleman
committed
typedef STARSDepIndVarVector::iterator STARSDepIndVarIter;
struct InductionVarFamily {
clc5q
committed
int BIVIncomingSSANum; // SSA number coming into the loop for BasicInductionVar
STARS_ea_t BIVIncomingDefAddr;
std::vector<STARS_ea_t> BIVInsideLoopDefAddrs;
struct InductionVarTriple BasicInductionVar;
clc5q
committed
STARSDepIndVarVector DependentInductionVars;
Clark Coleman
committed
STARSExpression *BIVInitExpr;
STARSExpression *BIVLimitExpr;
};
clc5q
committed
// We can have multiple basic induction vars for one loop, hence multiple families in a list.
typedef std::list<struct InductionVarFamily> STARSInductionVarFamilyList;
Clark Coleman
committed
typedef STARSInductionVarFamilyList::iterator STARSInductionVarFamilyIter;
clc5q
committed
// triple: memory write expr, ByteWidth, index into vector of stack pointer copy InstAddrs
typedef std::list<std::pair<STARSExprSetIter, std::pair<std::size_t, int> > > STARSMemWriteExprsList;
typedef STARSMemWriteExprsList::iterator STARSMemWriteExprListIter;
// Debug dump of induction variable.
void DumpInductionVar(const struct InductionVarTriple IndVar);
// Debug dump of InductionVarFamily.
void DumpInductionVarFamily(const struct InductionVarFamily IVFamily);
// Determine whether we have an incrementing or decrementing loop based on
// the BasicInductionVar.
bool IsPositiveIncrementBIV(const struct InductionVarTriple BIV);
// Class encapsulating all that the SMP static analyzer cares to know
// about a function.
class SMPFunction {
public:
// Constructors and destructors.
SMPFunction(STARS_Function_t *Info, SMPProgram *pgm); // Default constructor
clc5q
committed
inline SMPProgram *GetProg(void) const { return Program; };
inline const char *GetFuncName(void) const
{
SMP_get_func_name(GetFirstFuncAddr(), StaticFuncName, MAXSMPSTR-1);
return StaticFuncName;
};
inline STARS_ea_t GetFirstFuncAddr(void) const { return FirstEA; };
uint16_t GetJumpToFollowNodeCounter(STARS_ea_t InstAddr) const;
inline long GetTypedDefs(void) const { return TypedDefs; };
inline long GetUntypedDefs(void) const { return UntypedDefs; };
clc5q
committed
inline long GetTypedPhiDefs(void) const { return TypedPhiDefs; };
inline long GetUntypedPhiDefs(void) const { return UntypedPhiDefs; };
inline long GetSafeBlocks(void) const { return SafeBlocks; };
inline long GetUnsafeBlocks(void) const { return UnsafeBlocks; };
inline std::size_t GetInstCount(void) const { return Instrs.size(); };
inline unsigned short GetIncomingArgCount(void) const { return InArgCount; };
inline STARS_sval_t GetNetStackPtrDelta(void) const { return NetStackDelta; };
inline STARS_sval_t GetPreAllocationStackPtrDelta(void) const { return PreAllocStackDelta; };
inline STARS_sval_t GetFramePtrStackDelta(void) const { return FramePointerStackDelta; };
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; };
Clark Coleman
committed
inline STARSOpndSetIter GetFirstGlobalName(void) { return GlobalNames.begin(); };
inline STARSOpndSetIter GetLastGlobalName(void) { return GlobalNames.end(); };
inline std::size_t NumGlobalNames(void) { return GlobalNames.size(); };
Clark Coleman
committed
inline STARSOpndSetIter FindGlobalName(const STARSOpndTypePtr &SearchOp) { return GlobalNames.find(SearchOp); };
inline std::list<SMPInstr *>::iterator GetFirstInstIter(void) { return Instrs.begin(); };
inline std::list<SMPInstr *>::iterator GetLastInstIter(void) { return Instrs.end(); };
Clark Coleman
committed
STARSOpndSetIter GetFirstLiveIn(void); // LiveInSet.begin()
STARSOpndSetIter GetLastLiveIn(void); // LiveInSet.end()
STARSOpndSetIter GetFirstLiveOut(void); // LiveOutSet.begin()
STARSOpndSetIter GetLastLiveOut(void); // LiveOutSet.end()
STARSOpndSetIter GetFirstVarKill(void); // KillSet.begin()
STARSOpndSetIter GetLastVarKill(void); // KillSet.end()
inline FuncType GetReturnAddressStatus(void) const { return ReturnAddrStatus; };
inline unsigned short GetFastReturnStatus(void) const { return FastReturnStatus; };
// exposing the start address of the function. Used in RecurseAndMark
clc5q
committed
inline const STARS_ea_t GetStartAddr(void) const { return FirstEA; };
inline const std::vector<STARS_ea_t> GetCallTargets(void) const { return AllCallTargets; };
inline const std::set<STARS_ea_t> GetReturnTargets(void) const { return ReturnTargets; };
inline std::size_t GetNumCallTargets(void) const { return AllCallTargets.size(); };
inline STARS_ea_t GetCallTargetAddr(std::size_t index) const { return AllCallTargets.at(index); };
bool GetIsSpeculative() { return IsSpeculative; }
inline std::size_t GetNumCallers(void) const { return AllCallSources.size(); };
bool MDGetFGStackLocInfo(STARS_ea_t InstAddr, const STARSOpndTypePtr &TempOp, struct FineGrainedInfo &FGEntry);
// Return fine grained stack entry for stack op TempOp from instruction at InstAddr
STARS_ea_t GetGlobalDefAddrForRegHash(int RegHashValue); // retrieve from GlobalDefAddrBySSA or return BADADDR
STARS_ea_t GetGlobalDefAddr(const STARSOpndTypePtr &DefOp, int SSANum); // retrieve from GlobalDefAddrBySSA or return BADADDR
std::vector<SMPInstr *>::iterator GetBlockInstIterBySSA(const STARSOpndTypePtr &DefOp, int SSANum); // return iterator within DEF block
int GetBlockNumForPhiDef(const STARSOpndTypePtr &DefOp, int SSANum);
SMPBasicBlock *GetBlockFromInstAddr(STARS_ea_t InstAddr); // retrieve from InstBlockMap or assert
int GetBlockNumFromInstAddr(STARS_ea_t InstAddr); // return -1 if not in InstBlockMap, block # otherwise
std::list<SMPBasicBlock *>::iterator GetBlockIter(SMPBasicBlock *FindBlock); // Find FindBlock in Blocks, return iterator.
inline SMPBasicBlock *GetBlockByNum(std::size_t BlockIndex) const { return RPOBlocks.at(BlockIndex); };
inline STARSCFGBlock *GetCFGBlockByNum(std::size_t BlockIndex) const { return ShadowCFGBlocks.at(BlockIndex); };
inline std::list<SMPBasicBlock *>::iterator GetLastBlock(void) { return Blocks.end(); };
SMPInstr *GetInstFromAddr(STARS_ea_t InstAddr);
STARS_ea_t GetFirstUnprocessedCallee(void); // first addr of first callee in AllCallTargets with Processed == false
inline std::size_t GetNumBlocks(void) const { return Blocks.size(); };
STARSOpndTypePtr GetNormalizedOperand(STARS_ea_t InstAddr, const STARSOpndTypePtr &RTLop); // Return RTLop if not stack opnd; return normalized RTLop otherwise.
inline int GetReturnRegType(STARS_regnum_t RegNum) const { return ((RegNum < (decltype(RegNum))ReturnRegTypes.size()) ? (int) ReturnRegTypes[RegNum] : 0); };
inline struct FineGrainedInfo GetReturnRegFGInfo(STARS_regnum_t RegNum) const { return ReturnRegFGInfo.at(RegNum); };
inline std::size_t GetReturnRegFGInfoSize(void) const { return ReturnRegFGInfo.size(); };
SMPOperandType GetIncomingRegType(STARS_regnum_t RegNum); // Get reg type from all call sites.
clc5q
committed
bool GetMarkerInstDefType(STARSOpndTypePtr &LiveInOp, SMPOperandType &MarkerDefType); // return true if LiveInOp found in MarkerInst DEFs
inline std::map<STARS_ea_t, STARSOpndTypePtr>::iterator FindLeaOperand(STARS_ea_t addr) { return LeaInstOpMap.find(addr); };
inline std::map<STARS_ea_t, STARSOpndTypePtr>::iterator GetLastLeaOperand(void) { return LeaInstOpMap.end(); };
clc5q
committed
inline STARSSCCPMapIter FindConstValue(int DefHashValue) { return ConstantDefs.find(DefHashValue); };
inline STARSSCCPMapIter GetLastConstValueIter(void) { return ConstantDefs.end(); };
Clark Coleman
committed
// Fetch SCCP constant iter into block- or func-level constants. True only if const value.
bool FindSCCPConstIter(SMPBasicBlock *CurrBlock, int RegHashValue, bool LocalName, STARSSCCPMapIter &ConstIter);
inline std::size_t GetNumLoops(void) const { return LoopCount; };
inline int GetLoopType(std::size_t LoopNumber) const { return LoopTypesByLoopNum.at(LoopNumber); };
int GetLoopNumFromTestBlockNum(int BlockNum) const;
int GetInnermostLoopNum(int BlockNum) const; // find innermost loop # for BlockNum
int GetOutermostLoopNum(int BlockNum) const; // find outermost loop # for BlockNum
STARSExprBoundsIter GetFirstLoopMemWriteExprBoundsIter(std::size_t LoopIndex) const { return LoopMemWriteBoundsExprs[LoopIndex].cbegin(); };
STARSExprBoundsIter GetLastLoopMemWriteExprBoundsIter(std::size_t LoopIndex) const { return LoopMemWriteBoundsExprs[LoopIndex].cend(); };
STARSExprBoundsIter GetFirstLoopMemWriteExpandedExprBoundsIter(std::size_t LoopIndex) const { return LoopMemWriteBoundsExprsExpanded[LoopIndex].cbegin(); };
STARSExprBoundsIter GetLastLoopMemWriteExpandedExprBoundsIter(std::size_t LoopIndex) const { return LoopMemWriteBoundsExprsExpanded[LoopIndex].cend(); };
int FindInArgNumFromCopyAddr(STARS_ea_t CopyInstAddr); // return -1 if not found in InArgPointerCopyAddrs, InArg position # otherwise
std::set<SMPPhiFunction, LessPhi>::iterator GetPhiIterForPhiDef(std::size_t BlockNumber, const STARSOpndTypePtr &DefOp, int SSANum);
// Given block # and PhiDef op_t and SSANum, return the Phi iterator or assert.
clc5q
committed
// Eight methods to get values from the maps of global reg/SSA to FG info.
// For local names, see corresponding methods in SMPBasicBlock.
unsigned short GetDefSignMiscInfo(int DefHashValue);
unsigned short GetStackDefSignMiscInfo(STARS_ea_t InstAddr);
unsigned short GetUseSignMiscInfo(int UseHashValue);
unsigned short GetStackUseSignMiscInfo(STARS_ea_t InstAddr);
unsigned short GetDefWidthTypeInfo(int DefHashValue);
unsigned short GetUseWidthTypeInfo(int UseHashValue);
struct FineGrainedInfo GetDefFGInfo(int DefHashValue);
struct FineGrainedInfo GetUseFGInfo(int UseHashValue);
ControlFlowType GetControlFlowType(STARS_ea_t InstAddr) const;
std::size_t GetSwitchJumpMapSize(void) const { return SwitchJumpMap.size(); };
std::size_t GetSwitchInfoArraySize(void) const { return SwitchInfoArray.size(); };
inline int GetMaxStackSSANum(void) const { return MaxDirectStackAccessSSANum; };
inline int GetMaxRegSSANum(void) const { return MaxRegSSANum; };
int GetLoopNumFromHeaderBlockNum(const int HeaderBlockNum) const; // return -1 if HeaderBlockNum is not a loop header block #
std::size_t FindLoopNumFromHeadBlockNum(int LoopHeaderBlockNum) const; // find loop # corresponding to header block num
// inline STARSExpression *GetLoopMemWriteRangeExpr(std::size_t LoopNum) const { return LoopMemWriteRangeExprs[LoopNum]; };
inline std::size_t GetNumInArgsUsedInMemWrites(std::size_t LoopPlusOne) const { return InArgsUsedInMemWriteByteWidths[LoopPlusOne].size(); };
inline std::size_t GetInArgMemWriteWidth(std::size_t LoopPlusOne, std::size_t index) const { return InArgsUsedInMemWriteByteWidths[LoopPlusOne][index].second; };
inline STARSExprSetIter GetInArgExprUsedInMemWrite(std::size_t LoopPlusOne, std::size_t index) const { return InArgsUsedInMemWriteByteWidths[LoopPlusOne][index].first; };
inline std::size_t GetNumInheritedMemWriteExprs(std::size_t LoopIndexPlusOne) const { return MemAddrExprWidthsFromCallees[LoopIndexPlusOne].size(); };
inline std::size_t GetInheritedMemWriteWidth(std::size_t LoopIndexPlusOne, std::size_t ExprIndex) const { return MemAddrExprWidthsFromCallees[LoopIndexPlusOne][ExprIndex].second; };
inline STARSExprSetIter GetInheritedMemWriteExpr(std::size_t LoopIndexPlusOne, std::size_t ExprIndex) const { return MemAddrExprWidthsFromCallees[LoopIndexPlusOne][ExprIndex].first; };
inline std::size_t GetNumStringMemWriteRangeExprs(std::size_t LoopIndexPlusOne) const { return StringMemWriteRangeWidths[LoopIndexPlusOne].size(); };
inline std::size_t GetStringMemWriteRangeWidth(std::size_t LoopIndexPlusOne, std::size_t ExprIndex) const { return StringMemWriteRangeWidths[LoopIndexPlusOne][ExprIndex].first; };
inline STARSExprSetIter GetStringMemWriteRangeExpr(std::size_t LoopIndexPlusOne, std::size_t ExprIndex) const { return StringMemWriteRangeWidths[LoopIndexPlusOne][ExprIndex].second; };
clc5q
committed
inline std::size_t GetNumCalleeLoopMemExprs(void) const { return LoopMemAddrExprWidthsFromCallees.size(); };
// inline std::size_t GetCalleeLoopMemWriteWidth(std::size_t index) const { return LoopMemAddrExprWidthsFromCallees[index].second; };
// inline STARSExprSetIter GetCalleeLoopExprUsedInMemWrite(std::size_t index) const { return LoopMemAddrExprWidthsFromCallees[index].first; };
STARSInArgMap::const_iterator GetAddressRegToInArgMapping(const STARS_ea_t InstAddr) const { return MemWriteToInArgMap.find(InstAddr); };
STARSInArgMap::const_iterator GetLastAddressRegToInArgMapping(void) const { return MemWriteToInArgMap.cend(); };
const std::bitset<1 + MD_LAST_REG_NO> &GetInputRegs(void) const { return InputRegs; };
const std::bitset<1 + MD_LAST_REG_NO> &GetOutputRegs(void) const { return OutputRegs; };
const std::bitset<1 + MD_LAST_REG_NO> &GetPreservedRegs(void) const { return PreservedRegsBitmap; };
const std::bitset<1 + MD_LAST_REG_NO> &GetCalleePreservedRegs(void) const { return CalleePreservedRegs; };
uint32_t GetTaintInArgPositions(void) const { return TaintInArgPosBits; };
std::string GetFuncSPARKSuffixString(void) const; // produce string "_hexaddress" for first address in func
clc5q
committed
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; };
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 SetSharedChunks(bool v) { GetFuncInfo()->SetSharedChunks(v); };
// inline void SetSharedChunks(bool v) { SharedChunks=v; };
inline void SetReturnAddressStatus(FuncType funcType) {
ReturnAddrStatus = funcType;
}
inline void SetFuncProcessed(bool Status) { FuncProcessed = Status; return; };
inline void SetHasIndirectCalls(void) { IndirectCalls = true; };
inline void SetHasUnresolvedIndirectCalls(void) { UnresolvedIndirectCalls = true; };
inline void SetHasSystemCalls(void) { SystemCalls = true; };
inline void SetAltersSPARKMemory(void) { AltersMemory = true; };
inline void SetFuncSafe(bool Status) { SafeFunc = Status; return; };
inline void SetSpecFuncSafe(bool Status) { SpecSafeFunc = Status; return; };
inline void SetNeedsFrame(bool Status) { NeedsStackReferent = Status; return; };
inline void SetSpecNeedsFrame(bool Status) { SpecNeedsStackReferent = Status; return; };
inline void SetUnsafeForFastReturns(bool Status, UnsafeFastReturnReason Reason) { UnsafeForFastReturns = Status; FastReturnStatus |= (int) Reason; return; };
inline void SetIsSpeculative(bool IsS) { IsSpeculative = IsS; };
inline void SetIsMutuallyRecursive(void) { MutuallyRecursive = true; };
inline void SetIsCalledFromOrphanedCode(void) { CalledFromOrphanCode = true; };
inline void SetIsTailCallChainFromOrphanedCode(void) { TailCallChainFromOrphanCode = true; };
inline void SetCallsNonReturningFunc(void) { CallsNonReturningFunc = true; };
inline void SetCalleeChainCallsNonReturningFunc(void) { CalleeChainCallsNonReturningFunc = true; };
inline void SetHasHashingCode(bool Hashes) { HasHashingCode = Hashes; };
Clark Coleman
committed
inline void SetHasMallocCall(void) { HasMallocCall = true; };
void AddCallSource(STARS_ea_t addr); // Add a caller to the list of all callers of this function.
bool AddDirectCallTarget(STARS_ea_t addr); // Add a direct call target; return true if new target, false if target already added
bool AddIndirectCallTarget(STARS_ea_t addr); // Add an indirect call target; return true if new target, false if target already added
std::set<STARS_ea_t>::iterator RemoveDirectCallTarget(STARS_ea_t TargetAddr); // Remove TargetAddr from DirectCallTargets and AllCallTargets.
bool RemoveIndirectCallTarget(STARS_ea_t TargetAddr); // Remove TargetAddr from IndirectCallTargets and AllCallTargets.
inline void AddResolvedBranch(const STARS_ea_t BranchAddr) {
(void) ResolvedCondBranches.insert(BranchAddr);
}
Clark Coleman
committed
inline void AddMallocCallWithInArg(const CallAddrArgDefAddrPair InsertVal) {
(void) MallocCallInArgsMap.insert(InsertVal);
}
void AddBufferCallWithInArg(const CallAddrArgDefAddrPair InsertVal);
inline void SetMaxStackSSANum(int NewMaxSSANum) { MaxDirectStackAccessSSANum = NewMaxSSANum; };
inline void SetMaxRegSSANum(int NewMaxSSANum) { MaxRegSSANum = NewMaxSSANum; };
inline void SetCallerSavedLocalReg(STARS_regnum_t RegNum) { CallerSavedLocalRegsBitmap.set(RegNum); };
void UpdateLocalMaxSSANum(int CurrSSANum) { if (CurrSSANum > MaxLocalSSANum) MaxLocalSSANum = CurrSSANum; };
void AddLeaOperand(STARS_ea_t addr, STARSOpndTypePtr LeaOperand); // add map entry to LeaInstOpMap
void AddNormalizedStackOperand(STARSOpndTypePtr OldOp, STARS_ea_t InstAddr, STARSOpndTypePtr NormalizedOp); // add to map for RTL lookup later
void UpdateMaxDirectStackAccessOffset(STARS_sval_t NewOffset); // Update MaxDirectStackAccessDelta
void MarkTaintInArgReg(std::size_t ArgPos) { TaintInArgPosBits |= (1 << ArgPos); };
void SetControlFlowType(STARS_ea_t InstAddr, ControlFlowType JumpTypeCode); // insert into ControlFlowMap
clc5q
committed
STARSSCCPMapIter InsertGlobalConstValue(int DefHashValue, struct STARS_SCCP_Const_Struct NewConstEntry);
// Insert SCCP value for global name; change if already found.
clc5q
committed
clc5q
committed
// Eight methods to set values into the maps of global reg/stack/SSA to FG info.
// For local names, see corresponding methods in SMPBasicBlock.
void UpdateDefSignMiscInfo(int DefHashValue, unsigned short NewInfo);
void UpdateStackDefSignMiscInfo(STARS_ea_t InstAddr, unsigned short NewInfo);
void UpdateUseSignMiscInfo(int UseHashValue, unsigned short NewInfo);
void UpdateStackUseSignMiscInfo(STARS_ea_t InstAddr, unsigned short NewInfo);
void UpdateDefWidthTypeInfo(int DefHashValue, unsigned short NewInfo);
void UpdateUseWidthTypeInfo(int UseHashValue, unsigned short NewInfo);
void UpdateDefFGInfo(int DefHashValue, struct FineGrainedInfo NewFG);
void UpdateUseFGInfo(int UseHashValue, struct FineGrainedInfo NewFG);
void ClearDefSignedness(int DefHashValue);
bool MDUpdateFGStackLocInfo(STARS_ea_t InstAddr, const STARSOpndTypePtr &TempOp, struct FineGrainedInfo NewFG);
// Return true if we update fine grained stack entry for stack op TempOp from instruction at InstAddr
bool AddSwitchTableInfo(STARS_ea_t IndirJumpAddr, struct SwitchTableInfo TableInfo); // push_back new entries on switch data structures
inline bool IsFuncProcessed(void) const { return FuncProcessed; };
inline bool IsFuncEmpty(void) const { return (0 >= BlockCount); };
inline bool FuncReturnsToCaller(void) const { return FuncInfo->HasReturnPoints(); };
clc5q
committed
inline bool StackPtrAnalysisSucceeded(void) const { return AnalyzedSP; };
inline bool HasSTARSStackPtrAnalysisCompleted(void) const { return STARSStackPtrAnalysisPerformed; };
inline bool AreReturnTargetsComputed(void) const { return ReturnTargetsComputed; };
inline bool HasExplicitReturnInstruction(void) const { return HasReturnInst; };
inline bool HasIndirectCalls(void) const { return IndirectCalls; };
inline bool HasUnresolvedIndirectCalls(void) const { return UnresolvedIndirectCalls; };
inline bool HasIndirectJumps(void) const { return IndirectJumps; };
inline bool HasUnresolvedIndirectJumps(void) const { return UnresolvedIndirectJumps; };
inline bool HasSystemCalls(void) const { return SystemCalls; };
inline bool IsDirectlyRecursive(void) const { return DirectlyRecursive; };
inline bool IsMutuallyRecursive(void) const { return MutuallyRecursive; };
inline bool HasSharedChunks(void) const { return GetFuncInfo()->HasSharedChunks(); };
// inline bool HasSharedChunks(void) const { return SharedChunks; };
inline bool HasGoodRTLs(void) const { return BuiltRTLs; };
inline bool HasGoodSSAForm(void) const { return HasGoodSSA; };
inline bool HasReducibleControlFlow(void) const { return HasReducibleCFG; };
inline bool HasStructuredControlFlow(void) const { return HasStructuredCFG; };
inline bool HasPushAfterFrameAlloc(void) const { return PushAfterLocalVarAlloc; };
inline bool IsLinkerStub(void) const { return LinkerStub; };
clc5q
committed
inline bool IsThunkFunction(void) const { return ThunkFunc; };
inline bool IsInstIDInFunc(STARS_ea_t addr) { return this->FuncInfo->IsInstIDInFunc(addr); };
inline bool IsLibFunc(void) const { return LibFunc; };
Clark Coleman
committed
inline bool IsLeaf(void) const { return (!IndirectCalls && (!IsLinkerStub()) && (DirectCallTargets.empty() || ((1 == DirectCallTargets.size()) && IsDirectlyRecursive()))); };
clc5q
committed
inline bool IsSafe(void) const { return SafeFunc; }; // safe to follow stack access DEF-USE chains
inline bool IsSpecSafe(void) const { return SpecSafeFunc; }; // safe if we can resolve indirect calls at run time in mmStrata
inline bool IsSafeCallee(void) const { return SafeCallee; };
inline bool IsSpecSafeCallee(void) const { return SpecSafeCallee; };
inline bool IsUnsafeForFastReturns(void) const { return UnsafeForFastReturns; };
inline bool NeedsStackFrame(void) const { return NeedsStackReferent; };
inline bool SpecNeedsStackFrame(void) const { return SpecNeedsStackReferent; };
inline bool WritesAboveReturnAddress(void) const { return WritesAboveRA; }; // don't use before fixing this member
clc5q
committed
inline bool OutArgsRegionComputed(void) const { return OutgoingArgsComputed; };
bool IsInOutgoingArgsRegion(const STARSOpndTypePtr &DestOp); // Does DestOp fall within outgoing args area?
bool IsInIncomingArgsRegion(SMPInstr *SourceInst, const STARSOpndTypePtr &SourceOp) const; // Does SourceOp from SourceInst fall within incoming args area?
inline bool IsGlobalName(const STARSOpndTypePtr &RefOp) const { return (GlobalNames.end() != GlobalNames.find(RefOp)); };
inline bool UsesFramePointer(void) const { return UseFP; };
inline bool FuncHasHashingCode(void) const { return HasHashingCode; };
inline bool HasGoodFGStackTable(void) const { return (!(NegativeOffsetFineGrainedStackTable.empty())); };
bool IsLiveIn(const STARSOpndTypePtr &CurrOp) const;
inline bool IsLiveOut(const STARSOpndTypePtr &CurrOp) const {
clc5q
committed
return (LiveOutSet.end() != LiveOutSet.find(CurrOp));
}
inline bool IsVarKill(const STARSOpndTypePtr &CurrOp) const {
clc5q
committed
return (KillSet.end() != KillSet.find(CurrOp));
}
inline bool IsResolvedBranch(const STARS_ea_t BranchAddr) const {
return (ResolvedCondBranches.find(BranchAddr) != ResolvedCondBranches.cend());
}
bool IsInStackPtrCopySet(const STARSOpndTypePtr &CurrOp);
bool IsDefnInStackPtrCopySet(const STARSOpndTypePtr &CurrOp, const STARS_ea_t &DefAddr) const;
inline bool DoesStackFrameExtendPastStackTop(void) const { return StackFrameExtendsPastStackTop; };
inline bool IsRegPreserved(std::size_t RegNum) const { return (PreservedRegsBitmap[RegNum] != 0); };
inline bool IsCallerSavedLocalReg(std::size_t RegNum) const { return (CallerSavedLocalRegsBitmap[RegNum] != 0); };
inline bool IsPossibleIndirectCallTarget(void) const { return PossibleIndirectCallTarget; };
inline bool IsCalledFromOrphanedCode(void) const { return CalledFromOrphanCode; };
inline bool IsTailCallChainFromOrphanedCode(void) const { return TailCallChainFromOrphanCode; };
inline bool HasCallToNonReturningFunc(void) const { return CallsNonReturningFunc; };
inline bool HasCalleeChainWithNonReturningFunc(void) const { return CalleeChainCallsNonReturningFunc; };
Clark Coleman
committed
inline bool HasCallToMalloc(void) const { return HasMallocCall; };
inline bool TranslatingLoopToProc(void) const { return TranslatingSPARKLoop; };
inline bool IsMultiEntry(void) const { return MultipleEntryPoints; };
inline bool DoesLoopWriteMemory(std::size_t LoopIndex) const { return LoopWritesMemory.at(LoopIndex); };
inline bool DoesLoopReadMemory(std::size_t LoopIndex) const { return LoopReadsMemory.at(LoopIndex); };
inline bool DoesLoopUseStackPtrRegs(std::size_t LoopIndex) const { return LoopUsesStackPtrRegs.at(LoopIndex); };
inline bool DoesLoopHavePreconditions(std::size_t LoopIndex) const { return LoopHasPreconditions.at(LoopIndex); };
Clark Coleman
committed
bool IsLoopInductionVar(std::size_t LoopIndex, STARSOpndTypePtr &CurrOp, SMPInstr *UseInst, STARSInductionVarFamilyIter &ListIter, std::size_t &FamilyIndex); // For CurrOp in LoopIndex, return iterator and position in family if true
bool IsLoopInductionVarForAnySSANum(std::size_t LoopIndex, const STARSOpndTypePtr &CurrOp, STARSInductionVarFamilyIter &ListIter, std::size_t &FamilyIndex); // Relax the requirement to match SSA number to IV
bool IsLoopNestInductionVar(const STARSOpndTypePtr &CurrOp, SMPInstr *UseInst, STARSInductionVarFamilyIter &ListIter, std::size_t &FamilyIndex, int &LoopIndex); // For CurrOp in loop nest including UseInst, return iterator and position in family if true
inline bool AltersSPARKMemory(void) const { return AltersMemory; };
inline bool UsesInArgsForLoopMemWrites(void) const { return HasLoopInArgMemWrites; };
inline bool CalleeUsesInArgsForLoopMemWrites(void) const { return CalleeHasLoopInArgMemWrites; };
inline bool IsCriticalInArg(std::size_t ArgPos) const { return (0 != (TaintInArgPosBits & (1 << ArgPos))); };
clc5q
committed
inline bool DoesLoopHaveArgs(int LoopNum) const { return LoopMemRangeInArgRegsBitmap[(size_t) LoopNum].any(); };
clc5q
committed
// Printing methods
void Dump(void); // debug dump
clc5q
committed
void ResetProcessedBlocks(void); // Set Processed flag to false in all blocks
void MarkDominatedBlocks(int CurrBlockNum); // Set Processed flag for all blocks below CurrBlockNum in DomTree.
void ResetSCCPVisitedBlocks(void); // Set SCCPVisited flag to false in all blocks
void RPONumberBlocks(void); // Number basic blocks in reverse post-order and place pointers in RPOBlocks.
int GetFallThroughPredBlockNum(int CurrBlockNum); // return block # of block that falls through to CurrBlockNum; SMP_BLOCKNUM_UNINIT if none
void RemoveBlock(SMPBasicBlock *CurrBlock, std::list<SMPBasicBlock *>::iterator &BlockIter, bool IBTarget = false); // Remove a basic block and its instructions.
void RemoveCallingBlocks(void) const; // Func is empty, so add all blocks that call it to Program->BlocksPendingRemoval.
clc5q
committed
void ComputeGlobalSets(void); // compute LiveOut, Kill sets for function
bool ComputeInOutRegs(bool InheritPass, bool &WritesMem, bool &CallChainNonReturning); // compute InputRegs and OutputRegs, only inherit from callees on InheritPass
void BuildLoopingStringMemExprs(SMPBasicBlock *CurrBlock, SMPInstr *CurrInst); // Build lower and upper bounds exprs for memory writes in looping string opcode
void FindMatchingMemDEFAddrs(STARS_ea_t UseAddr, SMPBasicBlock *CurrBlock, STARSOpndTypePtr &MemUseOp, std::list<STARS_ea_t> &MemDefAddrs, std::set<int> &AddressRegs); // Fill MemDefAddrs with inst addrs that DEF MemUseOp, tracing back from UseAddr.
STARS_sval_t GetLoopIncomingStackDelta(std::size_t LoopNum) const; // Find first inst in loop, return its stack delta.
void AnalyzeFunc(void); // Analyze all instructions in function
clc5q
committed
void AdvancedAnalysis(void); // Analyses that fix IDA stack frame info, sync RTLs with DEFs and USEs, Live Variable Analysis
bool AdvancedAnalysis2(void); // fix call inst DEFs and USEs; return true if changes
void AdvancedAnalysis3(void); // Analyses that depend on whole program info but not SSA.
std::size_t UnprocessedCalleesCount(void); // Count of callees that have FuncProcessed == false
STARS_sval_t GetStackAdjustmentForCallee(STARS_ea_t CallAddr); // Get stack pointer adjustment in basic block, after CallAddr
STARS_sval_t GetStackDeltaForCallee(STARS_ea_t CallTargetAddr); // Get stack pointer delta for callee function, which starts at CallTargetAddr
STARS_sval_t ComputeGlobalStackAdjustment(void); // Find consistent or smallest stack adjustment after all calls to this function, program-wide
void ComputeTempReachingDefs(const STARSOpndTypePtr &TempOp, STARS_ea_t UseAddr); // Compute the TempReachingDefs set that reaches UseAddr for TempOp
void ComputeTempStackDeltaReachesList(const STARSOpndTypePtr &TempOp); // Compute the TempStackDeltaReachesList for TempOp for all DefAddrs in TempReachingDefs
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 TraceIncomingArgs(void); // Find all copies of incoming args and record in bitsets
Clark Coleman
committed
void AnalyzeBufferUses(void); // Analyze buffer sizes and the use of buffers by vulnerable library funcs.
bool ComputeReturnTargets(bool FirstIteration); // Determine inst ID set that func could return to, including tail call issues; return true if set changes
void EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile);
void PreProcessForSPARKAdaTranslation(void); // Perform look-ahead steps needed before translation to SPARK Ada.
bool EmitSPARKLoopMemRangePostCondition(FILE *HeaderFile, FILE *BodyFile, STARS_ea_t LoopAddr, bool PostPrintStarted); // specify mem ranges that loop changes; return true if printed
clc5q
committed
void EmitSPARKStackMemRangePostCondition(FILE *HeaderFile, std::size_t LoopIndex, STARS_ea_t LoopAddr, bool PostPrintStarted); // specify stack mem ranges that loop changes
void EmitSPARKAdaForLoopLimit(FILE *BodyFile, STARS_ea_t LoopAddr); // emit loop invariant for basic induction var bound
void EmitIncomingLoopRegExprs(FILE *OutputFile, std::size_t LoopNum, bool LoopInvariantSection); // emit LoopRegSourceExprPairs
void EmitSPARKLoopBIVLimits(FILE *BodyFile, STARS_ea_t LoopAddr, std::size_t LoopIndex, bool PragmaAssume); // Emit Assumes and Loop_Invariants for loop BIV and mem ranges.
void EmitSPARKMemRangeLoopInvariants(FILE *BodyFile, std::size_t LoopIndex, STARS_sval_t IncomingStackDelta, bool LoopInvariant, std::size_t &OutputCount); // Emit only the mem range Loop_Invariant (or pragma Assert)
void EmitFuncSPARKAda(void); // Emit SPARK Ada translation of function
Clark Coleman
committed
void SetMarkerInstDefs(void); // Set LiveIn operands as DEFs in SSA marker pseudo-inst at function entry.
void LiveVariableAnalysis(bool Recomputing); // Perform Live Variable Analysis across all blocks
Clark Coleman
committed
void RecomputeStackLVA(void); // After normalization, re-do stack ops in LVA sets.
void RecomputeSSA(void); // Recompute LVA and SSA and all dependent data structures now that unreachable blocks have been removed.
void ComputeSSA(void); // Compute SSA form data structures
bool DoesBlockDominateBlock(int HeadBlockNum, int TailBlockNum) const; // Does basic block HeadBlockNum dominate basic block TailBlockNum?
bool IsBlockInAnyLoop(int BlockNum) const; // Is block (with block # BlockNum) inside any loop?
bool IsBlockInLoop(int BlockNum, std::size_t LoopNum); // Is block (with block # BlockNum) inside loop # LoopNum?
bool AreBlocksInSameLoops(const int BlockNum1, const int BlockNum2) const;
void BuildLoopList(int BlockNum, std::list<std::size_t> &LoopList); // build list of loop numbers that BlockNum is part of.
void BuildLoopBlockList(const size_t LoopNum, std::list<std::size_t> &BlockList); // build list of Block numbers contained in LoopNum.
clc5q
committed
void AnalyzeLoopIterations(void); // analyze how many times each loop iterates
clc5q
committed
STARSExpression *CreateMemoryAddressExpr(const STARSOpndTypePtr &MemDefOp, SMPInstr *WriteInst); // create expression for the memory address computation in MemDefOp
void AliasAnalysis(void); // Find memory writes with possible aliases
void AliasAnalysis2(void); // Optimized: Find memory writes with possible aliases
void InferTypes(bool FirstIter); // Determine NUMERIC, POINTER, etc. for all operands
clc5q
committed
bool InferInterproceduralTypes(void); // Pass types across procedure bounds, return true if types change.
void InferFGInfo(void); // determine signedness and width info for all operands
SMPOperandType InferGlobalDefType(const STARSOpndTypePtr &DefOp, int SSANum, SMPBasicBlock *DefBlock, bool CallInst, STARS_ea_t DefAddr);
// Can DEF type be inferred from all USEs?
void ApplyProfilerInformation(ProfilerInformation *pi);
void AnalyzeMetadataLiveness(void); // Is metadata live or dead for each inst
bool PropagateGlobalMetadata(const STARSOpndTypePtr &UseOp, SMPMetadataType Status, int SSANum, STARS_ea_t UseAddr);
void FindRedundantMetadata(void); // Do consecutive DEFs have same type?
void SparseConditionalConstantPropagation(void); // perform SCCP to find constant values for DEFs, store in this->ConstantDefs
void AuditSCCPForIndirectTargets(void); // emit debug output if SCCP found constant call target for an indir call or jump
void EvaluateAllPhiConstants(int BlockNum, const std::vector<STARSBitSet> &ExecutedEdgeBitSet, std::list<std::pair<int, int> > &SSAWorkList); // part of SCCP processing; propagate const DEFs into Phi USEs and Phi DEFs
bool IsBenignUnderflowDEF(const STARSOpndTypePtr &DefOp, int DefSSANum, STARS_ea_t DefAddr, int &IdiomCode); // Do we not care if DEF underflowed, due to how it is used?
bool HasIntErrorCallSink(const STARSOpndTypePtr &DefOp, int DefSSANum, STARS_ea_t DefAddr, std::string &SinkString, bool &FoundAnyCall); // DEF is passed to known system/lib call
bool WritesAboveLocalFrame(const STARSOpndTypePtr &DestOp, bool OpNormalized, STARS_ea_t InstAddr); // Is DestOp direct stack access to caller's frame?
bool AccessAboveLocalFrame(const STARSOpndTypePtr &StackOp, bool OpNormalized, STARS_ea_t InstAddr, bool WriteAccess); // Is StackOp direct stack access to caller's frame?
StackAccessType GetStackAccessType(const STARSOpndTypePtr &StackOp, bool OpNormalized, STARS_ea_t InstAddr, bool WriteAccess); // Get StackAccessType from stack frame map
bool IsAccessToCalleeSavedReg(const STARSOpndTypePtr &StackOp, bool OpNormalized, STARS_ea_t InstAddr, bool WriteAccess); // Is StackOp pointing to a callee-saved reg?
bool IsDefUsedInUnsafeMemWrite(STARSOpndTypePtr DefOp, int DefSSANum, STARS_ea_t DefAddr); // Is Defop+DefSSANum at DefAddr used as address reg or as source operand in unsafe memory write?
bool IsAddressRegSafe(const STARSOpndTypePtr &UseOp, STARS_ea_t UseAddr, int UseSSANum); // Is UseOp+UseSSANum at UseAddr a safe write?
void MarkFunctionSafe(void); // Does analysis to see if the function can be marked safe
void FreeUnusedMemory2(void); // After loop 2 in SMPProgram::Analyze(), free memory
void FreeUnusedMemory3(void); // After loop 3 in SMPProgram::Analyze(), free memory
void FreeUnusedMemory4(void); // After loop 4 (type inference) in SMPProgram::Analyze(), free memory
clc5q
committed
SMPProgram* Program; // pointer to the program I'm part of
STARS_ea_t FirstEA; // address of first instruction in the function
int BlockCount; // number of basic blocks in the function
std::size_t LoopCount;
bool FuncProcessed; // Has function been analyzed in current whole-program analysis?
bool UseFP; // Does function use a frame pointer?
bool StaticFunc; // Is function declared static?
bool LibFunc; // is function a standard library function?
bool HasReturnInst; // Does function have a return instruction? (might just have a tail call)
bool IndirectCalls; // Does function make indirect calls?
bool UnresolvedIndirectCalls; // Calls could not all be linked to targets
bool IndirectJumps; // Does function make indirect jumps?
bool UnresolvedIndirectJumps; // Jumps could not all be linked to targets
bool SystemCalls; // has system calls, e.g. "int 0x80" in Linux
bool DirectlyRecursive; // Calls itself
bool MutuallyRecursive; // part of program call graph loop, or depends on loop funcs being processed first
// 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 CalledFromOrphanCode; // function is called from orphaned code, so program CFG is not complete at this function.
bool TailCallChainFromOrphanCode; // Part of chain orphancode ... func.. tailcallsfunc2 ... which can return to orphaned code
bool CallsNonReturningFunc; // calls exit() or abort(), et al., on some path; could return on other paths
bool CalleeChainCallsNonReturningFunc; // somewhere in callee chain we have CallsNonReturningFunc set
bool CallsAlloca; // Does function allocate stack space after initial allocation? NOTE:SMPInstr::IsAllocaCall() excludes immediate value alloca calls
bool PushAfterLocalVarAlloc; // Does function push onto the stack after allocating local var space?
bool LinkerStub; // Is function just a stub to be filled in by the linker, e.g. a PLT stub?
clc5q
committed
bool ThunkFunc; // Function is a thunk to get the code address by returning the return address in a reg
bool AnalyzedSP; // Were stack pointer change points successfully analyzed?
clc5q
committed
bool STARSStackPtrAnalysisPerformed; // Have we done our own stack pointer analysis yet?
bool StackAdjustmentComputed; // Have we cached a value for the stack adjustment seen after calls to this function throughout the program?
bool BuiltRTLs; // Were RTLs built succcessfully for all instructions?
bool HasReducibleCFG; // control flow graph is reducible
bool HasStructuredCFG; // control flow graph can be transated to a well-structured high-level language, namely SPARK Ada, with no gotos
bool HasGoodSSA; // Succeeded in building SSA form
bool SafeFunc; // Function needs no bounds checking from mmStrata
bool SpecSafeFunc; // Function needs no bounds checking from mmStrata
bool SafeCallee; // SafeFunc AND Caller of this func does not need a stack referent
bool SpecSafeCallee; // SafeFunc AND Caller of this func does not need a stack referent
bool UnsafeForFastReturns; // Strata fast returns mechanism cannot be used for this function
bool WritesAboveRA; // Function writes to stack above the return address
bool NeedsStackReferent; // mmStrata will need a stack referent to do bounds checking
bool SpecNeedsStackReferent; // mmStrata will need a stack referent to do bounds checking
bool HasIndirectWrites; // Function has at least one indirect memory write
clc5q
committed
bool HasUnsafeIndirectWrites; // Function has at least one unsafe indirect memory write
bool AltersMemory; // Function writes to memory, or its callees write to memory; for SPARK Ada contracts.
bool HasLoopInArgMemWrites; // Has loop mem write that traces back to InArg pointer value
bool CalleeHasLoopInArgMemWrites; // Callee has loop mem write that traces back to InArg pointer value
clc5q
committed
bool HasMemExprsFromCalleeLoops; // callee has loop mem write exprs, regardless of whether we called the callee from a loop
bool PossibleIndirectCallTarget; // function address appears in data, could indicate indirect calls to it
bool PossibleTailCallTarget; // function could be called by jump instruction acting as tail call
bool ReturnTargetsComputed; // finished computing all return targets (if func can be tail called, depends on other funcs)
bool OutgoingArgsComputed; // Were able to compute OutgoingArgsSize
bool GoodLocalVarTable; // LocalVarTable was built successfully
bool StackFrameExtendsPastStackTop; // Locals are accessed from unallocated space beyond the top of stack.
bool IsSpeculative; // Have we started the speculative portion of the analysis for this function.
bool HasHashingCode; // Has apparent hashing or crypto code that intentionally overflows.
bool HasInArgCodePointer; // Has incoming arg of type CODEPTR
bool HasInArgDataPointer; // Has incoming arg of type POINTER or a refinement of POINTER
Clark Coleman
committed
bool HasMallocCall; // calls malloc()
bool TranslatingSPARKLoop; // Currently translating a loop into a separate SPARK Ada procedure
long TypedDefs; // How many DEFs in instructions were not UNINIT type after InferTypes()
long UntypedDefs; // How many DEFs in instructions are UNINIT type after InferTypes()
clc5q
committed
long TypedPhiDefs;
long UntypedPhiDefs;
long SafeBlocks; // no unsafe memory writes in block; counter
long UnsafeBlocks; // possibly unsafe memory write in block; counter
std::size_t Size; // Function size in code bytes
STARS_asize_t LocalVarsSize; // size of local vars region of stack frame
uint16_t CalleeSavedRegsSize; // stack size of callee pushed regs
STARS_asize_t IncomingArgsSize; // size of incoming args on stack
int RetAddrSize; // size of return address on stack in bytes (4 for 32-bit machines)
STARS_sval_t AllocSizeAfterFrameAlloc; // bytes allocated in first block after primary frame alloc, e.g. by alloca
std::size_t OutgoingArgsSize; // portion of LocalVarsSize that is really outgoing args space
STARS_ea_t LocalVarsAllocInstr; // address of instr that allocates stack frame
STARS_ea_t LocalVarsDeallocInstr; // address of epilogue instr that deallocs frame
STARS_adiff_t AllocPointDelta; // IDA sp_delta AFTER stack frame allocation instruction
STARS_sval_t MinStackDelta; // smallest (negative) value that stack pointer reaches, relative
// to the value it has at the entry point of the function
STARS_sval_t MaxStackDelta; // highest (positive) value that stack pointer reaches, relative
// to the value it has at the entry point of the function
STARS_sval_t MinStackAccessOffset; // Normalized or unnormalized, min stack byte offset in any DEF or USE
STARS_sval_t MaxStackAccessLimit; // Normalized or unnormalized, 1 greater than max stack byte offset in any DEF or USE
STARS_sval_t NetStackDelta; // Net change to stack pointer after function returns; +4 for most functions,
clc5q
committed
// because they pop off the return address while returning.
STARS_sval_t PreAllocStackDelta; // Stack delta right before stack frame allocation, to which the stack
clc5q
committed
// delta should be reset when we see an instruction that deallocates the
// whole frame.
STARS_sval_t FramePointerStackDelta; // Stack delta when framepointer := stackpointer was encountered; zero if UseFP is false.
STARS_sval_t GlobalStackAdjustment; // Stack adjustment seen program-wide after calls to this function; zero or positive.
STARS_sval_t MaxDirectStackAccessDelta; // Normalized; max offset from incoming stack pointer for direct stack accesses into caller's frame
long LocalVarOffsetLimit; // upper bound on stack-relative offsets
long IDAReturnAddressOffset; // offset from local frame base of return address in IDA Pro stack frame
FuncType ReturnAddrStatus; // Marked true if the return address is safe from being overwritten
unsigned short FastReturnStatus; // Whether fast returns can be used for calls to, and returns from, this function, and why not if unsafe.
unsigned short InArgCount; // number of incoming arguments used
unsigned short MaxInArgIndex; // maximum arg # used (might be greater than InArgCount because some inargs might not be used)
uint32_t TaintInArgPosBits; // each set bit indicates InArg position that gets passed as a critical arg to a library call
int MaxDirectStackAccessSSANum; // highest SSANum seen on stack locations.
int MaxRegSSANum; // highest SSANum seen on registers
STARSExpression *DebugExpr; // for gdb printing ease
std::list<SMPInstr *> Instrs;
std::list<SMPBasicBlock *> Blocks;
std::set<STARS_ea_t> DirectCallTargets; // addresses called directly
std::set<STARS_ea_t> IndirectCallTargets; // addresses called by indirect calls
std::vector<STARS_ea_t> AllCallTargets; // union of direct and indirect
std::set<STARS_ea_t> AllCallSources; // functions that call this one
std::set<STARS_ea_t> AllCallSites; // instructions that call this function
std::set<STARS_ea_t> TailReturnTargets; // tail call return points from this function; subset of ReturnTargets
std::set<STARS_ea_t> ReturnTargets; // instructions that this function could return to
clc5q
committed
std::set<STARS_ea_t> JumpTableTargets; // code addresses found in jump tables for this func
std::set<STARS_ea_t> ResolvedCondBranches; // conditional branches resolved to always taken or never taken
std::set<SMPFunction *> UnresolvedCallers; // temp set to resolve during ComputeReturnTargets()
std::map<STARS_ea_t, int> JumpFollowNodesMap; // map COND_BRANCH addresses to their follow nodes when exiting if-then-elsif-else structures
std::map<STARS_ea_t, SMPBasicBlock *> InstBlockMap;
std::vector<SMPBasicBlock *> RPOBlocks; // blocks in reverse post-order numbering, index == RPO number
std::vector<STARSCFGBlock *> ShadowCFGBlocks; // skeleton CFG suitable for node coalescing analyses, index == RPO number
std::vector<unsigned short> InArgTypes; // types of incoming arguments, starting with argument zero.
std::vector<int> IDom; // Immediate dominators, indexed and valued by block RPO numbers
std::vector<std::pair<int, std::list<int> > > DomTree; // Dominator tree, as parent # and list of children
Clark Coleman
committed
STARSOpndSet GlobalNames; // operands used in more than one block; needed in SSA
std::vector<std::list<int> > BlocksDefinedIn; // What blocks DEF each GlobalName; index = op # in GlobalNames
std::vector<int> SSACounter; // SSA subscript #, indexed by GlobalNames op #
std::vector<std::list<int> > SSAStack; // SSA stack of most recent SSA number, indexed by global #
std::vector<struct LocalVar> LocalVarTable; // offset-sorted list of local vars / outgoing args
std::vector<struct StackFrameEntry> PositiveOffsetStackFrameMap; // memory map of every byte on stack frame, return address and up (inargs, etc.)
std::vector<struct StackFrameEntry> NegativeOffsetStackFrameMap; // memory map of every byte on stack frame, below return address (saved reg, locals, etc.)
std::vector<struct FineGrainedInfo> PositiveOffsetFineGrainedStackTable; // Inferences based on instruction accesses of stack
std::vector<struct FineGrainedInfo> NegativeOffsetFineGrainedStackTable; // Inferences based on instruction accesses of stack
std::vector<int> SavedRegLoc; // indexed by reg #; offset from return address of callee-saved reg
std::vector<SMPOperandType> ReturnRegTypes; // indexed by reg #; inferred types upon return
std::vector<SMPOperandType> IncomingRegTypes; // indexed by reg #; types from call sites of callers of this func
std::vector<struct FineGrainedInfo> ReturnRegFGInfo; // indexed by reg #; inferred FG info upon return
std::vector<STARSBitSet> FuncLoopsByBlock; // vector indexed by block number, bitset indexed by loop number, set bit means block # is in loop #
std::vector<STARSBitSet> FuncBlocksByLoop; // vector indexed by loop number, bitset indexed by block number, set bit means loop includes block #
std::vector<STARSBitSet> PositiveOffsetStackBytesWrittenByLoop; // vector indexed by loop number, bitset indexed by byte offset from incoming stack pointer, set bit means memory byte written
std::vector<STARSBitSet> NegativeOffsetStackBytesWrittenByLoop; // vector indexed by loop number, bitset indexed by byte offset from minimum stack pointer value, set bit means memory byte written
std::vector<int> LoopTypesByLoopNum; // indexed by loop number: top-testing, bottom-testing, middle-testing or infinite
std::vector<int> LoopTestBlocksByLoopNum; // indexed by loop number; block number of header block for top-testing or tail block for bottom-testing, -1 for middle-testing
std::vector<int> LoopHeadBlockNumbers; // indexed by loop number; block number of header block
std::vector<int> LoopFollowNodes; // indexed by loop number; block number of follow block
clc5q
committed
std::vector<bool> LoopHasMultipleExits;
std::vector<bool> LoopWritesMemory; // static, indirect or indexed writes
std::vector<bool> LoopReadsMemory; // static, indirect or indexed reads
clc5q
committed
std::vector<bool> LoopWritesGlobalStaticMemory;
std::vector<bool> LoopReadsGlobalStaticMemory;
std::vector<bool> LoopHasCalleeMemWrites;
std::vector<bool> LoopUsesStackPtrRegs;
std::vector<bool> LoopHasPreconditions; // Loop requires SPARK Ada preconditions
std::vector<bool> LoopExecutesWithLimitValue; // Loop executes a final iteration with BIV == LimitValue
std::vector<bool> LoopAnalysisProblems; // true if loop had problems with iterations analysis or mem range analysis
std::vector<bool> CalleeMemExprProblems; // indexed by LoopNum + 1; error in inheriting memory writing exprs from callees
std::vector<bool> SymbolicAnalysisProblems; // indexed by LoopNum + 1; error in symbolic analysis of memory writing exprs
std::vector<STARS_sval_t> LoopIncrementValue; // delta for primary BIV on each iteration; could be negative
clc5q
committed
std::vector<STARSInductionVarFamilyList> LoopInductionVars; // indexed by loop number
std::vector<struct LoopComparison> LoopComparisonExprs; // indexed by loop number
std::vector<STARSExpression *> LoopIterationsInitExprs; // indexed by loop number; primary BIV init for analyzed-iterations loops
std::vector<STARSExpression *> LoopIterationsLimitExprs; // indexed by loop number; primary BIV limit for analyzed-iterations loops
std::vector<STARSExpression *> LoopIterationsCountExprs; // indexed by loop number; primary BIV count for analyzed-iterations loops
std::vector<STARSExprSet> LoopMemWriteRangeExprs; // indexed by loop number; exprs describing memory writing ranges
std::vector<STARSExprBoundsSet> LoopMemWriteBoundsExprs; // indexed by loop number; pairs of <lower, upper> bounds exprs
std::vector<STARSExprBoundsSet> LoopMemWriteBoundsExprsExpanded; // indexed by loop number; lower/upper exprs expanded to InArg or constant address
std::vector<STARSExprSet > StringMemWriteRangeExprs; // indexed by loop number + 1; expr describing string writing range
std::vector<std::vector<std::pair<std::size_t, STARSExprSetIter> > > StringMemWriteRangeWidths; // width plus iters to relational range exprs
std::vector<STARSExprSet > RelationalLowerBoundExprs; // indexed by loop number + 1; lower bound expr split out from relational expr
std::vector<STARSExprSet > RelationalUpperBoundExprs; // indexed by loop number + 1; upper bound expr split out from relational expr
std::vector<std::list<std::pair<std::size_t, std::pair<STARSExprSetIter, STARSExprSetIter> > > > RelationalMemWriteWidths; // width plus iters to lower and upper bound exprs
std::vector<bool> NonStackFrameLoopMemWrites; // indexed by loop number; corresponding lower bound and/or upper bound expr is not just a local var
Clark Coleman
committed
std::vector<STARSInductionVarFamilyIter> LoopAnalyzedBIVIters; // indexed by loop number; iterator for BIV that was successfully analyzed for mem range & iteration count
std::vector<STARSExprSet > MemAddrExprsFromCallees; // non-loop mem addr exprs for this function after substitution of actual arg sources; indexed by LoopNum+1
std::vector<std::vector<std::pair<STARSExprSetIter, std::size_t> > > MemAddrExprWidthsFromCallees; // mem write byte widths for MemAddrExprsFromCallees. indexed by LoopNum + 1
std::vector<std::set<int> > LoopRegHashSets; // indexed by loop #; reg+SSA hashes for regs whose value is copied to another reg that is used for loop mem writes; not used directly as address reg for write
STARSExprSet LoopMemAddrRegSourceExprs; // Expanded exprs for regs in LoopRegHashSets
std::vector<std::list<std::pair<STARS_regnum_t, STARSExprSetIter> > > LoopRegSourceExprPairs; // map register to incoming-to-loop expr, indexed by loop #
std::vector<std::set<STARS_ea_t> > LoopIVUsedAsStringWriteCounter; // loop induction var InsideLoopDefAddrs that are used as RCX counter reg for looping string writes
clc5q
committed
// NOTE: The following two containers are indexed by [LoopNum+1]; if call inst is outside loop, LoopNum == -1 producing index 0.
std::vector<STARSExprSet > LoopMemAddrExprsFromCalleeLoops; // callee loop mem addr exprs for this function after substitution of actual arg sources
std::vector<std::list<std::pair<STARSExprSetIter, std::size_t> > > LoopMemAddrExprWidthsFromCalleeLoops; // mem write byte widths for LoopMemAddrExprsFromCallees
std::vector<std::vector<bool> > NonStackFrameCalleeMemWrites; // corresponding MemAddrExprWidthsFromCallees.first expr is not just a local var; indexed by LoopNum + 1
std::vector<STARSExprSet > LoopMemAddrExprsFromCallees; // mem addr exprs, indexed by loop, after substitution of actual arg sources
std::vector<std::vector<std::pair<STARSExprSetIter, std::size_t> > > LoopMemAddrExprWidthsFromCallees; // mem write byte widths for LoopMemAddrExprsFromCallees
std::vector<STARSExprSet > StoppedOnIVMemRangeExprs; // indexed by LoopNum+1; STARSExpression::Expand() stopped on hitting an induction variable, needs further analysis
std::vector<STARSExprSet > StoppedOnIVNonRangeExprs; // indexed by LoopNum+1; STARSExpression::Expand() stopped on hitting an induction variable, needs further analysis
std::vector<std::vector<std::pair<STARSExprSetIter, std::size_t> > > StoppedOnIVMemRangeIterWidths; // widths and iterators pointing to StoppedOnIVMemRangeExprs
std::vector<std::vector<std::pair<STARSExprSetIter, std::size_t> > > StoppedOnIVNonRangeIterWidths; // widths and iterators pointing to StoppedOnIVNonRangeExprs
clc5q
committed
// Temporary containers used only in the SPARK output stage for the current loop procedure being output.
// They are saved in these containers to be shared across the pre- and post-condition output stages.
// The saving is done by AggregateLoopMemExprs().
STARSExprSet TempLowerBoundsExprs;
STARSExprSet TempUpperBoundsExprs;
STARSExprSet TempNonRangeExprs;
std::vector<std::pair<STARSExprSetIter, STARSExprSetIter> > TempRangeExprWidthIters;
std::vector<std::pair<std::size_t, STARSExprSetIter> > TempNonRangeExprWidthIters;
std::vector<std::bitset<1 + MD_LAST_REG_NO> > LoopMemRangeInArgRegsBitmap; // indexed by loop number; memory writing range expr regs for each loop
std::vector<std::map<STARS_regnum_t, STARS_ea_t> > LoopBoundaryInArgRegs; // indexed by loop number; map InArg reg # to DefAddr that is live into the loop if InArg reg is used in mem range exprs
std::vector<std::set<STARS_ea_t> > LoopInvariantDEFs; // for each loop #, set of inst IDs in which first non-flags DEF is loop-invariant for its innermost containing loop
clc5q
committed
std::vector<STARSExprSet > InArgsUsedInMemWrites; // InArgs (or global static ops) used for loop-invariant mem writes (perhaps after copying the InArg)
std::vector<std::vector<std::pair<STARSExprSetIter, std::size_t> > > InArgsUsedInMemWriteByteWidths; // byte widths for each element of InArgsUsedInMemWrites; indexed by LoopNum+1
std::vector<bool> LoopMemExprsExpandToStackOffsets; // At least one of mem lower or upper bounds or init expr are just stack offsets when Expr->Expand() is done.
STARSInArgMap MemWriteToInArgMap; // mem write address reg at STARS_ea_t is copy of InArg found in STARSOpndTypePtr
std::vector<int> DFSMarkers; // vector indexed by block number, -1 => unvisited, 0 => visited but not all descendants visited, 1 => completed
std::map<STARS_ea_t, uint16_t> JumpToFollowNodeCounterMap; // map addr of follow-block to count of jumps seen to it within if-then-[elsif-else] structure
std::map<int, STARS_ea_t> GlobalDefAddrBySSA; // map hash of global name & SSANum to DEF inst addr
// If global DEF for that SSA is found in a Phi function, we use block number instead of inst addr
// Instruction addresses should never overlap block #s, as block #s start at 0 and top out at a few hundred.
// NOTE: We are currently limiting this map to registers, not all global names.
std::map<int64_t, STARS_ea_t> GlobalStackDefAddrBySSA; // map hash of normalized stack offset & SSANum to DEF inst addr
std::map<int, struct FineGrainedInfo> GlobalDefFGInfoBySSA; // map hash of global name & SSANum to DEF FG info.
// NOTE: We are currently limiting this map to registers, not all global names.
std::map<int, struct FineGrainedInfo> GlobalUseFGInfoBySSA; // map hash of global name & SSANum to USE FG info.
// NOTE: We are currently limiting this map to registers, not all global names.
std::map<STARS_ea_t, struct FineGrainedInfo> StackDefFGInfo; // map stack FG info to instruction address of stack def; UNUSED
std::map<STARS_ea_t, struct FineGrainedInfo> StackUseFGInfo; // map stack FG info to instruction address of stack use; UNUSED
std::map<STARS_ea_t, STARSOpndTypePtr> LeaInstOpMap; // map original Lea instruction pseudo-memory operand to instruction address.
std::map<STARS_ea_t, unsigned short> ControlFlowMap; // map InstAddr of each jump or branch to a type suitable for SPARK Ada translation.
std::map<int, struct STARS_SCCP_Const_Struct> ConstantDefs; // map hash of global name & SSANum to constant value from SCCP.
// NOTE: We are currently limiting this map to registers, not all global names. Flags are tracked separately (e.g.
// carry flag, zero flag) only in this SCCP data structure, whereas SSA form, DEFs, USEs and LVA sets have the flags
// register tracked in aggregate.
clc5q
committed
// Two sets used in live variable analysis. LiveIn and UpExposed can be obtained from Blocks.front().
Clark Coleman
committed
STARSOpndSet KillSet; // registers killed in this function
STARSOpndSet LiveOutSet; // Live-Out registers in this function
// Tracking stack pointer and frame pointer saves, copies, and restores
std::set<std::pair<STARSOpndTypePtr, std::pair<STARS_ea_t, STARS_sval_t> >, LessStackDeltaCopy> StackPtrCopySet; // triple: operand holding copy, InstAddr where copy is made, stack delta for copy
std::list<std::pair<STARS_ea_t, STARS_sval_t> > TempStackDeltaReachesList; // Used for temporary lookups of particular op_t in StackPtrCopySet.
std::set<STARS_ea_t, LessAddr> TempReachingDefs; // Temporary list of InstAddrs with defs of one op_t that reach a particular InstAddr.
std::map<STARSDefinition, STARSOpndTypePtr, LessDefinition> NormalizedStackOpsMap; // normalized stack operands, indexed by instruction address (for lookup from RTLs).
std::map<STARSDefinition, std::map<STARSDefinition, STARSOpndTypePtr, LessDefinition>::iterator, LessDefinition> InverseNormalizedStackOpsMap; // index: normalized op,
// mapped to: iterator into NormalizedStackOpsMap; only for use in functions that call alloca() and need to re-normalize stack ops repeatedly
clc5q
committed
std::bitset<1 + MD_LAST_REG_NO> PreservedRegsBitmap; // Registers that are saved on entry and restored before return from func, or never used, as a bitmap.
std::bitset<1 + MD_LAST_REG_NO> CallerSavedLocalRegsBitmap; // Reg numbers that are local names and are caller-saved
std::bitset<1 + MD_LAST_REG_NO> MemRangeRegsBitmap; // Reg numbers that are used in defining the memory writing range expr
std::bitset<1 + MD_LAST_REG_NO> InputRegs; // Reg numbers that are USEd in non-SSA, non-call, non-return instructions
std::bitset<1 + MD_LAST_REG_NO> OutputRegs; // Reg numbers that are DEFed in non-SSA, non-call, non-return instructions
std::bitset<1 + MD_LAST_REG_NO> CalleePreservedRegs; // Union of PreservedRegs sets of callees
std::vector<std::bitset<1 + MD_LAST_REG_NO> > OutputRegsByLoop; // save results of AnalyzeLoopGlobals() for each loop to emit Loop_Invariants
std::vector<std::bitset<1 + MD_LAST_REG_NO> > CalleePreservedRegsByLoop; // callee chain (from each loop) preserved regs since they were last altered
std::set<STARS_ea_t> ConstantIndirCalls; // addresses with indir calls that go to a constant address
std::list<std::pair<int, std::pair<int, int> > > SPARKLoopWorkList; // Worklist of loops to be translated to procs; pair<LoopIndex, pair<HeaderBlockNum, FollowBlockNum> >
std::list<SPARKTranslationCFType> SPARKControlStack; // stack of what CFG structure we are translating.
clc5q
committed
std::map<STARS_ea_t, STARS_ea_t> LoopToGuardMap; // map address of loop to address of guard if we have simple "if cond then ... loop ... endloop .. endif"
std::map<STARS_ea_t, STARS_ea_t> GuardToLoopMap; // inverse map of COND_BRANCH addr of guard to loop address for guarded loop
std::map<STARS_ea_t, std::size_t> SwitchJumpMap; // map inst ID of indirect jump to switch statement #; switch statements are
// numbered starting at zero as they are encountered in a post-order traversal of the graph
std::vector<struct SwitchTableInfo> SwitchInfoArray; // same index as the size_t value in SwitchJumpMap
std::vector<STARSBitSet> InArgPointerCopies; // indexed by GlobalNameIndex, bitset indexed by SSA #, bit set to 1 => copy of InArg of CODEPTR or POINTER type
std::vector<std::set<STARS_ea_t> > InArgPointerCopyAddrs; // Indexed by GlobalNameIndex, addrs where copies of POINTER or CODEPTR InArg are made
std::map<unsigned int, std::size_t> GlobalNameIndexMapToInArgIndex; // indexed by GlobalNameIndex, returns InArg position index, zero-based
std::map<std::size_t, STARSOpndTypePtr> InArgIndexMapToOperand; // indexed by InArg position
ShadowSet AlreadyShadowed; // avoid infinite recursion in FindShadowingPoint()
DefOrUseList TempShadowList; // all Refs being analyzed in current FindShadowingPoint() recursion chain
Clark Coleman
committed
std::map<STARS_ea_t, STARS_ea_t> MallocCallInArgsMap; // map addr of malloc(size) call inst to addr of size arg pass
std::map<STARS_ea_t, STARSDefinitionSet > BufferCallInArgsMap; // map addr of libfunc(bufferptr) call inst to (op, addr) of arg pass
typedef std::map<STARS_ea_t, std::list<std::pair<std::size_t, STARS_uval_t> > > STARSBufferCallArgMap;
STARSBufferCallArgMap BufferCallConstBufferArgsMap; // list of (bufptrargpos, bufsize) indexed by CallAddr
clc5q
committed
void DestroyLoopExprs(void); // release loop-based symbolic memory access expressions
void EraseInstRange(STARS_ea_t FirstAddr, STARS_ea_t LastAddr);
void SetLinks(void); // Link basic blocks and map instructions to blocks
bool FindDistantCodeFragment(STARS_ea_t TargetAddr); // Is TargetAddr the start of a code fragment that belongs to this func, not a separate func?
bool AnalyzeStackPointerDeltas(void); // Analyze changes in stack pointer for all instructions; return AnalyzedSP
bool UseIDAStackPointerDeltas(void); // Use IDA Pro values instead of doing our own analysis
bool AddToStackPtrCopySet(STARSOpndTypePtr CopyOp, STARS_ea_t InstAddr, STARS_sval_t StackDelta); // return true if inserted, false if present already (update delta in that case)
clc5q
committed
void FindPreservedRegs(void); // Determined which regs are not killed by func or its callees; set bits in PreservedRegsBitmap
clc5q
committed
void AuditCallingConvention(void); // Find failure to preserve callee-saved regs
clc5q
committed
void FindAllAllocsAndDeallocs(void); // Find all stack frame allocating and deallocating instructions and stack ptr offsets
void FindFramePointerDelta(void); // Compute FramePointerStackDelta
void SetStackFrameInfo(void); // Figure out the stack frame regions, and locate the alloc/dealloc frame instructions.
bool MDFixFrameInfo(void); // Redefine stack regions for our needs
void BuildLocalVarTable(void); // Determine local variable boundaries on the stack
void BuildStackAccessTables(void); // Build tables to characterize stack accesses.
void UpdateMinMaxStackOffsets(SMPInstr *CurrInst, const STARSOpndTypePtr &TempOp); // Update MinStackAccessOffset and MaxStackAccessLimit if TempOp is stack access
inline void SetStackFrameExtendsPastStackTop(void) { StackFrameExtendsPastStackTop = true; };
bool IndexedWritesAboveLocalFrame(const STARSOpndTypePtr &DestOp); // Is DestOp direct stack write to caller's frame?
bool MDGetStackOffsetAndSize(SMPInstr *Instr, const STARSOpndTypePtr &TempOp, STARS_sval_t BaseValue, STARS_ea_t &offset, std::size_t &DataSize,
bool &FP, bool &Indexed, bool &Signed, bool &Unsigned); // Find any stack memory access in TempOp, return offset, size,
// whether the Frame Pointer was used and signedness (if sign-extended or zero-extended).
bool FindAlloca(void); // true if found evidence of alloca() allocations
void MDFindSavedRegs(void); // Fill in SavedRegLoc[] offsets
void DetectMultiEntryFunction(void); // Detect multiple-entry-point func; probably IDA Pro error; not safe for fast returns.
void DetectLinkerStubFunction(void); // Determine whether func is a linker stub, e.g. a PLT stub
clc5q
committed
void DetectThunkFunction(void); // Detect function that just puts its return address into a reg and returns.
void MDAuditJumpXrefs(void); // Fix missing IDA Pro jump code xrefs
void RebuildCallTargets(void); // Rebuild AllCallTargets as the union of the direct and indirect call targets.
void EmitStackFrameAnnotations(FILE *AnnotFile, SMPInstr *Instr);
void ComputeIDoms(void); // Compute immediate dominators of all blocks into IDom[]
int IntersectDoms(int, int) const; // Find Dom intersection (as IDom[] index) for 2 blocks
void ComputeDomFrontiers(void); // Compute dominance frontiers for all blocks
void ComputeGlobalNames(void); // Compute the GlobalNames set
void ComputeBlocksDefinedIn(void); // Compute the BlocksDefinedIn vector
void InsertPhiFunctions(void); // Insert SSA phi functions at top of each basic block
void BuildDominatorTree(void); // Build the DomTree structure
bool TestCFGReducibility(void); // return true if CFG is a reducible graph.
bool CFGReducibilityHelper(std::size_t BlockNumber); // recursive depth-first-search helper for TestCFGReducibility()
int SSANewNumber(std::size_t GlobNameIndex); // SSA helper: increment and return SSA number
void SSARename(int BlockNumber); // SSA main helper: rename throughout block
void SSARenumber(void); // Renumber SSA subscripts for all names
void AnalyzeSystemCalls(void); // Analyze system calls for memory overwriting safety
void DetectUninitializedVars(void); // Find variables that are USEd before they are DEFed
void FindLoopHeadsAndTails(SMPBasicBlock *CurrBlock); // Detect loop head and/or tail block for loops and record in data structures
bool IsBlockNumLoopHeader(const int BlockNum, std::size_t &LoopNum) const; // Is BlockNum already in this->LoopHeadBlockNumbers? If so, put index in LoopNum
void FindLoopBlocksFromTailToHeader(const std::size_t LoopNumber, const int HeadBlockNum, std::list<SMPBasicBlock *>::iterator BlockIter, int &DoubleTailFollowBlockNum); // populate FuncLoopsByBlock and FuncBlocksByLoop data structures for DetectLoops()
void DetectLoops(void); // Detect which blocks are in which loops and populate FuncLoopsByBlock and FuncBlocksByLoop data structures.
void ClassifyLoop(std::size_t LoopNumber, int HeaderExitFollowNum, int TailExitFollowNum, SMPBasicBlock *CurrBlock, SMPBasicBlock *HeadBlock, bool HeaderBlockExitsLoop, bool TailBlockExitsLoop); // classify LoopNumber loop as top, middle, or bottom testing
bool DoesBlockExitLoop(std::size_t LoopNumber, SMPBasicBlock *LoopBlock, int &FollowBlockNum); // return true if block can exit the loop.
void DetectLoopInvariantDEFs(void); // Collect a set of loop-invariant DEFs with the inst IDs of the DEFs.
void DetectLoopInvariantDEFs2(void); // Collect a set of loop-invariant DEFs with the inst IDs of the DEFs.
bool IsUseLoopInvariantDEF(std::size_t LoopIndex, const STARSOpndTypePtr &UseOp, SMPInstr *UseInst); // Track UseOp to its DEF, see if loop-invariant for LoopIndex
void DetectLoopInductionVars(void); // Detect basic and dependent loop induction variable families for all loops
void FindDependentInductionVar(std::size_t LoopIndex, struct DependentInductionVar &DIV, STARSOpndTypePtr Add1, STARSOpndTypePtr Add2, STARSOpndTypePtr Mult1, STARSOpndTypePtr Mult2, SMPoperator RhsOperator, SMPInstr *DefInst); // pass in results of DefInst::IsDependentInductionVarArithmetic()
bool ReplaceLoopRegWithConst(std::size_t LoopIndex, STARSOpndTypePtr &RegOp, SMPInstr *UseInst); // If RegOp USE in UseInst is an SCCP constant, create an immediate operand for it.
STARSExpression *CreateLimitExpr(const std::size_t &LoopIndex, const struct InductionVarFamily &IVFamily, const struct LoopComparison &LoopCompExpr); // Create loop limit expr: BIVOpnd relationaloperator Opnd2
Clark Coleman
committed
STARSExpression *CreateSecondaryBIVLimitExpr(const std::size_t &LoopIndex, const struct InductionVarFamily &IVFamily); // Create loop limit expr: BIVOpnd_InitExpr + (stride * IterationCountExpr)
STARSExpression *CreateDIVInitExpr(const std::size_t &LoopIndex, const struct InductionVarFamily &IVFamily, const std::size_t DIVIndex); // Create DIV init expr as linear function of its BIV init expr
STARSExpression *CreateDIVLimitExpr(const std::size_t &LoopIndex, const struct InductionVarFamily &IVFamily, const std::size_t DIVIndex); // Create DIV limit expr as linear function of its BIV limit expr
STARSExpression *CreateIterationsExpr(std::size_t LoopIndex, const struct InductionVarFamily &IVFamily, bool PositiveIncrement, STARSExpression *InitExpr, STARSExpression *LimitExpr); // Create loop iteration count expr
bool CreateSPARKMemoryWriteRangeExpr(std::size_t LoopIndex, bool RecordLoopRegs, std::set<int> &LoopRegHashes, STARSExprSet &MemWriteExprs, STARSMemWriteExprsList &MemWriteExprWidths, std::vector<std::set<STARS_ea_t> > &StackPtrCopiesVector); // Create a Memory range expression set for indirect or indexed memory writes in the loop; return true on success
void CombineMemoryExprs(STARSMemWriteExprsList &MemWriteExprWidths, STARSExprSet &MemWriteExprs, std::vector<std::set<STARS_ea_t> > &StackPtrCopies); // Combine items in the expr set that have common regs, e.g. (RDI+1) and (RDI-2), into fewer set entries
bool CreateSPARKMemoryReadRangeExprs(std::size_t LoopIndex, bool RecordLoopRegs, std::set<int> &LoopRegHashes, STARSExprSet &MemWriteExprs, STARSMemWriteExprsList &MemWriteExprWidths, std::vector<std::set<STARS_ea_t> > &StackPtrCopiesVector); // Create a Memory range expression set for indirect or indexed memory writes in the loop; return true on success
bool ReplaceBIVWithExpr(std::size_t LoopIndex, const struct InductionVarFamily &IVFamily, STARSExpression *CurrExpr, bool InitCase); // Replace occurrences of IVFamily.BIV in CurrExpr with BIV InitExpr or LimitExpr
bool ReplaceAllBIVsWithExprs(std::size_t LoopIndex, STARSExpression *CurrExpr, bool InitCase, bool &changed); // Replace all BIVs in CurrExpr with lower or upper limit (depending on InitCase) exprs for BIV
bool ReplaceAllDIVsWithExprs(std::size_t LoopIndex, STARSExpression *CurrExpr, bool InitCase, bool &changed); // Replace all DIVs in CurrExpr with lower or upper limit (depending on InitCase) exprs for DIV
bool ReplaceAllIVsWithExprs(std::size_t LoopIndex, STARSExpression *CurrExpr, bool InitCase, bool &changed); // wrapper to call ReplaceAllBIVsWithExprs() and ReplaceAllDIVsWithExprs()
bool ExpandExprToInArgs(std::size_t LoopIndex, STARSExpression *CurrExpr, bool InitCase, std::set<STARS_ea_t> &StackPtrCopySet); // expand, replace IVs, simplify, until no more can be done
clc5q
committed
void DetectInArgRegsNeededForMemWriteExprs(void); // Fill in LoopMemRangeInArgRegsBitmap and MemRangeRegsBitmap
void ExpandLoopRegHashExprs(void); // take LoopRegHashSets and expand into LoopMemAddrRegSourceExprs
bool InheritCalleeMemExpr(std::size_t MemExprWidth, STARSExpression *CurrentMemAddrExpr, SMPInstr *CallInst, int LoopNum, const std::list<std::size_t> &LoopList); // return true if expr inherited
bool InheritCalleeMemRangeExpr(STARSExpression *CalleeMemRangeExpr, SMPInstr *CallInst, std::size_t MemWriteByteWidth, std::size_t LoopNumPlusOne, const std::list<std::size_t> &LoopList); // return true if expr inherited
void SplitAndSaveRelationalExpr(bool PositiveIncrement, std::size_t LoopNumPlusOne, std::size_t MemWidth, STARSExpression *RangeExpr); // Split relational RangeExpr into upper and lower bonds exprs and save them and their width
void TraceInArgPointers(void); // helper for TraceIncomingArgs(), focused on CODEPTR and POINTER types
void RemoveLocalRefs(STARSDefUseSet &RefSet); // Remove non-global SSA names from RefSet.
bool FindShadowingPoint2(const ShadowPoint CriticalOp, const bool TracingMemWrite, ShadowSet &ShadowAddrSet, bool &MemUnsafe, ShadowSet &NewCriticalOps, bool &NonConstSourceFound, std::set<STARS_uval_t> &ConstValues); // Trace CriticalOp via copies back to ShadowOp, return false if no shadowing possible
bool AnalyzeMemWriteSafety(void); // Try to find safe indirect memory writes
void UpdateLoopFollowBlockNum(int HeaderBlockNum, int FollowBlockNum);
int FindFollowBlockNum(SMPBasicBlock *CurrBlock, bool StartAtLastInst = false); // Based on control flow structure of CurrBlock, find Ada follow block num; -1 if no structure besides fall-through
bool AnalyzeSwitchStatement(SMPBasicBlock *CurrBlock); // Analyze switch starting at indir jump at end of CurrBlock; return false if not well-structured
void FindSwitchIDom(struct SwitchTableInfo &TableInfo); // Mark jumps to default case, find IDom of entire switch statement
void BuildShadowCFG(void); // build skeleton CFG, then use in coalescing nodes to analyze expressions
void CoalesceShadowBlocks(int LeftBlockNum, int RightBlockNum, bool NegateLeft, SMPoperator TopOper, int NewFTNum, int NewNFTNum); // Make LeftExpr be LeftExpr TopOper RightExpr
bool AnalyzeCompoundConditionalStatements(void); // Analyze if-statements with short-circuit operators
bool AnalyzeConditionalStatements(void); // Analyze if-then-elses starting at COND_BRANCH at end of all blocks; return false if not well-structured
int FindConditionalFollowNode(int HeadBlockNum); // Find candidate block # for if-else follow node for HeadBlockNum; return -1 otherwise
int TrackConditionalBranchTerminus(int BranchHeadBlockNum, int CurrBlockNum, STARSBitSet &BlocksSeen, int &BlockAlreadySeenCounter); // Track CurrBlockNum until we reach block that BranchHeadBlockNum doesn't dominate, or dead end. Return block num, possibly SMP_BLOCKNUM_COMMON_RETURN.
clc5q
committed
void FindGuardedLoops(void); // Find guarded loops and fill the GuardToLoopMap and LoopToGuardMap
clc5q
committed
bool IsSPARKLoopInTranslationStack(void) const; // Are we already translating a SPARK_LOOP when we encounter another loop?
void UpdateStackBytesWrittenByLoop(STARS_sval_t FinalStackPtrOffset, std::size_t MemWidth, std::size_t LoopNum); // update {Nega, Posi}tiveStackBytesWrittenByLoop[LoopNum]
void EmitAnalysisProblemWarnings(FILE *HeaderFile, int LoopIndex); // LoopIndex == -1 indicates main procedure; print warnings if proofs will fail
void EmitSPARKSavedArgs(FILE *BodyFile) const; // Save incoming args as locals to preserve their values
void EmitSPARKArgs(FILE *BodyFile, FILE *HeaderFile, bool Signature, std::size_t LoopIndex) const; // Emit loop function args, as Signature to HeaderFile or proc call to BodyFile.
void EmitSPARKProcPrePostMemConditions(FILE *BodyFile, FILE *HeaderFile, bool PreconditionSection); // Emit mem writing ranges for pre- and post-conditions
void EmitSPARKMemRange(FILE *HeaderFile, bool PreconditionSection, bool ProcessingLoop, bool HasArgs, STARSExpression *LowerExpr, STARSExpression *UpperExpr, std::size_t &OutputCount, std::size_t MemWidth); // helper for EmitSPARKProcPrePostMemConditions()
void EmitSPARKPrePostMemConditionsFromCalleeNonLoopWrites(FILE *HeaderFile, bool PreconditionSection, size_t LoopIndexPlusOne, std::size_t &OutputCount); // helper for EmitSPARKProcPrePostMemConditions()
void EmitSPARKPrePostMemConditionsFromCalleeLoops(FILE *HeaderFile, bool PreconditionSection, std::size_t &OutputCount); // helper for EmitSPARKProcPrePostMemConditions()
clc5q
committed
void AggregateLoopMemExprs(std::size_t LoopIndex); // collect temporary containers of mem exprs for one loop.
clc5q
committed
bool NeedsSPARKPreconditions(bool &HasLoopMemWrites, bool &HasNonLoopInArgMemWrites, bool &HasCalleeMemWrites, bool &HasCalleeLoopMemWrites); // Determine if any mem writes (or callee mem writes) are not just to the stack frame locals.
bool LoopRequiresNonStackPreconditions(size_t LoopIndex); // Loop indirect writes require pre-conditions
std::string EmitSPARKProcForLoopHeaderBlock(int LoopIndex, int HeaderBlockNum, int FollowBlockNum, FILE *BodyFile, FILE *HeaderFile); // Create SPARK procedure for loop starting at HeaderBlockNum
void AnalyzeLoopGlobals(int HeaderBlockNum, int FollowBlockNum, STARS_ea_t LoopAddr, bool &MemoryInput, bool &MemoryOutput, std::bitset<1 + MD_LAST_REG_NO> &InputRegs, std::bitset<1 + MD_LAST_REG_NO> &OutputRegs, std::bitset<1 + MD_LAST_REG_NO> &CalleePreservedRegs); // Analyze reg and mem accesses in loop
void EmitSPARKLoopProcGlobals(FILE *BodyFile, FILE *HeaderFile, bool MemoryInput, bool MemoryOutput, const std::bitset<1 + MD_LAST_REG_NO> &InputRegs, const std::bitset<1 + MD_LAST_REG_NO> &OutputRegs, const std::bitset<1 + MD_LAST_REG_NO> &CalleePreservedRegs); // emit Input, Output, In_Out flow annotations
void EmitSPARKAdaForBlock(int CurrBlockNum, int FollowBlockNum, FILE *SPARKBodyFile, bool ReadytoEmitSwitchDefault, bool LoopToProc = false); // recursive descent translation to SPARK Ada starting with CurrBlock, stop before Follow Block
void EmitSPARKAdaForLoop(int HeaderBlockNum, int FollowBlockNum, FILE *SPARKBodyFile); // recursive descent translation of loop to SPARK Ada starting with header CurrBlock, stop before Follow Block
void EmitSPARKAdaForSwitch(int HeaderBlockNum, int FollowBlockNum, FILE *SPARKBodyFile); // recursive descent translation of switch statement starting with INDIR_JUMP block, stop before Follow Block
void EmitSPARKAdaForConditional(int HeaderBlockNum, int FollowBlockNum, FILE *SPARKBodyFile); // recursive descent translation of if-else statement starting with COND_BRANCH block, stop before Follow Block
void EmitSPARKAdaLoopCall(STARS_ea_t LoopAddr, std::size_t LoopIndex, FILE *SPARKBodyFile); // emit call to loop proc that will be created later starting at LoopAddr
void FreeSSAMemory(void); // After SSA #s are in DEFs and USEs, free SSA data structures.
bool FindSwitchStatementFollowBlock(struct SwitchTableInfo &TableInfo); // return false if no consistent follow block
int FindCaseFollowBlock(int CaseBlockNum, int HeaderBlockNum, std::size_t IncomingEdgeCount) const; // Start at CaseBlockNum, return followblocknum with IncomingEdgeCount