Skip to content
Snippets Groups Projects
SMPFunction.h 54.4 KiB
Newer Older
jdh8d's avatar
jdh8d committed
/*
 * 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/
 *
jdh8d's avatar
jdh8d committed
 */

#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 <list>
#include <vector>
#include <map>
#include <set>

#include <cstddef>
#include "interfaces/STARSTypes.h"
#include "interfaces/SMPDBInterface.h"
#include "base/SMPDataFlowAnalysis.h"
#include "base/SMPInstr.h"
#include "base/SMPBasicBlock.h"
#include "base/ProfilerInformation.h"
class SMPProgram;	// forward declaration so we can declare a pointer to an SMPProgram
class STARS_IDA_Function_t;
class STARS_IRDB_Function_t;
#define SMP_DEBUG_STACK_GRANULARITY 0

// What is the default change to the stack pointer for a function?
//  NOTE: When we start handling different calling conventions beyond
//  the gcc model, we will have to make this a variable that gets
//  initialized.
#define CALLING_CONVENTION_DEFAULT_FUNCTION_STACK_DELTA global_STARS_program->GetSTARS_ISA_Bytewidth()

// 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()))
// 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.
// Emit CS: or FS: or GS: etc. segment reg prefix if found in operand
#define STARS_SPARK_EMIT_SEGMENT_REGS 0   

	char VarName[MAXSMPVARSTR];
// 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,
	RAUNSAFE_CALLEES = 64,
	MAKES_TAIL_CALL = 128,
	MULTIPLE_ENTRY_POINTS = 256,
clc5q's avatar
clc5q committed
	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
};

// Analyze control flow for structuring and decompilation into high level language
clc5q's avatar
clc5q committed
enum ControlFlowType {
	FALL_THROUGH = 0,
	BRANCH_IF_THEN = 1, // cond_branch around body within then-clause, no else-clause
	BRANCH_IF_THEN_ELSE = 2, // cond_branch around then-clause to else clause
	// JUMP_BEFORE_ELSE = 3,   // at the end of then section of if-then-else and before an ensuing else block
	LOOP_BACK = 4,  // back edge from loop tail block to loop header block
	LOOP_EXIT = 5,  // loop exit jump, becomes exit or exit-when in Ada
clc5q's avatar
clc5q committed
	JUMP_INTO_LOOP_TEST = 6, // jump to loop test block for first iteration of an optimized top-testing loop with loop test moved to the bottom
	JUMP_TO_DEFAULT_CASE = 7,  // jump to default case of a switch statement
	CASE_BREAK_TO_FOLLOW_NODE = 8, // jump at end of case in a switch statement to reach the switch follow node
	JUMP_TO_SWITCH_INDIR_JUMP = 9  // jump around default case or preliminary calculations to INDIR_JUMP block for switch
clc5q's avatar
clc5q committed
// 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

static char StaticFuncName[MAXSMPSTR];

// Class encapsulating all that the SMP static analyzer cares to know
//  about a function.
class SMPFunction {
public:
	// Constructors and destructors.
jdh8d's avatar
jdh8d committed
	SMPFunction(STARS_Function_t *Info, SMPProgram *pgm);  // Default constructor
	~SMPFunction();
clc5q's avatar
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; 
	};
jdh8d's avatar
jdh8d committed
	STARS_Function_t *GetFuncInfo(void) const;
	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; };
	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; };
	inline std::set<STARSOpndTypePtr, LessOp>::iterator GetFirstGlobalName(void) { return GlobalNames.begin(); };
	inline std::set<STARSOpndTypePtr, LessOp>::iterator GetLastGlobalName(void) { return GlobalNames.end(); };
	inline std::size_t NumGlobalNames(void) { return GlobalNames.size(); };
	inline std::set<STARSOpndTypePtr, LessOp>::iterator FindGlobalName(const STARSOpndTypePtr &SearchOp) { return GlobalNames.find(SearchOp); };
	inline std::list<SMPInstr *>::iterator GetFirstInstIter(void) { return Instrs.begin(); };
