diff --git a/SMPFunction.cpp b/SMPFunction.cpp
index 2cff5a677226bf987594b9247ec33f28bd86a9fb..d261d7a4e7d4308ed78f76dc8b980dbd59d28680 100644
--- a/SMPFunction.cpp
+++ b/SMPFunction.cpp
@@ -41,7 +41,8 @@
 #define SMP_DEBUG_FRAMEFIXUP 0
 #define SMP_DEBUG_DATAFLOW 0
 #define SMP_DEBUG_STACK_GRANULARITY 0
-#define SMP_DEBUG_BUILD_RTL 1   // should be left on; serious errors!
+#define SMP_DEBUG_FUNC 1
+#define SMP_DEBUG_BUILD_RTL 1   // leave this on; serious errors reported
 
 // Compute LVA/SSA or not? Turn it off for NICECAP demo on 31-JAN-2008
 #define SMP_COMPUTE_LVA_SSA 1
@@ -80,6 +81,7 @@ SMPFunction::SMPFunction(func_t *Info) {
 	this->LocalVarTable.clear();
 	this->StackFrameMap.clear();
 	this->DirectCallTargets.clear();
+	this->ReturnAddrStatus = FUNC_UNKNOWN;
 	this->Blocks.clear();
 	this->Instrs.clear();
 	this->GlobalNames.clear();
@@ -1301,11 +1303,13 @@ void SMPFunction::Analyze(void) {
 #if SMP_DEBUG_CONTROLFLOW
 		msg("SMPFunction::Analyze: set stack frame info.\n");
 #endif
-		// Figure out the stack frame and related info.
+#ifdef SMP_DEBUG_FUNC
+		msg(" %s has shared chunks \n", this->GetFuncName());
+#endif
+	// Figure out the stack frame and related info.
 		this->SetStackFrameInfo();
 	}
-
-	return;
+	this->MarkFunctionSafe();
 } // end of SMPFunction::Analyze()
 
 // Compute SSA form data structures across the function.
@@ -2430,6 +2434,26 @@ void SMPFunction::EmitAnnotations(FILE *AnnotFile) {
 		qfprintf(AnnotFile,	"%10x %6d FUNC GLOBAL %s ", this->FuncInfo.startEA,
 			this->Size, this->FuncName);
 	}
+	switch (this->ReturnAddrStatus)
+	{
+		case FUNC_UNKNOWN:
+		{
+			qfprintf(AnnotFile, "FUNC_UNKNOWN ");
+			break;
+		}
+		case FUNC_SAFE:
+		{
+			qfprintf(AnnotFile, "FUNC_SAFE ");
+			break;
+		}
+		case FUNC_UNSAFE:
+		{
+			qfprintf(AnnotFile, "FUNC_UNSAFE ");
+			break;
+		}
+		default:
+			assert(0);	
+	}
 	if (this->UseFP) {
 		qfprintf(AnnotFile, "USEFP ");
 	}
@@ -2437,11 +2461,17 @@ void SMPFunction::EmitAnnotations(FILE *AnnotFile) {
 		qfprintf(AnnotFile, "NOFP ");
 	}
 	if (this->FuncInfo.does_return()) {
-		qfprintf(AnnotFile, "\n");
+		qfprintf(AnnotFile, "RET \n");
 	}
 	else {
 		qfprintf(AnnotFile, "NORET \n");
 	}
+#ifdef SMP_DEBUG_FUNC
+	if (this->IsLeaf())
+		qfprintf(AnnotFile, "FUNC_LEAF ");
+	// store the return address
+	qfprintf(AnnotFile,"%10x ", this->FuncInfo.endEA - 1);
+#endif
 
 	// Loop through all instructions in the function.
 	// Output optimization annotations for those
