diff --git a/SMPBasicBlock.cpp b/SMPBasicBlock.cpp index 7e23f3cad83baa5b6aee74ac6e7807245884db63..97a84d2b3e1f9cdd0f7966e5cdb5bcfc27cbfc55 100644 --- a/SMPBasicBlock.cpp +++ b/SMPBasicBlock.cpp @@ -1187,21 +1187,21 @@ void SMPBasicBlock::FreeUnusedMemory4(void) { this->LiveInSet.clear(); #if 0 // PhiFunctions, LiveOutSet, Successors and AddrInstMap are used in SMPInstr::EmitIntegerErrorAnnotations() this->LiveOutSet.clear(); + this->Predecessors.clear(); this->Successors.clear(); this->PhiFunctions.clear(); this->AddrInstMap.clear(); #endif this->UpExposedSet.clear(); - this->Predecessors.clear(); #if SMP_SHRINK_TO_FIT std::set<op_t, LessOp>(this->KillSet).swap(this->KillSet); std::set<op_t, LessOp>(this->LiveInSet).swap(this->LiveInSet); std::set<op_t, LessOp>(this->UpExposedSet).swap(this->UpExposedSet); - std::list<SMPBasicBlock *>(this->Predecessors).swap(this->Predecessors); #if 0 std::set<op_t, LessOp>(this->LiveInSet).swap(this->LiveOutSet); std::set<SMPPhiFunction, LessPhi>(this->PhiFunctions).swap(this->PhiFunctions); std::map<ea_t, SMPInstr *>(this->AddrInstMap).swap(this->AddrInstMap); + std::list<SMPBasicBlock *>(this->Predecessors).swap(this->Predecessors); std::list<SMPBasicBlock *>(this->Successors).swap(this->Successors); #endif #endif @@ -2821,7 +2821,7 @@ bool SMPBasicBlock::IsDefRedefinedByAddition(ea_t DefAddr, op_t DefOp, ea_t &Add } // end of SMPBasicBlock::IsDefRedefinedByAddition() // Does value of DefOp/DefSSANum reach block end in any computation of any DEF at all? -bool SMPBasicBlock::DoesDefReachBlockEnd(ea_t DefAddr, op_t DefOp, int DefSSANum, set<int> NonEscapingRegisterHashes) { +bool SMPBasicBlock::DoesDefReachBlockEnd(ea_t DefAddr, op_t DefOp, int DefSSANum, set<int> &NonEscapingRegisterHashes) { set<op_t, LessOp>::iterator LocalIter = this->LocalNames.find(DefOp); bool LocalName = (LocalIter != this->LocalNames.end()); unsigned int DUIndex; @@ -2960,6 +2960,76 @@ bool SMPBasicBlock::DoesDefReachBlockEnd(ea_t DefAddr, op_t DefOp, int DefSSANum return DoesEscape; } // end of SMPBasicBlock::DoesDefReachBlockEnd() +// DefOp/DefSSANum is only used in LoopNum (outside of DefAddr) as address reg or Phi USE +bool SMPBasicBlock::IsDefOnlyUsedAsAddressReg(ea_t DefAddr, op_t DefOp, size_t LoopNum, size_t &AddrUseCounter, SMPOperandType &MemType) { + bool OnlyAddressReg = false; + + if (this->IsProcessed() || (!this->GetFunc()->IsBlockInLoop(this->GetNumber(), LoopNum))) { + // Must have already passed the test, or is an irrelevant block outside the loop. + return true; + } + + if (o_reg == DefOp.type) { + OnlyAddressReg = true; + list<SMPInstr *>::iterator InstIter; + op_t SearchOp = DefOp; + CanonicalizeOpnd(SearchOp); + for (InstIter = this->GetFirstInstr(); InstIter != this->GetLastInstr(); ++InstIter) { + SMPInstr *CurrInst = (*InstIter); + ea_t InstAddr = CurrInst->GetAddr(); + if (InstAddr != DefAddr) { // Skip induction variable re-definition. + set<DefOrUse, LessDefUse>::iterator UseIter = CurrInst->FindUse(SearchOp); + if (UseIter != CurrInst->GetLastUse()) { + // Found a USE of DefOp not at DefAddr. + if (CurrInst->HasDestMemoryOperand() || CurrInst->HasSourceMemoryOperand()) { + op_t MemOp = CurrInst->GetMemUse(); + if (o_void == MemOp.type) { + MemOp = CurrInst->GetMemDef(); + } + int BaseReg, IndexReg; + ushort ScaleFactor; + ea_t offset; + MDExtractAddressFields(MemOp, BaseReg, IndexReg, ScaleFactor, offset); + if ((BaseReg != DefOp.reg) && (IndexReg != DefOp.reg)) { + OnlyAddressReg = false; // USEd somehow, but not as an address reg. + } + else { + ++AddrUseCounter; + } + } + else { + // Definitely not an addressing reg, as there are no memory operands. + OnlyAddressReg = false; + } + if (!OnlyAddressReg) + break; + } + } + } // end for all insts + // If we passed all instructions in block with no problems, recurse into successors. + this->SetProcessed(true); + if (OnlyAddressReg) { + list<SMPBasicBlock *>::iterator SuccIter; + for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) { + if (!(*SuccIter)->IsDefOnlyUsedAsAddressReg(DefAddr, DefOp, LoopNum, AddrUseCounter, MemType)) { + OnlyAddressReg = false; + break; + } + } + } + } + + if (OnlyAddressReg) { + if (0 < AddrUseCounter) { + // NOTE: Future work: extract pointer type of base register above. + MemType = POINTER; + } + } + + return OnlyAddressReg; +} // end of SMPBasicBlock::IsDefOnlyUsedAsAddressReg() + + // erase() block starting at FirstAddr from Preds list void SMPBasicBlock::ErasePred(ea_t FirstAddr) { list<SMPBasicBlock *>::iterator PredIter; diff --git a/SMPBasicBlock.h b/SMPBasicBlock.h index 5150aa0ede4ee8dd3f660872a54839e6914fbea7..51db0c82b8800a2ba0aac57ee437753d51f769f8 100644 --- a/SMPBasicBlock.h +++ b/SMPBasicBlock.h @@ -272,7 +272,8 @@ public: void MarkDeadRegs(void); // Find dead registers for each mmStrata-instrumented instruction bool IsDefDead(ea_t DefAddr, op_t DefOp); // Does DefOp at DefAddr never get used? bool IsDefRedefinedByAddition(ea_t DefAddr, op_t DefOp, ea_t &AdditionAddr); // true if DefOp at DefAddr is redefined by addition; pass back AdditionAddr - bool DoesDefReachBlockEnd(ea_t DefAddr, op_t DefOp, int DefSSANum, set<int> NonEscapingRegisterHashes); // Does value of DefOp/DefSSANum reach block end in any DEF at all? + bool DoesDefReachBlockEnd(ea_t DefAddr, op_t DefOp, int DefSSANum, set<int> &NonEscapingRegisterHashes); // Does value of DefOp/DefSSANum reach block end in any DEF at all? + bool IsDefOnlyUsedAsAddressReg(ea_t DefAddr, op_t DefOp, size_t LoopNum, size_t &AddrUseCounter, SMPOperandType &MemType); // DefOp/DefSSANum is only used in LoopNum (outside of DefAddr) as address reg or Phi USE bool PropagateLocalDefType(op_t DefOp, SMPOperandType DefType, ea_t DefAddr, int SSANum, bool IsMemOp); // to all uses bool InferLocalDefType(op_t DefOp, unsigned int LocIndex, ea_t DefAddr); // Can DEF type be inferred from all USEs? void InferGlobalDefType(op_t DefOp, int SSANum, ea_t DefAddr, bool &FoundNumeric, bool &FoundPointer, diff --git a/SMPDataFlowAnalysis.cpp b/SMPDataFlowAnalysis.cpp index 585c4d83bd4831b6f1a76f999051829907f138b7..d4f3ebcc41b448bd222c9b1935fca16e392dfa37 100644 --- a/SMPDataFlowAnalysis.cpp +++ b/SMPDataFlowAnalysis.cpp @@ -1568,10 +1568,10 @@ void STARSBitSet::AllocateBits(size_t Size) { size_t ExtraBits = Size % 8; this->BitLimit = Size; if (0 != ExtraBits) { - this->STARSBits.reserve(1 + Bytes); + this->STARSBits.resize(1 + Bytes); } else { - this->STARSBits.reserve(Bytes); + this->STARSBits.resize(Bytes); } for (Bytes = 0; Bytes < this->STARSBits.size(); ++Bytes) { this->STARSBits[Bytes] = 0; diff --git a/SMPFunction.cpp b/SMPFunction.cpp index 2341a8473e74f40d87ac88161ca8d918c5a61c23..70d3691b09edec05a52c1e381615a797d1e9559b 100644 --- a/SMPFunction.cpp +++ b/SMPFunction.cpp @@ -89,7 +89,8 @@ using namespace std; #define SMP_AUDIT_STACK_POINTER_DELTAS 0 #define SMP_COMPARE_IDA_STARS_STACK_POINTER_DELTAS 1 #define STARS_AGGRESSIVE_SIGNEDNESS_PROPAGATION 1 -#define STARS_BUILD_LOOP_BITSET 0 // Build bitset in this->FuncLoopsByBlock +#define STARS_BUILD_LOOP_BITSET 1 // Build bitset in this->FuncLoopsByBlock +#define STARS_DEBUG_MEMORY_CORRUPTION 0 // Compute LVA/SSA or not? Turn it off for NICECAP demo on 31-JAN-2008 #define SMP_COMPUTE_LVA_SSA 1 @@ -3316,12 +3317,20 @@ void SMPFunction::Analyze(void) { if (CurrChunk.startEA < this->FirstEA) { this->FirstEA = CurrChunk.startEA; } +#endif +#if STARS_DEBUG_MEMORY_CORRUPTION + bool DebugFlag = (0 == strcmp("sub_8063BE0", this->GetFuncName())); #endif // Build the instruction and block lists for the function. for (ea_t addr = CurrChunk.startEA; addr < CurrChunk.endEA; addr = get_item_end(addr)) { flags_t InstrFlags = getFlags(addr); if (isHead(InstrFlags) && isCode(InstrFlags)) { +#if STARS_DEBUG_MEMORY_CORRUPTION + if (DebugFlag) { + SMP_msg("INFO: SANITY TRACE: addr = %x \n", addr); + } +#endif SMPInstr *CurrInst = new SMPInstr(addr); // Fill in the instruction data members. #if SMP_DEBUG_CONTROLFLOW @@ -4464,11 +4473,21 @@ bool SMPFunction::PropagateGlobalMetadata(op_t UseOp, SMPMetadataType Status, in // Find consecutive DEFs of the same type and mark the second one redundant. void SMPFunction::FindRedundantMetadata(void) { - list<SMPBasicBlock *>::iterator CurrBlock; + list<SMPBasicBlock *>::iterator BlockIter; + SMPBasicBlock *CurrBlock; bool changed = false; - for (CurrBlock = this->Blocks.begin(); CurrBlock != this->Blocks.end(); ++CurrBlock) { - changed |= (*CurrBlock)->FindRedundantLocalMetadata(this->SafeFunc); +#if STARS_DEBUG_MEMORY_CORRUPTION + bool DebugFlag = (0 == strcmp("sub_8063BE0", this->GetFuncName())); + if (DebugFlag) { + CurrBlock = this->GetBlockFromInstAddr(0x8063c68); + SMP_msg("INFO: CHECKPOINT 1: FindRedundantMetadata: Number of preds = %u \n", CurrBlock->GetNumPreds()); + } +#endif + + for (BlockIter = this->Blocks.begin(); BlockIter != this->Blocks.end(); ++BlockIter) { + CurrBlock = (*BlockIter); + changed |= CurrBlock->FindRedundantLocalMetadata(this->SafeFunc); } return; } // end of SMPFunction::FindRedundantMetadata() @@ -4634,20 +4653,27 @@ void SMPFunction::DetectLoops(void) { assert((TailBlockNum != SMP_BLOCKNUM_UNINIT) && (HeadBlockNum != SMP_BLOCKNUM_UNINIT)); list<list<SMPBasicBlock *>::iterator> BlockWorkList; BlockWorkList.push_back(BlockIter); + SMPBasicBlock *WorkBlock; + SMPBasicBlock *PredBlock; + list<SMPBasicBlock *>::iterator WorkIter; + list<SMPBasicBlock *>::iterator PredIter; do { - list<SMPBasicBlock *>::iterator WorkIter = BlockWorkList.front(); + WorkIter = BlockWorkList.front(); BlockWorkList.pop_front(); - SMPBasicBlock *WorkBlock = (*WorkIter); + WorkBlock = (*WorkIter); int WorkBlockNum = WorkBlock->GetNumber(); assert(WorkBlockNum != SMP_BLOCKNUM_UNINIT); - this->FuncLoopsByBlock[(size_t) WorkBlockNum].SetBit(LoopNumber); - WorkBlock->SetProcessed(true); - // Add unprocessed predecessors to the work list until we reach the loop head. - if (WorkBlockNum != HeadBlockNum) { - list<SMPBasicBlock *>::iterator PredIter; - for (PredIter = WorkBlock->GetFirstPred(); PredIter != WorkBlock->GetLastPred(); ++PredIter) { - if (!(*PredIter)->IsProcessed()) { - BlockWorkList.push_back(PredIter); + if (!(WorkBlock->IsProcessed())) { + this->FuncLoopsByBlock[(size_t) WorkBlockNum].SetBit(LoopNumber); + WorkBlock->SetProcessed(true); + // Add unprocessed predecessors to the work list until we reach the loop head. + if (WorkBlockNum != HeadBlockNum) { + for (PredIter = WorkBlock->GetFirstPred(); PredIter != WorkBlock->GetLastPred(); ++PredIter) { + PredBlock = (*PredIter); + bool AlreadyProcessed = PredBlock->IsProcessed(); + if (!AlreadyProcessed) { + BlockWorkList.push_back(PredIter); + } } } } @@ -5013,7 +5039,7 @@ void SMPFunction::SetLinks(void) { changed = false; list<SMPBasicBlock *>::iterator BlockIter = this->Blocks.begin(); while (BlockIter != this->Blocks.end()) { - SMPBasicBlock *CurrBlock = (*BlockIter); + CurrBlock = (*BlockIter); if (CurrBlock->IsProcessed()) { ++BlockIter; } @@ -5166,6 +5192,14 @@ void SMPFunction::SetLinks(void) { } #endif +#if STARS_DEBUG_MEMORY_CORRUPTION + bool DebugFlag = (0 == strcmp("sub_8063BE0", this->GetFuncName())); + if (DebugFlag) { + CurrBlock = this->GetBlockFromInstAddr(0x8063c68); + SMP_msg("INFO: CHECKPOINT 0: SetLinks: Number of preds = %u \n", CurrBlock->GetNumPreds()); + } +#endif + return; } // end of SMPFunction::SetLinks() @@ -5808,6 +5842,22 @@ bool SMPFunction::IsBlockInAnyLoop(int BlockNum) { return FoundInsideLoop; } // end of SMPFunction::IsBlockInAnyLoop() +// Is block (with block # BlockNum) inside loop # LoopNum? +bool SMPFunction::IsBlockInLoop(int BlockNum, size_t LoopNum) { + return ((LoopNum < this->LoopCount) && (this->FuncLoopsByBlock.at((size_t) BlockNum).GetBit(LoopNum))); +} // end of SMPFunction::IsBlockInLoop() + +// build list of loop numbers that BlockNum is part of. +void SMPFunction::BuildLoopList(int BlockNum, list<size_t> &LoopList) { + size_t LoopIndex; + for (LoopIndex = 0; LoopIndex < this->LoopCount; ++LoopIndex) { + if (this->FuncLoopsByBlock.at((size_t) BlockNum).GetBit(LoopIndex)) { + LoopList.push_back(LoopIndex); + } + } + return; +} // end of SMPFunction::BuildLoopList() + // Helper for SSA subscript renumbering: return the next SSA number for the global name // and increment the SSACounter to prepare the next number. Push the returned number onto // the SSAStack for the global name. @@ -6356,6 +6406,13 @@ void SMPFunction::InferFGInfo(void) { #endif } while (changed); +#if STARS_DEBUG_MEMORY_CORRUPTION + bool DebugFlag = (0 == strcmp("sub_8063BE0", this->GetFuncName())); + if (DebugFlag) { + CurrBlock = this->GetBlockFromInstAddr(0x8063c68); + SMP_msg("INFO: CHECKPOINT 5: InferFGInfo: Number of preds = %u \n", CurrBlock->GetNumPreds()); + } +#endif return; } // end of SMPFunction::InferFGInfo() @@ -6927,6 +6984,7 @@ void SMPFunction::MarkSpecialNumericErrorCases(void) { list<SMPInstr *>::reverse_iterator InstIter; SMPBasicBlock *CurrBlock; SMPInstr *CurrInst; + bool DebugFlag = (0 == strcmp("sub_8063BE0", this->GetFuncName())); if (this->LoopCount == 0) { return; @@ -6935,15 +6993,31 @@ void SMPFunction::MarkSpecialNumericErrorCases(void) { set<int> NonEscapingRegisterHashes; // memoization optimization: set of register/SSA# hashes that do not reach end of block #if STARS_BUILD_LOOP_BITSET +#if STARS_DEBUG_MEMORY_CORRUPTION + if (DebugFlag) { + CurrBlock = this->GetBlockFromInstAddr(0x8063c68); + SMP_msg("INFO: CHECKPOINT 2: MarkSpecialNumericErrorCases: Number of preds = %u \n", CurrBlock->GetNumPreds()); + } +#endif // Now that we know how many loops we have, we can allocate the loops data structure. this->FuncLoopsByBlock.resize(this->BlockCount); for (size_t BlockIndex = 0; BlockIndex < this->BlockCount; ++BlockIndex) { this->FuncLoopsByBlock.at(BlockIndex).AllocateBits(this->LoopCount); } + if (DebugFlag) { + CurrBlock = this->GetBlockFromInstAddr(0x8063c68); + SMP_msg("INFO: CHECKPOINT 3: Number of preds = %u \n", CurrBlock->GetNumPreds()); + } + if (this->LoopCount > 0) { this->DetectLoops(); } + + if (DebugFlag) { + CurrBlock = this->GetBlockFromInstAddr(0x8063c68); + SMP_msg("INFO: CHECKPOINT 4: Number of preds = %u \n", CurrBlock->GetNumPreds()); + } #endif // Loop through blocks and detect tight loops of hashing arithmetic. @@ -7116,6 +7190,8 @@ void SMPFunction::EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile) { // Output optimization annotations for those // instructions that do not require full computation // of their memory metadata by the Memory Monitor SDT. + list<size_t> LoopList; // for current block + int CurrBlockNum = SMP_BLOCKNUM_UNINIT; list<SMPInstr *>::iterator InstIter = Instrs.begin(); #if SMP_USE_SSA_FNOP_MARKER ++InstIter; // skip marker instruction @@ -7125,6 +7201,15 @@ void SMPFunction::EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile) { for ( ; InstIter != Instrs.end(); ++InstIter) { SMPInstr *CurrInst = (*InstIter); ea_t addr = CurrInst->GetAddr(); + CurrBlock = CurrInst->GetBlock(); + int BlockNum = CurrBlock->GetNumber(); + if (BlockNum != CurrBlockNum) { + CurrBlockNum = BlockNum; + if (0 < this->LoopCount) { + LoopList.clear(); + this->BuildLoopList(BlockNum, LoopList); + } + } SMP_fprintf(AnnotFile, "%10x %6d INSTR BELONGTO %x \n", addr, 0, GetStartAddr()); @@ -7172,7 +7257,7 @@ void SMPFunction::EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile) { #ifndef SMP_REDUCED_ANALYSIS if (this->StackPtrAnalysisSucceeded() && this->HasGoodRTLs() && !this->HasUnresolvedIndirectJumps() && !this->HasSharedChunks()) { CurrInst->EmitTypeAnnotations(this->UseFP, AllocSeen, this->NeedsStackReferent, AnnotFile, InfoAnnotFile); - CurrInst->EmitIntegerErrorAnnotations(InfoAnnotFile); + CurrInst->EmitIntegerErrorAnnotations(InfoAnnotFile, LoopList); } else #endif @@ -7203,6 +7288,7 @@ void SMPFunction::EmitAnnotations(FILE *AnnotFile, FILE *InfoAnnotFile) { } } // Free loop memory. + LoopList.clear(); this->FuncLoopsByBlock.clear(); #if SMP_SHRINK_TO_FIT vector<STARSBitSet>(this->FuncLoopsByBlock).swap(this->FuncLoopsByBlock); diff --git a/SMPFunction.h b/SMPFunction.h index df224e8560e2e4a73cc8d9711be3a70a90fb7fb8..99bbf2c02204b5cecaa67240c55e22e80b6b74c3 100644 --- a/SMPFunction.h +++ b/SMPFunction.h @@ -261,6 +261,8 @@ public: void ComputeSSA(void); // Compute SSA form data structures bool DoesBlockDominateBlock(int HeadBlockNum, int TailBlockNum); // Does basic block HeadBlockNum dominate basic block TailBlockNum? bool IsBlockInAnyLoop(int BlockNum); // Is block (with block # BlockNum) inside any loop? + bool IsBlockInLoop(int BlockNum, size_t LoopNum); // Is block (with block # BlockNum) inside loop # LoopNum? + void BuildLoopList(int BlockNum, list<size_t> &LoopList); // build list of loop numbers that BlockNum is part of. void AliasAnalysis(void); // Find memory writes with possible aliases void InferTypes(bool FirstIter); // Determine NUMERIC, POINTER, etc. for all operands void InferFGInfo(void); // determine signedness and width info for all operands diff --git a/SMPInstr.cpp b/SMPInstr.cpp index 4793c4102998bfb1041131e76a95b1406942e55c..221cb84367ebaa8944a19aae7c93c0c74808c6c6 100644 --- a/SMPInstr.cpp +++ b/SMPInstr.cpp @@ -7291,7 +7291,7 @@ unsigned short SMPInstr::SignMaskUnionFromUseRegs(void) { } // SMPInstr::SignMaskUnionFromUseRegs() // emit check annotations for signedness, overflow, truncation, etc. -void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile) { +void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile, list<size_t> &LoopList) { set<DefOrUse, LessDefUse>::iterator UseIter, DefIter; op_t UseOp, DefOp; unsigned short UseWidthInfo, DefWidthInfo, SourceDefWidthInfo; @@ -7343,6 +7343,7 @@ void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile) { DefOp = DefIter->GetOp(); SSANum = DefIter->GetSSANum(); SMPOperandType DefType = DefIter->GetType(); + SMPOperandType MemType; bool IgnoreOverflow = this->IsBenignOverflow(IdiomCode); uval_t ConstValue = 0; // NOTE: We no longer suppress the IgnoreOverflow annotations. Instead, we print @@ -7463,6 +7464,19 @@ void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile) { IgnoreOverflow = true; IdiomCode = 18; } + else if (1 == LoopList.size()) { // Start with simple case of blocks only present in one loop + size_t Counter = 0; + size_t LoopNum = LoopList.front(); + MemType = UNINIT; + this->GetBlock()->GetFunc()->ResetProcessedBlocks(); + bool AddrRegOnly = this->GetBlock()->IsDefOnlyUsedAsAddressReg(this->GetAddr(), DefOp, LoopNum, Counter, MemType); + if (AddrRegOnly && (0 < Counter)) { + // Similarly, let C7 (buffer overflow/underflow) defenses handle the issues if it is only an index register. + DefType = MemType; + IgnoreOverflow = true; + IdiomCode = 18; + } + } } if (IgnoreOverflow) { if (11 == IdiomCode) { @@ -8059,7 +8073,7 @@ void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile) { } // end of cases 4-5, (3 == OptType) checking for TRUNCATION and SIGNEDNESS errors else if ((this->MDIsLoadEffectiveAddressInstr()) && (!(this->IsNop() || this->IsRegClearIdiom()))) { // Case 6: Load Effective Address opcodes can do arithmetic that silently overflows. - this->MDEmitLeaOpcodeOverflowAnnotations(InfoAnnotFile); + this->MDEmitLeaOpcodeOverflowAnnotations(InfoAnnotFile, LoopList); } // end of case 6, LoadEffectiveAddress instruction else if (this->MDDoublesWidth()) { // case 7: half of register is sign-extended into the full register. @@ -8143,7 +8157,7 @@ void SMPInstr::EmitIntegerErrorAnnotations(FILE *InfoAnnotFile) { // Emit overflow annotations for lea opcodes that perform arithmetic that // can overflow without affecting the flags. -void SMPInstr::MDEmitLeaOpcodeOverflowAnnotations(FILE *InfoAnnotFile) { +void SMPInstr::MDEmitLeaOpcodeOverflowAnnotations(FILE *InfoAnnotFile, list<size_t> &LoopList) { set<DefOrUse, LessDefUse>::iterator UseIter, DefIter; size_t OpNum; int BaseReg; @@ -8163,7 +8177,7 @@ void SMPInstr::MDEmitLeaOpcodeOverflowAnnotations(FILE *InfoAnnotFile) { unsigned short BaseRegWidthInfo, UseBitWidthInfo; size_t BaseRegMaxWidth, IndexRegMaxWidth, TempMaxWidth; char OffsetString[MAX_OFFSET_STR_LEN]; - op_t TempOp; + op_t TempOp, DefOp; for (OpNum = 0; OpNum < UA_MAXOP; ++OpNum) { TempOp = this->SMPcmd.Operands[OpNum]; @@ -8190,7 +8204,7 @@ void SMPInstr::MDEmitLeaOpcodeOverflowAnnotations(FILE *InfoAnnotFile) { else { // Check for the benign overflow cases we want to ignore. DefIter = this->GetFirstNonFlagsDef(); assert(DefIter != this->GetLastDef()); - op_t DefOp = DefIter->GetOp(); + DefOp = DefIter->GetOp(); SSANum = DefIter->GetSSANum(); DefType = DefIter->GetType(); DataPointer = IsDataPtr(DefType); @@ -8217,16 +8231,28 @@ void SMPInstr::MDEmitLeaOpcodeOverflowAnnotations(FILE *InfoAnnotFile) { string CurrString(""); const char *ScaleStrings[4] = {"", "*2", "*4", "*8"}; string PtrString(""); - if (DataPointer) { - if (IsEqType(STACKPTR, DefType)) - PtrString = "STACKMEMSINK"; - else if (IsEqType(HEAPPTR, DefType)) - PtrString = "HEAPMEMSINK"; - else if (IsEqType(GLOBALPTR, DefType)) - PtrString = "GLOBALMEMSINK"; - else - PtrString = "MEMORYSINK"; - if (0 == IdiomCode) { + if (IdiomCode == 0) { + if (!DataPointer && (1 == LoopList.size())) { // Start with simple case of blocks only present in one loop + SMPOperandType MemType = UNINIT; + size_t Counter = 0; + size_t LoopNum = LoopList.front(); + this->GetBlock()->GetFunc()->ResetProcessedBlocks(); + bool AddrRegOnly = this->GetBlock()->IsDefOnlyUsedAsAddressReg(this->GetAddr(), DefOp, LoopNum, Counter, MemType); + if (AddrRegOnly && (0 < Counter)) { + // Similarly, let C7 (buffer overflow/underflow) defenses handle the issues if it is only an index register. + DefType = MemType; + DataPointer = true; + } + } + if (DataPointer) { + if (IsEqType(STACKPTR, DefType)) + PtrString = "STACKMEMSINK"; + else if (IsEqType(HEAPPTR, DefType)) + PtrString = "HEAPMEMSINK"; + else if (IsEqType(GLOBALPTR, DefType)) + PtrString = "GLOBALMEMSINK"; + else + PtrString = "MEMORYSINK"; IdiomCode = 18; } } diff --git a/SMPInstr.h b/SMPInstr.h index fdaa71f176eb5bd4a65eff6adfb21d56770ccc03..fd2e3b2cfb98760483e796775b79ba91c2ebf835 100644 --- a/SMPInstr.h +++ b/SMPInstr.h @@ -352,6 +352,8 @@ public: inline set<DefOrUse, LessDefUse>::iterator FindUse(op_t SearchOp) { return Uses.FindRef(SearchOp); }; inline set<DefOrUse, LessDefUse>::iterator FindDef(op_t SearchOp) { return Defs.FindRef(SearchOp); }; set<DefOrUse, LessDefUse>::iterator GetFirstNonFlagsDef(void); + inline op_t GetMemDef(void) const { return DEFMemOp; }; + inline op_t GetMemUse(void) const { return USEMemOp; }; #if 0 inline set<sval_t>::iterator GetFirstStackDelta(void) { return StackDeltaSet.begin(); }; inline set<sval_t>::iterator GetLastStackDelta(void) { return StackDeltaSet.end(); }; @@ -535,8 +537,8 @@ public: void EmitAnnotations(bool UseFP, bool AllocSeen, bool NeedsFrame, FILE *AnnotFile, FILE *InfoAnnotFile); // No RTLs available void EmitTypeAnnotations(bool UseFP, bool AllocSeen, bool NeedsFrame, FILE *AnnotFile, FILE *InfoAnnotFile); // Use RTL types void EmitSafeReturn(FILE *AnnotFile); // emit annotation to denote that the return belongs to a safe function. - void EmitIntegerErrorAnnotations(FILE *InfoAnnotFile); // emit check annotations for signedness, overflow, truncation, etc. - void MDEmitLeaOpcodeOverflowAnnotations(FILE *InfoAnnotFile); // check for silent overflow in load effective address opcodes + void EmitIntegerErrorAnnotations(FILE *InfoAnnotFile, list<size_t> &LoopList); // emit check annotations for signedness, overflow, truncation, etc. + void MDEmitLeaOpcodeOverflowAnnotations(FILE *InfoAnnotFile, list<size_t> &LoopList); // check for silent overflow in load effective address opcodes void UpdateMemLoadTypes(SMPOperandType newType); bool IsBenignTruncation(int &IdiomCode); // Is the instruction such that truncation is not an error? bool IsBenignOverflow(int &IdiomCode); // Is the instruction such that overflow is not an error?