clc5q's avatar
clc5q committed
	inline std::list<SMPInstr *>::iterator GetLastInstIter(void) { return Instrs.end(); };
	std::set<STARSOpndTypePtr, LessOp>::iterator GetFirstLiveIn(void); // LiveInSet.begin()
	std::set<STARSOpndTypePtr, LessOp>::iterator GetLastLiveIn(void); // LiveInSet.end()
	std::set<STARSOpndTypePtr, LessOp>::iterator GetFirstLiveOut(void); // LiveOutSet.begin()
	std::set<STARSOpndTypePtr, LessOp>::iterator GetLastLiveOut(void); // LiveOutSet.end()
	std::set<STARSOpndTypePtr, LessOp>::iterator GetFirstVarKill(void); // KillSet.begin()
	std::set<STARSOpndTypePtr, LessOp>::iterator GetLastVarKill(void); // KillSet.end()
	inline FuncType GetReturnAddressStatus(void) const { return ReturnAddrStatus; };
	inline unsigned short GetFastReturnStatus(void) const { return FastReturnStatus; };
jdh8d's avatar
jdh8d committed

	// exposing the start address of the function. Used in RecurseAndMark
	inline const STARS_ea_t GetStartAddr(void) const { return FirstEA; }; 
jdh8d's avatar
jdh8d committed

	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 GetGlobalDefAddr(const STARSOpndTypePtr &DefOp, int SSANum); // retrieve from GlobalDefAddrBySSA or return BADADDR
clc5q's avatar
clc5q committed
	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 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(uint16_t RegNum) const { return ((RegNum < ReturnRegTypes.size()) ? (int) ReturnRegTypes[RegNum] : 0); };
	inline struct FineGrainedInfo GetReturnRegFGInfo(uint16_t RegNum) const { return ReturnRegFGInfo.at(RegNum); };
	inline std::size_t GetReturnRegFGInfoSize(void) const { return ReturnRegFGInfo.size(); };
	SMPOperandType GetIncomingRegType(uint16_t RegNum); // Get reg type from all call sites.
	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(); };
	inline std::map<int, struct STARS_SCCP_Const_Struct>::iterator FindConstValue(int DefHashValue) { return ConstantDefs.find(DefHashValue); };
	inline std::map<int, struct STARS_SCCP_Const_Struct>::iterator GetLastConstValueIter(void) { return ConstantDefs.end(); };
	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 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.
	// 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; };
	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 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 SetHasHashingCode(bool Hashes) { HasHashingCode = Hashes; };
	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 SetMaxStackSSANum(int NewMaxSSANum) { MaxDirectStackAccessSSANum = NewMaxSSANum; };
	inline void SetMaxRegSSANum(int NewMaxSSANum) { MaxRegSSANum = NewMaxSSANum; };
	inline void SetCallerSavedLocalReg(uint16_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 SetControlFlowType(STARS_ea_t InstAddr, ControlFlowType JumpTypeCode); // insert into ControlFlowMap
	std::map<int, struct STARS_SCCP_Const_Struct>::iterator InsertGlobalConstValue(int DefHashValue, struct STARS_SCCP_Const_Struct NewConstEntry); 
		// Insert SCCP value for global name; change if already found.
	// 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(); };
	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 IsDirectlyRecursive(void) const { return DirectlyRecursive; };
	inline bool IsMutuallyRecursive(void) const { return MutuallyRecursive; };
jdh8d's avatar
jdh8d committed
	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; };
