#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> #include <vector> class SMPInstr; extern STARS_Interface_t* global_stars_interface; class STARS_IRDB_Instruction_t : public STARS_Instruction_t { public: // create SSA marker STARS_IRDB_Instruction_t(STARS_InstructionID_t id) : STARS_Instruction_t(id), features(0) { 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) : STARS_Instruction_t(insn->GetBaseID()), irdb_insn(insn), features(0) { assert(irdb_insn); 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); virtual STARS_InstructionID_t GetNextInstructionID(void) const { return STARS_InstructionID_t(irdb_insn->GetFallthrough()->GetBaseID()); } virtual STARS_InstructionID_t GetTargetInstructionID(void) const { return STARS_InstructionID_t(irdb_insn->GetTarget()->GetBaseID()); } // 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; // jdh: consider returning by reference? virtual STARSOpndTypePtr GetOpnd(std::size_t OpndNum) const { // if(Operands.at(OpndNum)->IsVoidOp()) // return nullptr; // assert(OpndNum < Operands.size()); return Operands.at(OpndNum); } // Set (mutator) methods // why do instructions need to keep track of this? // 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 // jdh: not needed for IRDB? // 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; } virtual bool mode64(void) const { 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; } // jdh: vex, etc. insns? // 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 { return !mode64() && !HasOperandSizePrefix(); } virtual bool IsRegOpnd(std::size_t OpndNum) const { return (Operands.at(OpndNum)->IsRegOp()); } virtual bool IsImmedOpnd(std::size_t OpndNum) const { return (Operands.at(OpndNum)->IsImmedOp()); } 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 ; 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 // 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. // ANSWER: Could be static factory methods of operand class. Current idapro/STARSIDAInstruction.cpp implementations // make use of IDA Pro headers. // jdh: what is a void operand? // 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); virtual STARSOpndTypePtr MakeNearPointerOpnd(STARS_ea_t TargetAddr) const ; 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; // 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; 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. }; #endif