@@ -2481,6 +2511,8 @@ void SMPFunction::EmitAnnotations(FILE *AnnotFile) {
 		else {
 			CurrInst->EmitAnnotations(this->UseFP, AllocSeen, AnnotFile);
 		}
+		if (CurrInst->MDIsReturnInstr() && this->GetReturnAddressStatus() == FUNC_SAFE )
+			CurrInst->EmitSafeReturn(AnnotFile);
 	}  // end for (ea_t addr = FuncInfo.startEA; ...)
 	return;
 } // end of SMPFunction::EmitAnnotations()
@@ -2527,3 +2559,209 @@ void SMPFunction::Dump(void) {
 	return;
 } // end of SMPFunction::Dump()
 
+
+// Analyzes the function to see if the return address can be marked as safe 
+void SMPFunction::MarkFunctionSafe() {
+#ifdef SMP_DEBUG_FUNC
+	msg(" Analyzing function name %s and isLeaf=%d ", this->GetFuncName(), this->IsLeaf());
+#endif
+
+	ReturnAddrStatus = FUNC_SAFE;
+	if (!AnalyzedSP || this->IndirectCalls) {
+#ifdef SMP_DEBUG_FUNC 
+		if (!AnalyzedSP)
+		msg(" Function marked as unsafe %s coz AnalyzedSP = false\n", this->GetFuncName());	
+		else
+		msg(" Function marked as unsafe %s coz function has indirect calls\n", this->GetFuncName());
+#endif
+
+		ReturnAddrStatus = FUNC_UNSAFE;
+		return;
+	}
+
+	if (!this->DirectCallTargets.empty()) {
+#ifdef SMP_DEBUG_FUNC 
+		msg(" Function marked as unknown %s \n", this->GetFuncName());
+#endif
+		ReturnAddrStatus = FUNC_UNKNOWN;
+	}
+	if (this->IndirectJumps) {
+#ifdef SMP_DEBUG_FUNC
+		msg(" Function marked as unsafe due to indirect jumps %s\n", this->GetFuncName());
+#endif
+		ReturnAddrStatus = FUNC_UNSAFE;
+		return ;
+	}
+	if (this->HasSharedChunks()) {
+		ReturnAddrStatus = FUNC_UNSAFE;
+		return;
+	}
+	list<SMPInstr>::iterator Instructions;
+
+	// while processing the stack pointer write the prolog  containing for
+	// saving frame register and allcating local variables needs to be
+	// handled
+	bool SaveEBP = false;
+	bool XferESPtoEBP = false;
+	for (Instructions = Instrs.begin(); Instructions != Instrs.end();	Instructions++) {
+#ifdef SMP_DEBUG_FUNC 
+		msg(" Total number of defs for this instruction %d\n", Instructions->NumDefs());
+#endif
+		if (!SaveEBP) { // still looking for "push ebp"
+			if (Instructions->MDIsPushInstr() && Instructions->GetCmd().Operands[0].is_reg(R_bp)) {
+				SaveEBP = true;
+				continue;
+			}
+		}
+		else if (!XferESPtoEBP) { // found "push ebp", looking for "mov ebp,esp"
+			insn_t CurrCmd = Instructions->GetCmd();
+			if ((CurrCmd.itype == NN_mov)
+					&& (Instructions->GetFirstDef()->GetOp().is_reg(R_bp))
+					&& (Instructions->GetFirstUse()->GetOp().is_reg(R_sp))) {
+				XferESPtoEBP = true;
+				continue;
+			}
+		}
+		ea_t address = Instructions->GetAddr();
+		if (address == this->LocalVarsAllocInstr ||
+		    address == this->LocalVarsDeallocInstr)
+			continue;
+
+		if (Instructions->MDIsStackPointerCopy(this->UseFP)) {
+#ifdef SMP_DEBUG_FUNC 
+			msg(" Function marked as unsafe %s due to stack pointer copy \n ", this->GetFuncName());
+			msg("%s %x \n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
+#endif
+			ReturnAddrStatus = FUNC_UNSAFE;
+			return;
+		}
+		if (Instructions->MDIsPushInstr()) {
+			// not exactly sure how to handle this instruction
+			// for the moment if its a push on a esp or usefp & ebp
+			// mark as unsafe
+			if (Instructions->GetCmd().Operands[0].is_reg(R_sp) || 	 
+					( this->UseFP && Instructions->GetCmd().Operands[0].is_reg(R_bp))) {
+#ifdef SMP_DEBUG_FUNC 
+				msg(" Function marked as unsafe %s due to push on ebp or esp outside of function header \n", this->GetFuncName());	
+				msg("%s %x\n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
+#endif
+				ReturnAddrStatus = FUNC_UNSAFE;
+				return;
+			}
+			continue;
+		}
+		if (Instructions->MDIsPopInstr()) {
+			// ignore pops for the moment
+			 continue;
+		}
+		set<DefOrUse, LessDefUse>::iterator setIterator;
+		for (setIterator = Instructions->GetFirstDef(); setIterator != Instructions->GetLastDef(); setIterator++) {
+			op_t Operand = setIterator->GetOp();
+			if (Operand.type == o_mem)	{
+				// now o_mem can have sib byte as well, as
+				// reported by IDA. check if the base reg is bp
+				// and index reg is sp. If it is, then this is
+				// probably a global write and can be marked
+				// safe
+				if (Operand.hasSIB) {
+					int BaseReg = sib_base(Operand);
+					short IndexReg = sib_index(Operand);
+					if ((BaseReg == R_none || BaseReg == R_bp) &&
+							(IndexReg == R_none || IndexReg == R_sp))					 {
+						// go onto next def
+						continue;
+					}	
+				}
+				else {
+					// o_mem should never have a base register (field should be zero)
+					if ((Operand.reg == 0) || (Operand.reg == R_bp)) // ignore 
+						continue;
+				}
+				ReturnAddrStatus = FUNC_UNSAFE;
+				return;
+			}
+			if (Operand.type == o_displ) {
+				if (Operand.hasSIB) {
+					int BaseReg = sib_base(Operand);
+					short IndexReg = sib_index(Operand);
+					if (((BaseReg==R_sp || (this->UseFP && BaseReg == R_bp)))) {
+						if (IndexReg == R_sp || IndexReg == R_none) {
+							ea_t offset = Operand.addr;
+							if (offset > this->LocalVarsSize ) {
+#ifdef SMP_DEBUG_FUNC 
+								msg(" Function marked as unsafe %s due to write above loc variables offset=%x  loc=%x\n ", this->GetFuncName(), offset, this->LocalVarsSize);	
+								msg("%s %x\n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
+#endif
+								ReturnAddrStatus = FUNC_UNSAFE;
+								return;
+							}
+						}
+						else {
+#ifdef SMP_DEBUG_FUNC 
+							msg(" Function marked as unsafe %s due to index write above loc variables \n", this->GetFuncName());	
+							msg("%s %x\n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
+#endif
+							ReturnAddrStatus = FUNC_UNSAFE;  
+							return;
+						}
+					}
+					else {
+						 ReturnAddrStatus = FUNC_UNSAFE;
+						 return;
+					} 
+
+				}
+				else {
+					// no index
+					ushort BaseReg = Operand.reg;
+					if (BaseReg == R_sp || (UseFP &&	BaseReg == R_bp)) {
+						ea_t offset = Operand.addr;
+						if (offset > this->LocalVarsSize ) {
+#ifdef SMP_DEBUG_FUNC 
+							msg(" Function marked as unsafe %s due to write above loc variables in no sib offset=%x loc=%x \n", this->GetFuncName(), offset, this->LocalVarsSize);
+							msg("%s %x \n", (Instructions)->GetDisasm(), (Instructions)->GetAddr());
+#endif
+							ReturnAddrStatus = FUNC_UNSAFE;
+							return;
+						}
+					}
+					else {
+						ReturnAddrStatus = FUNC_UNSAFE;
+						return;
+					}
+				}
+			}
+			if (Operand.type == o_phrase)	{
+				// so phrase is of the form [BASE_REG + IND ]
+				// if the index register is missing just make sure that
+				// the displacement is below stack frame top
+				if (Operand.hasSIB) {
+					// check the base reg
+					int BaseReg = sib_base(Operand);
+					short IndexReg = sib_index(Operand);
+					// if index reg is used mark as unsafe 
+					if ((BaseReg == R_sp || (this->UseFP && BaseReg == R_bp))
+                   && (IndexReg != R_sp) && (IndexReg != R_none)) {
+                 // index=sp implies there is no index register
+#ifdef SMP_DEBUG_FUNC 
+						msg(" Does function with phrase have displ %s %x  ", this->GetFuncName(), Operand.addr);	
+#endif
+						continue;
+					}
+					else {
+						ReturnAddrStatus = FUNC_UNSAFE;
+						return ;
+					}
+				}
+				else {
+					ushort BaseReg = Operand.reg;
+					if (BaseReg == R_sp || (this->UseFP && BaseReg == R_bp))
+						continue;
+					ReturnAddrStatus = FUNC_UNSAFE;
+					return;
+				}
+			}
+		}
+	}
+}
+
diff --git a/SMPFunction.h b/SMPFunction.h
index ca4eefed0ae4adcd238cc7f2779489c5794129a5..33a0bf5680070d8f88d6fd2afbf83563524f7760 100644
--- a/SMPFunction.h
+++ b/SMPFunction.h
@@ -41,6 +41,13 @@ struct StackFrameEntry {
 	bool EBPRelativeAccess; // ever accessed by EBP-const? (only if UseFP)
 };
 
+enum FuncType { 
+	FUNC_UNKNOWN = 0,
+	FUNC_SAFE = 1,
+	FUNC_UNSAFE = 2
+};
+
+
 // Class encapsulating all that the SMP static analyzer cares to know
 //  about a function.
 class SMPFunction {
@@ -73,6 +80,11 @@ public:
 	void SetLinks(void); // Link basic blocks and map instructions to blocks
 	void LiveVariableAnalysis(void);  // Perform Live Variable Analysis across all blocks
 	void ComputeSSA(void); // Compute SSA form data structures
+	inline FuncType GetReturnAddressStatus(void) const { return ReturnAddrStatus;}
+	void SetReturnAddressStatus(FuncType funcType) {ReturnAddrStatus = funcType;}
+	inline const vector<ea_t> GetCallTargets() const { return DirectCallTargets;}
+	inline const ea_t GetStartAddr() const { return FuncInfo.startEA; } // exposing the start address of the function. Used in RecurseAndMark
+
 	void InferTypes(void); // Determine NUMERIC, POINTER, etc. for all operands
 	bool InferGlobalDefType(op_t RefOp, int SSANum); // Can DEF type be inferred from all USEs?
 private:
@@ -115,6 +127,9 @@ private:
 	vector<struct LocalVar> LocalVarTable; // offset-sorted list of local vars / outgoing args
 	adiff_t LocalVarOffsetLimit; // upper bound on stack-relative offsets
 	vector<struct StackFrameEntry> StackFrameMap; // memory map of every byte on stack frame
+	FuncType  ReturnAddrStatus; // Marked true if the return address is safe from being overwritten
+	 void MarkFunctionSafe();   // Does analysis to see if the function can be marked safe
+
 	// Methods
 	void SetStackFrameInfo(void);
 	ea_t FindAllocPoint(asize_t); // Deal with difficult to find stack frame allocations
diff --git a/SMPInstr.cpp b/SMPInstr.cpp
index 99ce1556fd41dbb1728914fa05b0c85b96095181..8670a60f9a7b8c4e4a88175cf5d23c3e1897585b 100644
--- a/SMPInstr.cpp
+++ b/SMPInstr.cpp
@@ -1898,6 +1898,14 @@ void SMPInstr::EmitAnnotations(bool UseFP, bool AllocSeen, FILE *AnnotFile) {
 	return;
 } // end of SMPInstr::EmitAnnotations()
 
+/**
+ * Emits Safe Returns
+ */ 
+void SMPInstr::EmitSafeReturn(FILE *AnnotFile)
+{
+	qfprintf(AnnotFile, "%10x %6d INSTR RET_SAFE %s\n", this->address, this->SMPcmd.size, disasm);
+}
+
 // Emit all annotations for the instruction using RTL type inference.
 void SMPInstr::EmitTypeAnnotations(bool UseFP, bool AllocSeen, FILE *AnnotFile) {
 	ea_t addr = this->address;
diff --git a/SMPInstr.h b/SMPInstr.h
index 363babbbb5dff67b68ce5c5b704df6e15e8bfd58..5aecccba79ea8fe0a775e3d95b4f74d38ce8f0a6 100644
--- a/SMPInstr.h
+++ b/SMPInstr.h
@@ -212,8 +212,9 @@ public:
 	void AnnotateStackConstants(bool UseFP, FILE *AnnotFile);
 	void EmitAnnotations(bool UseFP, bool AllocSeen, FILE *AnnotFile); // No RTLs available
 	void EmitTypeAnnotations(bool UseFP, bool AllocSeen, FILE *AnnotFile); // Use RTL types
+	void EmitSafeReturn(FILE *AnnotFile); // emit annotation to denote that the return belongs to a safe function.
 private:
-	// Data
+	// Data 
 	SMPBasicBlock *BasicBlock;  // basic block containing this instruction
 	insn_t SMPcmd; // copy of 'cmd' for this instruction
 	ulong features; // Canonical features for SMPcmd
diff --git a/SMPProgram.cpp b/SMPProgram.cpp
index 6fc39fde92871009d85ca339a81b3fc62202cebe..83acac4325eefa837e9864c4b4ebf044fae99e48 100644
--- a/SMPProgram.cpp
+++ b/SMPProgram.cpp
@@ -37,6 +37,7 @@
 #define SMP_DEBUG_GLOBAL_GRANULARITY 0
 #define SMP_DEBUG_OPTIMIZATIONS 1
 #define SMP_DEBUG_OPTIMIZATIONS_VERBOSE 1
+#define SMP_DEBUG_FUNC 1
 
 // Compute fine-grained global static data boundaries?
 #define SMP_COMPUTE_GLOBAL_GRANULARITY 1
@@ -418,11 +419,101 @@ void SMPProgram::EmitAnnotations(FILE *AnnotFile) {
 	map<ea_t, SMPFunction *>::iterator FuncIter;
 	for (FuncIter = this->FuncMap.begin(); FuncIter != this->FuncMap.end(); ++FuncIter) {
 		SMPFunction *TempFunc = FuncIter->second;
+		if (TempFunc == NULL) continue;
+		FuncType Type; 
+		if (TempFunc->GetReturnAddressStatus() == FUNC_UNKNOWN)
+		{
+			// add func name to set
+			 set<const char*,LtStr>::const_iterator find = FuncNameSet.find(TempFunc->GetFuncName());
+			 if (find == FuncNameSet.end())
+			 {
+				 FuncNameSet.insert(TempFunc->GetFuncName());
+				 RecurseAndMarkRetAdd(TempFunc);
+				 FuncNameSet.erase(TempFunc->GetFuncName());
+			 }
+			//remove name
+		}
 		TempFunc->EmitAnnotations(AnnotFile);
 	} // end for all functions
 	return;
 } // end of SMPProgram::EmitAnnotations()
 
+/**
+ * If a function is still marked FUNC_UNKNOWN at the time of emitting
+ * annotations, this function traverses over the call graph rooted at this
+ * function and checks if they are marked safe.
+ */  
+FuncType SMPProgram::RecurseAndMarkRetAdd(SMPFunction* FuncAttrib)
+{
+	if (FuncAttrib->IsLeaf())
+	{
+#ifdef SMP_DEBUG_FUNC
+		if (FuncAttrib->GetReturnAddressStatus()  == FUNC_UNKNOWN)
+			msg(" Leaf Function %s found with status unknown", FuncAttrib->GetFuncName()); 
+#endif
+		assert(FuncAttrib->GetReturnAddressStatus()  != FUNC_UNKNOWN);
+	       	return FuncAttrib->GetReturnAddressStatus();
+	}
+	vector<ea_t> CallTargets = FuncAttrib->GetCallTargets();
+	for (int i = 0; i < CallTargets.size(); i++) 
+	{
+		 ea_t CallAddr = CallTargets[i];
+		 SMPFunction* ChildInstance = FuncMap[CallAddr];
+		 if (!ChildInstance)
+		 {
+#ifdef SMP_DEBUG_FUNC
+			  // if a call target doesnt have a SMPFunction instance
+			                   // note it down
+			 msg(" Function doesnt have SMPFunction instance at %x \n", CallAddr);
+#endif
+		              continue;
+		 }
+                switch (ChildInstance->GetReturnAddressStatus()) 
+		{
+			case FUNC_SAFE:
+                             continue;
+                	case FUNC_UNSAFE:
+                	{
+				FuncAttrib->SetReturnAddressStatus(FUNC_UNSAFE);
+#ifdef SMP_DEBUG_FUNC
+				// if a call target doesnt have a SMPFunction instance
+				// note it down
+				msg("Function marked as unsafe %s\n", FuncAttrib->GetFuncName());
+#endif
+				return FUNC_UNSAFE;
+			}
+			case FUNC_UNKNOWN:
+			{
+				set<const char*,LtStr>::const_iterator find = FuncNameSet.find(ChildInstance->GetFuncName());
+				if (find == FuncNameSet.end())
+				{
+					FuncNameSet.insert(ChildInstance->GetFuncName());
+					FuncType Type = RecurseAndMarkRetAdd(ChildInstance);
+					FuncNameSet.erase(ChildInstance->GetFuncName());
+					if (Type == FUNC_UNSAFE)
+					{
+						FuncAttrib->SetReturnAddressStatus(FUNC_UNSAFE);
+#ifdef SMP_DEBUG_FUNC
+						// if a call target doesnt have a SMPFunction instance
+						// note it down
+						msg("Function marked as unsafe %s\n", FuncAttrib->GetFuncName());
+#endif
+						return FUNC_UNSAFE;
+					}
+				}
+			}
+		}	
+	}
+#ifdef SMP_DEBUG_FUNC
+	// if a call target doesnt have a SMPFunction instance
+	// note it down
+	msg("Function marked as safe %s\n", FuncAttrib->GetFuncName());
+#endif
+
+	FuncAttrib->SetReturnAddressStatus(FUNC_SAFE);
+	return FUNC_SAFE;	
+}
+
 // Debug output dump.
 void SMPProgram::Dump(void) {
 	// Loop through all functions and call the debug Dump() for each.
diff --git a/SMPProgram.h b/SMPProgram.h
index 6788cd010b1305cab25418225259ab53e7f68417..3c016274dba28e210db60ca165b17ea47b34d40c 100644
--- a/SMPProgram.h
+++ b/SMPProgram.h
@@ -58,6 +58,14 @@ struct GlobalVar {
 	set<pair<size_t, bool>, LessOff> FieldOffsets; // bool = accessed through index register by any instruction?
 };
 
+class LtStr{
+	public:
+	bool operator() (const char* c1, const char* c2) const {
+		return strcmp(c1, c2) < 0;
+	}
+};
+
+
 // Class encapsulating all that the SMP static analyzer cares to know
 //  about a whole program.
 class SMPProgram {
@@ -77,10 +85,12 @@ private:
 	// Data
 	map<ea_t, SMPFunction *> FuncMap; // all functions in the program
 	map<ea_t, struct GlobalVar> GlobalVarTable; // all global static variables
+	set<const char*,LtStr> FuncNameSet;	
 
 	// Methods
 	void InitStaticDataTable(void); // Gather info about global static data locations
 	void ComputeGlobalFieldOffsets(struct GlobalVar &CurrGlobal);
+	FuncType RecurseAndMarkRetAdd(SMPFunction*);
 }; // end class SMPProgram
 
 #endif