Example #1
0
        public Backwalker(IBackWalkHost host, RtlTransfer xfer, ExpressionSimplifier eval)
        {
            if (xfer is RtlGoto) //$DEBUG
            {
                xfer.ToString();
            }
            this.host = host;
            this.eval = eval;
            var target = xfer.Target;
            var seq    = xfer.Target as MkSequence;

            if (seq != null)
            {
                target = seq.Tail;
            }
            var mem = target as MemoryAccess;

            if (mem == null)
            {
                Index = RegisterOf(target as Identifier);
            }
            else
            {
                Index = DetermineIndexRegister(mem);
            }
            Operations = new List <BackwalkOperation>();
        }
Example #2
0
        private void RunTest(IntelArchitecture arch, RtlTransfer rtlTransfer, string outputFile)
        {
            using (var fut = new FileUnitTester(outputFile))
            {
                m.Procedure.Write(false, fut.TextWriter);
                fut.TextWriter.Flush();

                var ibw     = new Backwalker <Block, Instruction>(host, rtlTransfer, expSimp);
                var bwoList = ibw.BackWalk(m.CurrentBlock);
                Assert.IsNotNull(bwoList);
                foreach (BackwalkOperation bwo in bwoList)
                {
                    fut.TextWriter.WriteLine(bwo);
                }
                fut.TextWriter.WriteLine("Index register: {0}", ibw.Index);
                fut.AssertFilesEqual();
            }
        }
Example #3
0
        public Backwalker(IBackWalkHost <TBlock, TInstr> host, RtlTransfer xfer, ExpressionSimplifier eval)
        {
            this.host = host;
            this.eval = eval;
            var target = xfer.Target;

            if (xfer.Target is MkSequence seq && seq.Expressions.Length == 2)
            {
                target = seq.Expressions[1];
            }
            if (target is MemoryAccess mem)
            {
                Index = DetermineIndexRegister(mem);
            }
            else
            {
                Index = RegisterOf(target as Identifier);
            }
            Operations = new List <BackwalkOperation>();
            JumpSize   = target.DataType.Size;
        }
Example #4
0
		public Backwalker(IBackWalkHost host, RtlTransfer xfer, ExpressionSimplifier eval)
		{
            if (xfer is RtlGoto) //$DEBUG
                xfer.ToString();
            this.host = host;
            this.eval = eval;
            var target = xfer.Target;
            var seq = xfer.Target as MkSequence;
            if (seq != null)
            {
                target = seq.Tail;
            }
            var mem = target as MemoryAccess;
            if (mem == null)
            {
                Index = RegisterOf(target as Identifier);
            }
            else
            {
                Index = DetermineIndexRegister(mem);
            }
            Operations = new List<BackwalkOperation>();
		}
Example #5
0
        public Backwalker(IBackWalkHost <TBlock, TInstr> host, RtlTransfer xfer, ExpressionSimplifier eval)
        {
            this.host = host;
            this.eval = eval;
            var target = xfer.Target;
            var seq    = xfer.Target as MkSequence;

            if (seq != null)
            {
                target = seq.Tail;
            }
            var mem = target as MemoryAccess;

            if (mem == null)
            {
                Index = RegisterOf(target as Identifier);
            }
            else
            {
                Index = DetermineIndexRegister(mem);
            }
            Operations = new List <BackwalkOperation>();
            JumpSize   = target.DataType.Size;
        }
Example #6
0
 private void ScanVectorTargets(RtlTransfer xfer, List <Address> vector)
 {
     foreach (Address addr in vector)
     {
         var st = state.Clone();
         if (xfer is RtlCall)
         {
             var pbase   = scanner.ScanProcedure(addr, null, st);
             var pcallee = pbase as Procedure;
             if (pcallee != null)
             {
                 program.CallGraph.AddEdge(blockCur.Statements.Last, pcallee);
             }
         }
         else
         {
             if (!program.SegmentMap.IsValidAddress(addr))
             {
                 break;
             }
             BlockFromAddress(ric.Address, addr, blockCur.Procedure, state);
         }
     }
 }
Example #7
0
        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,
            });
        }
