Skip to content
Snippets Groups Projects
SMPInstr.cpp 135 KiB
Newer Older
//
// SMPInstr.cpp
//
// This module performs the instruction level analyses needed for the
//   SMP project (Software Memory Protection).
//

#include <cstring>

#include <pro.h>
#include <assert.h>
#include <ida.hpp>
#include <idp.hpp>
#include <allins.hpp>
#include <auto.hpp>
#include <bytes.hpp>
#include <funcs.hpp>
#include <intel.hpp>
#include <loader.hpp>
#include <lines.hpp>
#include <name.hpp>

#include "SMPStaticAnalyzer.h"
#include "SMPDataFlowAnalysis.h"
#include "SMPInstr.h"

// Set to 1 for debugging output
#define SMP_DEBUG 1
#define SMP_DEBUG2 0   // verbose
#define SMP_DEBUG_XOR 0
#define SMP_DEBUG_BUILD_RTL  0

// Make the CF_CHG1 .. CF_CHG6 and CF_USE1..CF_USE6 macros more usable
//  by allowing us to pick them up with an array index.
static ulong DefMacros[UA_MAXOP] = {CF_CHG1, CF_CHG2, CF_CHG3, CF_CHG4, CF_CHG5, CF_CHG6};
static ulong UseMacros[UA_MAXOP] = {CF_USE1, CF_USE2, CF_USE3, CF_USE4, CF_USE5, CF_USE6};

// Text to be printed in each optimizing annotation explaining why
//  the annotation was emitted.
static char *OptExplanation[LAST_OPT_CATEGORY + 1] =
	{ "NoOpt", "NoMetaUpdate", "AlwaysNUM", "NUMVia2ndSrcIMMEDNUM",
	  "Always1stSrc", "1stSrcVia2ndSrcIMMEDNUM", "AlwaysPtr",
	  "AlwaysNUM", "AlwaysNUM", "NUMViaFPRegDest"
	};



// *****************************************************************
// Class SMPGuard
// *****************************************************************
// Constructor
SMPGuard::SMPGuard(void) {
	this->LeftOperand.type = o_void;
	this->RightOperand.type = o_void;
	return;
}

// *****************************************************************
// Class SMPRegTransfer
// *****************************************************************
// Constructor
SMPRegTransfer::SMPRegTransfer(void) {
	this->LeftOperand.type = o_void;
	this->RightOperand.type = o_void;
	this->RTop.type = UNINIT;
	this->RightSubTree = false;
	this->RightRT = NULL;
	this->Guard = NULL;
	return;
}

// Destructor
SMPRegTransfer::~SMPRegTransfer() {
#if 0
	msg("Destroying SMPRegTransfer.\n");
#endif
	if (NULL != this->RightRT)
		delete this->RightRT;
	if (NULL != this->Guard)
		delete this->Guard;
	return;
}

// *****************************************************************
// Class SMPRTL
// *****************************************************************

// Constructor
SMPRTL::SMPRTL() {
	this->ExtraKills.clear();
	this->RTCount = 0;
	return;
}

// Destructor
SMPRTL::~SMPRTL() {
	for (size_t index = 0; index < this->RTCount; ++index) {
		delete (this->RTvector[index]);
	}
	this->ExtraKills.clear();
	return;
}

// Get methods
SMPRegTransfer *SMPRTL::GetRT(size_t index) {
	if (index > this->RTCount)
		return NULL;
	else
		return this->RTvector[index];
}

// Set methods
void SMPRTL::push_back(SMPRegTransfer *NewEffect) {
	assert(SMP_RT_LIMIT > this->RTCount);
	this->RTvector[this->RTCount] = NewEffect;
	++(this->RTCount);
	return;
}

// *****************************************************************
// Class SMPInstr
// *****************************************************************

// Constructor for instruction.
SMPInstr::SMPInstr(ea_t addr) {
	this->address = addr;
	this->analyzed = false;
	this->JumpTarget = false;
	this->BlockTerm = false;
	this->DefsFlags = false;
	this->UsesFlags = false;
	return;
}

// Is the instruction the type that terminates a basic block?
bool SMPInstr::IsBasicBlockTerminator() const {
	return ((type == JUMP) || (type == COND_BRANCH)
			|| (type == INDIR_JUMP) || (type == RETURN));
}

// Is the destination operand a memory reference?
bool SMPInstr::HasDestMemoryOperand(void) {
	bool MemDest = false;
	set<DefOrUse, LessDefUse>::iterator CurrDef;
	for (CurrDef = this->GetFirstDef(); CurrDef != this->GetLastDef(); ++CurrDef) {
		optype_t CurrType = CurrDef->GetOp().type;
		MemDest = ((CurrType == o_mem) || (CurrType == o_phrase) || (CurrType == o_displ));
		if (MemDest)
			break;
	}
	return MemDest;
} // end of SMPInstr::HasDestMemoryOperand()

// Is a source operand a memory reference?
bool SMPInstr::HasSourceMemoryOperand(void) {
	bool MemSrc = false;
	set<DefOrUse, LessDefUse>::iterator CurrUse;
	for (CurrUse = this->GetFirstUse(); CurrUse != this->GetLastUse(); ++CurrUse) {
		optype_t CurrType = CurrUse->GetOp().type;
		MemSrc = ((CurrType == o_mem) || (CurrType == o_phrase)	|| (CurrType == o_displ));
		if (MemSrc)
			break;
	}
	return MemSrc;
} // end of SMPInstr::HasSourceMemoryOperand()

// Does the instruction whose flags are in F have a numeric type
//   as the second source operand?
// NOTE: We can only analyze immediate values now, using a heuristic
//   that values in the range +/- 8K are numeric and others are
//   probably addresses. When data flow analyses are implemented,
//   we will be able to analyze many non-immediate operands.
#define IMMEDNUM_LOWER -8191
#define IMMEDNUM_UPPER 8191
bool SMPInstr::IsSecondSrcOperandNumeric(flags_t F) const {
	bool SecondOpImm = (SMPcmd.Operands[1].type == o_imm);
	signed long TempImm;

	if (SecondOpImm) {
		TempImm = (signed long) SMPcmd.Operands[1].value;
	}

#if SMP_DEBUG
	if (SecondOpImm && (0 > TempImm)) {
#if 0
		msg("Negative immediate: %d Hex: %x ASM: %s\n", TempImm,
			SMPcmd.Operands[1].value, disasm);
#endif
	}
	else if ((!SecondOpImm) && (SMPcmd.Operands[1].type == o_imm)) {
		msg("Problem with flags on immediate src operand: %s\n", disasm);
	}
#endif

	return (SecondOpImm && (TempImm > IMMEDNUM_LOWER)
		&& (TempImm < IMMEDNUM_UPPER));
} // end of SMPInstr::IsSecondSrcOperandNumeric()

// DEBUG print operands for Inst.
Loading
Loading full blame...