From cf0f5d4fa7710ac9e3530f48ea49ee879c980ca9 Mon Sep 17 00:00:00 2001
From: clc5q <clc5q@git.zephyr-software.com>
Date: Thu, 10 Aug 2017 02:03:24 +0000
Subject: [PATCH] Trace fptrs back to constant operands, emit COMPLETE xref
 annotations if all traces lead to constants.

Former-commit-id: 29251dbd5a2fffa953d7477cf782e8f0426406bf
---
 include/base/SMPFunction.h |  4 +--
 src/base/SMPFunction.cpp   | 64 +++++++++++++++++++++++++++++++-------
 2 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/include/base/SMPFunction.h b/include/base/SMPFunction.h
index 6554d10e..98f8e528 100644
--- a/include/base/SMPFunction.h
+++ b/include/base/SMPFunction.h
@@ -913,7 +913,7 @@ private:
 	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); // Trace CriticalOp via copies back to ShadowOp, return false if no shadowing possible
+	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
@@ -962,7 +962,7 @@ private:
 	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 EmitShadowingHelper(FILE *InfoAnnotFile, SMPInstr *CurrInst, bool FuncPtr); // common code for different cases in shadowing func ptr, critical args
+	void EmitShadowingHelper(FILE *InfoAnnotFile, SMPInstr *CurrInst, bool FuncPtr, STARS_ea_t CallAddr); // common code for different cases in shadowing func ptr, critical args
 	void EmitFuncPtrShadowingAnnotations2(FILE *InfoAnnotFile); // Emit annotations for func ptr shadowing defense
 	void EmitArgShadowingAnnotations(FILE *InfoAnnotFile); // Emit annotations for critical argument shadowing defense
 	bool MDFindReturnTypes(void); // Fill ReturnRegTypes[]
diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp
index df3b7ecb..ba8d70e4 100644
--- a/src/base/SMPFunction.cpp
+++ b/src/base/SMPFunction.cpp
@@ -13386,16 +13386,25 @@ bool SMPFunction::IsAlreadyShadowed(const ShadowPoint &CriticalOp) {
 // Trace CriticalOp via copies back to ShadowAddr, return false if no valid means of shadowing it.
 //  Add new CriticalOp shadow-checking points to NewCriticalOps, which will be shadowed with separate indices.
 //  If TracingMemWrite, terminate early when we can prove that CriticalOp was unsafe to use as address reg in memory write.
-bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool TracingMemWrite, ShadowSet &ShadowAddrSet, bool &MemUnsafe, ShadowSet &NewCriticalOps) {
+bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool TracingMemWrite, ShadowSet &ShadowAddrSet, bool &MemUnsafe, ShadowSet &NewCriticalOps, bool &NonConstSourceFound, set<STARS_uval_t> &ConstValues) {
 	bool UnsafeChain = false;
 	STARS_ea_t ShadowCheckAddr = CriticalOp.first;
 	STARSOpndTypePtr ShadowCheckUseOp = this->TempShadowList.GetRefNum(CriticalOp.second)->GetOp();
 
 	bool DataFlowOpnd = MDIsDataFlowOpnd(ShadowCheckUseOp, this->UsesFramePointer());
+	bool Duplicate = this->IsAlreadyShadowed(CriticalOp);
 	if (TracingMemWrite && (!DataFlowOpnd))
 		return false;
-	else if ((!DataFlowOpnd) || this->IsAlreadyShadowed(CriticalOp)) {
+	else if ((!DataFlowOpnd) || Duplicate) {
 		// end the recursion.
+		bool ImmedOp = ShadowCheckUseOp->IsImmedOp();
+		if (!Duplicate && (!ImmedOp))
+			NonConstSourceFound = true;
+		else if (ImmedOp) {
+			// Save in the set of constant values we traced back to.
+			pair<set<STARS_uval_t>::iterator, bool> InsertResult = ConstValues.insert(ShadowCheckUseOp->GetImmedValue());
+			assert(InsertResult.first != ConstValues.end());
+		}
 		return true;  // if recursion has not started, ShadowAddrSet will be empty and no annotations will be emitted.
 	}
 	else {
@@ -13444,7 +13453,7 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 				}
 				this->TempShadowList.SetRef(UseOp->clone(), PhiIter->GetUseType(PhiIndex), PhiUseSSANum);
 				ShadowPoint PhiUsePoint(CurrShadowAddr, this->TempShadowList.GetSize() - 1);
-				ValidShadowing = this->FindShadowingPoint2(PhiUsePoint, TracingMemWrite, TempShadowAddrSet, MemUnsafe, NewCriticalOps);
+				ValidShadowing = this->FindShadowingPoint2(PhiUsePoint, TracingMemWrite, TempShadowAddrSet, MemUnsafe, NewCriticalOps, NonConstSourceFound, ConstValues);
 				if (!ValidShadowing) {
 					break;  // we must succeed on all Phi USEs
 				}
@@ -13467,6 +13476,7 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 			break; // success if ValidShadowing is true, failure otherwise
 		}
 		else if (STARS_IsSSAMarkerPseudoID(CurrShadowAddr)) {
+			NonConstSourceFound = true;
 			if (MDIsStackAccessOpnd(UseOp, this->UsesFramePointer())) {
 				// We need to guard against the corner case of a stack location that is
 				//  apparently used before it is defined. We cannot emit FPTRSHADOW [RSP-128]
@@ -13519,6 +13529,7 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 			}
 			STARSOpndTypePtr NewUseOp = nullptr;
 			if (!CurrInst->IsSimpleCopy(NewUseOp)) {
+				NonConstSourceFound = true;
 				// We could have something like [rsp+32] := [rsp+32] + 8.
 				//  The DEF is the DEF of our CriticalOp, and we cannot trace any farther for this shadowing index.
 				//  But the USE of the same operand could be a vulnerable DEF-USE chain that needs its own
@@ -13530,6 +13541,7 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 				//  due to the non-copy operation, unless it is a stack pointer copy.
 				if (TracingMemWrite) {
 					if (CurrInst->MDIsStackPointerCopy(this->UsesFramePointer())) {
+						// Stack pointer copy, but not a simple copy. Must be load-effective-address copy.
 						STARSOpndTypePtr LeaMemOp = CurrInst->GetLeaMemUseOp();
 						if ((nullptr != LeaMemOp) && (!LeaMemOp->IsVoidOp())) {
 							ValidShadowing = MDIsDirectStackAccessOpnd(LeaMemOp, this->UsesFramePointer());
@@ -13606,7 +13618,7 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 						if (!MDIsDirectStackAccessOpnd(NewUseOp, this->UsesFramePointer())) {
 							// The TracingMemWrite case differs from the shadowing case here.
 							//  The shadowing case would try (and fail) to trace [eax] while the
-							//  TracingMemWrite case is concerned with tracing eax. If eax is a 
+							//  TracingMemWrite case is concerned with tracing eax, not [eax]. If eax is a 
 							//  loop-invariant value and satisfies the other criteria for memory
 							//  write safety, then it should point to the return address only if
 							//  it is a copy of an unsafe pointer that was stored to memory. That
@@ -13617,6 +13629,7 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 #define STARS_AGGRESSIVE_MEM_TRACING 1
 #if STARS_AGGRESSIVE_MEM_TRACING
 							if (NewUseOp->IsStaticMemOp()) {
+								NonConstSourceFound = true;
 								ValidShadowing = true;
 								break;
 							}
@@ -13671,10 +13684,18 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 				}
 				if (!MDIsDataFlowOpnd(NewUseOp, this->UsesFramePointer())) {
 					// We are finished following the chain.
+					if (!(NewUseOp->IsImmedOp())) {
+						NonConstSourceFound = true;
+					}
+					else {
+						// Save in the set of constant values we traced back to.
+						pair<set<STARS_uval_t>::iterator, bool> InsertResult = ConstValues.insert(ShadowCheckUseOp->GetImmedValue());
+						assert(InsertResult.first != ConstValues.end());
+					}
 					break;
 				}
 				else { // recurse on NextCriticalOp
-					ValidShadowing = this->FindShadowingPoint2(NextCriticalOp, TracingMemWrite, ShadowAddrSet, MemUnsafe, NewCriticalOps);
+					ValidShadowing = this->FindShadowingPoint2(NextCriticalOp, TracingMemWrite, ShadowAddrSet, MemUnsafe, NewCriticalOps, NonConstSourceFound, ConstValues);
 					break; // recursion handled rest of the chain
 				}
 			} // end if not SimpleCopy else ...
@@ -13684,6 +13705,9 @@ bool SMPFunction::FindShadowingPoint2(const ShadowPoint CriticalOp, const bool T
 	// Success if we found any shadow points before chain had to terminate in non-mem-write case.
 	//  In mem-write case, must be ValidShadowing.
 	bool success = TracingMemWrite ? ValidShadowing : (ValidShadowing || ShadowPointFound);
+	if (!success) {
+		NonConstSourceFound = true;
+	}
 	return success;
 } // end of SMPFunction::FindShadowingPoint2()
 
@@ -13740,7 +13764,9 @@ bool SMPFunction::AnalyzeMemWriteSafety(void) {
 								ShadowSet ShadowUses;      // dummy set of addr+USE pairs to shadow values that will be checked at ShadowCheckAddr
 								ShadowSet NewCriticalOps;  // dummy worklist of new shadow USEs and their addresses
 								bool MemUnsafe = false;
-								bool SafeWrite = this->FindShadowingPoint2(CriticalOp, true, ShadowUses, MemUnsafe, NewCriticalOps);
+								bool NonConstSourceFound = false;
+								set<STARS_uval_t> ConstValues;
+								bool SafeWrite = this->FindShadowingPoint2(CriticalOp, true, ShadowUses, MemUnsafe, NewCriticalOps, NonConstSourceFound, ConstValues);
 								if (SafeWrite) {
 									assert(NewCriticalOps.empty());  // FindShadowingPoint2() should stop before adding to this set
 									STARSDefUseIter DefIter = CurrInst->FindDef(DefOp);
@@ -18470,9 +18496,11 @@ int SMPFunction::FindFollowBlockNum(SMPBasicBlock *CurrBlock, bool StartAtLastIn
 } // end of SMPFunction::FindFollowBlockNum()
 
 // common code for different cases in EmitFuncPtrShadowingAnnotations2()
-void SMPFunction::EmitShadowingHelper(FILE *InfoAnnotFile, SMPInstr *CurrInst, bool FuncPtr) {
+void SMPFunction::EmitShadowingHelper(FILE *InfoAnnotFile, SMPInstr *CurrInst, bool FuncPtr, STARS_ea_t CallAddr) {
 	STARS_ea_t ShadowCheckAddr = CurrInst->GetAddr();
 	STARS_ea_t OldShadowCheckAddr = STARS_BADADDR;
+	bool GoodCallAddr = (STARS_BADADDR != CallAddr);
+	bool InterruptCall = CurrInst->MDIsInterruptCall();
 	bool ImproveCFG = global_STARS_program->ShouldSTARSMaximizeCFGImprovement();
 	bool ShadowFuncPtrs = (FuncPtr && global_STARS_program->ShouldSTARSShadowFuncPtrs());
 	bool ShadowArgs = !FuncPtr;
@@ -18494,7 +18522,21 @@ void SMPFunction::EmitShadowingHelper(FILE *InfoAnnotFile, SMPInstr *CurrInst, b
 		bool UnsafeCodePointerChain = false;
 		if (ShadowFuncPtrs)
 			++STARS_FuncPtrShadowPointsAttempted;
-		bool ValidShadowing = this->FindShadowingPoint2(CriticalOp, false, ShadowUses, UnsafeCodePointerChain, NewCriticalOps);
+		bool NonConstSourceFound = false;
+		set<STARS_uval_t> ConstValues;
+		bool ValidShadowing = this->FindShadowingPoint2(CriticalOp, false, ShadowUses, UnsafeCodePointerChain, NewCriticalOps, NonConstSourceFound, ConstValues);
+		if (!NonConstSourceFound && ValidShadowing && ShadowFuncPtrs && GoodCallAddr && (!InterruptCall)) {
+			SMP_msg("INFO: Only constants found in tracing func ptr at %llx\n", (uint64_t) ShadowCheckAddr);
+			FILE *XrefsFile = global_STARS_program->GetXrefsFile();
+			for (set<STARS_uval_t>::const_iterator ValIter = ConstValues.cbegin(); ValIter != ConstValues.cend(); ++ValIter) {
+				SMP_fprintf(XrefsFile, "%18llx %6d INSTR XREF IBT FROMIB %18llx INDIRCALL\n",
+					(uint64_t) (*ValIter), CurrInst->GetSize(), (uint64_t) CallAddr);
+			}
+			if (!ConstValues.empty()) {
+				SMP_fprintf(XrefsFile, "%18llx %6d INSTR XREF FROMIB COMPLETE %6zu INDIRCALL\n",
+					(uint64_t) CallAddr, CurrInst->GetSize(), ConstValues.size());
+			}
+		}
 		if (ValidShadowing && UnsafeCodePointerChain) {
 			if (ShadowFuncPtrs)
 				++STARS_FuncPtrShadowPointsSucceeded;
@@ -18600,7 +18642,7 @@ void SMPFunction::EmitFuncPtrShadowingAnnotations2(FILE *InfoAnnotFile) {
 						this->TempShadowList.clear();
 						this->TempShadowList.SetRef(UseIter->GetOp(), UseIter->GetType(), UseIter->GetSSANum());
 
-						this->EmitShadowingHelper(InfoAnnotFile, CurrInst, true);
+						this->EmitShadowingHelper(InfoAnnotFile, CurrInst, true, CurrInst->GetAddr());
 					} // end if INDIR_CALL
 					else if (CALL == CurrInst->GetDataFlowType()) {
 						// Search for case 3: CODEPTR passed as outgoing arg.
@@ -18628,7 +18670,7 @@ void SMPFunction::EmitFuncPtrShadowingAnnotations2(FILE *InfoAnnotFile) {
 								assert(UseIter != CurrInst->GetLastUse());
 								this->TempShadowList.clear();
 								this->TempShadowList.SetRef(ArgOp, UseIter->GetType(), UseIter->GetSSANum());
-								this->EmitShadowingHelper(InfoAnnotFile, CurrInst, true);
+								this->EmitShadowingHelper(InfoAnnotFile, CurrInst, true, STARS_BADADDR);
 							}
 						} // end if CODEPTR ArgIter
 					} // end if INDIR_CALL elsif CALL elsif Case3 arg pass
@@ -18696,7 +18738,7 @@ void SMPFunction::EmitArgShadowingAnnotations(FILE *InfoAnnotFile) {
 										assert(UseIter != CurrInst->GetLastUse());
 										this->TempShadowList.clear();
 										this->TempShadowList.SetRef(ArgOp, UseIter->GetType(), UseIter->GetSSANum());
-										this->EmitShadowingHelper(InfoAnnotFile, CurrInst, false);
+										this->EmitShadowingHelper(InfoAnnotFile, CurrInst, false, STARS_BADADDR);
 									}
 								}
 							}
-- 
GitLab