Beispiel #1
0
        public SlicerResult VisitGoto(RtlGoto go)
        {
            var sr = go.Target.Accept(this, BackwardSlicerContext.Jump(RangeOf(go.Target)));

            if (JumpTableFormat == null)
            {
                JumpTableFormat = go.Target;
            }
            return(sr);
        }
Beispiel #2
0
        public SlicerResult VisitBranch(RtlBranch branch)
        {
            var se         = branch.Condition.Accept(this, BackwardSlicerContext.Jump(new BitRange(0, 0)));
            var addrTarget = branch.Target as Address;

            if (addrTarget == null)
            {
                throw new NotImplementedException();    //#REVIEW: do we ever see this?
            }
            if (this.addrSucc != addrTarget)
            {
                this.invertCondition = true;
            }
            return(se);
        }
Beispiel #3
0
        /// <summary>
        /// Start the analysis with the expression in the indirect jump.
        /// Detect any live expressions, and place them in the `Live`
        /// collection.
        /// </summary>
        /// <param name="indirectJump"></param>
        /// <returns></returns>
        public bool Start(Expression indirectJump)
        {
            var sr = indirectJump.Accept(this, BackwardSlicerContext.Jump(RangeOf(indirectJump)));

            if (JumpTableFormat == null)
            {
                JumpTableFormat = indirectJump;
            }

            this.Live = sr.LiveExprs;
            if (!sr.LiveExprs.Keys.OfType <Identifier>().Any())
            {
                // Couldn't find any indirect registers, so there is no work to do.
                DebugEx.Warn(BackwardSlicer.trace, "Bwslc: No indirect registers?");
                return(false);
            }
            DebugEx.Verbose(BackwardSlicer.trace, "  live: {0}", DumpLive(this.Live));
            return(true);
        }
Beispiel #4
0
        /// <summary>
        /// Start the analysis with the expression in the indirect jump.
        /// Detect any live expressions, and place them in the `Live`
        /// collection.
        /// </summary>
        /// <param name="indirectJump"></param>
        /// <returns></returns>
        public bool Start(Expression indirectJump)
        {
            var sr = indirectJump.Accept(this, BackwardSlicerContext.Jump(RangeOf(indirectJump)));

            if (JumpTableFormat == null)
            {
                JumpTableFormat = indirectJump;
            }

            this.Live = sr.LiveExprs;
            if (sr.LiveExprs.Count == 0)
            {
                // Couldn't find any indirect registers, so there is no work to do.
                DebugEx.PrintIf(BackwardSlicer.trace.TraceWarning, "  No indirect registers?");
                return(false);
            }
            DebugEx.PrintIf(BackwardSlicer.trace.TraceVerbose, "  live: {0}", DumpLive(this.Live));
            return(true);
        }
Beispiel #5
0
        public SlicerResult VisitBinaryExpression(BinaryExpression binExp, BackwardSlicerContext ctx)
        {
            if (binExp.Operator == Operator.Eq || binExp.Operator == Operator.Ne)
            {
                // Equality comparisons cannot contribute to determining the size
                // of the jump table; stop processing this instruction.
                return(null);
            }

            if ((binExp.Operator == Operator.Xor || binExp.Operator == Operator.ISub) &&
                this.slicer.AreEqual(binExp.Left, binExp.Right))
            {
                // XOR r,r (or SUB r,r) clears a register. Is it part of a live register?
                var regDst = this.assignLhs as Identifier;
                var regHi  = binExp.Left as Identifier;
                if (regHi != null && regDst != null &&
                    DomainOf(regDst) == regHi.Storage.Domain &&
                    regDst.Storage.OffsetOf(regHi.Storage) == 8)
                {
                    // The 8086 didn't have a MOVZX instruction, so clearing the high byte of a
                    // register BX was done by issuing XOR BH,BH
                    var seXor = new SlicerResult
                    {
                        SrcExpr   = new Cast(regDst.DataType, new Cast(PrimitiveType.Byte, this.assignLhs)),
                        LiveExprs = new Dictionary <Expression, BackwardSlicerContext>
                        {
                            {
                                this.assignLhs,
                                BackwardSlicerContext.Jump(new BitRange(0, 8))
                            }
                        }
                    };
                    return(seXor);
                }
            }

            var seLeft  = binExp.Left.Accept(this, ctx);
            var seRight = binExp.Right.Accept(this, ctx);

            if (seLeft == null && seRight == null)
            {
                return(null);
            }
            if (binExp.Operator == Operator.ISub && this.Live != null && (ctx.Type & ContextType.Condition) != 0)
            {
                var domLeft = DomainOf(seLeft.SrcExpr);

                if (Live.Count > 0)
                {
                    foreach (var live in Live)
                    {
                        if (live.Value.Type != ContextType.Jumptable)
                        {
                            continue;
                        }
                        if ((domLeft != StorageDomain.Memory && DomainOf(live.Key) == domLeft)
                            ||
                            (this.slicer.AreEqual(live.Key, binExp.Left)))
                        {
                            //$TODO: if jmptableindex and jmptableindextouse not same, inject a statement.
                            this.JumpTableIndex         = live.Key;
                            this.JumpTableIndexToUse    = binExp.Left;
                            this.JumpTableIndexInterval = MakeInterval_ISub(live.Key, binExp.Right as Constant);
                            DebugEx.Verbose(BackwardSlicer.trace, "  Found range of {0}: {1}", live, JumpTableIndexInterval);
                            return(new SlicerResult
                            {
                                SrcExpr = binExp,
                                Stop = true
                            });
                        }
                    }
                }
                else
                {
                    // We have no live variables, which means this subtraction instruction
                    // is both computing the jumptable index and also performing the
                    // comparison.
                    this.JumpTableIndex         = assignLhs;
                    this.JumpTableIndexToUse    = assignLhs;
                    this.JumpTableIndexInterval = MakeInterval_ISub(assignLhs, binExp.Right as Constant);
                    DebugEx.Verbose(BackwardSlicer.trace, "  Found range of {0}: {1}", assignLhs, JumpTableIndexInterval);
                    return(new SlicerResult
                    {
                        SrcExpr = null,     // the jump table expression already has the correct shape.
                        Stop = true
                    });
                }
            }
            else if (binExp.Operator == Operator.And)
            {
                this.JumpTableIndex         = binExp.Left;
                this.JumpTableIndexToUse    = binExp.Left;
                this.JumpTableIndexInterval = MakeInterval_And(binExp.Left, binExp.Right as Constant);
                return(new SlicerResult
                {
                    SrcExpr = binExp,
                    Stop = true,
                });
            }
            IEnumerable <KeyValuePair <Expression, BackwardSlicerContext> > liveExpr = seLeft.LiveExprs;

            if (seRight != null)
            {
                liveExpr = liveExpr.Concat(seRight.LiveExprs);
            }
            var se = new SlicerResult
            {
                LiveExprs = liveExpr
                            .GroupBy(e => e.Key)
                            .ToDictionary(k => k.Key, v => v.Max(vv => vv.Value)),
                SrcExpr = binExp,
            };

            return(se);
        }
