#ifndef STARS_IDA_Instruction_h #define STARS_IDA_Instruction_h #include <memory> #include <vector> #include <cstddef> #include <cstdint> #include <pro.h> #include <ua.hpp> #include <intel.hpp> #include "interfaces/STARSTypes.h" #include "interfaces/SMPDBInterface.h" #include "interfaces/abstract/STARSInstruction.h" #include "interfaces/abstract/STARSInstructionID.h" // struct to hold items that mimic the IDA Pro type insn_t. struct STARS_IDA_insn_t { #if 0 // duplicate info // Current segment base paragraph. Initialized by the kernel. STARS_ea_t cs; // segment base (in paragraphs) // Virtual address of the instruction (address within the segment) // Initialized by the kernel. STARS_ea_t ip; // offset in the segment // Linear address of the instruction. // Initialized by the kernel. STARS_ea_t ea; // instruction start addresses #endif // Internal code of instruction. IDP should define its own instruction // codes. These codes are usually defined in ins.hpp. The array of instruction // names and features (ins.cpp) is accessed using this code. uint16_t itype; // instruction code (see ins.hpp) // only for canonical insns (not user defined!): // Size of instruction in bytes. // The analyzer should put here the actual size of the instruction. uint16_t size; // instruction size in bytes // Additional information about the instruction. // Definitions are processor-dependent. union { uint16_t auxpref; // processor dependent field struct { uchar low; uchar high; } auxpref_chars; }; char segpref; // processor dependent field char insnpref; // processor dependent field // Information about instruction operands. std::vector<STARSOpndTypePtr> Operands; char flags; // instruction flags }; // end of struct STARS_IDA_insn_t class STARS_IDA_Instruction_t : public STARS_Instruction_t { public: // Constructors and destructors STARS_IDA_Instruction_t(const STARS_InstructionID_t& p_id) : STARSCmd({}), STARS_Instruction_t(p_id), ImplicitDEFs(false) { if (STARS_IsSSAMarkerPseudoID(p_id.GetIDWithinFile())) { // SSA marker pseudo-inst STARScmd.itype = NN_fnop; STARScmd.size = 1; } }; // Data initialization methods bool STARS_GetCmd(void); // Get (accessor) methods inline uint16_t GetSize(void) const { return STARScmd.size; }; // Size of instruction in bytes inline uint16_t GetIDAOpcode(void) { return STARScmd.itype; }; STARS_InstructionID_t GetNextInstructionID(void) const; STARS_InstructionID_t GetTargetInstructionID(void) const; uint32_t GetInstFeatures(void) const { return STARSfeatures; }; STARSOpndTypePtr GetOpnd(std::size_t OpndNum) const { assert(OpndNum < STARScmd.Operands.size()); return STARScmd.Operands.at(OpndNum); }; // Set (mutator) methods void SetOpUsed(std::size_t OpndNum); // set the USE bit void SetOpNotUsed(std::size_t OpndNum); // reset the USE bit void SetOpDefed(std::size_t OpndNum); // set the DEF bit void SetOpNotDefed(std::size_t OpndNum); // reset the DEF bit void RemoveIDAOp1ForIMUL(void); // Fix up IDA Pro IMUL instruction by removing operand 1 // Query methods inline bool HasRepeatIfEqualPrefix(void) const { return (0 != (STARScmd.auxpref & aux_rep)); }; inline bool HasRepeatIfNotEqualPrefix(void) const { return (0 != (STARScmd.auxpref & aux_repne)); }; inline bool HasAnyRepeatPrefix(void) const { return (0 != (STARScmd.auxpref & (aux_rep | aux_repne))); }; bool Has64BitOperands(void); inline bool Uses64BitAddressing(void) const { #ifdef __EA64__ return ((STARScmd.auxpref & (aux_use32 | aux_use64 | aux_natad)) == (aux_natad | aux_use64)); #else return false; #endif }; bool Uses32BitAddressing(void) const; inline bool IsRegOpnd(std::size_t OpndNum) const { return (STARScmd.Operands.at(OpndNum)->IsRegOp()); }; inline bool IsImmedOpnd(std::size_t OpndNum) const { return (STARScmd.Operands.at(OpndNum)->IsImmedOp()); }; inline bool RegOpndMatches(std::size_t OpndNum, STARS_regnum_t RegNum) const { return STARScmd.Operands.at(OpndNum)->MatchesReg(RegNum); }; inline bool HasImplicitlyModifiedRegs(void) const { return ImplicitDEFs; }; bool IsUseOpnd(std::size_t OpndNum) const; bool IsDefOpnd(std::size_t OpndNum) const; bool IsBranchToFarChunk(SMPInstr *CurrInst, STARS_ea_t &TargetAddr); // Operand creation methods STARSOpndTypePtr MakeVoidOpnd(void) const ; STARSOpndTypePtr MakeImmediateOpnd(STARS_uval_t value) const; STARSOpndTypePtr MakeRegOpnd(STARS_regnum_t RegNum, bool DefaultToMachineWidth = true); STARSOpndTypePtr MakeFloatingPointRegOpnd(STARS_regnum_t RegNum); STARSOpndTypePtr MakeMMXRegOpnd(STARS_regnum_t RegNum); STARSOpndTypePtr MakeXMMRegOpnd(STARS_regnum_t RegNum); STARSOpndTypePtr MakeYMMRegOpnd(STARS_regnum_t RegNum); STARSOpndTypePtr MakeNearPointerOpnd(STARS_ea_t TargetAddr) const; STARSOpndTypePtr MakeMemDisplacementOpnd(STARS_regnum_t BaseRegNum, STARS_regnum_t IndexRegNum, uint16_t ScaleFactor, STARS_ea_t offset); STARSOpndTypePtr MakeMemPhraseOpnd(STARS_regnum_t BaseRegNum, STARS_regnum_t IndexRegNum, uint16_t ScaleFactor); // Analysis methods virtual bool IsPushFromFixedCall(void) const; // Is push from a call that became a push/jump pair? virtual STARS_InstructionID_Set_t GetReferencedInstructionIDs(bool &success); // Get inst IDs of jump targets, call targets, etc., including for analyzeable indirect calls and jumps; success = false otherwise virtual STARS_InstructionID_Set_t GetTargetedInstructionIDs(bool &success); // return inst ID addr for fall-through from this inst virtual STARS_ea_t GetFallThroughInstID(void); // Analyze the indirect jump at IndirJumpInst, put switch table info in TableInfo if available, return false otherwise. // Note: The TableInfo.FollowNodeNum field must be determined by later analysis. virtual bool AnalyzeSwitchStatement(SMPInstr *IndirJumpInst, struct SwitchTableInfo &TableInfo); protected: struct STARS_IDA_insn_t STARScmd; uint32_t STARSfeatures; STARSOpndTypePtr VoidOpndsPtr; // common pointer to a void operand for all operands not used, to save memory private: bool ImplicitDEFs; // Modifies regs that do not appear as operands, e.g. many mul/div void InitOperand(op_t &InitOp) const; }; #endif