Skip to content
Snippets Groups Projects
SMPFunction.cpp 121 KiB
Newer Older
		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++) {

#if SMP_USE_SSA_FNOP_MARKER
		if (this->Instrs.begin() == Instructions)
			continue;  // skip marker instruction
#endif

clc5q's avatar
clc5q committed
#if SMP_VERBOSE_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)) {
clc5q's avatar
clc5q committed
#if 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))) {
clc5q's avatar
clc5q committed
#if 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 R_none
				// and index reg is R_none. If they are, then this is
				// probably a global write and can be marked safe.
				MDExtractAddressFields(Operand, BaseReg, IndexReg, ScaleFactor, offset);
				if ((BaseReg == R_none) && (IndexReg == R_none))					 {
					// go onto next def
					continue;
				}
				ReturnAddrStatus = FUNC_UNSAFE;
				return;
			}
			if (Operand.type == o_displ) {
				MDExtractAddressFields(Operand, BaseReg, IndexReg, ScaleFactor, offset);
				if ((BaseReg == R_sp) || (this->UseFP && (BaseReg == R_bp))) {
					if (IndexReg == R_none) {
						if (offset > this->LocalVarsSize ) {
clc5q's avatar
clc5q committed
#if 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
clc5q's avatar
clc5q committed
#if 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());
			}
			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 
				if ((BaseReg == R_sp || (this->UseFP && BaseReg == R_bp))
					&& (IndexReg == R_none)) {
clc5q's avatar
clc5q committed
#if SMP_DEBUG_FUNC 
					msg(" Does function with phrase have displ %s %x  ", this->GetFuncName(), Operand.addr);	
				}
				else {
					ReturnAddrStatus = FUNC_UNSAFE;
					return;
				}
			}
		}
	}
} // end of SMPFunction::MarkFunctionSafe()