diff --git a/SMPBasicBlock.cpp b/SMPBasicBlock.cpp index 50056e15a945471ce44f0d0cb515843e7d8c0cc5..3af1da43042104439c9c962ecdef9eb347a3207f 100644 --- a/SMPBasicBlock.cpp +++ b/SMPBasicBlock.cpp @@ -4380,19 +4380,22 @@ bool SMPBasicBlock::IsDefMasked(op_t DefOp, int DefSSANum, ea_t DefAddr) { // Recurse through successor blocks if needed to find all USEs of the DEF. bool SMPBasicBlock::IsCriticalSink(op_t DefOp, int DefSSANum, std::string &SinkString) { // Call recursive helper that finds argument-passing USEs of the DEF. - bool FoundSink = this->UseHasCriticalSink(DefOp, DefSSANum, SinkString); + op_t AlternateDefOp = InitOp; + bool FoundSink = this->UseHasCriticalSink(DefOp, DefSSANum, AlternateDefOp, SMP_SSA_UNINIT, SinkString); return FoundSink; } // end of SMPBasicBlock::IsCriticalSink() // Can we find USE being passed to a critical system or library call? -bool SMPBasicBlock::UseHasCriticalSink(op_t UseOp, int DefSSANum, std::string &SinkString) { +bool SMPBasicBlock::UseHasCriticalSink(op_t DefOp, int DefSSANum, op_t DefOp2, int DefSSANum2, std::string &SinkString) { bool FoundSink = false; list<SMPInstr *>::iterator InstIter; - set<DefOrUse, LessDefUse>::iterator UseIter; + set<DefOrUse, LessDefUse>::iterator UseIter, DefIter; bool FoundArgPass = false; int SearchSSANum = DefSSANum; + int SearchSSANum2 = DefSSANum2; ea_t InstAddr; // for debugging, breakpoints, etc. + size_t ArgumentNumber = 7; // init to bad number // avoid infinite recursion if (this->IsProcessed()) { @@ -4400,12 +4403,12 @@ bool SMPBasicBlock::UseHasCriticalSink(op_t UseOp, int DefSSANum, std::string &S } this->SetProcessed(true); - // We need to make the recursion robust by finding UseOp in Phi functions + // We need to make the recursion robust by finding DefOp in Phi functions // and altering the DefSSANum we are searching for. - set<SMPPhiFunction, LessPhi>::iterator CurrPhi = this->FindPhi(UseOp); + set<SMPPhiFunction, LessPhi>::iterator CurrPhi = this->FindPhi(DefOp); if (CurrPhi != this->GetLastPhi()) { - // Found Phi function for UseOp. That means we will not be finding DefSSANum for - // UseOp in this block or its successors, because the Phi function will redefine + // Found Phi function for DefOp. That means we will not be finding DefSSANum for + // DefOp in this block or its successors, because the Phi function will redefine // to a new SSA number. size_t PhiNumUses = CurrPhi->GetPhiListSize(); bool FoundPhiUse = false; @@ -4416,24 +4419,108 @@ bool SMPBasicBlock::UseHasCriticalSink(op_t UseOp, int DefSSANum, std::string &S break; } } - if (!FoundPhiUse) - return false; - SearchSSANum = CurrPhi->GetDefSSANum(); // new SSA name to search for is Phi DEF + if (FoundPhiUse) { + SearchSSANum = CurrPhi->GetDefSSANum(); // new SSA name to search for is Phi DEF + } + } + + // Do the same for DefOp2/DefSSANum2. + if (o_void != DefOp2.type) { + CurrPhi = this->FindPhi(DefOp2); + if (CurrPhi != this->GetLastPhi()) { + // Found Phi function for DefOp2. That means we will not be finding DefSSANum2 for + // DefOp2 in this block or its successors, because the Phi function will redefine + // to a new SSA number. + size_t PhiNumUses = CurrPhi->GetPhiListSize(); + bool FoundPhiUse = false; + for (size_t i = 0; i < PhiNumUses; ++i) { + // Confirm that DefSSANum2 was actually a Phi USE in this block. + if (CurrPhi->GetUseSSANum(i) == DefSSANum2) { + FoundPhiUse = true; + break; + } + } + if (FoundPhiUse) { + SearchSSANum2 = CurrPhi->GetDefSSANum(); // new SSA name to search for is Phi DEF + } + } } + for (InstIter = this->GetFirstInstr(); InstIter != this->GetLastInstr(); ++InstIter) { SMPInstr *CurrInst = (*InstIter); InstAddr = CurrInst->GetAddr(); // Two stage search: Find argument pass, then find next call instruction. if (!FoundArgPass) { - UseIter = CurrInst->FindUse(UseOp); + UseIter = CurrInst->FindUse(DefOp); if (UseIter != CurrInst->GetLastUse()) { int UseSSANum = UseIter->GetSSANum(); if (UseSSANum == SearchSSANum) { // Found a use that matches the DEF. Is it passed as an argument? - if (CurrInst->MDIsArgumentPass()) { + if (CurrInst->MDIsArgumentPass(ArgumentNumber)) { FoundArgPass = true; } + else if (CurrInst->MDIsMoveInstr() && (o_void == DefOp2.type)) { + // DefOp is getting stored, but not as an argument pass. + // Hard to say if we should keep following DefOp or follow + // the stored copy. Let's try following the stored copy also if + // it is a register or stack location. + DefIter = CurrInst->GetFirstNonFlagsDef(); + assert(DefIter != CurrInst->GetLastDef()); + op_t NewDefOp = DefIter->GetOp(); + if (MDIsDataFlowOpnd(NewDefOp, this->GetFunc()->UsesFramePointer())) { + // Follow NewDefOp from now on in addition to DefOp. + CanonicalizeOpnd(NewDefOp); + DefOp2 = NewDefOp; + SearchSSANum2 = DefIter->GetSSANum(); + } + } + else { // Stop searching for DefOp if it gets redefined. + DefIter = CurrInst->FindDef(DefOp); + if (DefIter != CurrInst->GetLastDef()) { + // DefOp was USE and DEF in CurrInst. + if (o_void != DefOp2.type) { + // We have an alternate DEF to search for. Make it primary. + DefOp = DefOp2; + SearchSSANum = SearchSSANum2; + DefOp2 = InitOp; // No more alternate. + SearchSSANum2 = SMP_SSA_UNINIT; + } + else { // No alternate to search for; search has failed. + break; + } + } + } + } + } + else if (o_void != DefOp2.type) { // DefOp is not used; search for DefOp2 + UseIter = CurrInst->FindUse(DefOp2); + if (UseIter != CurrInst->GetLastUse()) { + int UseSSANum = UseIter->GetSSANum(); + if (UseSSANum == SearchSSANum2) { + // Found a use that matches the DEF. Is it passed as an argument? + if (CurrInst->MDIsArgumentPass(ArgumentNumber)) { + FoundArgPass = true; + } + else if (CurrInst->MDIsMoveInstr()) { // DefOp2 is copied somewhere + // We cannot follow a third location currently, but we can see + // if DefOp2 is redefining DefOp in this move, and get a new + // SearchSSANum for DefOp in that case. + DefIter = CurrInst->FindDef(DefOp); + if (DefIter != CurrInst->GetLastDef()) { + // DefOp2 was copied to DefOp. + SearchSSANum = DefIter->GetSSANum(); // new DefOp/DefSSANum pair to search for. + } + } + else { // Stop searching for DefOp2 if it gets redefined. + DefIter = CurrInst->FindDef(DefOp2); + if (DefIter != CurrInst->GetLastDef()) { + // DefOp2 was USE and DEF in CurrInst. + DefOp2 = InitOp; // No more alternate. + SearchSSANum2 = SMP_SSA_UNINIT; + } + } + } } } } @@ -4443,19 +4530,29 @@ bool SMPBasicBlock::UseHasCriticalSink(op_t UseOp, int DefSSANum, std::string &S if (!(CalleeName.empty())) { GetSinkStringForCallName(CalleeName, SinkString); if (!(SinkString.empty())) { - FoundSink = true; + // ArgumentNumber needs to be 0 for malloc(), 0 or 1 for calloc(), + // and 1 for realloc. + if (ArgumentNumber < 2) { + bool FoundMalloc = (0 == CalleeName.compare("malloc")); + bool FoundCalloc = (0 == CalleeName.compare("calloc")); + bool FoundRealloc = (0 == CalleeName.compare("realloc")); + if (((ArgumentNumber == 0) && (FoundMalloc || FoundCalloc)) + || ((ArgumentNumber == 1) && (FoundCalloc || FoundRealloc))) { + FoundSink = true; + } + } } - break; } + break; } } } // end for all instructions - if (!FoundArgPass) { + if (!FoundArgPass && (this->IsLiveOut(DefOp) || ((o_void != DefOp2.type) && this->IsLiveOut(DefOp2)))) { // Need to recurse through successor blocks to keep searching for arg pass. list<SMPBasicBlock *>::iterator SuccIter; for (SuccIter = this->GetFirstSucc(); SuccIter != this->GetLastSucc(); ++SuccIter) { - if ((*SuccIter)->UseHasCriticalSink(UseOp, SearchSSANum, SinkString)) { + if ((*SuccIter)->UseHasCriticalSink(DefOp, SearchSSANum, DefOp2, SearchSSANum2, SinkString)) { FoundSink = true; break; } diff --git a/SMPBasicBlock.h b/SMPBasicBlock.h index e23820503ba7113a2bf95ae4763597ba7d6169ee..82bb7d712068d6c24269004766ff2e8592e6fc28 100644 --- a/SMPBasicBlock.h +++ b/SMPBasicBlock.h @@ -377,7 +377,7 @@ private: set<SMPPhiFunction, LessPhi>::iterator InferPhiDefType(set<SMPPhiFunction, LessPhi>::iterator DefPhi, bool &changed); // infer, propagate to all uses unsigned int GetLocalDUIndex(op_t DefOp, int SSANum); unsigned int GetGlobalDUIndex(op_t DefOp, ea_t DefAddr); - bool UseHasCriticalSink(op_t UseOp, int DefSSANum, string &SinkString); // USE is passed as arg to critical system or lib call + bool UseHasCriticalSink(op_t DefOp, int DefSSANum, op_t DefOp2, int DefSSANum2, string &SinkString); // DefOp or DefOp2 is passed as arg to critical system or lib call bool IsBranchSignednessUnreliable(void); // Is branch signedness misleading due to odd code generation idiom or hand coding? }; diff --git a/SMPInstr.cpp b/SMPInstr.cpp index 12e73eebe44eb226648e9ed4fd4c5350654f1bb5..06b5a7916c83c8eb8a17160074bfd97690b19157 100644 --- a/SMPInstr.cpp +++ b/SMPInstr.cpp @@ -5046,8 +5046,8 @@ bool SMPInstr::SkipSignednessCheckOnStackWrite(int DefSSANum) { return SkipCheck; } // end of SMPInstr::SkipSignednessCheckOnStackWrite() -// Does inst pass an outgoing argument? -bool SMPInstr::MDIsArgumentPass(void) { +// Does inst pass an outgoing argument? If so, pass back argument position #, starting at zero for [esp], 1 for [esp+4], etc. +bool SMPInstr::MDIsArgumentPass(size_t &ArgumentNumber) { bool OutArgPass = false; // Current model is writing outargs to stack. For other compiler targets in the @@ -5056,6 +5056,12 @@ bool SMPInstr::MDIsArgumentPass(void) { if (this->GetBlock()->GetFunc()->OutArgsRegionComputed()) { op_t DefOp = this->DEFMemOp; OutArgPass = this->GetBlock()->GetFunc()->IsInOutgoingArgsRegion(DefOp); + if (OutArgPass) { + op_t UnnormalizedDefOp = DefOp; + this->MDGetUnnormalizedOp(UnnormalizedDefOp); + size_t StandardByteSize = (MD_NORMAL_MACHINE_BITWIDTH / 8); + ArgumentNumber = (UnnormalizedDefOp.addr / StandardByteSize); + } } } return OutArgPass; diff --git a/SMPInstr.h b/SMPInstr.h index 14229d8c3c7b18edab7691b871c5faaf65a53e9f..c9d9aff236ef8a535ebf40e9207784ad0271e65b 100644 --- a/SMPInstr.h +++ b/SMPInstr.h @@ -543,7 +543,7 @@ public: void SyncAllRTs(bool UseFP, sval_t FPDelta); // calls SyncRTLDefUse() for all RTs in RTL op_t GetPushedOpnd(void); // Extract source operand from PUSH RTL int MDGetImmedUse(void); // Get immed value from USE list of inst - bool MDIsArgumentPass(void); // Does inst pass an outgoing argument? + bool MDIsArgumentPass(size_t &ArgumentNumber); // Does inst pass an outgoing argument? bool OperandTransfersValueToDef(op_t UseOp); // Does UseOp arithmetically affect the value of the NonFlagsDef for this inst? string GetTrimmedCalledFunctionName(void); // Get funcname from call inst and remove "." and "_" prefices void SetImmedTypes(bool UseFP); // type all immediate operands as NUMERIC, CODEPTR, GLOBALPTR