Skip to content
Snippets Groups Projects
STARSInstruction.h 7.79 KiB
Newer Older
#ifndef STARS_IRDB_Instruction_h
#define STARS_IRDB_Instruction_h

#include <assert.h>

#include "interfaces/abstract/STARSInstruction.h"
#include "interfaces/abstract/STARSInstructionID.h"
#include "interfaces/irdb/STARSOp.h"
#include "interfaces/irdb/STARSInterface.h"
#include <libIRDB-core.hpp>

class SMPInstr;

extern STARS_Interface_t* global_stars_interface;

class STARS_IRDB_Instruction_t : public STARS_Instruction_t
{
	public:

jdh8d's avatar
jdh8d committed
		// create SSA marker
		STARS_IRDB_Instruction_t(STARS_InstructionID_t id) 
jdh8d's avatar
jdh8d committed
			: STARS_Instruction_t(id), features(0)
jdh8d's avatar
jdh8d committed
		{ 	
			irdb_insn=NULL; 
			memset(&disasm, 0, sizeof(disasm));
			disasm.Argument1.ArgType=NO_ARGUMENT;
			disasm.Argument2.ArgType=NO_ARGUMENT;
			disasm.Argument3.ArgType=NO_ARGUMENT;
			disasm.Argument4.ArgType=NO_ARGUMENT;
			strcpy(disasm.Instruction.Mnemonic, "fnop ");	// set to fnop
			IDAOpcode = STARS_NN_fnop;
			IDAOpcodeCached = true;
		// Constructors and destructors
		STARS_IRDB_Instruction_t(const libIRDB::Instruction_t *insn) 
jdh8d's avatar
jdh8d committed
			: STARS_Instruction_t(insn->GetBaseID()), irdb_insn(insn), features(0)
			IDAOpcodeCached = false;
			irdb_insn->Disassemble(disasm);
			bool res=STARS_GetCmd();
			assert(res);

		STARS_InstructionID_t GetID() { return irdb_insn->GetBaseID(); }

		// Data initialization methods

		// return true/false if instruction is valid.
		// all irdb insns are valid?
		virtual bool STARS_GetCmd(void);

		// Get (accessor) methods
		virtual uint16_t GetSize(void) const 
		{ return irdb_insn->GetDataBits().length(); } 

		// see .cpp
		virtual uint16_t GetIDAOpcode(void);
jdh8d's avatar
 
jdh8d committed
		virtual STARS_InstructionID_t GetNextInstructionID(void)  const
		{ return STARS_InstructionID_t(irdb_insn->GetFallthrough()->GetBaseID()); }
jdh8d's avatar
 
jdh8d committed
		virtual STARS_InstructionID_t GetTargetInstructionID(void)  const
		{ return STARS_InstructionID_t(irdb_insn->GetTarget()->GetBaseID()); }
jdh8d's avatar
jdh8d committed

		// example:
		// add rax, rdx (intel) means rax=rax+rdx;
		// features = STARS_CF_USE1 | STARS_CF_USE2 | STARS_CF_CHG1
		virtual uint32_t GetInstFeatures(void) const { return features; }
		virtual uint32_t GetInitialInstFeatures(void) const;
jdh8d's avatar
jdh8d committed

		// jdh: consider returning by reference?
		virtual STARSOpndTypePtr GetOpnd(std::size_t OpndNum) const 
		{                         
//			if(Operands.at(OpndNum)->IsVoidOp())
//				return nullptr;
//			assert(OpndNum < Operands.size());

		// Set (mutator) methods
jdh8d's avatar
jdh8d committed

		// why do instructions need to keep track of this?
clc5q's avatar
clc5q committed
		// ANSWER: Imitating IDA Pro structure. Operands appear in many containers where it would not make
		//  sense to carry around DEF or USE bits, but the features bitmap in the instruction holds them
		//  within the context of the instruction they are part of. These mutators set bits in STARSfeatures.
		// REPLY: I'm a bit confused.  let's discuss in person.
		// final: these are part of the IDA fix-up of missing operands, etc.
		virtual void SetOpUsed(std::size_t OpndNum) {assert(0); } // set the USE bit
		virtual void SetOpNotUsed(std::size_t OpndNum) {assert(0); } // reset the USE bit
		virtual void SetOpDefed(std::size_t OpndNum) {assert(0); } // set the DEF bit
		virtual void SetOpNotDefed(std::size_t OpndNum) {assert(0); } // reset the DEF bit
jdh8d's avatar
jdh8d committed

// jdh: not needed for IRDB?
clc5q's avatar
clc5q committed
// ANSWER: Should never be called for IRDB variant.
		virtual void RemoveIDAOp1ForIMUL(void) {assert(0); } // Fix up IDA Pro IMUL instruction by removing operand 1

		// Query methods
		virtual bool HasRepeatIfEqualPrefix(void) const 
		{ return disasm.Prefix.RepnePrefix!=NotUsedPrefix; }
		virtual bool HasRepeatIfNotEqualPrefix(void) const 
		{ return disasm.Prefix.RepPrefix!=NotUsedPrefix; }

		virtual bool HasAnyRepeatPrefix(void) const 
		{ return HasRepeatIfEqualPrefix() || HasRepeatIfNotEqualPrefix(); }

		virtual bool HasOperandSizePrefix(void) const 
		{ return disasm.Prefix.OperandSize!=NotUsedPrefix; }

		virtual bool HasREXWPrefix(void) const 
		{ return disasm.Prefix.REX.W_!=0; }

		{
			STARS_IRDB_Interface_t *my_global_stars_interface=NULL;
			my_global_stars_interface=
				dynamic_cast<STARS_IRDB_Interface_t*>(global_stars_interface);
			assert(my_global_stars_interface);
			return my_global_stars_interface->GetArchitectureBitWidth()==64;
		}
jdh8d's avatar
jdh8d committed
		// jdh: vex, etc. insns?  
clc5q's avatar
clc5q committed
		// ANSWER: Yes. See implementations in STARSIDAInstruction.cpp.
		virtual bool Has64BitOperands(void) 
		{

			// not a 64-bit machine, can't be a 64-bit op.
			if  ( !this->mode64()  )
				return false;
		
			// has the REXW indicates it's a 64-bit op.
			if  ( this->HasREXWPrefix() )
				return true; 
		
			// no size prefix and opcode defaults to 64-bit 
			if (!this->HasOperandSizePrefix() && this->OpcodeDefaultsTo64BitOperands() )  
				return true;
		
			// size prefix or non-64 bit operand
			return false;
		}

		virtual bool Uses64BitAddressing(void) const 
		{ return mode64() && !HasOperandSizePrefix(); }

		virtual bool Uses32BitAddressing(void) const 
jdh8d's avatar
jdh8d committed
		{ return !mode64() && !HasOperandSizePrefix(); } 
		virtual bool IsRegOpnd(std::size_t OpndNum) const 
		{ return (Operands.at(OpndNum)->IsRegOp()); }
jdh8d's avatar
jdh8d committed

		virtual bool IsImmedOpnd(std::size_t OpndNum) const 
		{ return (Operands.at(OpndNum)->IsImmedOp()); }
clc5q's avatar
clc5q committed

		virtual bool RegOpndMatches(std::size_t OpndNum, uint16_t RegNum) const 
		{ return Operands.at(OpndNum)->MatchesReg(RegNum); }

		// see .cpp
		virtual bool IsUseOpnd(std::size_t OpndNum) const ;

		// see .cpp
		virtual bool IsDefOpnd(std::size_t OpndNum) const ;
jdh8d's avatar
jdh8d committed

		virtual bool IsBranchToFarChunk(SMPInstr *CurrInst, STARS_ea_t &TargetAddr) 
		{ return false; /* no far chunks in irdb. */ }
		virtual STARS_InstructionID_Set_t GetReferencedInstructionIDs(bool &success);
		// Operand creation methods
jdh8d's avatar
jdh8d committed


// jdh: do these "make operand" methods create an operand that's somehow linked/related to this instruction,
// or are these generic operand for any instruction.  If generic, we should make them static factory-type methods
// of the operand class.
clc5q's avatar
clc5q committed
// ANSWER: Could be static factory methods of operand class. Current idapro/STARSIDAInstruction.cpp implementations
//  make use of IDA Pro headers.
jdh8d's avatar
jdh8d committed


// jdh: what is a void operand?
clc5q's avatar
clc5q committed
// ANSWER: Placeholder, e.g. in an RTL tree, when there is no operand. Also, IDA Pro has an array of six operands
//  for each instruction, and many of them have IDA Pro type o_void, which is now simulated in our brave new world
//  of shared_ptrs to operands by having a VoidOpnd.
		virtual STARSOpndTypePtr MakeVoidOpnd(void) const;
		virtual STARSOpndTypePtr MakeImmediateOpnd(STARS_uval_t value) const;
		virtual STARSOpndTypePtr MakeRegOpnd(uint16_t RegNum);
		virtual STARSOpndTypePtr MakeFloatingPointRegOpnd(uint16_t RegNum);
		virtual STARSOpndTypePtr MakeMMXRegOpnd(uint16_t RegNum);
		virtual STARSOpndTypePtr MakeXMMRegOpnd(uint16_t RegNum);
		virtual STARSOpndTypePtr MakeYMMRegOpnd(uint16_t RegNum);
jdh8d's avatar
jdh8d committed
		virtual STARSOpndTypePtr MakeNearPointerOpnd(STARS_ea_t TargetAddr) const ;
clc5q's avatar
clc5q committed
		virtual STARSOpndTypePtr MakeMemDisplacementOpnd(uint16_t BaseRegNum,
			uint16_t IndexRegNum, uint16_t ScaleFactor, STARS_ea_t offset);
		virtual STARSOpndTypePtr MakeMemPhraseOpnd(uint16_t BaseRegNum, 
			uint16_t IndexRegNum, uint16_t ScaleFactor);

		// Analysis methods

		// Is push from a call that became a push/jump pair?
		virtual bool IsPushFromFixedCall(void) const;
jdh8d's avatar
jdh8d committed
		// useful for other IRDB classes.
		virtual const libIRDB::Instruction_t* GetIRDBInstruction() const { return irdb_insn;}

	private:
		const libIRDB::Instruction_t* irdb_insn;
		DISASM disasm;
		std::vector<STARSOpndTypePtr> Operands;
jdh8d's avatar
jdh8d committed
		uint32_t features;
		uint16_t IDAOpcode;   // cached result from GetIDAOpcode()
		bool IDAOpcodeCached; // does IDAOpcode contain a result, or does GetIDAOpcode() need to compute for first time?
		std::size_t DetermineRegByteWidth(uint16_t RegNum); // Based on RegNum, determine byte width to set for new operand.