diff --git a/SMPInstr.cpp b/SMPInstr.cpp index 7b67204d9a26d5b4da13904665af04d21c7ca2bb..6085406d603d6ff56752b542035c75324bfa7538 100644 --- a/SMPInstr.cpp +++ b/SMPInstr.cpp @@ -1114,13 +1114,20 @@ void SMPInstr::MDFixupDefUseLists(void) { // If we can definitely identify which part of the addressing expression // used in MemOp is the POINTER type, and it is not a STACKPTR or GLOBALPTR // immediate, set the USE type for that register to POINTER and return true. +// If we can find definite NUMERIC addressing registers that are not already +// typed as NUMERIC, set their USE types to NUMERIC and return true. bool SMPInstr::MDFindPointerUse(op_t MemOp, bool UseFP) { bool changed = false; int BaseReg; int IndexReg; + op_t BaseOp; + op_t IndexOp; + SMPOperandType BaseType = UNKNOWN; + SMPOperandType IndexType = UNKNOWN; ushort ScaleFactor; ea_t offset; - set<DefOrUse, LessDefUse>::iterator UseIter; + set<DefOrUse, LessDefUse>::iterator BaseIter; + set<DefOrUse, LessDefUse>::iterator IndexIter; if (NN_lea == this->SMPcmd.itype) return false; // lea instruction really has no memory operands @@ -1128,28 +1135,74 @@ bool SMPInstr::MDFindPointerUse(op_t MemOp, bool UseFP) { return false; // SSA marker instruction MDExtractAddressFields(MemOp, BaseReg, IndexReg, ScaleFactor, offset); - if ((R_sp == BaseReg) || (R_sp == IndexReg)) - return false; // stack accesses will get STACKPTR type in SetImmedTypes() - if (UseFP && ((R_bp == BaseReg) || (R_bp == IndexReg))) - return false; - if (IsImmedGlobalAddress(offset)) - return false; // handled in SetImmedTypes() + if (R_none != IndexReg) { + IndexOp.type = o_reg; + IndexOp.reg = MDCanonicalizeSubReg(IndexReg); + IndexIter = this->FindUse(IndexOp); + assert(IndexIter != this->GetLastUse()); + IndexType = IndexIter->GetType(); + } + if (R_none != BaseReg) { + BaseOp.type = o_reg; + BaseOp.reg = MDCanonicalizeSubReg(BaseReg); + BaseIter = this->FindUse(BaseOp); + assert(BaseIter != this->GetLastUse()); + BaseType = BaseIter->GetType(); + } + if ((R_sp == BaseReg) || (UseFP && (R_bp == BaseReg))) { + if ((R_none != IndexReg) && (!IsNumeric(IndexType))) { + // We have an indexed access into the stack frame. + // Set IndexReg USE type to NUMERIC. + changed = true; + IndexIter = this->SetUseType(IndexOp, NUMERIC); + assert(IndexIter != this->GetLastUse()); + } + return changed; // stack accesses will get STACKPTR type in SetImmedTypes() + } + if ((R_sp == IndexReg) || (UseFP && (R_bp == IndexReg))) { + if ((R_none != BaseReg) && (!IsNumeric(BaseType))) { + // We have an indexed access into the stack frame. + // Set BaseReg USE type to NUMERIC. + // Note that BaseReg is really an IndexReg and vice versa. + changed = true; + BaseIter = this->SetUseType(BaseOp, NUMERIC); + assert(BaseIter != this->GetLastUse()); + msg("WARNING: BaseReg is index, IndexReg is base: %s\n", + this->GetDisasm()); + } + return changed; // stack accesses will get STACKPTR type in SetImmedTypes() + } + if (IsImmedGlobalAddress(offset)) { + if ((R_none != IndexReg) && (!IsNumeric(IndexType))) { + // We have an indexed access into a global. + // Set IndexReg USE type to NUMERIC. + changed = true; + IndexIter = this->SetUseType(IndexOp, NUMERIC); + assert(IndexIter != this->GetLastUse()); + } + if ((R_none != BaseReg) && (!IsNumeric(BaseType))) { + // We have an indexed access into a global. + // Set BaseReg USE type to NUMERIC. + // Note that BaseReg is really an index register. + changed = true; + BaseIter = this->SetUseType(BaseOp, NUMERIC); + assert(BaseIter != this->GetLastUse()); + msg("WARNING: BaseReg used as index: %s\n", this->GetDisasm()); + } + return changed; // handled in SetImmedTypes() + } - // At this point, we must have a base address in a register. + // At this point, we must have a base address in a register, not used + // to directly address the stack or a global. if ((0 < ScaleFactor) || (R_none == IndexReg)) { // IndexReg is scaled, meaning it is NUMERIC, so BaseReg must // be a POINTER; or IndexReg is not present, so BaseReg is the // only possible holder of an address. if (R_none != BaseReg) { - op_t BaseOp; - BaseOp.type = o_reg; - BaseOp.reg = MDCanonicalizeSubReg(BaseReg); - UseIter = this->FindUse(BaseOp); - assert(UseIter != this->GetLastUse()); - if (UNINIT == UseIter->GetType()) { + if (UNINIT == BaseIter->GetType()) { changed = true; - UseIter = this->SetUseType(BaseOp, POINTER); - assert(UseIter != this->GetLastUse()); + BaseIter = this->SetUseType(BaseOp, POINTER); + assert(BaseIter != this->GetLastUse()); } } } @@ -1157,48 +1210,54 @@ bool SMPInstr::MDFindPointerUse(op_t MemOp, bool UseFP) { // We have an unscaled IndexReg and no BaseReg and offset was // not a global offset, so IndexReg must be a POINTER. if (R_none != IndexReg) { - op_t IndexOp; - IndexOp.type = o_reg; - IndexOp.reg = MDCanonicalizeSubReg(IndexReg); - UseIter = this->FindUse(IndexOp); - assert(UseIter != this->GetLastUse()); - if (UNINIT == UseIter->GetType()) { + if (UNINIT == IndexType) { changed = true; - UseIter = this->SetUseType(IndexOp, POINTER); - assert(UseIter != this->GetLastUse()); + IndexIter = this->SetUseType(IndexOp, POINTER); + assert(IndexIter != this->GetLastUse()); } } } else { // We have BaseReg and an unscaled IndexReg. // The only hope for typing something like [ebx+edx] is for // one register to already be typed NUMERIC, in which case - // the other one must be a POINTER. - op_t IndexOp; - IndexOp.type = o_reg; - IndexOp.reg = MDCanonicalizeSubReg(IndexReg); - op_t BaseOp; - BaseOp.type = o_reg; - BaseOp.reg = MDCanonicalizeSubReg(BaseReg); - UseIter = this->FindUse(BaseOp); - assert(UseIter != this->GetLastUse()); - if (IsNumeric(UseIter->GetType())) { - UseIter = this->FindUse(IndexOp); - assert(UseIter != this->GetLastUse()); - if (UNINIT == UseIter->GetType()) { + // the other one must be a POINTER, or if one register is + // already POINTER, then the other one must be NUMERIC. + if (IsNumeric(BaseType)) { + if (UNINIT == IndexType) { // Set to POINTER or PROF_POINTER changed = true; - UseIter = this->SetUseType(IndexOp, POINTER); - assert(UseIter != this->GetLastUse()); + IndexIter = this->SetUseType(IndexOp, POINTER); + assert(IndexIter != this->GetLastUse()); + } + else if (IsNumeric(IndexType)) { + msg("ERROR: BaseReg and IndexReg both NUMERIC at %x: %s\n", + this->address, this->GetDisasm()); } } else { // BaseReg was not NUMERIC - if (UNINIT == UseIter->GetType()) { // BaseReg is UNINIT - UseIter = this->FindUse(IndexOp); - assert(UseIter != this->GetLastUse()); - if (IsNumeric(UseIter->GetType())) { + if (UNINIT == BaseType) { // BaseReg is UNINIT + if (IsNumeric(IndexType)) { + changed = true; + BaseIter = this->SetUseType(BaseOp, POINTER); + assert(BaseIter != this->GetLastUse()); + } + else if (IsDataPtr(IndexType)) { + // IndexReg is POINTER, so make BaseReg NUMERIC. changed = true; - UseIter = this->SetUseType(BaseOp, POINTER); - assert(UseIter != this->GetLastUse()); + BaseIter = this->SetUseType(BaseOp, NUMERIC); + assert(BaseIter != this->GetLastUse()); + } + } + else if (IsDataPtr(BaseType)) { + // BaseReg was a pointer type. IndexReg must be NUMERIC. + if (UNINIT == IndexType) { + changed = true; + IndexIter = this->SetUseType(IndexOp, NUMERIC); + assert(IndexIter != this->GetLastUse()); + } + else if (IsDataPtr(IndexType)) { + msg("ERROR: BaseReg and IndexReg both POINTER at %x: %s\n", + this->address, this->GetDisasm()); } } } @@ -1390,15 +1449,21 @@ bool SMPInstr::InferTypes(void) { } if ((DFAType >= JUMP) && (DFAType <= INDIR_CALL)) { // All USEs are either the flags (NUMERIC) or the target address (CODEPTR). - // The exception is the USE list for interrupt calls, which includes - // the caller-saved regs. + // The exceptions are the USE list for interrupt calls, which includes + // the caller-saved regs, and indirect calls through a memory + // operand, such as call [ebx+esi+20h], where the memory operand + // is a CODEPTR but the addressing registers are a BaseReg and + // IndexReg as in any other memory addressing. CurrUse = this->GetFirstUse(); while (CurrUse != this->GetLastUse()) { UseOp = CurrUse->GetOp(); if (UseOp.is_reg(X86_FLAGS_REG)) CurrUse = this->SetUseType(UseOp, NUMERIC); else if ((CurrUse->GetType() != CODEPTR) - && (!(this->MDIsInterruptCall() && (o_reg == UseOp.type)))) { + && (!(this->MDIsInterruptCall() && (o_reg == UseOp.type))) + && (!(this->HasSourceMemoryOperand() + && (INDIR_CALL == this->GetDataFlowType()) + && (o_reg == UseOp.type)))) { CurrUse = this->SetUseType(UseOp, CODEPTR); } ++CurrUse;