Example #8
0
        public bool ProcessIndirectControlTransfer(Address addrSwitch, RtlTransfer xfer)
        {
            List <Address>      vector;
            ImageMapVectorTable imgVector;
            Expression          swExp;
            UserIndirectJump    indJump;

            var listener = scanner.Services.RequireService <DecompilerEventListener>();

            if (program.User.IndirectJumps.TryGetValue(addrSwitch, out indJump))
            {
                vector    = indJump.Table.Addresses;
                swExp     = this.frame.EnsureIdentifier(indJump.IndexRegister);
                imgVector = indJump.Table;
            }
            else
            {
                var bw = new Backwalker <Block, Instruction>(new BackwalkerHost(this), xfer, eval);
                if (!bw.CanBackwalk())
                {
                    return(false);
                }
                var bwops = bw.BackWalk(blockCur);
                if (bwops == null || bwops.Count == 0)
                {
                    return(false);     //$REVIEW: warn?
                }
                Identifier idIndex = bw.Index != null
                    ? blockCur.Procedure.Frame.EnsureRegister(bw.Index)
                    : null;

                VectorBuilder builder = new VectorBuilder(scanner.Services, program, new DirectedGraphImpl <object>());
                if (bw.VectorAddress == null)
                {
                    return(false);
                }

                vector = builder.BuildAux(bw, addrSwitch, state);
                if (vector.Count == 0)
                {
                    var rdr = program.CreateImageReader(bw.VectorAddress);
                    if (!rdr.IsValid)
                    {
                        return(false);
                    }
                    // Can't determine the size of the table, but surely it has one entry?
                    var    addrEntry = arch.ReadCodeAddress(bw.Stride, rdr, state);
                    string msg;
                    if (this.program.SegmentMap.IsValidAddress(addrEntry))
                    {
                        vector.Add(addrEntry);
                        msg = "Can't determine size of jump vector; probing only one entry.";
                    }
                    else
                    {
                        // Nope, not even that.
                        msg = "No valid entries could be found in jump vector.";
                    }
                    var nav = listener.CreateJumpTableNavigator(program, addrSwitch, bw.VectorAddress, bw.Stride);
                    listener.Warn(nav, msg);
                    if (vector.Count == 0)
                    {
                        return(false);
                    }
                }
                imgVector = new ImageMapVectorTable(
                    bw.VectorAddress,
                    vector.ToArray(),
                    builder.TableByteSize);
                swExp = idIndex;
                if (idIndex == null || idIndex.Name == "None")
                {
                    swExp = bw.IndexExpression;
                }
            }
            ScanVectorTargets(xfer, vector);

            if (xfer is RtlGoto)
            {
                var blockSource = scanner.FindContainingBlock(ric.Address);
                blockCur = blockSource;
                foreach (Address addr in vector)
                {
                    var dest = scanner.FindContainingBlock(addr);
                    Debug.Assert(dest != null, "The block at address " + addr + "should have been enqueued.");
                    blockSource.Procedure.ControlGraph.AddEdge(blockSource, dest);
                }

                if (swExp == null)
                {
                    scanner.Warn(addrSwitch, "Unable to determine index variable for indirect jump.");
                    Emit(new ReturnInstruction());
                    blockSource.Procedure.ControlGraph.AddEdge(
                        blockSource,
                        blockSource.Procedure.ExitBlock);
                }
                else
                {
                    Emit(new SwitchInstruction(swExp, blockCur.Procedure.ControlGraph.Successors(blockCur).ToArray()));
                }
            }
            if (imgVector.Size > 0)
            {
                program.ImageMap.AddItemWithSize(imgVector.Address, imgVector);
            }
            else
            {
                program.ImageMap.AddItem(imgVector.Address, imgVector);
            }
            return(true);
        }
Example #9
0
        public bool ProcessIndirectControlTransfer(Address addrSwitch, RtlTransfer xfer)
        {
            var bw = new Backwalker(new BackwalkerHost(this), xfer, eval);

            if (!bw.CanBackwalk())
            {
                return(false);
            }
            var bwops = bw.BackWalk(blockCur);

            if (bwops == null || bwops.Count == 0)
            {
                return(false);     //$REVIEW: warn?
            }
            var idIndex = blockCur.Procedure.Frame.EnsureRegister(bw.Index);

            VectorBuilder builder = new VectorBuilder(scanner, program, new DirectedGraphImpl <object>());

            if (bw.VectorAddress == null)
            {
                return(false);
            }

            List <Address> vector = builder.BuildAux(bw, addrSwitch, state);

            if (vector.Count == 0)
            {
                var addrNext = bw.VectorAddress + bw.Stride;
                var rdr      = scanner.CreateReader(bw.VectorAddress);
                if (!rdr.IsValid)
                {
                    return(false);
                }
                // Can't determine the size of the table, but surely it has one entry?
                var addrEntry = arch.ReadCodeAddress(bw.Stride, rdr, state);
                if (this.program.Image.IsValidAddress(addrEntry))
                {
                    vector.Add(addrEntry);
                    scanner.Warn(addrSwitch, "Can't determine size of jump vector; probing only one entry.");
                }
                else
                {
                    // Nope, not even that.
                    scanner.Warn(addrSwitch, "No valid entries could be found in jump vector.");
                }
            }

            //$TODO: mark the vector
            ScanVectorTargets(xfer, vector);

            if (xfer is RtlGoto)
            {
                var blockSource = scanner.FindContainingBlock(ric.Address);
                blockCur = blockSource;
                foreach (Address addr in vector)
                {
                    var dest = scanner.FindContainingBlock(addr);
                    Debug.Assert(dest != null, "The block at address " + addr + "should have been enqueued.");
                    blockSource.Procedure.ControlGraph.AddEdge(blockSource, dest);
                }
                Expression swExp = idIndex;
                if (idIndex.Name == "None")
                {
                    swExp = bw.IndexExpression;
                }
                if (swExp == null)
                {
                    throw new NotImplementedException();
                }
                Emit(new SwitchInstruction(swExp, blockCur.Procedure.ControlGraph.Successors(blockCur).ToArray()));
            }
            //vectorUses[wi.addrFrom] = new VectorUse(wi.Address, builder.IndexRegister);
            program.ImageMap.AddItem(bw.VectorAddress,
                                     new ImageMapVectorTable(xfer is RtlCall, vector.ToArray(), builder.TableByteSize));
            return(true);
        }
Example #10
0
        private void RunTest(IntelArchitecture arch, RtlTransfer rtlTransfer, string outputFile)
        {
            using (var fut = new FileUnitTester(outputFile))
            {
                m.Procedure.Write(false, fut.TextWriter);
                fut.TextWriter.Flush();

                var ibw = new Backwalker(host, rtlTransfer, expSimp);
                var bwoList = ibw.BackWalk(m.CurrentBlock);
                Assert.IsNotNull(bwoList);
                foreach (BackwalkOperation bwo in bwoList)
                {
                    fut.TextWriter.WriteLine(bwo);
                }
                fut.TextWriter.WriteLine("Index register: {0}", ibw.Index);
                fut.AssertFilesEqual();
            }
        }