clc5q's avatar
clc5q committed
	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; };
	inline bool IsInstIDInFunc(STARS_ea_t addr) { return this->FuncInfo->IsInstIDInFunc(addr); };
	inline bool IsLibFunc(void) const { return LibFunc; };
	inline bool IsLeaf(void) const { return (!IndirectCalls && (DirectCallTargets.empty() || ((1 == DirectCallTargets.size()) && IsDirectlyRecursive()))); };
	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
	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())); };
	inline bool IsLiveIn(const STARSOpndTypePtr &CurrOp) const {
	inline bool IsLiveOut(const STARSOpndTypePtr &CurrOp) const {
		return (LiveOutSet.end() != LiveOutSet.find(CurrOp));
	}
	inline bool IsVarKill(const STARSOpndTypePtr &CurrOp) const {
		return (KillSet.end() != KillSet.find(CurrOp));
	}
	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 TranslatingLoopToProc(void) const { return TranslatingSPARKLoop; };
	inline bool IsMultiEntry(void) const { return MultipleEntryPoints; };
	// Printing methods
	void Dump(void); // debug dump
	// Analysis methods
	void ResetProcessedBlocks(void); // Set Processed flag to false in all blocks
	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.
	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.
	void ComputeGlobalSets(void); // compute LiveOut, Kill sets for function
	void AnalyzeFunc(void);  // Analyze all instructions in function
	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
	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.
clc5q's avatar
clc5q committed
	void EmitFuncSPARKAda(void); // Emit SPARK Ada translation of function
	void LiveVariableAnalysis(bool Recomputing);  // Perform Live Variable Analysis across all blocks
	void RecomputeSSA(void); // Recompute LVA and SSA and all dependent data structures now that unreachable blocks have been removed.
	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); // Is block (with block # BlockNum) inside any loop?
	bool IsBlockInLoop(int BlockNum, std::size_t LoopNum); // Is block (with block # BlockNum) inside loop # LoopNum?
	void BuildLoopList(int BlockNum, std::list<std::size_t> &LoopList); // build list of loop numbers that BlockNum is part of.
	void AliasAnalysis(void); // Find memory writes with possible aliases
	void InferTypes(bool FirstIter); // Determine NUMERIC, POINTER, etc. for all operands
	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, 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?
	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
	SMPProgram* Program;		// pointer to the program I'm part of
jdh8d's avatar
jdh8d committed
	STARS_Function_t *FuncInfo;
	STARS_ea_t FirstEA;   // address of first instruction in the function
#if 0
	char FuncName[MAXSMPSTR];
#endif
	int BlockCount; // number of basic blocks in the function
	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 DirectlyRecursive; // Calls itself
	bool MutuallyRecursive; // part of program call graph loop, or depends on loop funcs being processed first
jdh8d's avatar
jdh8d committed
//	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 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?
	bool AnalyzedSP; // Were stack pointer change points successfully analyzed?
	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
	bool HasUnsafeIndirectWrites; // Function has at least one unsafe indirect memory write
	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
	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()
	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
clc5q's avatar
clc5q committed
	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,
						  //  because they pop off the return address while returning.
	STARS_sval_t PreAllocStackDelta; // Stack delta right before stack frame allocation, to which the stack
								//  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)
	int MaxDirectStackAccessSSANum; // highest SSANum seen on stack locations.
	int MaxRegSSANum; // highest SSANum seen on registers
	int MaxLocalSSANum;
	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
	std::set<STARS_ea_t> JumpTableTargets; // code addresses found in jump tables for this func
	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;
	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
	std::set<STARSOpndTypePtr, LessOp> 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<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
clc5q's avatar
clc5q committed
	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
	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.
		// Two sets used in live variable analysis. LiveIn and UpExposed can be obtained from Blocks.front().
	std::set<STARSOpndTypePtr, LessOp> KillSet;   // registers killed in this function
	std::set<STARSOpndTypePtr, LessOp> 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<std::pair<STARSOpndTypePtr, STARS_ea_t>, STARSOpndTypePtr, LessDefinition> NormalizedStackOpsMap; // normalized stack operands, indexed by instruction address (for lookup from RTLs).
	std::map<std::pair<STARSOpndTypePtr, STARS_ea_t>, std::map<std::pair<STARSOpndTypePtr, STARS_ea_t>, 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
	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
clc5q's avatar
clc5q committed
	std::set<STARS_ea_t> LoopInvariantDEFs; // set of inst IDs in which first non-flags DEF is loop-invariant for its innermost containing loop
	std::set<STARS_ea_t> ConstantIndirCalls; // addresses with indir calls that go to a constant address
	std::list<std::pair<int, int> > SPARKLoopWorkList; // Worklist of loops to be translated to procs; pair<HeaderBlockNum, FollowBlockNum>
	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
	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)
	void FindPreservedRegs(void); // Determined which regs are not killed by func or its callees; set bits in PreservedRegsBitmap
	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
	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 DetectLoops(void); // Detect which blocks are in which loops and populate FuncLoopsByBlock data structure.
	bool DoesBlockExitLoop(std::size_t LoopNumber, SMPBasicBlock *LoopBlock, int &FollowBlockNum); // return true if block can exit the loop.