Beispiel #6
0
        public SlicerResult VisitBinaryExpression(BinaryExpression binExp, BackwardSlicerContext ctx)
        {
            if (binExp.Operator == Operator.Eq || binExp.Operator == Operator.Ne)
            {
                // Equality comparisons cannot contribute to determining the size
                // of the jump table; stop processing this instruction.
                return(null);
            }

            if ((binExp.Operator == Operator.Xor || binExp.Operator == Operator.ISub) &&
                this.slicer.AreEqual(binExp.Left, binExp.Right))
            {
                // XOR r,r (or SUB r,r) clears a register. Is it part of a live register?
                var regDst = this.assignLhs as Identifier;
                var regHi  = binExp.Left as Identifier;
                if (regHi != null && regDst != null &&
                    DomainOf(regDst) == regHi.Storage.Domain &&
                    regDst.Storage.OffsetOf(regHi.Storage) == 8)
                {
                    // The 8086 didn't have a MOVZX instruction, so clearing the high byte of a
                    // register BX was done by issuing XOR BH,BH
                    var seXor = new SlicerResult
                    {
                        SrcExpr   = new Cast(regDst.DataType, new Cast(PrimitiveType.Byte, this.assignLhs)),
                        LiveExprs = new Dictionary <Expression, BackwardSlicerContext>
                        {
                            {
                                this.assignLhs,
                                BackwardSlicerContext.Jump(new BitRange(0, 8))
                            }
                        }
                    };
                    return(seXor);
                }
            }

            var seLeft  = binExp.Left.Accept(this, ctx);
            var seRight = binExp.Right.Accept(this, ctx);

            if (seLeft == null && seRight == null)
            {
                return(null);
            }
            if (binExp.Operator == Operator.ISub && Live != null)
            {
                var domLeft = DomainOf(seLeft.SrcExpr);
                foreach (var live in Live.Keys)
                {
                    if (DomainOf(live) == domLeft)
                    {
                        if (slicer.AreEqual(this.assignLhs, this.JumpTableIndex))
                        {
                            //$TODO: if jmptableindex and jmptableindextouse not same, inject a statement.
                            this.JumpTableIndex         = live;
                            this.JumpTableIndexToUse    = binExp.Left;
                            this.JumpTableIndexInterval = MakeInterval_ISub(live, binExp.Right as Constant);
                            DebugEx.PrintIf(BackwardSlicer.trace.TraceVerbose, "  Found range of {0}: {1}", live, JumpTableIndexInterval);
                            return(new SlicerResult
                            {
                                SrcExpr = binExp,
                                Stop = true
                            });
                        }
                    }
                    if (this.slicer.AreEqual(live, binExp.Left))
                    {
                        this.JumpTableIndex         = live;
                        this.JumpTableIndexToUse    = binExp.Left;
                        this.JumpTableIndexInterval = MakeInterval_ISub(live, binExp.Right as Constant);
                        return(new SlicerResult
                        {
                            SrcExpr = binExp,
                            Stop = true,
                        });
                    }
                }
            }
            else if (binExp.Operator == Operator.And)
            {
                this.JumpTableIndex         = binExp.Left;
                this.JumpTableIndexToUse    = binExp.Left;
                this.JumpTableIndexInterval = MakeInterval_And(binExp.Left, binExp.Right as Constant);
                return(new SlicerResult
                {
                    SrcExpr = binExp,
                    Stop = true,
                });
            }
            var se = new SlicerResult
            {
                LiveExprs = seLeft.LiveExprs.Concat(seRight.LiveExprs)
                            .GroupBy(e => e.Key)
                            .ToDictionary(k => k.Key, v => v.Max(vv => vv.Value)),
                SrcExpr = binExp,
            };

            return(se);
        }