diff --git a/SMPBasicBlock.cpp b/SMPBasicBlock.cpp index 5ff293850ec90cf5aebe093b32265e8c627e638e..34754fb069ed97b3cd7811092482c3375b54c213 100644 --- a/SMPBasicBlock.cpp +++ b/SMPBasicBlock.cpp @@ -3681,9 +3681,30 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd op_t UseOp; list<SMPInstr *>::iterator InstIter; set<DefOrUse, LessDefUse>::iterator UseIter, DefIter; + bool RegDef = (o_reg == DefOp.type); + struct FineGrainedInfo DefFGInfo; + bool LocalDefName = this->IsLocalName(DefOp); + if (RegDef) { + unsigned int DefHashValue = HashGlobalNameAndSSA(DefOp, DefSSANum); + if (LocalDefName) { + // Local name, find in basic block maps. + DefFGInfo = this->GetDefFGInfo(DefHashValue); + } + else { // Global name, find in global maps. + DefFGInfo = this->GetFunc()->GetDefFGInfo(DefHashValue); + } + } + else if (MDIsStackAccessOpnd(DefOp, this->GetFunc()->UsesFramePointer())) { + bool success = this->GetFunc()->MDGetFGStackLocInfo(DefAddr, DefOp, DefFGInfo); + assert(success); + } + else { + return false; // we can only handle register and stack DefOp types. + } + bool DefIsUnsigned = (FG_MASK_UNSIGNED == (DefFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS)); // First, we find the USEs of the DEF. - if (o_reg == DefOp.type) { + if (RegDef) { for (InstIter = this->GetFirstInstr(); InstIter != this->GetLastInstr(); ++InstIter) { SMPInstr *CurrInst = (*InstIter); size_t InstAddr = CurrInst->GetAddr(); @@ -3741,7 +3762,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd if (!benign) { SMPInstr *DefInst = this->GetFunc()->GetInstFromAddr(DefAddr); int UseSSANum; - if (UnderflowOpcode && (DefOp.type == o_reg)) { + if (UnderflowOpcode && RegDef) { UseIter = DefInst->FindUse(DefOp); // DEF is also USE in subtraction UseSSANum = UseIter->GetSSANum(); // Prepare for possible recursive traversals through the function blocks. @@ -3793,23 +3814,12 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd // value in many cases (but not for signed values). else if (!benign) { // Check for UNSIGNED. - unsigned int DefHashValue = HashGlobalNameAndSSA(DefOp, DefSSANum); - struct FineGrainedInfo DefFGInfo; - bool LocalName = this->IsLocalName(DefOp); - if (LocalName) { - // Local name, find in basic block maps. - DefFGInfo = this->GetDefFGInfo(DefHashValue); - } - else { // Global name, find in global maps. - DefFGInfo = this->GetFunc()->GetDefFGInfo(DefHashValue); - } - bool DefIsUnsigned = (FG_MASK_UNSIGNED == (DefFGInfo.SignMiscInfo & FG_MASK_SIGNEDNESS_BITS)); if (DefIsUnsigned) { // Does the subtraction use a value from a shift? UseIter = DefInst->FindUse(DefOp); if (UseIter != DefInst->GetLastUse()) { int UseSSANum = UseIter->GetSSANum(); - ea_t UseDefAddr = this->GetDefAddrFromUseAddr(DefOp, DefAddr, UseSSANum, LocalName); + ea_t UseDefAddr = this->GetDefAddrFromUseAddr(DefOp, DefAddr, UseSSANum, LocalDefName); if (UseDefAddr >= this->GetFirstAddr()) { // Limit to the simple case in which UseDefAddr is in our block, not Phi function or function entry marker inst. SMPInstr *UseDefInst = this->GetFunc()->GetInstFromAddr(UseDefAddr); @@ -3825,7 +3835,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd // // We have backtracked from the subtraction to the USE of EDI in the shift. Now we need to // find the move that is the DEF of this USE of EDI, i.e. we need to find EAX. - UseDefAddr = this->GetDefAddrFromUseAddr(DefOp, UseDefAddr, UseSSANum, LocalName); + UseDefAddr = this->GetDefAddrFromUseAddr(DefOp, UseDefAddr, UseSSANum, LocalDefName); if (UseDefAddr >= this->GetFirstAddr()) { SMPInstr *MoveInst = this->GetFunc()->GetInstFromAddr(UseDefAddr); if (MoveInst->MDIsMoveInstr()) { @@ -3851,7 +3861,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd } } } - } // end if (UnderflowOpcode && o_reg) + } // end if (UnderflowOpcode && RegDef) // Fourth case: lea reg, [basereg+indexreg*scalefactor+offset], where // basereg and indexreg both got their values from condition codes, so the // computational values are too small for non-benign overflow or underflow. @@ -3896,12 +3906,11 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd // Bitwise NOT is likely to produce an overflow/underflow for a subsequent add/subtract. SMPInstr *DefInst = this->GetFunc()->GetInstFromAddr(DefAddr); int UseSSANum; - if (DefOp.type == o_reg) { + if (RegDef) { UseIter = DefInst->FindUse(DefOp); // DEF is also USE in addition or subtraction ... if (UseIter != DefInst->GetLastUse()) { // ... but not always on lea opcode UseSSANum = UseIter->GetSSANum(); - bool LocalName = this->IsLocalName(DefOp); - ea_t UseDefAddr = this->GetDefAddrFromUseAddr(DefOp, DefAddr, UseSSANum, LocalName); + ea_t UseDefAddr = this->GetDefAddrFromUseAddr(DefOp, DefAddr, UseSSANum, LocalDefName); if (UseDefAddr >= this->GetFunc()->GetFirstFuncAddr()) { // inst DEF, not Phi DEF DefInst = this->GetFunc()->GetInstFromAddr(UseDefAddr); if (DefInst->MDIsBitwiseNotOpcode()) { @@ -3911,7 +3920,7 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd } } } - else if (MDIsStackAccessOpnd(DefOp, this->GetFunc()->UsesFramePointer())) { + else { // We need the canonicalized stack operand as found in DEFs and USEs. UseOp = DefInst->MDGetMemUseOp(); // DEF is also USE in addition or subtraction ... assert(o_void != UseOp.type); @@ -3980,8 +3989,47 @@ bool SMPBasicBlock::IsBenignOverflowDEF(op_t DefOp, int DefSSANum, size_t DefAdd } } + if (!benign && !UnderflowOpcode && DefIsUnsigned) { + // Search for a sequence of ADD, OR, and AND operations that + // use constant operands that add up to an UNSIGNED OVERFLOW. + InstIter = this->GetInstIterFromAddr(DefAddr); + assert(InstIter != this->GetLastInstr()); + uval_t ImmedValue = (uval_t) (*InstIter)->MDGetImmedUse(); + // NOTE: If ImmedValue is very large, we catch this elsewhere as IDIOM 11. + if (ImmedValue != 0) { + list<SMPInstr *>::reverse_iterator RevInstIter(InstIter); + uval_t ConstLimit = 0xffffffff - ImmedValue; + while (RevInstIter != this->Instrs.rend()) { + SMPInstr *SearchInst = (*RevInstIter); + DefIter = SearchInst->FindDef(DefOp); + if (DefIter != SearchInst->GetLastDef()) { // found previous DEF + if (SearchInst->MDIsBitwiseAndOpcode() || SearchInst->MDIsBitwiseOrOpcode() || SearchInst->MDIsAddition()) { + ImmedValue = (uval_t) SearchInst->MDGetImmedUse(); + if (0 < ImmedValue) { + if (ImmedValue >= ConstLimit) { + benign = true; + IdiomCode = 22; + break; // no need to search further + } + else { + ConstLimit -= ImmedValue; // set new limiting value + } + } + else { + break; // not the pure chain we are searching for + } + } + else { + break; // not the pure chain we are searching for + } + } + ++RevInstIter; + } + } + } + return benign; -} // end of SMPBasicBlock::BenignOverflowDEF() +} // end of SMPBasicBlock::IsBenignOverflowDEF() // We don't care if we truncate computing some DEFs, because of how they are used. @@ -4134,7 +4182,7 @@ bool SMPBasicBlock::IsBenignTruncationDEF(op_t DefOp, int DefSSANum, size_t DefA unsigned short SignMask; if (CopyInst->MDIsSignedLoad(SignMask)) { // Truncation use came from a zero-extended or sign-extended load. So, - // we know that the later truncation store is probalby a benign truncation. + // we know that the later truncation store is probably a benign truncation. benign = true; } else { // regular move. Is it reg to reg? diff --git a/SMPInstr.cpp b/SMPInstr.cpp index 7b0031cd305e3554f4f12718349ec4ce5ec85c07..d4dc20fdbe76ffca5972dfa61bfbe853028033a3 100644 --- a/SMPInstr.cpp +++ b/SMPInstr.cpp @@ -5268,7 +5268,6 @@ bool SMPInstr::InferOperatorType(SMPRegTransfer *CurrRT) { case SMP_U_DIVIDE: case SMP_S_DIVIDE: case SMP_U_REMAINDER: - case SMP_BITWISE_NOT: // unary operator case SMP_BITWISE_XOR: case SMP_BITWISE_AND_NOT: case SMP_S_COMPARE: // signed compare (subtraction-based) @@ -5361,6 +5360,7 @@ bool SMPInstr::InferOperatorType(SMPRegTransfer *CurrRT) { } break; + case SMP_BITWISE_NOT: // unary operator case SMP_NEGATE: // unary negation UseOp = CurrRT->GetLeftOperand(); assert(o_void != UseOp.type); @@ -5385,11 +5385,14 @@ bool SMPInstr::InferOperatorType(SMPRegTransfer *CurrRT) { // in our analysis and the operator was set to NUMERIC. CurrRT->SetOperatorType(PTROFFSET, this); updated = true; + if (CurrOp == SMP_BITWISE_NOT) + SMP_msg("INFO: NOT of PTROFFSET at %x %s\n", this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr())); } else if (IsDataPtr(LeftType)) { // Override any prior operator type, in case POINTER was inferred late // in our analysis and the operator was set to NUMERIC. CurrRT->SetOperatorType(NEGATEDPTR, this); + SMP_msg("INFO: Pointer negated at %x %s\n", this->GetAddr(), DisAsmText.GetDisAsm(this->GetAddr())); updated = true; } else if (OperType == UNINIT) {