private StridedInterval MakeInterval_IAdd(Expression left, Constant right) { if (right == null) { return(StridedInterval.Empty); } var cc = this.ccNext; if (this.invertCondition) { cc = cc.Invert(); } switch (cc) { default: return(StridedInterval.Empty); case ConditionCode.UGE: long max = ~right.ToInt64(); if (max < 0) { return(StridedInterval.Empty); } return(StridedInterval.Create(1, 0, max)); } }
private StridedInterval MakeInterval_ISub(Expression left, Constant right) { if (right == null) { return(StridedInterval.Empty); } var cc = this.ccNext; if (this.invertCondition) { cc = cc.Invert(); } switch (cc) { case ConditionCode.ULE: return(StridedInterval.Create(1, 0, right.ToInt64())); case ConditionCode.ULT: return(StridedInterval.Create(1, 0, right.ToInt64() - 1)); case ConditionCode.UGE: return(StridedInterval.Create(1, right.ToInt64(), long.MaxValue)); case ConditionCode.UGT: return(StridedInterval.Create(1, right.ToInt64() + 1, long.MaxValue)); case ConditionCode.EQ: case ConditionCode.NE: case ConditionCode.None: return(StridedInterval.Empty); default: throw new NotImplementedException($"Unimplemented condition code {cc}."); } }
public override ValueSet And(Constant right) { long v = right.ToInt64(); return(new IntervalValueSet( this.DataType, StridedInterval.Create(1, 0, v))); }
public override ValueSet Shl(Constant cRight) { int v = (int)cRight.ToInt64(); return(new IntervalValueSet( this.DataType, StridedInterval.Create( SI.Stride << v, SI.Low << v, SI.High << v))); }
public override ValueSet IMul(Constant cRight) { long v = cRight.ToInt64(); return(new IntervalValueSet( this.DataType, StridedInterval.Create( SI.Stride * (int)v, SI.Low * v, SI.High * v))); }
public override ValueSet Sub(Constant right) { if (SI.Stride < 0) { return(new IntervalValueSet( this.DataType, StridedInterval.Empty)); } long v = right.ToInt64(); return(new IntervalValueSet( this.DataType, StridedInterval.Create( SI.Stride, SI.Low - v, SI.High - v))); }
private StridedInterval MakeInterval_ISub(Expression left, Constant right) { if (right == null) { return(StridedInterval.Empty); } var cc = this.ccNext; if (this.invertCondition) { cc = cc.Invert(); } switch (cc) { // NOTE: GE and GT should really be modeled with the semi-open range // [right,inf) and the open range (right,inf), respectively. See comment // for LE/LT. case ConditionCode.GE: return(StridedInterval.Create(1, right.ToInt64(), long.MaxValue)); case ConditionCode.GT: return(StridedInterval.Create(1, right.ToInt64() + 1, long.MaxValue)); // NOTE: LE and LT should really be modeled with the semi-open range // (inf,right] and the open range (inf,right). However, typically compilers // make the mistake and use LE/LT for boundary checking in indirect transfers. case ConditionCode.LE: return(StridedInterval.Create(1, 0, right.ToInt64())); case ConditionCode.LT: return(StridedInterval.Create(1, 0, right.ToInt64() - 1)); case ConditionCode.ULE: return(StridedInterval.Create(1, 0, right.ToInt64())); case ConditionCode.ULT: return(StridedInterval.Create(1, 0, right.ToInt64() - 1)); case ConditionCode.UGE: return(StridedInterval.Create(1, right.ToInt64(), long.MaxValue)); case ConditionCode.UGT: return(StridedInterval.Create(1, right.ToInt64() + 1, long.MaxValue)); case ConditionCode.EQ: case ConditionCode.NE: case ConditionCode.None: return(StridedInterval.Empty); default: throw new NotImplementedException($"Unimplemented condition code {cc}."); } }
private StridedInterval MakeInterval_And(Expression left, Constant right) { if (right == null) { return(StridedInterval.Empty); } long n = right.ToInt64(); if (Bits.IsEvenPowerOfTwo(n + 1)) { // n is a mask (0000...00111..111) return(StridedInterval.Create(1, 0, n)); } else { return(StridedInterval.Empty); } }
/// <summary> /// Returns a valueset whose values are the truncation of this valueset's /// values. /// </summary> /// <param name="dt"></param> /// <returns></returns> public override ValueSet Truncate(DataType dt) { if (SI.Stride < 0) { return(this); } var mask = (1 << dt.BitSize) - 1; StridedInterval siNew; if (SI.Low == SI.High) { siNew = StridedInterval.Constant( Constant.Create(dt, SI.Low & mask)); } else { siNew = StridedInterval.Create( SI.Stride, 0, Math.Min(mask, SI.High)); } return(new IntervalValueSet(dt, siNew)); }
public TableExtent DiscoverTableExtent(Address addrSwitch, RtlTransfer xfer, DecompilerEventListener listener) { if (!Start(rtlBlock, host.BlockInstructionCount(rtlBlock) - 1, xfer.Target)) { // No registers were found, so we can't trace back. return(null); } while (Step()) { ; } var jumpExpr = this.JumpTableFormat; var interval = this.JumpTableIndexInterval; var index = this.JumpTableIndexToUse; var ctx = new Dictionary <Expression, ValueSet>(new ExpressionValueComparer()); if (index == null) { // Weren't able to find the index register, // try finding it by blind pattern matching. index = this.FindIndexWithPatternMatch(this.JumpTableFormat); if (index == null) { // This is likely an indirect call like a C++ // vtable dispatch. Since these are common, we don't // spam the user with warnings. return(null); } // We have a jump table, and we've guessed the index expression. // At this point we've given up on knowing the exact size // of the table, but we do know that it must be at least // more than one entry. The safest assumption is that it // has two entries. listener.Warn( listener.CreateAddressNavigator(host.Program, addrSwitch), "Unable to determine size of call or jump table; there may be more than 2 entries."); ctx.Add(index, new IntervalValueSet(index.DataType, StridedInterval.Create(1, 0, 1))); } else if (interval.IsEmpty) { return(null); } else if (interval.High == Int64.MaxValue) { // We have no reasonable upper bound. We make the arbitrary // assumption that the jump table has 2 items; it wouldn't // make sense to be indexing otherwise. listener.Warn( listener.CreateAddressNavigator(host.Program, addrSwitch), "Unable to determine the upper bound of an indirect call or jump; there may be more than 2 entries."); var vs = new IntervalValueSet( this.JumpTableIndex.DataType, StridedInterval.Create(1, interval.Low, interval.Low + 1)); ctx.Add(this.JumpTableIndexToUse, vs); } else { ctx.Add(this.JumpTableIndex, new IntervalValueSet(this.JumpTableIndex.DataType, interval)); } var vse = new ValueSetEvaluator(host.Architecture, host.SegmentMap, ctx, this.processorState); var(values, accesses) = vse.Evaluate(jumpExpr); var vector = values.Values .TakeWhile(c => c != Constant.Invalid) .Take(2000) // Arbitrary limit .Select(ForceToAddress) .TakeWhile(a => a != null) .ToList(); if (vector.Count == 0) { return(null); } return(new TableExtent { Targets = vector, Accesses = accesses, Index = index, }); }
private ValueSet IVS(int stride, long low, long high) { return(new IntervalValueSet(PrimitiveType.Word32, StridedInterval.Create(stride, low, high))); }