Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • opensrc/SMPStaticAnalyzer
1 result
Show changes
Commits on Source (11)
Showing
with 704 additions and 303 deletions
......@@ -712,6 +712,7 @@ extern DisAsmString DisAsmText;
#define DEFORUSE_RESET_UNUSED5 0xbf
#define DEFORUSE_RESET_UNUSED6 0x7f
#pragma pack(1)
class DefOrUse {
public:
// Constructors
......@@ -764,6 +765,7 @@ private:
bool GloballyLoopInvariant; // DEF is not variant in any loop
#endif
}; // end of class DefOrUse
#pragma pack() // back to normal packing
// Comparison operator class to permit use of DefOrUse type in sets.
class LessDefUse {
......
......@@ -886,6 +886,7 @@ private:
STARSBufferCallArgMap BufferCallConstBufferArgsMap; // list of (bufptrargpos, bufsize) indexed by CallAddr
// Methods
void DestroyLoopExprs(void); // release loop-based symbolic memory access expressions
void EraseInstRange(STARS_ea_t FirstAddr, STARS_ea_t LastAddr);
void SetLinks(void); // Link basic blocks and map instructions to blocks
bool FindDistantCodeFragment(STARS_ea_t TargetAddr); // Is TargetAddr the start of a code fragment that belongs to this func, not a separate func?
......
......@@ -464,6 +464,7 @@ public:
void ListInArgRegsUsed(std::bitset<1 + MD_LAST_REG_NO> &RegNums); // list incoming argument register numbers encountered (SSA #0 in an InArg reg)
bool IsStackPtrOffset(const STARS_sval_t CurrentStackPtrOffset, STARS_sval_t &FinalStackPtrOffset) const; // If expr is SP+offset, add offset to Current to get Final
void SubstituteSSANum(SMPInstr *CallInst, const int NewSSANum, const STARSOpndTypePtr &InArgOp); // Find all uses of InArgOp, SSANum == 0, and give it NewSSANum; replace all ParentInsts with CallInst
bool SubstituteGlobalRangeValues(const bool InitCase); // Use MinVal if InitCase, MaxVal otherwise for global vars in expression
STARSOpndTypePtr FindLeftPreLoopDefOp(void) const; // For loop exprs, find the DefOp at LeftPreLoopDefAddr
bool AreAllRegsLoopInvariant(void) const; // Detect loop-invariant exprs, which can occur inside loops.
void SplitMemoryRangeExpr(bool PositiveIncrement, STARSExpression *&InitExpr, STARSExpression *&LimitExpr); // If this is a relational range expr, produce the lower and limit exprs
......
......@@ -101,6 +101,12 @@ struct GlobalVar {
std::set<std::pair<std::size_t, bool>, LessOff> FieldOffsets; // bool = accessed through index register by any instruction?
};
// For tracking the minimum and maximum values seen that were written to a global var.
struct STARSValueRange {
STARS_uval_t MinVal;
STARS_uval_t MaxVal;
};
class LtStr {
public:
bool operator() (const char* c1, const char* c2) const {
......@@ -124,6 +130,9 @@ public:
inline std::map<std::string, STARS_ea_t>::iterator GetLastGlobalName(void) {
return GlobalNameMap.end();
}
// Methods for recovering min or max value seen directly written to a global var.
bool FindGlobalMinValue(const STARS_ea_t GlobalAddr, STARS_uval_t &MinValue) const;
bool FindGlobalMaxValue(const STARS_ea_t GlobalAddr, STARS_uval_t &MaxValue) const;
inline ProfilerInformation *GetProfInfo(void) { return ProfInfo; };
SMPFunction* FindFunction(STARS_ea_t FirstAddr) const; // get function from first addr in function
SMPFunction* FindFunctionAndBlockFromInstID(const STARS_ea_t AnyInstID, int &BlockNum) const; // get function and block # for any instruction ID, not just first ID
......@@ -140,7 +149,8 @@ public:
void SetProgramThrowsExceptions(void); // Record detection of __cxa_throw in the binary
void AddBlockToRemovalList(SMPBasicBlock *UnreachableBlock); // Add block, e.g. with "call 0" instruction, to later removal list.
std::pair<std::map<std::string, STARS_ea_t>::iterator, bool> InsertGlobalNameAddrMapEntry(std::pair<std::string, STARS_ea_t> TempPair) { return GlobalNameMap.insert(TempPair); };
void InsertGlobalVarTableEntry(std::pair<STARS_ea_t, struct GlobalVar> VarItem) { GlobalVarTable.insert(VarItem); };
inline void InsertGlobalVarTableEntry(std::pair<STARS_ea_t, struct GlobalVar> VarItem) { GlobalVarTable.insert(VarItem); };
void InsertGlobalVarMinMaxValue(const STARS_ea_t GlobalAddr, const STARS_uval_t ValueSeen); // Update min or max value seen if needed
inline std::pair<std::set<std::string>::iterator, bool> InsertLibraryFuncName(std::string FuncName) { return LibraryCallTargetNames.insert(FuncName); };
// Query methods
......@@ -175,6 +185,7 @@ private:
std::list<SMPFunction *> PrioritizedFuncList; // Functions in bottom-up call-graph analysis order
std::map<STARS_ea_t, struct GlobalVar> GlobalVarTable; // all global static variables
std::map<std::string, STARS_ea_t> GlobalNameMap; // map global name to address
std::map<STARS_ea_t, struct STARSValueRange> GlobalValueRangeMap; // map global addr to min/max values directly written to it
std::list<std::pair<STARS_ea_t, SMPFunction *> > FuncList; // FuncMap entries prioritized in desired order for analysis
std::set<STARS_ea_t> UnsharedFragments; // Code fragments incorporated into their callers; remove from FuncMaps
std::set<STARS_ea_t> DataToCodeXrefTargets; // Code targets of data xrefs; probably will be called indirectly
......@@ -189,7 +200,6 @@ private:
// Methods
void InitStaticDataTable(void); // Gather info about global static data locations
void ComputeGlobalFieldOffsets(struct GlobalVar &CurrGlobal);
FuncType RecurseAndMarkRetAdd(SMPFunction *);
void ProcessExceptionHandlingFileSections(void); // If exception throwing code is detected, mark exception-handling functions as unsafe for fast returns.
void ResetFuncsProcessed(void); // set all funcs to not processed before a whole program analysis
......
......@@ -7,6 +7,7 @@
#include <assert.h>
#include <map>
#include <iostream>
#include "interfaces/STARSTypes.h"
#include "interfaces/SMPDBInterface.h"
......@@ -20,9 +21,15 @@ class STARS_Instruction_t
// Constructors and destructors
STARS_Instruction_t(const STARS_InstructionID_t& p_id) : m_id(p_id)
{ p_id.AddIDToInsnMapping(this);}
{
objects_created++;
p_id.AddIDToInsnMapping(this);
}
virtual ~STARS_Instruction_t(){}
virtual ~STARS_Instruction_t()
{
objects_destroyed++;
}
// Data initialization methods
virtual bool STARS_GetCmd(void) = 0;
......@@ -83,9 +90,21 @@ class STARS_Instruction_t
virtual void Dump() { } ;
static void DumpCreationStats(std::ostream & out)
{
out<<"#ATTRIBUTE STARS_Instruction_t_created: "<<std::dec<<objects_created<<std::endl;
out<<"#ATTRIBUTE STARS_Instruction_t_destroyed: "<<std::dec<<objects_destroyed<<std::endl;
out<<"#ATTRIBUTE STARS_Instruction_t_current : "<<std::dec<<objects_created-objects_destroyed<<std::endl;
}
protected:
STARS_InstructionID_t m_id;
private:
static uint64_t objects_created;
static uint64_t objects_destroyed;
};
#endif
......
......@@ -12,8 +12,14 @@ class STARS_op_t
public:
// Constructors
STARS_op_t() = default;
virtual ~STARS_op_t() = default;
STARS_op_t()
{
objects_created++;
}
virtual ~STARS_op_t()
{
objects_destroyed++;
}
// Clone method (deep copy).
virtual STARSOpndTypePtr clone(void) const = 0;
......@@ -78,6 +84,18 @@ class STARS_op_t
// Printing methods.
virtual void Dump() { }
static void DumpCreationStats(std::ostream & out)
{
out<<"#ATTRIBUTE STARS_op_t_created: "<<std::dec<<objects_created<<std::endl;
out<<"#ATTRIBUTE STARS_op_t_destroyed: "<<std::dec<<objects_destroyed<<std::endl;
out<<"#ATTRIBUTE STARS_op_t_current : "<<std::dec<<objects_created-objects_destroyed<<std::endl;
}
private:
static uint64_t objects_created;
static uint64_t objects_destroyed;
};
......
......@@ -18,6 +18,58 @@ extern STARS_Interface_t* global_stars_interface;
class STARS_IRDB_Instruction_t : public STARS_Instruction_t
{
private:
class DecodedInstructionMicro_t
{
public:
DecodedInstructionMicro_t(const libIRDB::virtual_offset_t addr, const void* bits, const uint32_t length)
{
const auto disasm=libIRDB::DecodedInstruction_t(addr, bits,length);
init(disasm);
}
DecodedInstructionMicro_t(const libIRDB::Instruction_t* irdb_insn)
{
const auto disasm=libIRDB::DecodedInstruction_t(irdb_insn);
init(disasm);
}
bool hasRelevantRepnePrefix() const { return m_hasRelevantRepnePrefix;}
bool hasRelevantRepPrefix() const { return m_hasRelevantRepPrefix;}
bool hasRelevantOperandSizePrefix() const { return m_hasRelevantOperandSizePrefix;}
bool hasRexWPrefix() const { return m_hasRexWPrefix;}
bool hasImplicitlyModifiedRegs() const { return m_hasImplicitlyModifiedRegs;}
bool isUnconditionalBranch() const { return m_isUnconditionalBranch;}
bool isCall() const { return m_isCall;}
uint32_t length() const { return m_length;}
libIRDB::virtual_offset_t getAddress() const { return m_getAddress; }
const std::string& getMnemonic() const { return m_getMnemonic; }
private:
bool m_hasRelevantRepnePrefix:1;
bool m_hasRelevantRepPrefix:1;
bool m_hasRelevantOperandSizePrefix:1;
bool m_hasRexWPrefix:1;
bool m_hasImplicitlyModifiedRegs:1;
bool m_isUnconditionalBranch:1;
bool m_isCall:1;
uint32_t m_length:6;
libIRDB::virtual_offset_t m_getAddress;
std::string m_getMnemonic;
private:
void init(const libIRDB::DecodedInstruction_t& disasm)
{
m_hasRelevantRepnePrefix=disasm.hasRelevantRepnePrefix();
m_hasRelevantRepPrefix=disasm.hasRelevantRepPrefix();
m_hasRelevantOperandSizePrefix=disasm.hasRelevantOperandSizePrefix();
m_hasRexWPrefix=disasm.hasRexWPrefix();
m_hasImplicitlyModifiedRegs=disasm.hasImplicitlyModifiedRegs();
m_getMnemonic=disasm.getMnemonic();
m_isUnconditionalBranch=disasm.isUnconditionalBranch();
m_isCall=disasm.isCall();
m_length=disasm.length();
m_getAddress=disasm.getAddress();
}
};
public:
// create SSA marker
......@@ -42,8 +94,10 @@ class STARS_IRDB_Instruction_t : public STARS_Instruction_t
{
assert(irdb_insn);
IDAOpcodeCached = false;
#if 0 // Redundant; called from SMPInstr::Analyze()
bool res=STARS_GetCmd();
assert(res);
#endif
}
virtual ~STARS_IRDB_Instruction_t() {}
......@@ -71,7 +125,7 @@ class STARS_IRDB_Instruction_t : public STARS_Instruction_t
// 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(bool ShiftOperands = false) const;
virtual uint32_t GetInitialInstFeatures(bool ShiftOperands, const libIRDB::DecodedInstruction_t& p_disasm) const;
// jdh: consider returning by reference?
virtual STARSOpndTypePtr GetOpnd(std::size_t OpndNum) const
......@@ -213,9 +267,12 @@ class STARS_IRDB_Instruction_t : public STARS_Instruction_t
// useful for other IRDB classes.
virtual const libIRDB::Instruction_t* GetIRDBInstruction() const { return irdb_insn;}
protected:
static STARSOpndTypePtr VoidOpndsPtr; // common pointer to a void operand for all operands not used, to save memory
private:
const libIRDB::Instruction_t* irdb_insn;
libIRDB::DecodedInstruction_t disasm;
DecodedInstructionMicro_t disasm;
std::vector<STARSOpndTypePtr> Operands;
uint32_t features;
uint16_t IDAOpcode; // cached result from GetIDAOpcode()
......
......@@ -15,6 +15,7 @@ class STARS_IRDB_op_t;
// to help easy porting if this ever changes.
typedef std::shared_ptr<STARS_IRDB_op_t> STARSIRDBOpndTypePtr;
#pragma pack(1)
class STARS_IRDB_op_t : public STARS_op_t
{
public:
......@@ -98,6 +99,14 @@ class STARS_IRDB_op_t : public STARS_op_t
switch(OpType)
{
case op_Reg:
case op_CrReg:
case op_DrReg:
case op_Eflags:
case op_MMXReg:
case op_XMMReg:
case op_YMMReg:
case op_FPReg:
case op_Mxcsr:
return operand.reg.RegNum;
case op_Mem:
return operand.mem.base;
......@@ -182,14 +191,10 @@ class STARS_IRDB_op_t : public STARS_op_t
virtual bool IsMemNoDisplacementOp(void) const { return OpType==op_Mem && operand.mem.disp==0; }
virtual bool IsMemOp(void) const { return OpType==op_Mem; }
virtual bool HasSIBByte(void) const { assert(OpType==op_Mem); return operand.mem.hasSIB; }
virtual bool IsFloatingPointRegOp(void) const
{ if(OpType!=op_Reg) return false; return STARS_x86_R_st0<= operand.reg.RegNum && operand.reg.RegNum<=STARS_x86_R_st7; }
virtual bool IsMMXRegOp(void) const
{ if(OpType!=op_Reg) return false; return STARS_x86_R_mm0<= operand.reg.RegNum && operand.reg.RegNum<=STARS_x86_R_mm7; }
virtual bool IsXMMRegOp(void) const
{ if(OpType!=op_Reg) return false; return STARS_x86_R_xmm0<= operand.reg.RegNum && operand.reg.RegNum<=STARS_x86_R_xmm15; }
virtual bool IsYMMRegOp(void) const
{ if(OpType!=op_Reg) return false; return STARS_x86_R_ymm0<= operand.reg.RegNum && operand.reg.RegNum<=STARS_x86_R_ymm15; }
virtual bool IsFloatingPointRegOp(void) const { return (OpType == op_FPReg); }
virtual bool IsMMXRegOp(void) const { return (OpType == op_MMXReg); }
virtual bool IsXMMRegOp(void) const { return (OpType == op_XMMReg); }
virtual bool IsYMMRegOp(void) const { return (OpType == op_YMMReg); }
virtual bool IsTestRegOp(void) const { return false; }
virtual bool IsDebugRegOp(void) const { return false; }
virtual bool IsControlRegOp(void) const { return false; }
......@@ -242,11 +247,6 @@ class STARS_IRDB_op_t : public STARS_op_t
private:
// what's the global_index for Get/SetOpGlobalIndex
std::size_t global_index;
STARS_RegNo SegReg;
int byteWidth;
enum OperandType_t { op_Void, op_Reg, op_Mem, op_Imm, op_CrReg, op_DrReg, op_Eflags, op_MMXReg, op_XMMReg, op_YMMReg, op_FPReg, op_Mxcsr, op_SegReg, op_Addr } OpType;
union
{
struct
......@@ -257,8 +257,8 @@ class STARS_IRDB_op_t : public STARS_op_t
{
STARS_RegNo base;
STARS_RegNo index;
unsigned int scale:4; // can take values 0, 1, 2, 4, 8.
libIRDB::virtual_offset_t disp; // may be 64-bit imm in some x86-64 instructions.
unsigned int scale:4; // can take values 0, 1, 2, 4, 8.
bool hasSIB:1;
} mem;
struct
......@@ -273,24 +273,17 @@ class STARS_IRDB_op_t : public STARS_op_t
} operand;
bool visible;
void Init()
{
SegReg=STARS_x86_R_none;
OpType=op_Void;
// init the operand to 0, because the it should have no semantically valid meaning in any sense anyhow if OpType==Void.
memset(&operand,0,sizeof(operand));
enum OperandType_t { op_Void, op_Reg, op_Mem, op_Imm, op_CrReg, op_DrReg, op_Eflags, op_MMXReg, op_XMMReg, op_YMMReg, op_FPReg, op_Mxcsr, op_SegReg, op_Addr } OpType;
STARS_RegNo SegReg;
uint32_t byteWidth:6;
bool visible:1;
visible=0;
byteWidth=0;
}
void Init(void);
virtual void Dump();
};
#pragma pack()
#endif
......
......@@ -778,15 +778,48 @@ list<SMPBasicBlock *>::const_iterator SMPBasicBlock::GetFallThroughSucc(void) co
if ((JUMP != LastDataFlow) && (INDIR_JUMP != LastDataFlow) && (RETURN != LastDataFlow) && (HALT != LastDataFlow) && (!LastInst->IsFixedCallJump())) {
// Block has fall-through.
STARS_InstructionID_t NextInstID = LastInst->GetInstID().GetInstruction()->GetNextInstructionID();
STARS_ea_t FallThroughSuccAddr = NextInstID.GetIDWithinFile();
for (list<SMPBasicBlock *>::const_iterator SuccIter = this->GetFirstConstSucc(); SuccIter != this->GetLastConstSucc(); ++SuccIter) {
STARS_ea_t FirstSuccAddr = (*SuccIter)->GetFirstAddr();
if (FirstSuccAddr == FallThroughSuccAddr) { // found fall-through
FallThroughSuccIter = SuccIter;
break;
STARS_ea_t FallThroughSuccAddr = STARS_BADADDR;
#if 0
bool ValidLastInst = ((nullptr != LastInst) && (nullptr != LastInst->GetInstID().GetInstruction()));
if (ValidLastInst) {
STARS_InstructionID_t NextInstID = LastInst->GetInstID().GetInstruction()->GetNextInstructionID();
FallThroughSuccAddr = NextInstID.GetIDWithinFile();
for (list<SMPBasicBlock *>::const_iterator SuccIter = this->GetFirstConstSucc(); SuccIter != this->GetLastConstSucc(); ++SuccIter) {
STARS_ea_t FirstSuccAddr = (*SuccIter)->GetFirstAddr();
if (FirstSuccAddr == FallThroughSuccAddr) { // found fall-through
FallThroughSuccIter = SuccIter;
break;
}
}
}
#else
if (COND_BRANCH == LastDataFlow) {
STARS_ea_t NonFallThroughAddr = LastInst->GetJumpTarget();
assert(STARS_BADADDR != NonFallThroughAddr);
for (list<SMPBasicBlock *>::const_iterator SuccIter = this->GetFirstConstSucc(); SuccIter != this->GetLastConstSucc(); ++SuccIter) {
SMPBasicBlock *SuccBlock = (*SuccIter);
if (SuccBlock->GetFirstAddr() != NonFallThroughAddr) {
FallThroughSuccIter = SuccIter;
break;
}
}
}
else {
assert((DEFAULT == LastDataFlow) || (CALL == LastDataFlow) || (INDIR_CALL == LastDataFlow));
if (1 >= this->GetNumSuccessors())
FallThroughSuccIter = this->GetFirstConstSucc();
else { // computed call or indir_call targets
STARS_ea_t FallThroughAddr = LastInst->GetFallThroughAddr();
for (list<SMPBasicBlock *>::const_iterator SuccIter = this->GetFirstConstSucc(); SuccIter != this->GetLastConstSucc(); ++SuccIter) {
SMPBasicBlock *SuccBlock = (*SuccIter);
if (SuccBlock->GetFirstAddr() == FallThroughAddr) {
FallThroughSuccIter = SuccIter;
break;
}
}
}
}
#endif
}
return FallThroughSuccIter;
......@@ -798,12 +831,13 @@ list<SMPBasicBlock *>::const_iterator SMPBasicBlock::GetCondNonFallThroughSucc(v
vector<SMPInstr *>::const_reverse_iterator LastInstIter = this->GetRevInstCBegin();
SMPInstr *LastInst = (*LastInstIter);
SMPitype LastDataFlow = LastInst->GetDataFlowType();
if (COND_BRANCH == LastDataFlow) {
STARS_InstructionID_t NextInstID = LastInst->GetInstID().GetInstruction()->GetNextInstructionID();
STARS_ea_t FallThroughSuccAddr = NextInstID.GetIDWithinFile();
STARS_ea_t NonFallThroughAddr = LastInst->GetJumpTarget();
assert(STARS_BADADDR != NonFallThroughAddr);
for (list<SMPBasicBlock *>::const_iterator SuccIter = this->GetFirstConstSucc(); SuccIter != this->GetLastConstSucc(); ++SuccIter) {
STARS_ea_t FirstSuccAddr = (*SuccIter)->GetFirstAddr();
if (FirstSuccAddr != FallThroughSuccAddr) { // found non-fall-through
SMPBasicBlock *SuccBlock = (*SuccIter);
if (SuccBlock->GetFirstAddr() == NonFallThroughAddr) {
BranchTakenSuccIter = SuccIter;
break;
}
......
......@@ -371,6 +371,7 @@ SMPFunction::SMPFunction(STARS_Function_t *Info, SMPProgram* pgm) {
return;
} // end of SMPFunction() constructor
 
// Destructor
SMPFunction::~SMPFunction() {
list<SMPInstr *>::iterator InstIter;
for (InstIter = this->Instrs.begin(); InstIter != this->Instrs.end(); ++InstIter) {
......@@ -383,8 +384,65 @@ SMPFunction::~SMPFunction() {
SMPBasicBlock *CurrBlock = (*BlockIter);
if (NULL != CurrBlock) delete CurrBlock;
}
}
 
if (global_STARS_program->ShouldSTARSTranslateToSPARKAda()) {
// DestroyLoopExprs() was not called from AnalyzeLoopIterations()
// when we saved the exprs for SPARK Ada translation.
this->DestroyLoopExprs();
}
} // end of SMPFunction::destructor
void SMPFunction::DestroyLoopExprs(void) {
size_t i;
for (i = 0; i < this->LoopIterationsCountExprs.size(); ++i)
if (nullptr != this->LoopIterationsCountExprs[i]) {
delete this->LoopIterationsCountExprs[i];
this->LoopIterationsCountExprs[i] = nullptr;
}
for (i = 0; i < this->LoopIterationsInitExprs.size(); ++i)
if (nullptr != this->LoopIterationsInitExprs[i]) {
delete this->LoopIterationsInitExprs[i];
this->LoopIterationsInitExprs[i] = nullptr;
}
for (i = 0; i < this->LoopIterationsLimitExprs.size(); ++i)
if (nullptr != this->LoopIterationsLimitExprs[i]) {
delete this->LoopIterationsLimitExprs[i];
this->LoopIterationsLimitExprs[i] = nullptr;
}
for (i = 0; i < this->LoopMemWriteRangeExprs.size(); ++i)
this->LoopMemWriteRangeExprs[i].clear();
for (i = 0; i < this->LoopMemWriteBoundsExprs.size(); ++i) {
for (STARSExprBoundsPair CurrPair : this->LoopMemWriteBoundsExprs[i]) {
if (nullptr != CurrPair.first) {
delete CurrPair.first;
CurrPair.first = nullptr;
}
if (nullptr != CurrPair.second) {
delete CurrPair.second;
CurrPair.second = nullptr;
}
}
}
for (i = 0; i < this->LoopMemWriteBoundsExprsExpanded.size(); ++i) {
for (STARSExprBoundsPair CurrPair : this->LoopMemWriteBoundsExprsExpanded[i]) {
if (nullptr != CurrPair.first) {
delete CurrPair.first;
CurrPair.first = nullptr;
}
if (nullptr != CurrPair.second) {
delete CurrPair.second;
CurrPair.second = nullptr;
}
}
}
return;
}
// Get a non-stale pointer to the STARS_Function_t info for the current function.
STARS_Function_t *SMPFunction::GetFuncInfo(void) const {
STARS_Function_t *myPtr = SMP_get_func(this->GetFirstFuncAddr());
......@@ -559,6 +617,7 @@ bool SMPFunction::ComputeInOutRegs(bool InheritPass, bool &WritesMem, bool &Call
STARSOpndTypePtr DefOp = DefIter->GetOp();
if (DefOp->IsRegOp() || DefOp->IsFloatingPointRegOp()) {
STARS_regnum_t RegNo = DefOp->GetReg();
assert(0 <= (int) RegNo);
this->OutputRegs.set((size_t) RegNo, true);
}
else if (DefOp->IsMemOp()) {
......@@ -8736,7 +8795,16 @@ STARSExpression* SMPFunction::CreateMemoryAddressExpr(const STARSOpndTypePtr &Me
}
}
else { // just offset or SegReg or SegReg+offset
assert(HasOffset || HasSegReg);
if (!(HasOffset || HasSegReg)) {
// Code might be unreachable debug path code, not removed
// due to low level of compiler optimization.
SMP_msg("SERIOUS WARNING: (Unreachable?) mem offset zero at %llx\n",
(uint64_t) WriteAddr);
WriteInst->Dump();
HasOffset = true; // offset is zero
OffsetOp = WriteInst->MakeImmediateOpnd((STARS_uval_t) offset);
OffsetOp->SetByteWidth(MemDefOp->GetByteWidth());
}
MemoryAddressExpr->SetOperator(SMP_ASSIGN); // signal that only LeftOperand is valid
 
if (HasOffset && HasSegReg && (!IPRelative)) {
......@@ -13181,7 +13249,7 @@ void SMPFunction::AnalyzeLoopIterations(void) {
delete MemWriteUpperBound;
MemWriteUpperBound = nullptr;
this->LoopAnalysisProblems[LoopIndex] = true;
SMP_msg("INFO: Failure to ReplaceIVsWithLimitExpr for MemListIndex %zu loop %zu in function at %llx\n",
SMP_msg("INFO: Failure to ReplaceIVsWithLimitExpr for write MemListIndex %zu loop %zu in function at %llx\n",
MemListIndex, LoopIndex, (uint64_t) this->GetFirstFuncAddr());
}
if (PositiveIncrement) {
......@@ -13203,7 +13271,7 @@ void SMPFunction::AnalyzeLoopIterations(void) {
}
}
 
// Clone the lower and upper bounds expr for inheritance into callers.
// Clone the lower and upper bounds expr for annotations and inheritance into callers.
STARSExpression *MemWriteLowerBoundExpanded = MemWriteLowerBound->Clone();
STARSExpression *MemWriteUpperBoundExpanded = nullptr;
if (nullptr != MemWriteUpperBound)
......@@ -13231,6 +13299,17 @@ void SMPFunction::AnalyzeLoopIterations(void) {
std::inserter(UnionedStackPtrCopiesSet, UnionedStackPtrCopiesSet.begin()));
}
 
// Substitute global min and max values for global mem reads that
// are still in the expr, and see if we can simplify as a result.
bool FinalChange = MemWriteLowerBoundExpanded->SubstituteGlobalRangeValues(true);
if (FinalChange)
(void) MemWriteLowerBoundExpanded->SimplifyDriver();
if (LimitSuccess) {
FinalChange = MemWriteUpperBoundExpanded->SubstituteGlobalRangeValues(false);
if (FinalChange)
(void) MemWriteUpperBoundExpanded->SimplifyDriver();
}
// To assist in stack transformation security defenses, if the
// memory range expression is stack-relative, we emit an annotation
// that identifies the memory range written to at InstAddr.
......@@ -13304,7 +13383,7 @@ void SMPFunction::AnalyzeLoopIterations(void) {
}
else if (!StackAnnotation) {
// LowerBoundExpanded expr was neither static mem nor stack.
SMP_msg("INFO: LOOP: Expr neither static mem nor stack mem: \n");
SMP_msg("INFO: LOOP: Write expr neither static mem nor stack mem: \n");
if (VerboseOutput) {
MemWriteLowerBoundExpanded->Dump(0);
}
......@@ -13356,10 +13435,10 @@ void SMPFunction::AnalyzeLoopIterations(void) {
if (MemRangeSuccess) {
SMP_msg("INFO: LOOP: Computed %zu LoopMemReadExprs for loop %d in function at %llx\n",
MemReadExprs.size(), LoopIndex, (uint64_t) this->GetFirstFuncAddr());
for (STARSMemWriteExprListIter MemListIter = MemReadExprWidths.begin(); MemListIter != MemReadExprWidths.end(); ++MemListIter) {
size_t MemListIndex = 0; // for debugging and diagnostic output
for (STARSMemWriteExprListIter MemListIter = MemReadExprWidths.begin(); MemListIter != MemReadExprWidths.end(); ++MemListIter, ++MemListIndex) {
STARSExprSetIter ExprIter = (*MemListIter).first;
STARSExpression *MemAddressRangeExpr = (*ExprIter);
// pair<STARSExprSetIter, bool> InsertResult = this->LoopMemWriteRangeExprs[LoopIndex].insert(MemAddressRangeExpr);
if (VerboseOutput) {
SMP_msg("INFO: LOOP: LoopMemRead EXPR:");
MemAddressRangeExpr->Dump(0);
......@@ -13367,127 +13446,154 @@ void SMPFunction::AnalyzeLoopIterations(void) {
SMP_msg("INFO: LOOP: LoopMemRead EXPR is stack-based.\n");
}
}
// Create the lower and upper bounds of the memory writing range.
// Create the lower and upper bounds of the memory reading range.
STARSExpression *MemReadLowerBound = MemAddressRangeExpr->Clone(); // deep copy, for editing
bool changed = false;
bool success = this->ReplaceAllIVsWithExprs(LoopIndex, MemReadLowerBound, true, changed);
if (success) {
(void) MemReadLowerBound->SimplifyDriver();
STARSExpression *MemReadUpperBound = MemAddressRangeExpr->Clone(); // deep copy, for editing
success = this->ReplaceAllIVsWithExprs(LoopIndex, MemReadUpperBound, false, changed);
if (success) {
if (VerboseOutput) {
SMP_msg("INFO: LOOP: Successfully replaced read IVs with InitExpr and LimitExpr for loop %d in function at %llx\n",
LoopIndex, (uint64_t) this->GetFirstFuncAddr());
}
(void) MemReadLowerBound->SimplifyDriver();
bool LimitSuccess = this->ReplaceAllIVsWithExprs(LoopIndex, MemReadUpperBound, false, changed);
if (LimitSuccess) {
(void) MemReadUpperBound->SimplifyDriver();
}
else {
// We will emit annotations that have a useful starting address for the
// memory range read, and a code that indicates the range limit is unknown.
delete MemReadUpperBound;
MemReadUpperBound = nullptr;
SMP_msg("INFO: Failure to ReplaceIVsWithLimitExpr for read MemListIndex %zu loop %zu in function at %llx\n",
MemListIndex, LoopIndex, (uint64_t) this->GetFirstFuncAddr());
}
 
int StackPtrCopiesVecIndex = (*MemListIter).second.second;
if (VerboseOutput) {
SMP_msg("INFO: LOOP: MemReadLowerBound EXPR:");
MemReadLowerBound->Dump(0);
int StackPtrCopiesVecIndex = (*MemListIter).second.second;
if (VerboseOutput) {
SMP_msg("INFO: LOOP: MemReadLowerBound EXPR:");
MemReadLowerBound->Dump(0);
if (LimitSuccess) {
SMP_msg("INFO: LOOP: MemReadUpperBound EXPR:");
MemReadUpperBound->Dump(0);
}
}
 
// Clone the lower and upper bounds expr for inheritance into callers (future SPARK).
STARSExpression *MemReadLowerBoundExpanded = MemReadLowerBound->Clone();
STARSExpression *MemReadUpperBoundExpanded = MemReadUpperBound->Clone();
// Clone the lower and upper bounds expr for inheritance into callers (future SPARK).
STARSExpression *MemReadLowerBoundExpanded = MemReadLowerBound->Clone();
STARSExpression *MemReadUpperBoundExpanded = nullptr;
if (LimitSuccess)
MemReadUpperBoundExpanded = MemReadUpperBound->Clone();
 
// For annotation output, we want to expand the expressions beyond loop boundaries,
// hopefully as far as incoming args or constant initializers.
set<STARS_ea_t> NewStackPtrCopiesSet;
success = this->ExpandExprToInArgs(LoopIndex, MemReadLowerBoundExpanded, true, NewStackPtrCopiesSet);
if (success) {
success = this->ExpandExprToInArgs(LoopIndex, MemReadUpperBoundExpanded, false, NewStackPtrCopiesSet);
}
if (success) {
if (VerboseOutput) {
SMP_msg("INFO: LOOP: MemReadLowerBoundExpanded EXPR:");
MemReadLowerBoundExpanded->Dump(0);
// For annotation output, we want to expand the expressions beyond loop boundaries,
// hopefully as far as incoming args or constant initializers.
set<STARS_ea_t> NewStackPtrCopiesSet;
success = this->ExpandExprToInArgs(LoopIndex, MemReadLowerBoundExpanded, true, NewStackPtrCopiesSet);
if (LimitSuccess) {
LimitSuccess = this->ExpandExprToInArgs(LoopIndex, MemReadUpperBoundExpanded, false, NewStackPtrCopiesSet);
}
if (success) {
if (VerboseOutput) {
SMP_msg("INFO: LOOP: MemReadLowerBoundExpanded EXPR:");
MemReadLowerBoundExpanded->Dump(0);
if (LimitSuccess) {
SMP_msg("INFO: LOOP: MemReadUpperBoundExpanded EXPR:");
MemReadUpperBoundExpanded->Dump(0);
}
}
 
set<STARS_ea_t> UnionedStackPtrCopiesSet;
insert_iterator<set<STARS_ea_t> > EndIter = std::inserter(UnionedStackPtrCopiesSet, UnionedStackPtrCopiesSet.begin());
if (0 <= StackPtrCopiesVecIndex) { // vector has entry for a set
EndIter = merge(StackPtrCopiesVector[StackPtrCopiesVecIndex].begin(),
StackPtrCopiesVector[StackPtrCopiesVecIndex].end(),
NewStackPtrCopiesSet.begin(), NewStackPtrCopiesSet.end(),
std::inserter(UnionedStackPtrCopiesSet, UnionedStackPtrCopiesSet.begin()));
}
else { // just copy the NewStackPtrCopiesSet
EndIter = std::copy(NewStackPtrCopiesSet.begin(), NewStackPtrCopiesSet.end(),
std::inserter(UnionedStackPtrCopiesSet, UnionedStackPtrCopiesSet.begin()));
}
set<STARS_ea_t> UnionedStackPtrCopiesSet;
insert_iterator<set<STARS_ea_t> > EndIter = std::inserter(UnionedStackPtrCopiesSet, UnionedStackPtrCopiesSet.begin());
if (0 <= StackPtrCopiesVecIndex) { // vector has entry for a set
EndIter = merge(StackPtrCopiesVector[StackPtrCopiesVecIndex].begin(),
StackPtrCopiesVector[StackPtrCopiesVecIndex].end(),
NewStackPtrCopiesSet.begin(), NewStackPtrCopiesSet.end(),
std::inserter(UnionedStackPtrCopiesSet, UnionedStackPtrCopiesSet.begin()));
}
else { // just copy the NewStackPtrCopiesSet
EndIter = std::copy(NewStackPtrCopiesSet.begin(), NewStackPtrCopiesSet.end(),
std::inserter(UnionedStackPtrCopiesSet, UnionedStackPtrCopiesSet.begin()));
}
 
// To assist in stack transformation security defenses, if the
// memory range expression is stack-relative, we emit an annotation
// that identifies the memory range written to at InstAddr.
// The annotation should look like:
// [hex InstAddr] [InstSize] INSTR STACKMEMRANGE MIN [ESP-k] MAX [ESP-j] ZZ
set<STARS_ea_t> StaticMemLeaAddrSet;
if (MemReadLowerBoundExpanded->IsStackPtrPlusOffset() && MemReadUpperBoundExpanded->IsStackPtrPlusOffset()) {
this->EmitStackMemRangeAnnotations(MemReadLowerBoundExpanded, MemReadUpperBoundExpanded, PositiveIncrement, UnionedStackPtrCopiesSet, StaticMemLeaAddrSet);
}
if (!StaticMemLeaAddrSet.empty()) {
SMP_msg("INFO: LOOP: StaticMemLeaAddrSet size (reads): %zu \n", StaticMemLeaAddrSet.size());
}
// Substitute global min and max values for global mem reads that
// are still in the expr, and see if we can simplify as a result.
bool FinalChange = MemReadLowerBoundExpanded->SubstituteGlobalRangeValues(true);
if (FinalChange)
(void) MemReadLowerBoundExpanded->SimplifyDriver();
if (LimitSuccess) {
FinalChange = MemReadUpperBoundExpanded->SubstituteGlobalRangeValues(false);
if (FinalChange)
(void) MemReadUpperBoundExpanded->SimplifyDriver();
}
 
// To assist in defenses related to static global memory, output ranges
// of memory written when the lower and upper bounds have simplified to
// constants.
if (MemReadLowerBoundExpanded->IsConstExpr() && MemReadUpperBoundExpanded->IsConstExpr()) {
SMPInstr *MemReadInst = MemReadLowerBoundExpanded->GetOriginalParentInst();
STARS_ea_t MemReadAddr = MemReadInst->GetAddr();
if (StaticMemReadAddrsEmitted.find(MemReadAddr) == StaticMemReadAddrsEmitted.cend()) {
if (MemReadAddr != MemReadUpperBoundExpanded->GetOriginalParentInst()->GetAddr()) {
SMP_msg("ERROR: LOOP: Constant lower and upper bound exprs don't have same InstAddr for loop %zu in func %s.\n",
LoopIndex, this->GetFuncName());
// To assist in stack transformation security defenses, if the
// memory range expression is stack-relative, we emit an annotation
// that identifies the memory range written to at InstAddr.
// The annotation should look like:
// [hex InstAddr] [InstSize] INSTR STACKMEMRANGE MIN [ESP-k] MAX [ESP-j] ZZ
set<STARS_ea_t> StaticMemLeaAddrSet;
bool StackAnnotation = false;
if (LimitSuccess && MemReadLowerBoundExpanded->IsStackPtrPlusOffset() && MemReadUpperBoundExpanded->IsStackPtrPlusOffset()) {
this->EmitStackMemRangeAnnotations(MemReadLowerBoundExpanded, MemReadUpperBoundExpanded, PositiveIncrement, UnionedStackPtrCopiesSet, StaticMemLeaAddrSet);
StackAnnotation = true;
}
if (!StaticMemLeaAddrSet.empty()) {
SMP_msg("INFO: LOOP: StaticMemLeaAddrSet size (reads): %zu \n", StaticMemLeaAddrSet.size());
}
// To assist in defenses related to static global memory, output ranges
// of memory written when the lower and upper bounds have simplified to
// constants.
if (MemReadLowerBoundExpanded->IsConstExpr()) {
SMPInstr *MemReadInst = MemReadLowerBoundExpanded->GetOriginalParentInst();
STARS_ea_t MemReadAddr = MemReadInst->GetAddr();
if (StaticMemReadAddrsEmitted.find(MemReadAddr) == StaticMemReadAddrsEmitted.cend()) {
if (LimitSuccess && (MemReadAddr != MemReadUpperBoundExpanded->GetOriginalParentInst()->GetAddr())) {
SMP_msg("ERROR: LOOP: Constant lower and upper bound exprs don't have same InstAddr for loop %zu in func %s.\n",
LoopIndex, this->GetFuncName());
}
else {
int InstSize = MemReadInst->GetSize();
STARS_uval_t LowerBoundVal = MemReadLowerBoundExpanded->GetConstLeftOperand()->GetImmedValue();
STARS_uval_t UpperBoundVal = (STARS_uval_t)0xfffffffffffffffe; // Code for unknown limit value
if (LimitSuccess
&& (nullptr != MemReadUpperBoundExpanded->GetConstLeftOperand())
&& (MemReadUpperBoundExpanded->GetConstLeftOperand()->IsImmedOp())) {
UpperBoundVal = MemReadUpperBoundExpanded->GetConstLeftOperand()->GetImmedValue();
}
FILE *InfoAnnotFile = global_STARS_program->GetInfoAnnotFile();
// NOTE: Replace WRITE with READ or RANGE in annotation
SMP_fprintf(InfoAnnotFile, "%18llx %6zu INSTR STATICMEMWRITE MIN ", (uint64_t) MemReadAddr, InstSize);
if (LowerBoundVal == UpperBoundVal) {
// A simple read from a static mem address with no index registers has
// the same expr for lower bound and upper bound. Use the ByteWidth to
// expand the upper bound.
uint16_t ByteWidth = MemReadLowerBoundExpanded->GetConstLeftOperand()->GetByteWidth();
UpperBoundVal += (STARS_uval_t) ByteWidth;
}
if (LowerBoundVal < UpperBoundVal) {
SMP_fprintf(InfoAnnotFile, "%llx LIMIT %llx ZZ %s\n",
(uint64_t) LowerBoundVal, (uint64_t) UpperBoundVal, MemReadInst->GetDisasm());
}
else {
int InstSize = MemReadInst->GetSize();
STARS_uval_t LowerBoundVal = MemReadLowerBoundExpanded->GetConstLeftOperand()->GetImmedValue();
STARS_uval_t UpperBoundVal = MemReadUpperBoundExpanded->GetConstLeftOperand()->GetImmedValue();
FILE *InfoAnnotFile = global_STARS_program->GetInfoAnnotFile();
// NOTE: Replace WRITE with READ or RANGE in annotation
SMP_fprintf(InfoAnnotFile, "%18llx %6zu INSTR STATICMEMWRITE MIN ", (uint64_t) MemReadAddr, InstSize);
if (LowerBoundVal == UpperBoundVal) {
// A simple read from a static mem address with no index registers has
// the same expr for lower bound and upper bound. Use the ByteWidth to
// expand the upper bound.
uint16_t ByteWidth = MemReadLowerBoundExpanded->GetConstLeftOperand()->GetByteWidth();
UpperBoundVal += (STARS_uval_t) ByteWidth;
}
if (LowerBoundVal < UpperBoundVal) {
SMP_fprintf(InfoAnnotFile, "%llx LIMIT %llx ZZ %s\n",
(uint64_t) LowerBoundVal, (uint64_t) UpperBoundVal, MemReadInst->GetDisasm());
}
else {
SMP_fprintf(InfoAnnotFile, "%llx LIMIT %llx ZZ %s\n",
(uint64_t) UpperBoundVal, (uint64_t) LowerBoundVal, MemReadInst->GetDisasm());
}
(void) StaticMemReadAddrsEmitted.insert(MemReadAddr);
SMP_fprintf(InfoAnnotFile, "%llx LIMIT %llx ZZ %s\n",
(uint64_t) UpperBoundVal, (uint64_t) LowerBoundVal, MemReadInst->GetDisasm());
}
(void) StaticMemReadAddrsEmitted.insert(MemReadAddr);
}
}
}
else {
SMP_msg("ERROR: LOOP: ExpandExprToInArg failure for loop %zu in function at %llx\n",
LoopIndex, (uint64_t) this->GetFirstFuncAddr());
delete MemReadLowerBoundExpanded;
delete MemReadUpperBoundExpanded;
// this->LoopAnalysisProblems[LoopIndex] = true;
else if (!StackAnnotation) {
// LowerBoundExpanded expr was neither static mem nor stack.
SMP_msg("INFO: LOOP: Read expr neither static mem nor stack mem: \n");
if (VerboseOutput) {
MemReadLowerBoundExpanded->Dump(0);
}
}
}
else {
SMP_msg("ERROR: LOOP: Failure to ReplaceIVsWithLimitExpr for loop %zu in function at %llx\n",
SMP_msg("ERROR: LOOP: ExpandExprToInArg failure for loop %zu in function at %llx\n",
LoopIndex, (uint64_t) this->GetFirstFuncAddr());
delete MemReadLowerBound;
delete MemReadUpperBound;
delete MemReadLowerBoundExpanded;
delete MemReadUpperBoundExpanded;
// this->LoopAnalysisProblems[LoopIndex] = true;
// this->LoopWritesGlobalStaticMemory[LoopIndex] = false; // reset
}
}
else {
......@@ -13511,6 +13617,8 @@ void SMPFunction::AnalyzeLoopIterations(void) {
LoopIndex, (uint64_t) this->GetFirstFuncAddr());
}
}
MemReadExprWidths.clear();
MemReadExprs.clear();
 
} // end for all loops: loop4, memory range analysis
 
......@@ -13518,6 +13626,11 @@ void SMPFunction::AnalyzeLoopIterations(void) {
this->DetectInArgRegsNeededForMemWriteExprs();
this->ExpandLoopRegHashExprs();
 
if (!global_STARS_program->ShouldSTARSTranslateToSPARKAda()) {
// Not inheriting expressions across call boundaries, so
// deallocate memory.
this->DestroyLoopExprs();
}
return;
} // end of SMPFunction::AnalyzeLoopIterations()
 
......
......@@ -2219,10 +2219,25 @@ STARSExpression::STARSExpression(const STARSDefUseIter Ref, SMPInstr *CurrInst)
 
// Destructor
STARSExpression::~STARSExpression() {
if (this->HasRightSubTree() && (nullptr != this->RightExpr))
#if 1
if (this->HasRightSubTree() && (nullptr != this->RightExpr)) {
delete this->RightExpr;
if (this->HasLeftSubTree() && (nullptr != this->LeftExpr))
this->RightExpr = nullptr;
}
if (this->HasLeftSubTree() && (nullptr != this->LeftExpr)) {
delete this->LeftExpr;
this->LeftExpr = nullptr;
}
#else
if (nullptr != this->RightExpr) {
delete this->RightExpr;
this->RightExpr = nullptr;
}
if (nullptr != this->LeftExpr) {
delete this->LeftExpr;
this->LeftExpr = nullptr;
}
#endif
return;
}
 
......@@ -3398,8 +3413,19 @@ bool STARSExpression::SimplifyExpr(STARSExpression *ParentExpr) {
if (ConstLeftOperand) {
STARS_uval_t LeftValue = this->GetConstLeftOperand()->GetImmedValue();
SMPoperator CurrOperator = this->GetOperator();
// Simplify increment or decrement of a constant.
if ((SMP_INCREMENT == CurrOperator) || (SMP_DECREMENT == CurrOperator)) {
// Hardware wraps around, so we don't have to prevent underflow or overflow here.
if (SMP_INCREMENT == CurrOperator)
++LeftValue;
else
--LeftValue;
STARSOpndTypePtr NewLeftOp = this->GetParentInst()->MakeImmediateOpnd(LeftValue);
this->SetLeftOperand(NewLeftOp);
return true; // Nothing more can be done at this level of the expr.
}
// Simplify multiplication by 0 or 1, division by 1, addition or subtraction of 0.
if (1 == LeftValue) {
else if (1 == LeftValue) {
if ((SMP_U_MULTIPLY == CurrOperator) || (SMP_S_MULTIPLY == CurrOperator)) {
// Multiply by 1, produces right tree as result.
// We can simplify the current expr by making it just be the RightTree or RightOperand.
......@@ -4474,6 +4500,47 @@ void STARSExpression::SubstituteSSANum(SMPInstr *CallInst, const int NewSSANum,
return;
} // end of STARSExpression::SubstituteSSANum()
 
// Use MinVal if InitCase, MaxVal otherwise for global vars in expression
bool STARSExpression::SubstituteGlobalRangeValues(const bool InitCase) {
bool changed = false;
if (this->HasLeftSubTree()) {
changed = this->GetLeftTree()->SubstituteGlobalRangeValues(InitCase);
}
else if (this->GetConstLeftOperand()->IsStaticMemOp()) {
STARS_ea_t GlobalAddr = this->GetConstLeftOperand()->GetAddr();
STARS_uval_t ImmedVal;
bool found = false;
if (InitCase)
found = this->GetParentFunc()->GetProg()->FindGlobalMinValue(GlobalAddr, ImmedVal);
else
found = this->GetParentFunc()->GetProg()->FindGlobalMaxValue(GlobalAddr, ImmedVal);
if (found) {
STARSOpndTypePtr ImmedOp = this->GetParentInst()->MakeImmediateOpnd(ImmedVal);
this->SetLeftOperand(ImmedOp);
changed = true;
}
}
if (this->HasRightSubTree()) {
changed = (this->GetRightTree()->SubstituteGlobalRangeValues(InitCase) || changed);
}
else if ((nullptr != this->GetConstRightOperand()) && this->GetConstRightOperand()->IsStaticMemOp()) {
STARS_ea_t GlobalAddr = this->GetConstRightOperand()->GetAddr();
STARS_uval_t ImmedVal;
bool found = false;
if (InitCase)
found = this->GetParentFunc()->GetProg()->FindGlobalMinValue(GlobalAddr, ImmedVal);
else
found = this->GetParentFunc()->GetProg()->FindGlobalMaxValue(GlobalAddr, ImmedVal);
if (found) {
STARSOpndTypePtr ImmedOp = this->GetParentInst()->MakeImmediateOpnd(ImmedVal);
this->SetRightOperand(ImmedOp);
changed = true;
}
}
return changed;
} // end of STARSExpression::SubstituteGlobalRangeValues()
// For loop exprs, find the DefOp at LeftPreLoopDefAddr
STARSOpndTypePtr STARSExpression::FindLeftPreLoopDefOp(void) const {
STARS_ea_t DefAddr = this->GetLeftPreLoopDefAddr();
......@@ -4814,6 +4881,12 @@ SMPInstr::~SMPInstr() {
this->Defs.clear();
this->Uses.clear();
}
#if 0 // fix crashes before enabling this
if (nullptr != this->STARSInstPtr) {
delete this->STARSInstPtr;
this->STARSInstPtr = nullptr;
}
#endif
return;
}
 
......@@ -5155,17 +5228,18 @@ bool SMPInstr::HasNegatedPtrUSE(void) {
// Detect indirect memory DEFs or USEs
void SMPInstr::AnalyzeIndirectRefs(bool UseFP) {
STARS_ea_t InstAddr = this->GetAddr();
bool HasBlock = (nullptr != this->GetBlock());
if (this->HasDestMemoryOperand()) {
// Found a memory DEF. Is it indirect?
STARSOpndTypePtr DefMemOp = this->MDGetMemDefOp();
if (MDIsIndirectMemoryOpnd(DefMemOp, UseFP)) {
this->SetIndirectMemWrite();
if (NULL != this->GetBlock()) {
if (HasBlock) {
this->GetBlock()->SetHasIndirectMemWrite();
}
}
if (DefMemOp->IsStaticMemOp()) {
if (NULL != this->GetBlock()) {
if (HasBlock) {
this->GetBlock()->SetHasStaticMemWrite();
}
}
......@@ -5176,7 +5250,7 @@ void SMPInstr::AnalyzeIndirectRefs(bool UseFP) {
STARSOpndTypePtr UseMemOp = this->MDGetMemUseOp();
if (MDIsIndirectMemoryOpnd(UseMemOp, UseFP)) {
this->SetIndirectMemRead();
if (NULL != this->GetBlock()) {
if (HasBlock) {
this->GetBlock()->SetHasIndirectMemRead();
}
}
......@@ -5186,12 +5260,36 @@ void SMPInstr::AnalyzeIndirectRefs(bool UseFP) {
SMP_msg("INFO: Doubtful identification of %llx as StaticMem at %llx\n",
(uint64_t) AddrOffset, (uint64_t) InstAddr);
}
if (NULL != this->GetBlock()) {
if (HasBlock) {
this->GetBlock()->SetHasStaticMemRead();
}
}
}
 
if (HasBlock && this->HasDestMemoryOperand() && this->GetMemDef()->IsStaticMemOp() && (!MDIsIndirectMemoryOpnd(this->GetMemDef(), false))) {
// Direct write to static mem op. Is this a simple assignment RTL?
STARSOpndTypePtr rhs = nullptr;
STARS_ea_t GlobalAddr = this->GetMemDef()->GetAddr();
SMPRegTransfer *CurrRT = this->RTL.GetRT(0);
if ((NULL != CurrRT) && (this->RTL.GetCount() == 1)) {
bool Simple = ((!CurrRT->HasRightSubTree()) || this->IsRegUpperBitsClearIdiom());
if (Simple && (SMP_ASSIGN == CurrRT->GetOperator())) {
bool SimpleCopyRTL = (DEFAULT == this->GetDataFlowType());
if (SimpleCopyRTL) {
rhs = this->GetFirstRightOperandNoNorm();
if ((nullptr != rhs) && rhs->IsImmedOp()) {
STARS_uval_t ImmedVal = rhs->GetImmedValue();
this->GetBlock()->GetFunc()->GetProg()->InsertGlobalVarMinMaxValue(GlobalAddr, ImmedVal);
if (global_stars_interface->VerboseLoopsMode()) {
SMP_msg("INFO: GLOBALS: Found const value %llx written to global addr %llx at %llx\n",
(uint64_t)ImmedVal, (uint64_t)GlobalAddr, (uint64_t)InstAddr);
}
}
}
}
}
}
return;
} // end of SMPInstr::AnalyzeIndirectRefs()
 
......@@ -8671,8 +8769,9 @@ bool SMPInstr::FillCmd(void) {
// Analyze the instruction and its operands.
void SMPInstr::Analyze(void) {
bool DebugFlag = false;
STARS_ea_t InstAddr = this->GetAddr();
 
if (0x8049b00 == this->GetAddr()) {
if (0x8049b00 == InstAddr) {
// Setting up breakpoint line.
DebugFlag = true;
}
......@@ -8747,8 +8846,8 @@ void SMPInstr::Analyze(void) {
this->MDFixFloatingPointRTL();
}
else {
SMP_msg("ERROR: RTL not built at %llx %s\n", (unsigned long long) this->GetAddr(),
DisAsmText.GetDisAsm(this->GetAddr()));
SMP_msg("ERROR: RTL not built at %llx %s\n", (uint64_t) InstAddr,
DisAsmText.GetDisAsm(InstAddr));
return;
}
 
......@@ -8788,20 +8887,21 @@ void SMPInstr::Analyze(void) {
}
}
if (STARS_BADADDR == this->CallTarget) {
SMP_msg("ERROR: Target not found for direct call at %llx\n", (unsigned long long) this->GetAddr());
SMP_msg("ERROR: Target not found for direct call at %llx\n", (uint64_t) InstAddr);
}
}
 
if (this->MDIsPushInstr()) {
if (this->STARSInstPtr->IsPushFromFixedCall()) {
this->SetFixedCallPush();
SMP_msg("INFO: Found internal code address push from fixed call at %llx\n", (unsigned long long) this->GetAddr());
SMP_msg("INFO: Found internal code address push from fixed call at %llx\n", (uint64_t) InstAddr);
}
}
 
if (DebugFlag) {
SMP_msg("Analyzed debug instruction at %llx\n", (unsigned long long) this->GetAddr());
SMP_msg("Analyzed debug instruction at %llx\n", (uint64_t) InstAddr);
}
return;
} // end of SMPInstr::Analyze()
 
......@@ -165,6 +165,25 @@ SMPProgram::~SMPProgram(void) {
return;
}
// Methods for recovering min or max value seen directly written to a global var.
bool SMPProgram::FindGlobalMinValue(const STARS_ea_t GlobalAddr, STARS_uval_t &MinValue) const {
map<STARS_ea_t, struct STARSValueRange>::const_iterator MapIter = this->GlobalValueRangeMap.find(GlobalAddr);
bool found = (MapIter != this->GlobalValueRangeMap.cend());
if (found)
MinValue = MapIter->second.MinVal;
return found;
} // end of SMPProgram::FindGlobalMinValue()
bool SMPProgram::FindGlobalMaxValue(const STARS_ea_t GlobalAddr, STARS_uval_t &MaxValue) const {
map<STARS_ea_t, struct STARSValueRange>::const_iterator MapIter = this->GlobalValueRangeMap.find(GlobalAddr);
bool found = (MapIter != this->GlobalValueRangeMap.cend());
if (found)
MaxValue = MapIter->second.MaxVal;
return found;
} // end of SMPProgram::FindGlobalMaxValue()
// Return SMPFunction pointer from FuncMap for FirstAddr if it exists
// in the FuncMap, else return NULL.
SMPFunction *SMPProgram::FindFunction(STARS_ea_t FirstAddr) const {
......@@ -267,6 +286,26 @@ void SMPProgram::AddBlockToRemovalList(SMPBasicBlock *UnreachableBlock) {
return;
} // end of SMPProgram::AddBlockToRemovalList()
// Update, as needed, the min or max value seen so far for GlobalAddr.
void SMPProgram::InsertGlobalVarMinMaxValue(const STARS_ea_t GlobalAddr, const STARS_uval_t ValueSeen) {
map<STARS_ea_t, struct STARSValueRange>::iterator MapIter = this->GlobalValueRangeMap.find(GlobalAddr);
bool found = (MapIter != this->GlobalValueRangeMap.end());
if (found) {
if (ValueSeen < MapIter->second.MinVal)
MapIter->second.MinVal = ValueSeen;
else if (ValueSeen > MapIter->second.MaxVal)
MapIter->second.MaxVal = ValueSeen;
}
else {
struct STARSValueRange TempRange;
TempRange.MinVal = ValueSeen;
TempRange.MaxVal = ValueSeen;
this->GlobalValueRangeMap[GlobalAddr] = TempRange;
}
return;
}
// Is InstAddr in the set of unshared code fragments?
bool SMPProgram::IsUnsharedFragment(STARS_ea_t InstAddr) {
bool Found = (this->UnsharedFragments.find(InstAddr) != this->UnsharedFragments.end());
......
......@@ -36,6 +36,7 @@
#include <vector>
#include <set>
#include <string>
#include <sstream>
#include <ctime>
......@@ -530,6 +531,8 @@ bool IDAP_run(size_t arg) {
delete CurrProg;
delete global_STARS_program;
delete global_stars_interface;
#if (IDA_SDK_VERSION < 700)
return;
#else
......@@ -627,6 +630,10 @@ bool IDAP_run(size_t arg) {
delete prof_info;
SMP_msg("INFO: Deleted prof_info.\n");
delete CurrProg;
stringstream sout;
STARS_Instruction_t::DumpCreationStats(sout);
STARS_op_t::DumpCreationStats(sout);
SMP_msg("Interface stats: \n %s", sout.str().c_str());
SMP_msg("INFO: Deleted CurrProg. Returning to IDA Pro.\n");
delete global_STARS_program;
delete global_stars_interface;
......
......@@ -148,8 +148,9 @@ void OutputStatistics()
}
#endif
// mark that we've completed analysis.
SMP_fprintf(global_STARS_program->GetInfoAnnotFile(), " 8000000 2 SUCCESS ANALYSISCOMPLETED\n");
SMP_fprintf(global_STARS_program->GetInfoAnnotFile(), " 8000000 2 SUCCESS ANALYSISCOMPLETED\n");
STARS_Instruction_t::DumpCreationStats(cout);
STARS_op_t::DumpCreationStats(cout);
}
int STARS::IRDB_Interface_t::do_STARS(FileIR_t* firp)
......
......@@ -7,6 +7,9 @@
// declare global static data for STARS_InstructionID_t class
std::map<STARS_ea_t, const STARS_Instruction_t*> STARS_InstructionID_t::id_to_insn_map;
uint64_t STARS_Instruction_t::objects_created=0;
uint64_t STARS_Instruction_t::objects_destroyed=0;
bool STARS_Instruction_t::OpcodeDefaultsTo64BitOperands(void)
{
......
......@@ -5,6 +5,10 @@
#include <interfaces/SMPDBInterface.h>
#include <interfaces/STARSTypes.h>
uint64_t STARS_op_t::objects_created=0;
uint64_t STARS_op_t::objects_destroyed=0;
void STARS_op_t::MDExtractAddressFields(int &BaseReg, int &IndexReg, uint16_t &Scale, STARS_ea_t &Offset) const {
assert(this->IsMemOp());
......
......@@ -225,7 +225,10 @@ void STARS_IDA_Program_t::InitStaticDataTable(SMPProgram *CurrProg) {
SMP_msg(" SegName: %s", SegName);
SMP_msg(" from %lx to %lx\n", (unsigned long)seg->get_startEA(), (unsigned long)seg->get_endEA());
#endif
if ((seg->IsDataSegment()) || (seg->IsBSSSegment()) || (seg->IsCommonSegment())) {
bool DataSegFlag = seg->IsDataSegment();
bool BSSSegFlag = seg->IsBSSSegment();
bool CommonSegFlag = seg->IsCommonSegment();
if (DataSegFlag || BSSSegFlag || CommonSegFlag) {
// Loop through each of the segments we are interested in,
// examining all data objects (effective addresses).
ReadOnlyFlag = ((seg->IsReadableSegment()) && (!(seg->IsWriteableSegment())));
......@@ -304,49 +307,51 @@ void STARS_IDA_Program_t::InitStaticDataTable(SMPProgram *CurrProg) {
pair<STARS_ea_t, struct GlobalVar> TempItem(ea, VarTemp);
CurrProg->InsertGlobalVarTableEntry(TempItem);
// Check for code xrefs from the data.
// Can have a table of pointers, so iterate through large data objects.
STARS_ea_t TempAddr = ea;
while ((NextEA - TempAddr) >= MD_DEFAULT_RETURN_ADDRESS_SIZE) {
SMP_xref_t xrefs;
for (bool ok = xrefs.SMP_first_from(TempAddr, XREF_DATA); ok; ok = xrefs.SMP_next_from()) {
STARS_ea_t TargetAddr = xrefs.GetTo();
if ((TargetAddr != 0) && (!xrefs.GetIscode())) {
// Found a target, with its address in xrefs.to
// Is the target code?
STARS_Segment_t *SegInfo = SMP_getseg(TargetAddr);
if ((NULL != SegInfo) && (SegInfo->IsCodeSegment())) {
if (!ReadOnlyFlag) {
SMP_msg("INFO: Code Xref from writeable data at %llx\n", (uint64_t) ea);
if (!BSSSegFlag) {
// Check for code xrefs from the data.
// Can have a table of pointers, so iterate through large data objects.
STARS_ea_t TempAddr = ea;
while ((NextEA - TempAddr) >= MD_DEFAULT_RETURN_ADDRESS_SIZE) {
SMP_xref_t xrefs;
for (bool ok = xrefs.SMP_first_from(TempAddr, XREF_DATA); ok; ok = xrefs.SMP_next_from()) {
STARS_ea_t TargetAddr = xrefs.GetTo();
if ((TargetAddr != 0) && (!xrefs.GetIscode())) {
// Found a target, with its address in xrefs.to
// Is the target code?
STARS_Segment_t *SegInfo = SMP_getseg(TargetAddr);
if ((NULL != SegInfo) && (SegInfo->IsCodeSegment())) {
if (!ReadOnlyFlag) {
SMP_msg("INFO: Code Xref from writeable data at %llx\n", (uint64_t)ea);
}
bool NewTarget = CurrProg->InsertDataToCodeXref(TargetAddr);
if (NewTarget)
global_STARS_program->PrintDataToCodeXref(TempAddr, TargetAddr, 0);
}
bool NewTarget = CurrProg->InsertDataToCodeXref(TargetAddr);
if (NewTarget)
global_STARS_program->PrintDataToCodeXref(TempAddr, TargetAddr, 0);
}
}
}
STARS_ea_t DataValue;
if (4 < global_STARS_program->GetSTARS_ISA_Bytewidth())
DataValue = (STARS_ea_t) ::get_qword(TempAddr);
else
STARS_ea_t DataValue;
if (4 < global_STARS_program->GetSTARS_ISA_Bytewidth())
DataValue = (STARS_ea_t) ::get_qword(TempAddr);
else
#if (IDA_SDK_VERSION < 700)
DataValue = (STARS_ea_t) ::get_long(TempAddr);
DataValue = (STARS_ea_t) ::get_long(TempAddr);
#else
DataValue = (STARS_ea_t) ::get_dword(TempAddr);
DataValue = (STARS_ea_t) ::get_dword(TempAddr);
#endif
if (DataValue != 0) {
// Is this a code address?
STARS_ea_t PossibleCodeAddr = (STARS_ea_t) DataValue;
STARS_Segment_t *SegInfo = SMP_getseg(PossibleCodeAddr);
if ((NULL != SegInfo) && (SegInfo->IsCodeSegment())) {
bool NewTarget = CurrProg->InsertDataToCodeXref(PossibleCodeAddr);
if (NewTarget)
global_STARS_program->PrintDataToCodeXref(TempAddr, PossibleCodeAddr, 0);
if (DataValue != 0) {
// Is this a code address?
STARS_ea_t PossibleCodeAddr = (STARS_ea_t)DataValue;
STARS_Segment_t *SegInfo = SMP_getseg(PossibleCodeAddr);
if ((NULL != SegInfo) && (SegInfo->IsCodeSegment())) {
bool NewTarget = CurrProg->InsertDataToCodeXref(PossibleCodeAddr);
if (NewTarget)
global_STARS_program->PrintDataToCodeXref(TempAddr, PossibleCodeAddr, 0);
}
}
}
TempAddr += MD_DEFAULT_RETURN_ADDRESS_SIZE;
}
TempAddr += MD_DEFAULT_RETURN_ADDRESS_SIZE;
} // end while ((NextEA - TempAddr) >= MD_DEFAULT_RETURN_ADDRESS_SIZE)
} // end if (!BSSSegFlag)
// Move on to next data object
ea = NextEA;
......@@ -359,7 +364,7 @@ void STARS_IDA_Program_t::InitStaticDataTable(SMPProgram *CurrProg) {
#endif
}
} // end while (ea < seg->endEA)
} // end if (seg->type == SEG_DATA ...)
} // end if (DataSegFlag || BSSSegFlag || CommonSegFlag)
else if (seg->IsCodeSegment()) {
if (seg->get_startEA() < TempLowestCodeAddress)
TempLowestCodeAddress = seg->get_startEA();
......@@ -544,7 +549,7 @@ void STARS_IDA_Program_t::FindCodeAddressesTaken(SMPProgram *CurrProg) {
STARS_ea_t ea = seg->get_startEA();
RecentAddr = ea;
bool ReadOnlyFlag = ((seg->IsReadableSegment()) && (!(seg->IsWriteableSegment())));
bool DataSegment = ((seg->IsDataSegment()) || (seg->IsBSSSegment()) || (seg->IsCommonSegment()));
bool DataSegment = ((seg->IsDataSegment()) || (seg->IsCommonSegment()));
#if 0
if (ReadOnlyFlag && DataSegment) {
#else
......
......@@ -211,6 +211,8 @@ bool STARS_IRDB_Function_t::IsInstIDInFunc(STARS_ea_t InstID)
return false;
const STARS_Instruction_t *stars_insn=id.GetInstruction();
if (nullptr == stars_insn)
return false;
const STARS_IRDB_Instruction_t* interface_insn=dynamic_cast<const STARS_IRDB_Instruction_t*>(stars_insn);
assert(interface_insn);
libIRDB::Instruction_t* irdb_insn=(libIRDB::Instruction_t*)interface_insn->GetIRDBInstruction();
......
......@@ -17,6 +17,9 @@ using namespace libIRDB;
#define ALLOF(a) begin(a),end(a)
#endif
STARSOpndTypePtr STARS_IRDB_Instruction_t::VoidOpndsPtr=dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IRDB_op_t>());
static uint32_t UseMacros[STARS_UA_MAXOP] = {STARS_CF_USE1, STARS_CF_USE2, STARS_CF_USE3, STARS_CF_USE4, STARS_CF_USE5, STARS_CF_USE6};
static uint32_t DefMacros[STARS_UA_MAXOP] = {STARS_CF_CHG1, STARS_CF_CHG2, STARS_CF_CHG3, STARS_CF_CHG4, STARS_CF_CHG5, STARS_CF_CHG6};
......@@ -1479,7 +1482,7 @@ uint16_t STARS_IRDB_Instruction_t::GetIDAOpcode(void)
cerr<<"Cannot match opcode Mneumonic ("<< disasm.getMnemonic() <<") to stars insn."<<endl;
cerr<<"Cannot match opcode Mnemonic ("<< disasm.getMnemonic() <<") to stars insn."<<endl;
assert(0);
exit(1);
}
......@@ -1496,36 +1499,29 @@ uint16_t STARS_IRDB_Instruction_t::GetIDAOpcode(void)
// add rax, rdx (intel) means rax=rax+rdx;
// features = STARS_CF_USE1 | STARS_CF_USE2 | STARS_CF_CHG1
inline uint32_t STARS_IRDB_Instruction_t::GetInitialInstFeatures(bool ShiftOperands) const
inline uint32_t STARS_IRDB_Instruction_t::GetInitialInstFeatures(bool ShiftOperands, const DecodedInstruction_t& p_disasm) const
{
uint32_t my_features=0;
// nervous that bea isn't marking operands as both read and write. May need to update.
#if 0
#define CHECK_ARG(arg,use,def) \
if(arg.ArgType!=NO_ARGUMENT && (arg.AccessMode&READ)==READ) my_features|=use; \
if(arg.ArgType!=NO_ARGUMENT && (arg.AccessMode&WRITE)==WRITE) my_features|=def; \
#endif
#define CHECK_ARG(disasm,num,use,def) \
if(disasm.hasOperand(num) && disasm.getOperand(num).isRead()) my_features|=use; \
if(disasm.hasOperand(num) && disasm.getOperand(num).isWritten()) my_features|=def; \
#define CHECK_ARG(p_disasm,num,use,def) \
if(p_disasm.hasOperand(num) && p_disasm.getOperand(num).isRead()) my_features|=use; \
if(p_disasm.hasOperand(num) && p_disasm.getOperand(num).isWritten()) my_features|=def; \
if (!ShiftOperands) {
CHECK_ARG(disasm, 0, STARS_CF_USE1, STARS_CF_CHG1);
CHECK_ARG(disasm, 1, STARS_CF_USE2, STARS_CF_CHG2);
CHECK_ARG(disasm, 2, STARS_CF_USE3, STARS_CF_CHG3);
CHECK_ARG(disasm, 3, STARS_CF_USE4, STARS_CF_CHG4);
CHECK_ARG(p_disasm, 0, STARS_CF_USE1, STARS_CF_CHG1);
CHECK_ARG(p_disasm, 1, STARS_CF_USE2, STARS_CF_CHG2);
CHECK_ARG(p_disasm, 2, STARS_CF_USE3, STARS_CF_CHG3);
CHECK_ARG(p_disasm, 3, STARS_CF_USE4, STARS_CF_CHG4);
}
else {
// An invisible operands has been inserted, e.g. "div rsi" has rax
// as an invisible operand inserted as the first operand. So, RSI
// gets shifted to the second operand, but the disasm still has it
// as the first operand. Shift the bit masks used in the CHECK_ARG macro.
CHECK_ARG(disasm, 0, STARS_CF_USE2, STARS_CF_CHG2);
CHECK_ARG(disasm, 1, STARS_CF_USE3, STARS_CF_CHG3);
CHECK_ARG(disasm, 2, STARS_CF_USE4, STARS_CF_CHG4);
CHECK_ARG(p_disasm, 0, STARS_CF_USE2, STARS_CF_CHG2);
CHECK_ARG(p_disasm, 1, STARS_CF_USE3, STARS_CF_CHG3);
CHECK_ARG(p_disasm, 2, STARS_CF_USE4, STARS_CF_CHG4);
}
return my_features;
......@@ -1533,11 +1529,18 @@ inline uint32_t STARS_IRDB_Instruction_t::GetInitialInstFeatures(bool ShiftOpera
bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
{
bool do_default=true;
disasm = DecodedInstruction_t(irdb_insn);
int length = disasm.length(); /*Disassemble(irdb_insn, disasm); */
// Save memory by having all void operands use a shared_ptr to a single void operand.
// this->VoidOpndsPtr = nullptr;
// this->VoidOpndsPtr = dynamic_pointer_cast<STARS_op_t>(std::make_shared<STARS_IRDB_op_t>());
bool do_default = true;
// disasm = DecodedInstruction_t(irdb_insn);
const auto my_disasm = DecodedInstruction_t(irdb_insn);
disasm = DecodedInstructionMicro_t(irdb_insn);
int length = my_disasm.length(); /*Disassemble(irdb_insn, disasm); */
for (int i = 0; i < STARS_UA_MAXOP; ++i) // all operands are void to start.
Operands.push_back(MakeVoidOpnd());
Operands.push_back(this->MakeVoidOpnd());
uint16_t IDAOpcode = this->GetIDAOpcode();
switch (IDAOpcode)
{
......@@ -1584,15 +1587,15 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
case STARS_NN_call:
{
//if((disasm.Argument1.ArgType & 0xffff0000 & CONSTANT_TYPE)==CONSTANT_TYPE)
if(disasm.getOperand(0).isConstant())
if(my_disasm.getOperand(0).isConstant())
{
shared_ptr<STARS_IRDB_op_t> p=(std::make_shared<STARS_IRDB_op_t>());
shared_ptr<STARS_IRDB_op_t> p=(std::make_shared<STARS_IRDB_op_t>());
if(irdb_insn->GetTarget())
p->MakeNearPointerOpnd(irdb_insn->GetTarget()->GetBaseID());
else
p->MakeNearPointerOpnd(0);
Operands[0]=p;
features=STARS_CF_USE1;
features=STARS_CF_USE1;
do_default=false;
}
break;
......@@ -1603,8 +1606,7 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
case STARS_NN_push:
{
// make op[0] from reg/imm in Argument2
// Operands[0]=(std::make_shared<STARS_IRDB_op_t>(disasm,1,disasm.Argument2,length));
Operands[0]=(std::make_shared<STARS_IRDB_op_t>(disasm,1,disasm.getOperand(0),length));
Operands[0]=(std::make_shared<STARS_IRDB_op_t>(my_disasm,1,my_disasm.getOperand(0),length));
// reset the features of this insn to say we use op 1.
features=STARS_CF_USE1;
do_default=false;
......@@ -1616,8 +1618,7 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
case STARS_NN_pop:
{
// make op[0] from reg/imm in Argument2
// Operands[0]=(std::make_shared<STARS_IRDB_op_t>(disasm,1,disasm.Argument1,length));
Operands[0]=(std::make_shared<STARS_IRDB_op_t>(disasm,1,disasm.getOperand(0),length));
Operands[0]=(std::make_shared<STARS_IRDB_op_t>(my_disasm,1,my_disasm.getOperand(0),length));
// reset the features of this insn to say we use op 1.
features=STARS_CF_CHG1;
do_default=false;
......@@ -1688,7 +1689,7 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
case STARS_NN_cdq: // EAX -> EDX:EAX (with sign)
case STARS_NN_cqo: // RAX -> RDX:RAX (with sign)
{
if (!disasm.hasOperand(0)) { // all operands are implicit; create them to match IDA
if (!my_disasm.hasOperand(0)) { // all operands are implicit; create them to match IDA
do_default = false;
const auto p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_ax);
......@@ -1723,21 +1724,21 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
//if (this->disasm.Argument1.ArgType == REGISTER_TYPE + GENERAL_REG + REG0 + REG2)
// this->disasm.Argument1.ArgType = REGISTER_TYPE + GENERAL_REG + REG0;
// get reg num of reg0+reg2 now returns reg0.
if(!disasm.hasOperand(1)) // e.g. div rsi or mul rcx; RAX is hidden operand
if(!my_disasm.hasOperand(1)) // e.g. div rsi or mul rcx; RAX is hidden operand
{
shared_ptr<STARS_IRDB_op_t> p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_ax);
p->SetByteWidth(disasm.getOperand(0).getArgumentSizeInBytes());
p->SetByteWidth(my_disasm.getOperand(0).getArgumentSizeInBytes());
Operands[0]=p;
do_default = false;
for(auto i=0;i<3;i++)
{
if(disasm.hasOperand(i))
Operands[i+1]=(std::make_shared<STARS_IRDB_op_t>(disasm,0,disasm.getOperand(i),length));
if(my_disasm.hasOperand(i))
Operands[i+1]=(std::make_shared<STARS_IRDB_op_t>(my_disasm,0,my_disasm.getOperand(i),length));
else
Operands[i+1]=(std::make_shared<STARS_IRDB_op_t>());
Operands[i+1] = this->MakeVoidOpnd();
}
features=GetInitialInstFeatures(true) | (STARS_CF_CHG1 | STARS_CF_USE1);
features=GetInitialInstFeatures(true,my_disasm) | (STARS_CF_CHG1 | STARS_CF_USE1);
}
else
do_default=true;
......@@ -1794,24 +1795,25 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
FPStore = true;
}
else
p->MakeRegOpnd(STARS_x86_R_st0);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st0);
p->SetByteWidth(this->DetermineRegByteWidth(p->GetReg()));
Operands[0] = p;
do_default = false;
for (auto i = 0; i < 3; ++i)
{
if (disasm.hasOperand(i))
Operands[i + 1] = (std::make_shared<STARS_IRDB_op_t>(disasm, 0, disasm.getOperand(i),length));
if (my_disasm.hasOperand(i))
Operands[i + 1] = (std::make_shared<STARS_IRDB_op_t>(my_disasm, 0, my_disasm.getOperand(i),length));
else
Operands[i + 1] = (std::make_shared<STARS_IRDB_op_t>());
Operands[i + 1] = this->MakeVoidOpnd();
}
if (FloatingStackLoad)
features = GetInitialInstFeatures(true) | (STARS_CF_CHG1 | STARS_CF_USE2);
features = GetInitialInstFeatures(true,my_disasm) | (STARS_CF_CHG1 | STARS_CF_USE2);
else if (FloatingImmediateLoad) // e.g. ST0 := 0.0 or ST0 := pi;
features = GetInitialInstFeatures(true) | (STARS_CF_CHG1);
features = GetInitialInstFeatures(true,my_disasm) | (STARS_CF_CHG1);
else if (FPStore)
features = GetInitialInstFeatures(true) | (STARS_CF_CHG2 | STARS_CF_USE1);
features = GetInitialInstFeatures(true,my_disasm) | (STARS_CF_CHG2 | STARS_CF_USE1);
else
features = GetInitialInstFeatures(true) | (STARS_CF_CHG1 | STARS_CF_USE1);
features = GetInitialInstFeatures(true,my_disasm) | (STARS_CF_CHG1 | STARS_CF_USE1);
break;
}
......@@ -1832,12 +1834,12 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
do_default = false;
for(auto i=0;i<3;i++)
{
if(disasm.hasOperand(i))
Operands[i+1]=(std::make_shared<STARS_IRDB_op_t>(disasm,0,disasm.getOperand(i),length));
if(my_disasm.hasOperand(i))
Operands[i+1]=(std::make_shared<STARS_IRDB_op_t>(my_disasm,0,my_disasm.getOperand(i),length));
else
Operands[i+1]=(std::make_shared<STARS_IRDB_op_t>());
Operands[i+1] = this->MakeVoidOpnd();
}
features=GetInitialInstFeatures(true) | (STARS_CF_USE1);
features=GetInitialInstFeatures(true,my_disasm) | (STARS_CF_USE1);
break;
}
......@@ -1848,15 +1850,15 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
auto p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st0);
Operands[0]=p;
if(disasm.hasOperand(0))
Operands[1]=(std::make_shared<STARS_IRDB_op_t>(disasm,0,disasm.getOperand(0),length));
if(my_disasm.hasOperand(0))
Operands[1]=(std::make_shared<STARS_IRDB_op_t>(my_disasm,0,my_disasm.getOperand(0),length));
else
{
p->MakeRegOpnd(STARS_x86_R_st1);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st1);
Operands[1]=p;
}
features=GetInitialInstFeatures(true)
features=GetInitialInstFeatures(true,my_disasm)
| (STARS_CF_CHG1 | STARS_CF_USE1)
| (STARS_CF_CHG2 | STARS_CF_USE2);
break;
......@@ -1868,16 +1870,16 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
case STARS_NN_fucomp:
{
auto p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st0);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st0);
Operands[0]=p;
if(disasm.hasOperand(0))
Operands[1]=(std::make_shared<STARS_IRDB_op_t>(disasm,0,disasm.getOperand(0),length));
if(my_disasm.hasOperand(0))
Operands[1]=(std::make_shared<STARS_IRDB_op_t>(my_disasm,0,my_disasm.getOperand(0),length));
else
{
p->MakeRegOpnd(STARS_x86_R_st1);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st1);
Operands[1]=p;
}
features=GetInitialInstFeatures(true)
features=GetInitialInstFeatures(true,my_disasm)
| (STARS_CF_USE1)
| (STARS_CF_USE2);
break;
......@@ -1897,25 +1899,25 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
case STARS_NN_fsubp:
case STARS_NN_fsubrp:
{
if(disasm.hasOperand(1))
if(my_disasm.hasOperand(1))
{
do_default=true;
}
else if(disasm.hasOperand(0)) // missing st0
else if(my_disasm.hasOperand(0)) // missing st0
{
do_default=false;
shared_ptr<STARS_IRDB_op_t> p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st0);
p->SetByteWidth(disasm.getOperand(0).getArgumentSizeInBytes());
p->MakeFloatingPointRegOpnd(STARS_x86_R_st0);
p->SetByteWidth(my_disasm.getOperand(0).getArgumentSizeInBytes());
Operands[0]=p;
for(auto i=0;i<3;i++)
{
if(disasm.hasOperand(i))
Operands[i+1]=(std::make_shared<STARS_IRDB_op_t>(disasm,0,disasm.getOperand(i),length));
if(my_disasm.hasOperand(i))
Operands[i+1]=(std::make_shared<STARS_IRDB_op_t>(my_disasm,0,my_disasm.getOperand(i),length));
else
Operands[i+1]=(std::make_shared<STARS_IRDB_op_t>());
Operands[i+1] = this->MakeVoidOpnd();
}
features=GetInitialInstFeatures(true) | (STARS_CF_CHG1 | STARS_CF_USE1);
features=GetInitialInstFeatures(true,my_disasm) | (STARS_CF_CHG1 | STARS_CF_USE1);
}
else /// missing st0 and st1
{
......@@ -1923,14 +1925,14 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
shared_ptr<STARS_IRDB_op_t> p;
p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st0);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st0);
Operands[0]=p;
p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st1);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st1);
Operands[1]=p;
features=GetInitialInstFeatures(false) | (STARS_CF_CHG1 | STARS_CF_USE1 | STARS_CF_USE2);
features=GetInitialInstFeatures(false,my_disasm) | (STARS_CF_CHG1 | STARS_CF_USE1 | STARS_CF_USE2);
}
break;
}
......@@ -1945,14 +1947,14 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
shared_ptr<STARS_IRDB_op_t> p;
p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st0);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st0);
Operands[0]=p;
p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st1);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st1);
Operands[1]=p;
features=GetInitialInstFeatures(false) | (STARS_CF_CHG1 | STARS_CF_USE1 | STARS_CF_USE2);
features=GetInitialInstFeatures(false,my_disasm) | (STARS_CF_CHG1 | STARS_CF_USE1 | STARS_CF_USE2);
break;
}
......@@ -1993,14 +1995,14 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
shared_ptr<STARS_IRDB_op_t> p;
p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st0);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st0);
Operands[0]=p;
p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st1);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st1);
Operands[1]=p;
features=GetInitialInstFeatures(false) | (STARS_CF_USE1 | STARS_CF_USE2);
features=GetInitialInstFeatures(false,my_disasm) | (STARS_CF_USE1 | STARS_CF_USE2);
break;
}
......@@ -2014,14 +2016,14 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
shared_ptr<STARS_IRDB_op_t> p;
p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st0);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st0);
Operands[0]=p;
p = (std::make_shared<STARS_IRDB_op_t>());
p->MakeRegOpnd(STARS_x86_R_st1);
p->MakeFloatingPointRegOpnd(STARS_x86_R_st1);
Operands[1]=p;
features=GetInitialInstFeatures(false) | (STARS_CF_CHG2 | STARS_CF_USE1 | STARS_CF_USE2);
features=GetInitialInstFeatures(false,my_disasm) | (STARS_CF_CHG2 | STARS_CF_USE1 | STARS_CF_USE2);
break;
}
default:
......@@ -2030,18 +2032,14 @@ bool STARS_IRDB_Instruction_t::STARS_GetCmd(void)
if(do_default)
{
//Operands[0]=(std::make_shared<STARS_IRDB_op_t>(disasm,0,disasm.Argument1,length));
//Operands[1]=(std::make_shared<STARS_IRDB_op_t>(disasm,1,disasm.Argument2,length));
//Operands[2]=(std::make_shared<STARS_IRDB_op_t>(disasm,2,disasm.Argument3,length));
//Operands[3]=(std::make_shared<STARS_IRDB_op_t>(disasm,3,disasm.Argument4,length));
for(auto i=0;i<4;i++)
{
if(disasm.hasOperand(i))
Operands[i]=(std::make_shared<STARS_IRDB_op_t>(disasm,0,disasm.getOperand(i),length));
if(my_disasm.hasOperand(i))
Operands[i]=(std::make_shared<STARS_IRDB_op_t>(my_disasm,0,my_disasm.getOperand(i),length));
else
Operands[i]=(std::make_shared<STARS_IRDB_op_t>());
Operands[i] = this->MakeVoidOpnd();
}
features=GetInitialInstFeatures(false);
features=GetInitialInstFeatures(false,my_disasm);
}
// Simplify the operand encoding so that identical operands don't appear to be different.
......@@ -2071,15 +2069,7 @@ std::size_t STARS_IRDB_Instruction_t::DetermineRegByteWidth(STARS_regnum_t RegNu
STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeVoidOpnd(void) const
{
//ARGTYPE the_arg;
//memset(&the_arg,0,sizeof(the_arg));
//the_arg.ArgType=NO_ARGUMENT;
//const auto d=DecodedInstruction_t(0,"\xd9\xd0", 2);
//const auto the_arg=d.getOperand(0);
STARSOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
return p;
return this->VoidOpndsPtr; // shared for memory reduction
}
......@@ -2098,7 +2088,7 @@ STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeImmediateOpnd(STARS_uval_t value)
// STARSIRDBOpndTypePtr p=std::dynamic_cast<STARSIRDBOpndTypePtr>(p);
STARSIRDBOpndTypePtr p=std::dynamic_pointer_cast<STARS_IRDB_op_t>(MakeVoidOpnd());
STARSIRDBOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
assert(p);
p->MakeImmediateOpnd(value);
return p;
......@@ -2106,7 +2096,7 @@ STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeImmediateOpnd(STARS_uval_t value)
STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeRegOpnd(STARS_regnum_t RegNum, bool DefaultToMachineWidth)
{
STARSIRDBOpndTypePtr p=std::dynamic_pointer_cast<STARS_IRDB_op_t>(MakeVoidOpnd());
STARSIRDBOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
assert(p);
uint16_t ByteWidth = this->DetermineRegByteWidth(RegNum);
p->MakeRegOpnd(RegNum);
......@@ -2117,7 +2107,7 @@ STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeRegOpnd(STARS_regnum_t RegNum, bo
STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeFloatingPointRegOpnd(STARS_regnum_t RegNum)
{
STARSIRDBOpndTypePtr p=std::dynamic_pointer_cast<STARS_IRDB_op_t>(MakeVoidOpnd());
STARSIRDBOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
assert(p);
p->MakeFloatingPointRegOpnd(RegNum);
p->SetByteWidth(this->DetermineRegByteWidth(RegNum));
......@@ -2126,7 +2116,7 @@ STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeFloatingPointRegOpnd(STARS_regnum
STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeMMXRegOpnd(STARS_regnum_t RegNum)
{
STARSIRDBOpndTypePtr p=std::dynamic_pointer_cast<STARS_IRDB_op_t>(MakeVoidOpnd());
STARSIRDBOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
assert(p);
p->MakeMMXRegOpnd(RegNum);
p->SetByteWidth(this->DetermineRegByteWidth(RegNum));
......@@ -2135,7 +2125,7 @@ STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeMMXRegOpnd(STARS_regnum_t RegNum)
STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeXMMRegOpnd(STARS_regnum_t RegNum)
{
STARSIRDBOpndTypePtr p=std::dynamic_pointer_cast<STARS_IRDB_op_t>(MakeVoidOpnd());
STARSIRDBOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
assert(p);
p->MakeXMMRegOpnd(RegNum);
p->SetByteWidth(this->DetermineRegByteWidth(RegNum));
......@@ -2144,7 +2134,7 @@ STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeXMMRegOpnd(STARS_regnum_t RegNum)
STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeYMMRegOpnd(STARS_regnum_t RegNum)
{
STARSIRDBOpndTypePtr p=std::dynamic_pointer_cast<STARS_IRDB_op_t>(MakeVoidOpnd());
STARSIRDBOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
assert(p);
p->MakeYMMRegOpnd(RegNum);
p->SetByteWidth(this->DetermineRegByteWidth(RegNum));
......@@ -2153,7 +2143,7 @@ STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeYMMRegOpnd(STARS_regnum_t RegNum)
STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeNearPointerOpnd(STARS_uval_t value) const
{
STARSIRDBOpndTypePtr p=std::dynamic_pointer_cast<STARS_IRDB_op_t>(MakeVoidOpnd());
STARSIRDBOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
assert(p);
p->MakeNearPointerOpnd(disasm.getAddress() /*Instruction.AddrValue*/);
return p;
......@@ -2163,7 +2153,7 @@ STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeNearPointerOpnd(STARS_uval_t valu
STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeMemDisplacementOpnd
(STARS_regnum_t BaseRegNum, STARS_regnum_t IndexRegNum, uint16_t ScaleFactor, STARS_ea_t offset)
{
STARSIRDBOpndTypePtr p=std::dynamic_pointer_cast<STARS_IRDB_op_t>(MakeVoidOpnd());
STARSIRDBOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
assert(p);
p->MakeMemDisplacementOpnd(BaseRegNum, IndexRegNum, ScaleFactor, offset);
return p;
......@@ -2171,7 +2161,7 @@ STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeMemDisplacementOpnd
STARSOpndTypePtr STARS_IRDB_Instruction_t::MakeMemPhraseOpnd
(STARS_regnum_t BaseRegNum, STARS_regnum_t IndexRegNum, uint16_t ScaleFactor)
{
STARSIRDBOpndTypePtr p=std::dynamic_pointer_cast<STARS_IRDB_op_t>(MakeVoidOpnd());
STARSIRDBOpndTypePtr p=std::make_shared<STARS_IRDB_op_t>();
assert(p);
p->MakeMemPhraseOpnd(BaseRegNum, IndexRegNum, ScaleFactor);
return p;
......
......@@ -19,7 +19,7 @@
STARS_Instruction_t * STARS_IRDB_Interface_t::CreateInst(STARS_InstructionID_t InstID)
{
// check for psuedo-instructions
// check for pseudo-instructions
if(STARS_IsSSAMarkerPseudoID(InstID.GetIDWithinFile()))
return new STARS_IRDB_Instruction_t(InstID);
// already created, just return what we need.
......@@ -33,6 +33,8 @@ bool STARS_IRDB_Interface_t::STARS_generate_disasm_line(STARS_ea_t addr, char *b
{
STARS_InstructionID_t id(addr);
const STARS_Instruction_t* insn=id.GetInstruction();
if (nullptr == insn)
return false;
const STARS_IRDB_Instruction_t* irdb_insn=dynamic_cast<const STARS_IRDB_Instruction_t*>(insn);
strncpy(buf,irdb_insn->GetIRDBInstruction()->getDisassembly().c_str(), bufsize);
return true;
......