clc5q's avatar
clc5q committed
	void DetectLoopInvariantDEFs(void); // Collect a set of loop-invariant DEFs with the inst IDs of the DEFs.
	void TraceInArgPointers(void); // helper for TraceIncomingArgs(), focused on CODEPTR and POINTER types
	void RemoveLocalRefs(STARSDefUseSet &RefSet); // Remove non-global SSA names from RefSet.
	bool FindShadowingPoint(const STARS_ea_t ShadowCheckAddr, const STARSOpndTypePtr &CriticalOp, STARS_ea_t &ShadowAddr, STARSOpndTypePtr &ShadowOp); // Trace CriticalOp via copies back to ShadowOp, return true if mem-unsafe
	bool FindShadowingPoint2(const ShadowPoint CriticalOp, const bool TracingMemWrite, ShadowSet &ShadowAddrSet, bool &MemUnsafe, ShadowSet &NewCriticalOps); // 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 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
	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
clc5q's avatar
clc5q committed
	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
	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
	std::string EmitSPARKProcForLoopHeaderBlock(int HeaderBlockNum, int FollowBlockNum, FILE *BodyFile, FILE *HeaderFile); // Create SPARK procedure for loop starting at HeaderBlockNum
	void EmitSPARKProcGlobals(int HeaderBlockNum, int FollowBlockNum, FILE *BodyFile, FILE *HeaderFile); // 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, 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 
	std::size_t FindSwitchIndexForDefaultCaseAddr(STARS_ea_t DefaultCaseAddr) const; // Search SwitchInfoArray for DefaultCaseAddr, return index
	bool FindPossibleChainAlias(SMPInstr *CurrInst, const STARSOpndTypePtr &DefOp, int SSANum); 
	   // Does the DefOp DEF_USE chain starting at CurrInst contain an indirect mem write?
	bool FindChainAliasHelper(std::list<SMPBasicBlock *>::iterator CurrBlock, const STARSOpndTypePtr &DefOp);
		// recursive helper for global DefOp with DU-chain that traverses CFG
	void FindCounterVariables(void); // Mark NUMERIC (and propagate) any DEF that starts at small immed. value and gets only small inc/dec operations.
	bool CounterVarHelper(const STARSOpndTypePtr &DefOp, int DefSSANum, int BlockNum, bool LocalName, std::list<std::pair<int, STARS_ea_t> > &CounterSSANums); // recursive helper for FindCounterVariables()
	bool ConditionalTypePropagation(void); // Apply SCC algorithm to unresolved Phi DEFs
	bool PropagateSignedness(void); // Propagate signedness FG info from DEFs to USEs whenever there is no USE sign info.
	void MarkSpecialNumericErrorCases(void); // Detect and mark special cases before emitting numeric error annotations.
	void EmitReturnTargetAnnotations(void); // Emit Indirect Branch Target destinations for return instructions in this func.
	void EmitFuncPtrShadowingAnnotations(FILE *InfoAnnotFile); // Emit annotations for func ptr shadowing defense
	bool IsAlreadyShadowed(const ShadowPoint &CriticalOp); // Is CriticalOp already represented in AlreadyShadowed set?
	void EmitFuncPtrHelper(FILE *InfoAnnotFile, SMPInstr *CurrInst); // common code for different cases
	void EmitFuncPtrShadowingAnnotations2(FILE *InfoAnnotFile); // Emit annotations for func ptr shadowing defense
	bool MDFindReturnTypes(void); // Fill ReturnRegTypes[]
	void MDFindIncomingTypes(void); // Fill IncomingRegTypes[]
	bool IsCallerReturnAddressReadOrWritten(void); // Can the return address of any caller be read or written directly from this function?

	friend class STARS_IDA_Function_t;
	friend class STARS_IRDB_Function_t;
}; // end class SMPFunction

#endif