diff --git a/.gitattributes b/.gitattributes index 40d44f34f2cd8f2fcd5c5a0c0132bb31bd84a6dc..3a625c81a70565fce04cd68f30d012c548ad0d67 100644 --- a/.gitattributes +++ b/.gitattributes @@ -19,11 +19,13 @@ include/interfaces/abstract/STARSFunction.h -text include/interfaces/abstract/STARSInstruction.h -text include/interfaces/abstract/STARSInstructionID.h -text include/interfaces/abstract/STARSInterface.h -text +include/interfaces/abstract/STARSOp.h -text include/interfaces/abstract/STARSSegment.h -text include/interfaces/abstract/all.h -text include/interfaces/idapro/STARSFunction.h -text include/interfaces/idapro/STARSInstruction.h -text include/interfaces/idapro/STARSInterface.h -text +include/interfaces/idapro/STARSOp.h -text include/interfaces/idapro/STARSSegment.h -text include/interfaces/idapro/all.h -text /install-sh -text @@ -49,6 +51,7 @@ src/interfaces/abstract/STARSInstruction.cpp -text src/interfaces/idapro/Makefile.in -text src/interfaces/idapro/STARSFunction.cpp -text src/interfaces/idapro/STARSIDAInstruction.cpp -text +src/interfaces/idapro/STARSIDAOp.cpp -text src/interfaces/idapro/STARSInterface.cpp -text src/interfaces/irdb/Makefile.in -text tests/commit/busybox.psexe -text diff --git a/include/base/SMPInstr.h b/include/base/SMPInstr.h index 7c9ccf008cef7d988f4775ab017c9a0a7ada3d49..5c9db66f961e61ae5c0b79abd55e3aec8ef47a28 100644 --- a/include/base/SMPInstr.h +++ b/include/base/SMPInstr.h @@ -659,6 +659,7 @@ private: SMPBasicBlock *BasicBlock; // basic block containing this instruction insn_t SMPcmd; // copy of 'cmd' for this instruction STARS_InstructionID_t STARS_ID; // instruction ID; could be IDA Pro address or IRDB inst ID + STARS_Instruction_t *STARSInstPtr; // pointer to either STARS_IDA_Instruction_t or STARS_IRDB_Instruction_t uint32 features; // Canonical features for SMPcmd SMPitype type; // Data flow analysis category int OptType; // Optimization category (see OptCategory[]) diff --git a/include/interfaces/abstract/STARSOp.h b/include/interfaces/abstract/STARSOp.h new file mode 100644 index 0000000000000000000000000000000000000000..4e38766b2acd4fc6d943746c5ad9ae9fcc266e99 --- /dev/null +++ b/include/interfaces/abstract/STARSOp.h @@ -0,0 +1,44 @@ +#ifndef STARSOp_h +#define STARSOp_h + +#include <stdint.h> +#include <assert.h> +#include <map> + +class STARS_op_t +{ + public: + + // Constructors + STARS_op_t(); + + // Operators + virtual bool operator<(const STARS_op_t &rOp) const = 0; + + // Get methods + virtual uintptr_t GetAddr(void) const = 0; + virtual unsigned char GetType(void) const = 0; // Get type o_reg, o_displ, etc. + virtual uint16 GetReg(void) const = 0; // Get reg field of operand, whether it is an addressing reg or directly used reg in register operand + virtual char GetSIB(void) const = 0; // Get x86 SIB byte (dense encoding of base reg, index reg, and scale factor) + virtual char GetSpecFlag4(void) const = 0; // Get specflag4 byte, used to hold a copy of the auxpref byte in x86-64 programs. + virtual uintptr_t GetImmedValue(void) const = 0; // Get value field for immediate operands; uint32 for x86-32, uint64 for x86-64 + + // Set methods + virtual void SetSpecFlag4(char value) = 0; + virtual void SetBitInSpecFlag4(char value) = 0; // OR in the value to set a bit + + // Query methods + virtual bool IsRegOp(void) const = 0; + virtual bool IsVoidOp(void) const = 0; + virtual bool IsMemDisplacementOp(void) const = 0; + virtual bool IsStaticMemOp(void) const = 0; + virtual bool IsMemNoDisplacementOp(void) const = 0; + virtual bool HasSIBByte(void) const = 0; + + +}; + +#endif + + + diff --git a/include/interfaces/abstract/all.h b/include/interfaces/abstract/all.h index 1c7259f5f526d8914eb83f8c6aab4c5effad11d1..92b69437bdf9eec1e9b84c03649388296f9448b6 100644 --- a/include/interfaces/abstract/all.h +++ b/include/interfaces/abstract/all.h @@ -6,4 +6,5 @@ #include <interfaces/abstract/STARSFunction.h> #include <interfaces/abstract/STARSInstructionID.h> #include <interfaces/abstract/STARSInstruction.h> +#include <interfaces/abstract/STARSOp.h> diff --git a/include/interfaces/idapro/STARSInstruction.h b/include/interfaces/idapro/STARSInstruction.h index 6e3508fdf15013376f2dc9acd1171116555588d5..41205475877714f64adc6f8e8b7f08183fd786b1 100644 --- a/include/interfaces/idapro/STARSInstruction.h +++ b/include/interfaces/idapro/STARSInstruction.h @@ -4,6 +4,7 @@ #include <pro.h> #include <ua.hpp> #include "interfaces/SMPDBInterface.h" +#include "interfaces/idapro/all.h" // struct to hold items that mimic the IDA Pro type insn_t. struct STARS_IDA_insn_t @@ -57,7 +58,7 @@ struct STARS_IDA_insn_t char insnpref; // processor dependent field // Information about instruction operands. - op_t Operands[UA_MAXOP]; + STARS_IDA_op_t *Operands[UA_MAXOP]; char flags; // instruction flags @@ -68,11 +69,11 @@ class STARS_IDA_Instruction_t : public STARS_Instruction_t public: STARS_IDA_Instruction_t(const STARS_InstructionID_t& p_id) : STARS_Instruction_t(p_id) {}; - STARS_InstructionID_t GetNextInstructionID(); - STARS_InstructionID_t GetTargetInstructionID(); + STARS_InstructionID_t GetNextInstructionID(void); + STARS_InstructionID_t GetTargetInstructionID(void); bool STARS_GetCmd(void); inline uint32 GetFeatures(void) const { return STARSfeatures; }; - inline bool IsRegOpnd(size_t OpndNum) const { return (STARScmd.Operands[OpndNum].type == o_reg); }; + inline bool IsRegOpnd(size_t OpndNum) const { return (STARScmd.Operands[OpndNum]->GetType() == o_reg); }; #if 0 STARSOpndTypePtr GetOpnd(size_t OpndNum); STARSOpndTypePtr MakeVoidOpnd(void); diff --git a/include/interfaces/idapro/STARSOp.h b/include/interfaces/idapro/STARSOp.h new file mode 100644 index 0000000000000000000000000000000000000000..5a32bb7b47c11eedfd97d9853e401b3e044feea4 --- /dev/null +++ b/include/interfaces/idapro/STARSOp.h @@ -0,0 +1,45 @@ +#ifndef STARS_IDA_op_h +#define STARS_IDA_op_h + +#include <stdint.h> +#include <pro.h> +#include <ua.hpp> + +class STARS_IDA_op_t : public STARS_op_t +{ + public: + + // Constructors + STARS_IDA_op_t(op_t IDAOp) : m_Opnd(IDAOp) {}; + + // Operators + bool operator<(const STARS_op_t &rOp) const; + + // Get methods + uintptr_t GetAddr(void) const { return m_Opnd.addr; }; + unsigned char GetType(void) const { return m_Opnd.type; }; + uint16 GetReg(void) const { return m_Opnd.reg; }; + char GetSIB(void) const { return m_Opnd.sib; }; // Get x86 SIB byte (dense encoding of base reg, index reg, and scale factor) + char GetSpecFlag4(void) const {return m_Opnd.specflag4; }; // Get specflag4 byte, used to hold a copy of the auxpref byte in x86-64 programs. + uintptr_t GetImmedValue(void) const {return m_Opnd.value; }; // Get value field for immediate operands; uint32 for x86-32, uint64 for x86-64 + + // Set methods + void SetSpecFlag4(char value) { m_Opnd.specflag4 = value; }; + void SetBitInSpecFlag4(char value) { m_Opnd.specflag4 |= value; }; + + // Query methods + bool IsRegOp(void) const { return (m_Opnd.type == o_reg); }; + bool IsVoidOp(void) const { return (m_Opnd.type == o_void); }; + bool IsMemDisplacementOp(void) const { return (m_Opnd.type == o_displ); }; + bool IsStaticMemOp(void) const { return (m_Opnd.type == o_mem); }; + bool IsMemNoDisplacementOp(void) const { return (m_Opnd.type == o_phrase); }; + bool HasSIBByte(void) const { return (m_Opnd.hasSIB != 0); }; + + protected: + op_t m_Opnd; +}; + +#endif + + + diff --git a/include/interfaces/idapro/all.h b/include/interfaces/idapro/all.h index 2197d6d128c4170e16f3724ae5e634f89132944b..1ff16a1e85112ddfdff9cad740c79a2a6508d36c 100644 --- a/include/interfaces/idapro/all.h +++ b/include/interfaces/idapro/all.h @@ -21,4 +21,5 @@ #include <interfaces/idapro/STARSFunction.h> #include <interfaces/idapro/STARSInterface.h> #include <interfaces/idapro/STARSInstruction.h> +#include <interfaces/idapro/STARSOp.h> diff --git a/src/base/SMPInstr.cpp b/src/base/SMPInstr.cpp index 3403eec92332fc8b9c95697ebb888e88c2200611..4050e3d4ae71cca970227c5a688d471384e0a7f6 100644 --- a/src/base/SMPInstr.cpp +++ b/src/base/SMPInstr.cpp @@ -1551,9 +1551,11 @@ SMPInstr::SMPInstr(ea_t addr) : STARS_ID((uintptr_t) addr) { this->OptType = 0; this->address = addr; this->StackPtrOffset = 0; - // We do not store the pointer returned by the following allocation because - // we can look it up later via the STARS_ID member. - STARS_IDA_Instruction_t* TempPtr = new STARS_IDA_Instruction_t(this->STARS_ID); +#ifdef STARS_IDA_INTERFACE + this->STARSInstPtr = new STARS_IDA_Instruction_t(this->STARS_ID); +#else + this->STARSInstPtr = new STARS_IRDB_Instruction_t(this->STARS_ID); +#endif #if 0 this->ResetGoodRTL(); this->ResetJumpTarget(); diff --git a/src/interfaces/idapro/Makefile.in b/src/interfaces/idapro/Makefile.in index b658e8ffba2eab14b3a5a164d06c905a4efc3f0f..d57b178d3e4f84f19a2dc6b1d0f3d33a78ba625f 100644 --- a/src/interfaces/idapro/Makefile.in +++ b/src/interfaces/idapro/Makefile.in @@ -1,5 +1,5 @@ -OBJS=STARSFunction.o STARSInterface.o STARSIDAInstruction.o +OBJS=STARSFunction.o STARSInterface.o STARSIDAInstruction.o STARSIDAOp.o CXX=@CXX@ LD=@LD@ EXTRA_CXXFLAGS=@EXTRA_CXXFLAGS@ diff --git a/src/interfaces/idapro/STARSIDAInstruction.cpp b/src/interfaces/idapro/STARSIDAInstruction.cpp index 6f4f8cbca2f3a85320dd352671575e57316e09cd..8d21672995d2a08faa8e0213704ecb55897338c6 100644 --- a/src/interfaces/idapro/STARSIDAInstruction.cpp +++ b/src/interfaces/idapro/STARSIDAInstruction.cpp @@ -1,3 +1,4 @@ +#include <assert.h> #include "base/SMPDataFlowAnalysis.h" #include "base/SMPStaticAnalyzer.h" @@ -20,7 +21,8 @@ STARS_InstructionID_t STARS_IDA_Instruction_t::GetNextInstructionID(void) }; STARS_InstructionID_t STARS_IDA_Instruction_t::GetTargetInstructionID(void) { - STARS_ea_t TargetAddr = this->STARScmd.Operands[0].addr; + assert(NULL != this->STARScmd.Operands[0]); + STARS_ea_t TargetAddr = this->STARScmd.Operands[0]->GetAddr(); return STARS_InstructionID_t(TargetAddr); } @@ -57,18 +59,19 @@ bool STARS_IDA_Instruction_t::STARS_GetCmd(void) { this->STARSfeatures = cmd.get_canon_feature(); for (int i = 0; i < UA_MAXOP; ++i) { - this->STARScmd.Operands[i].specflag4 = 0; + this->STARScmd.Operands[i] = new STARS_IDA_op_t(cmd.Operands[i]); + this->STARScmd.Operands[i]->SetSpecFlag4(0); #ifdef __EA64__ if (STARS_ISA_Bitwidth == 64) { // Copy the cmd.rex prefix into the op_t.specflag4 field for each operand // that has a SIB byte. - this->STARScmd.Operands[i].specflag4 = this->STARScmd.rex; + this->STARScmd.Operands[i]->SetSpecFlag4(this->STARScmd.rex); } #endif // See comments on STARS_VEXPR and STARS_VSIB in SMPDataFlowAnalysis.h. // These bits do not (as of IDA Pro 6.4) conflict with cmd.rex bits. if ((cmd.auxpref & aux_vexpr) != 0) { - this->STARScmd.Operands[i].specflag4 |= STARS_VEXPR; + this->STARScmd.Operands[i]->SetBitInSpecFlag4(STARS_VEXPR); } switch (this->STARScmd.itype) { @@ -80,7 +83,7 @@ bool STARS_IDA_Instruction_t::STARS_GetCmd(void) { case NN_vpgatherdq: case NN_vpgatherqd: case NN_vpgatherqq: - this->STARScmd.Operands[i].specflag4 |= STARS_VSIB; + this->STARScmd.Operands[i]->SetBitInSpecFlag4(STARS_VSIB); default: ; } diff --git a/src/interfaces/idapro/STARSIDAOp.cpp b/src/interfaces/idapro/STARSIDAOp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..438ade08da0b2fe258c6ec908bb99e8570f29245 --- /dev/null +++ b/src/interfaces/idapro/STARSIDAOp.cpp @@ -0,0 +1,45 @@ +#include <pro.h> +#include <ua.hpp> + +#include "base/SMPDataFlowAnalysis.h" +#include "base/SMPStaticAnalyzer.h" +#include "interfaces/SMPDBInterface.h" +#include "interfaces/abstract/all.h" +#include "interfaces/idapro/all.h" + + +bool STARS_IDA_op_t::operator<(const STARS_op_t &rOp) const { + unsigned char Type1 = this->GetType(); + unsigned char Type2 = rOp.GetType(); + if (Type1 != Type2) + return (Type1 < Type2); + switch (Type1) { + case o_void: return false; + case o_reg: return MDLessReg(this->GetReg(), rOp.GetReg()); + case o_mem: return (this->GetAddr() < rOp.GetAddr()); + case o_phrase: if (this->HasSIBByte() && rOp.HasSIBByte()) return ((this->GetSIB() < rOp.GetSIB()) || ((this->GetSIB() == rOp.GetSIB()) && (this->GetSpecFlag4() < rOp.GetSpecFlag4()))); + else if (rOp.HasSIBByte()) return true; // no SIB < has SIB + else if (this->HasSIBByte()) return false; // no SIB < has SIB + else return MDLessReg(this->GetReg(), rOp.GetReg()); // no SIB bytes + case o_displ: if (this->HasSIBByte() && rOp.HasSIBByte()) + return ((this->GetSIB() < rOp.GetSIB()) + || ((this->GetSIB() == rOp.GetSIB()) + && ((this->GetAddr() < rOp.GetAddr()) || ((this->GetAddr() == rOp.GetAddr()) && (this->GetSpecFlag4() < rOp.GetSpecFlag4()))))); + else if (rOp.HasSIBByte()) return true; // no SIB < has SIB + else if (this->HasSIBByte()) return false; // no SIB < has SIB + else return ((this->GetAddr() < rOp.GetAddr()) + || ((this->GetAddr() == rOp.GetAddr()) && MDLessReg(this->GetReg(), rOp.GetReg()))); // no SIB bytes + case o_imm: return (this->GetImmedValue() < rOp.GetImmedValue()); + case o_far: // fall through to o_near case + case o_near: return (this->GetAddr() < rOp.GetAddr()); + case o_trreg: // fall through + case o_dbreg: // fall through + case o_crreg: // fall through + case o_fpreg: // fall through + case o_mmxreg: // fall through + case o_xmmreg: return (this->GetReg() < rOp.GetReg()); // no subword regs to deal with, don't need MDLessReg() + + default: msg("ERROR: Unknown operand type in LessOp.\n"); return false; + }; // end switch (Opnd1.type) +}; // end of operator less-than +