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;
}
......
This diff is collapsed.
......@@ -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();
......
......@@ -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;
......