Skip to content
Snippets Groups Projects
SMPFunction.cpp 286 KiB
Newer Older
clc5q's avatar
clc5q committed
#if SMP_DEBUG_FUNC 
			SMP_msg(" Function %s marked as unsafe due to stack pointer copy \n ", this->GetFuncName());
			SMP_msg("%s %x \n", CurrInst->GetDisasm(), CurrInst->GetAddr());
		if (CurrInst->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 (CurrInst->GetCmd().Operands[0].is_reg(R_sp) || 	 
					(this->UseFP && CurrInst->GetCmd().Operands[0].is_reg(R_bp))) {
clc5q's avatar
clc5q committed
#if SMP_DEBUG_FUNC 
				SMP_msg(" Function %s marked as unsafe due to push on ebp or esp outside of function header \n", this->GetFuncName());	
				SMP_msg("%s %x\n", CurrInst->GetDisasm(), CurrInst->GetAddr());
		if (CurrInst->MDIsPopInstr() || CurrInst->MDIsReturnInstr()) {
			// ignore pops and returns for the moment
			 continue;
		}
		set<DefOrUse, LessDefUse>::iterator setIterator;
		for (setIterator = CurrInst->GetFirstDef(); setIterator != CurrInst->GetLastDef(); ++setIterator) {
			op_t Operand = setIterator->GetOp();
clc5q's avatar
clc5q committed
			if (Operand.type == o_mem) {
				// now o_mem can have sib byte as well, as
				// reported by IDA. Check if the base reg is R_none
				// and index reg is R_none. If they are, then this is
				// a direct global write and can be marked safe.
				MDExtractAddressFields(Operand, BaseReg, IndexReg, ScaleFactor, offset);
clc5q's avatar
clc5q committed
				if ((BaseReg == R_none) && (IndexReg == R_none)) {
clc5q's avatar
clc5q committed
				else {
					HasIndirectGlobalWrite = true;
				}
clc5q's avatar
clc5q committed
			else if (Operand.type == o_displ) {
				MDExtractAddressFields(Operand, BaseReg, IndexReg, ScaleFactor, offset);
				bool FramePointerRelative = (this->UseFP && (BaseReg == R_bp));
				bool StackPointerRelative = (BaseReg == R_sp);
				if (StackPointerRelative || FramePointerRelative) {
						bool tempWritesAboveLocalFrame = this->WritesAboveLocalFrame(Operand, CurrInst->AreDefsNormalized());
clc5q's avatar
clc5q committed
						WritesAboveLocalFrame |= tempWritesAboveLocalFrame;
#if SMP_DEBUG_FUNC 
clc5q's avatar
clc5q committed
						if (tempWritesAboveLocalFrame) {
							SMP_msg(" Function %s marked as unsafe due to direct write above loc "
								"variables offset=%x  loc=%x\n ", this->GetFuncName(), 
								offset, this->LocalVarsSize);	
							SMP_msg("Write above local frame in %s : offset: %d ",
								this->GetFuncName(), offset);
							SMP_msg("LocalVarsSize: %d OutgoingArgsSize: %d frsize: %d frregs: %d",
								this->LocalVarsSize, this->OutgoingArgsSize, 
								this->FuncInfo.frsize, this->FuncInfo.frregs);
							Instructions->Dump();
						}
#endif
clc5q's avatar
clc5q committed
					else {
						bool tempWritesAboveLocalFrameIndirect = this->IndexedWritesAboveLocalFrame(Operand);

						/* separate indirect writes to this frame from indirect writes to another frame */
clc5q's avatar
clc5q committed
						if (tempWritesAboveLocalFrameIndirect) {
							WritesAboveLocalFrameIndirect = true;
clc5q's avatar
clc5q committed
#if SMP_DEBUG_FUNC 
							SMP_msg(" Function %s marked as unsafe due to indexed stack write above "
								"loc variable offset\n", this->GetFuncName());	
							SMP_msg("%s %x\n", CurrInst->GetDisasm(), CurrInst->GetAddr());
clc5q's avatar
clc5q committed
#endif
clc5q's avatar
clc5q committed
						else {
							HasIndexedStackWrite = true;
clc5q's avatar
clc5q committed
#if SMP_DEBUG_FUNC 
							SMP_msg(" Function %s marked as unsafe due to indexed stack write\n", 
								this->GetFuncName());	
							SMP_msg("%s %x\n", CurrInst->GetDisasm(), CurrInst->GetAddr());
clc5q's avatar
clc5q committed
				else {
					/* check whether there is profiler information for this indirect reference */
			else 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
				MDExtractAddressFields(Operand, BaseReg, IndexReg, ScaleFactor, offset);
				// check the base reg
				// if index reg is used mark as unsafe 
clc5q's avatar
clc5q committed
				if ((BaseReg == R_sp || (this->UseFP && BaseReg == R_bp))) {
					if (IndexReg == R_none) {
						/* addressing mode is *esp or *ebp */
						continue;
					}
					else {
						HasIndexedStackWrite = true;
#if SMP_DEBUG_FUNC 
						SMP_msg(" Function %s marked as unsafe due to indexed stack write\n", this->GetFuncName());	
						SMP_msg("%s %x\n", CurrInst->GetDisasm(), CurrInst->GetAddr());
clc5q's avatar
clc5q committed
				else {
					/* check whether there is profiler information for this indirect reference */
			// else not memory, and we don't care.
		} // end for all DEFs in current instruction
	} // end for all instructions
	// For mmStrata bounds checking of the stack frame, we don't care
	//  about indirect writes unless they are to the stack.
	bool SpecUnsafe = (HasStackPointerCopy || HasStackPointerPush 
		|| HasIndexedStackWrite || this->SharedChunks
		|| this->UnresolvedIndirectJumps);
	bool Unsafe = SpecUnsafe || this->UnresolvedIndirectCalls;

	this->SafeFunc = (!Unsafe);
	this->SpecSafeFunc = (!SpecUnsafe);

	this->WritesAboveRA = WritesAboveLocalFrameIndirect;
	this->SafeCallee = (!Unsafe) && (!WritesAboveLocalFrameIndirect) && this->AnalyzedSP;
	this->SpecSafeCallee = (!SpecUnsafe) && (!WritesAboveLocalFrameIndirect) && this->AnalyzedSP;
	this->NeedsStackReferent = Unsafe;
	this->SpecNeedsStackReferent = SpecUnsafe;

	this->HasIndirectWrites = (HasIndexedStackWrite || HasIndirectWrite
		|| WritesAboveLocalFrameIndirect || HasIndirectGlobalWrite);

	bool UnsafeReturnAddr = (Unsafe || WritesAboveLocalFrame || WritesAboveLocalFrameIndirect || HasIndirectGlobalWrite 
		|| HasIndirectWrite || (!this->AnalyzedSP));
#if SMP_DECLARE_INDIRECT_TARGETS_UNSAFE
	if (!UnsafeReturnAddr && this->PossibleIndirectCallTarget) {
		SMP_msg("INFO: Function at %x becoming UNSAFE because it is indirect call target.\n", this->FirstEA);
		UnsafeReturnAddr =  true;
	}
	else if (!UnsafeReturnAddr && this->PossibleTailCallTarget) {
		SMP_msg("INFO: Function at %x becoming UNSAFE because it is tail call target.\n", this->FirstEA);
		UnsafeReturnAddr =  true;
	}
	else if (!UnsafeReturnAddr && HasNoCallers) {
		SMP_msg("INFO: Function at %x becoming UNSAFE because it has no callers.\n", this->FirstEA);
		UnsafeReturnAddr =  true;
	}
#endif

	if (UnsafeReturnAddr) {
		this->SetReturnAddressStatus(FUNC_UNSAFE);
#if SMP_DEBUG_FUNC_SAFETY
		SMP_msg("UNSAFE function %s ", this->GetFuncName());
		SMP_msg("StackPtrCopy: %d StackPtrPush: %d IndirectGlobal: %d ",
			HasStackPointerCopy, HasStackPointerPush, HasIndirectGlobalWrite);
		SMP_msg("WritesAboveFrame: %d IndirectStack: %d IndirectWrite: %d ",
			WritesAboveLocalFrame, HasIndexedStackWrite, HasIndirectWrite);
		SMP_msg("AnalyzedSP: %d UnresolvedCalls: %d UnresolvedJumps: %d SharedChunks: %d IsLeaf: %d",
			this->AnalyzedSP, this->UnresolvedIndirectCalls, this->UnresolvedIndirectJumps,
			this->SharedChunks, this->IsLeaf());
		SMP_msg("IndirCallTarget: %d TailCallTarget: %d HasNoCallers: %d\n", this->PossibleIndirectCallTarget,
			this->PossibleTailCallTarget, HasNoCallers);
clc5q's avatar
clc5q committed
#endif
		this->SetReturnAddressStatus(FUNC_UNKNOWN);
	if (this->GetReturnAddressStatus() == FUNC_SAFE)
		SMP_msg("Function %s is SAFE\n", GetFuncName());
	else if (this->GetReturnAddressStatus() == FUNC_SAFE)
		SMP_msg("Function %s is UNSAFE\n", GetFuncName());
	else if (this->GetReturnAddressStatus() == FUNC_SAFE)
		SMP_msg("Function %s is UNKNOWN\n", GetFuncName());
clc5q's avatar
clc5q committed
	if (!Unsafe) 
		SMP_msg("Function %s is mmSAFE\n", GetFuncName());
		SMP_msg("Function %s is mmUNSAFE\n", GetFuncName());
clc5q's avatar
clc5q committed
	if (!SpecUnsafe) 
		SMP_msg("Function %s is Speculatively mmSAFE\n", GetFuncName());
		SMP_msg("Function %s is Speculatively mmUNSAFE\n", GetFuncName());
} // end of SMPFunction::MarkFunctionSafe()