public void Dfa2_UserDefinedStackArgs()
        {
            var arch = new X86ArchitectureFlat32(new ServiceContainer(), "x86-protected-32", new Dictionary <string, object>());
            var pb   = new ProgramBuilder(arch);
            var test = pb.Add(
                new UserProcedure(pb.NextAddress(), "test")
            {
                CSignature = "void test(int a, int b)"
            },
                m => {
                var r1 = m.Reg32("r1", 1);
                var r2 = m.Reg32("r2", 2);
                var fp = m.Frame.FramePointer;
                m.Assign(r1, m.Mem32(m.IAdd(fp, 4)));
                m.Assign(r2, m.Mem32(m.IAdd(fp, 8)));
                m.Assign(r1, m.IAdd(r1, r2));
                m.MStore(m.Ptr32(0x010008), r1);
                m.Return();
            });
            var program  = pb.BuildProgram();
            var platform = new Mock <IPlatform>();

            platform.Setup(p => p.Architecture).Returns(arch);
            platform.Setup(p => p.IsImplicitArgumentRegister(It.IsAny <RegisterStorage>()))
            .Returns(false);
            platform.Setup(p => p.DefaultCallingConvention).Returns("__cdecl");
            platform.Setup(p => p.GetCallingConvention(null))
            .Returns(new X86CallingConvention(4, 4, 4, true, false));
            platform.Setup(p => p.GetBitSizeFromCBasicType(CBasicType.Int)).Returns(32);
            platform.Setup(p => p.PointerType).Returns(PrimitiveType.Ptr32);
            platform.Setup(p => p.CreateCParser(It.IsAny <TextReader>(), It.IsAny <ParserState>()))
            .Returns(new Func <TextReader, ParserState, CParser>((r, s) =>
            {
                var lex = new CLexer(r, CLexer.MsvcKeywords);
                return(new CParser(s ?? new ParserState(), lex));
            }));

            var dynamicLinker = new Mock <IDynamicLinker>().Object;

            program.Platform = platform.Object;
            var usb = new UserSignatureBuilder(program);

            usb.BuildSignatures(new FakeDecompilerEventListener());
            var dfa = new DataFlowAnalysis(program, dynamicLinker, sc);

            dfa.AnalyzeProgram();
            var sExp = @"// test
// Return size: 4
void test(int32 a, int32 b)
test_entry:
	// succ:  l1
l1:
	Mem6[0x00010008<p32>:word32] = a + b
	return
	// succ:  test_exit
test_exit:
";

            AssertProgram(sExp, pb.Program);
        }
Esempio n. 2
0
        public void Dfa2_Simple()
        {
            var pb = new ProgramBuilder(new FakeArchitecture(new ServiceContainer()));

            pb.Add("test", m =>
            {
                var r1 = m.Reg32("r1", 1);
                var r2 = m.Reg32("r2", 2);
                m.Assign(m.Frame.EnsureRegister(m.Architecture.StackRegister), m.Frame.FramePointer);
                m.Assign(r1, m.Mem32(m.Word32(0x010000)));
                m.Assign(r2, m.Mem32(m.Word32(0x010004)));
                m.MStore(m.Word32(0x010008), m.IAdd(r1, r2));
                m.Return();
            });

            var dfa = new DataFlowAnalysis(pb.BuildProgram(), dynamicLinker.Object, sc);

            dfa.AnalyzeProgram();
            var sExp = @"// test
// Return size: 0
void test()
test_entry:
	// succ:  l1
l1:
	Mem6[0x10008<32>:word32] = Mem0[0x10000<32>:word32] + Mem0[0x10004<32>:word32]
	return
	// succ:  test_exit
test_exit:
";

            AssertProgram(sExp, pb.Program);
        }
Esempio n. 3
0
        public void Dfa2_CallProc()
        {
            pb = new ProgramBuilder();
            pb.Add("test", m =>
            {
                var sp = m.Register(m.Architecture.StackRegister);

                var fooProc = GivenFunction("foo", m.Architecture.GetRegister("r1"), 4, 8);
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(sp, m.ISub(sp, 4));
                m.MStore(sp, m.Word32(2));
                m.Assign(sp, m.ISub(sp, 4));
                m.MStore(sp, m.Word32(1));
                m.Call(fooProc, 4);
                m.Assign(sp, m.IAdd(sp, 8));
                m.Return();
            });

            var dfa = new DataFlowAnalysis(pb.BuildProgram(), null, sc);

            dfa.AnalyzeProgram();
            var sExp = @"// test
// Return size: 0
void test()
test_entry:
	// succ:  l1
l1:
	foo(1<32>, 2<32>)
	return
	// succ:  test_exit
test_exit:
";

            AssertProgram(sExp, pb.Program);
        }
Esempio n. 4
0
        public void Dfa2_StackArgs()
        {
            var pb = new ProgramBuilder(new FakeArchitecture(new ServiceContainer()));

            pb.Add("test", m =>
            {
                var sp = m.Register(m.Architecture.StackRegister);
                var r1 = m.Reg32("r1", 1);
                var r2 = m.Reg32("r2", 2);
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(r1, m.Mem32(m.IAdd(sp, 4)));
                m.Assign(r2, m.Mem32(m.IAdd(sp, 8)));
                m.Assign(r1, m.IAdd(r1, r2));
                m.MStore(m.Ptr32(0x010008), r1);
                m.Return();
            });
            var dfa = new DataFlowAnalysis(pb.BuildProgram(), dynamicLinker.Object, sc);

            dfa.AnalyzeProgram();
            var sExp = @"// test
// Return size: 0
void test(word32 dwArg04, word32 dwArg08)
test_entry:
	// succ:  l1
l1:
	Mem7[0x00010008<p32>:word32] = dwArg04 + dwArg08
	return
	// succ:  test_exit
test_exit:
";

            AssertProgram(sExp, pb.Program);
        }
Esempio n. 5
0
        public void Dfa2_Byte_Arg()
        {
            pb = new ProgramBuilder();
            pb.Add("main", m =>
            {
                var r1 = m.Register("r1");
                var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister);
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(r1, m.Mem32(m.IAdd(sp, 4)));
                m.Call("level1", 4);
                m.Return();
            });
            pb.Add("level1", m =>
            {
                var r1 = m.Register("r1");
                var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister);
                m.Assign(sp, m.Frame.FramePointer);
                m.MStore(m.Ptr32(0x1234), m.Slice(PrimitiveType.Byte, r1, 0));
                m.Return();
            });
            var program = pb.BuildProgram();

            var dfa = new DataFlowAnalysis(program, dynamicLinker.Object, sc);

            dfa.AnalyzeProgram();

            var sExp =
                #region Expected
                @"// Trashed   r1
// Preserved r63
// Used      (Stack +0004:[0..31])
// main
// Return size: 0
void main(word32 dwArg04)
main_entry:
	// succ:  l1
l1:
	level1(dwArg04)
	return
	// succ:  main_exit
main_exit:
===
// Trashed   
// Preserved r63
// Used      (r1:[0..7])
// level1
// Return size: 0
void level1(word32 r1)
level1_entry:
	// succ:  l1
l1:
	Mem4[0x00001234<p32>:byte] = SLICE(r1, byte, 0)
	return
	// succ:  level1_exit
level1_exit:
";

            #endregion
            AssertProgramFlow(sExp, pb.Program, dfa.ProgramDataFlow);
        }
Esempio n. 6
0
        protected void RunHexTest(string hexFile, string outputFile)
        {
            var svc           = new ServiceContainer();
            var cfg           = new FakeDecompilerConfiguration();
            var eventListener = new FakeDecompilerEventListener();

            svc.AddService <IConfigurationService>(cfg);
            svc.AddService <DecompilerEventListener>(eventListener);
            svc.AddService <IDecompiledFileService>(new FakeDecompiledFileService());
            ILoader ldr       = new Loader(svc);
            var     imgLoader = new DchexLoader(FileUnitTester.MapTestPath(hexFile), svc, null);
            var     program   = imgLoader.Load(null);
            var     project   = new Project {
                Programs = { program }
            };
            var ep             = ImageSymbol.Procedure(program.Architecture, program.ImageMap.BaseAddress);
            var importResolver = new ImportResolver(project, program, eventListener);
            var scan           = new Scanner(program, importResolver, svc);

            scan.EnqueueImageSymbol(ep, true);
            scan.ScanImage();

            var dfa = new DataFlowAnalysis(program, null, eventListener);

            dfa.AnalyzeProgram();
            RunTest(program, outputFile);
        }
Esempio n. 7
0
        protected Program RewriteFile(string relativePath, Address addrBase)
        {
            var sc            = new ServiceContainer();
            var config        = new FakeDecompilerConfiguration();
            var eventListener = new FakeDecompilerEventListener();

            sc.AddService <IConfigurationService>(config);
            sc.AddService <DecompilerHost>(new FakeDecompilerHost());
            sc.AddService <DecompilerEventListener>(eventListener);
            sc.AddService <IFileSystemService>(new FileSystemServiceImpl());
            ILoader ldr     = new Loader(sc);
            var     program = ldr.AssembleExecutable(
                FileUnitTester.MapTestPath(relativePath),
                new X86TextAssembler(sc, new X86ArchitectureReal()),
                addrBase);

            program.Platform = new DefaultPlatform(sc, program.Architecture);
            var ep      = new EntryPoint(program.ImageMap.BaseAddress, program.Architecture.CreateProcessorState());
            var project = new Project {
                Programs = { program }
            };
            var scan = new Scanner(
                program,
                new ImportResolver(project, program, eventListener),
                sc);

            scan.EnqueueEntryPoint(ep);
            scan.ScanImage();

            var importResolver = new ImportResolver(project, program, eventListener);
            var dfa            = new DataFlowAnalysis(program, importResolver, eventListener);

            dfa.AnalyzeProgram();
            return(program);
        }
Esempio n. 8
0
        protected Program RewriteFile(string relativePath, Address addrBase)
        {
            var services = new ServiceContainer();
            var config   = new FakeDecompilerConfiguration();

            services.AddService <IConfigurationService>(config);
            ILoader ldr     = new Loader(services);
            var     program = ldr.AssembleExecutable(
                FileUnitTester.MapTestPath(relativePath),
                new X86TextAssembler(new IntelArchitecture(ProcessorMode.Real)),
                addrBase);

            program.Platform = new DefaultPlatform(services, program.Architecture);
            var ep      = new EntryPoint(program.Image.BaseAddress, program.Architecture.CreateProcessorState());
            var project = new Project {
                Programs = { program }
            };
            var scan = new Scanner(
                program,
                new Dictionary <Address, ProcedureSignature>(),
                new ImportResolver(project),
                new FakeDecompilerEventListener());

            scan.EnqueueEntryPoint(ep);
            scan.ScanImage();

            var dfa = new DataFlowAnalysis(program, new FakeDecompilerEventListener());

            dfa.AnalyzeProgram();
            return(program);
        }
Esempio n. 9
0
        private void RunTest(Program program, TextWriter writer)
        {
            var dfa = new DataFlowAnalysis(program, dynamicLinker.Object, sc);

            dfa.AnalyzeProgram();
            foreach (var proc in program.Procedures.Values)
            {
                proc.Write(false, writer);
            }
        }
Esempio n. 10
0
        private void RunTest(Program program, TextWriter writer)
        {
            var dfa = new DataFlowAnalysis(program, importResolver.Object, new FakeDecompilerEventListener());

            dfa.AnalyzeProgram();
            foreach (var proc in program.Procedures.Values)
            {
                proc.Write(false, writer);
            }
        }
Esempio n. 11
0
        public void TrcoIntelIndexedAddressingMode()
        {
            ProgramBuilder m = new ProgramBuilder();

            m.Add(new IntelIndexedAddressingMode());
            Program          program = m.BuildProgram();
            DataFlowAnalysis dfa     = new DataFlowAnalysis(program, null, new FakeDecompilerEventListener());

            dfa.AnalyzeProgram();
            RunTest(program, "Typing/TrcoIntelIndexedAddressingMode.txt");
        }
Esempio n. 12
0
        public void TrcoTreeFind()
        {
            ProgramBuilder m = new ProgramBuilder();

            m.Add(new TreeFindMock());
            Program          program = m.BuildProgram();
            DataFlowAnalysis dfa     = new DataFlowAnalysis(program, null, new FakeDecompilerEventListener());

            dfa.AnalyzeProgram();
            RunTest(program, "Typing/TrcoTreeFind.txt");
        }
Esempio n. 13
0
        public void Dfa2_UserDefinedStackArgs()
        {
            var arch = new X86ArchitectureFlat32(new ServiceContainer(), "x86-protected-32");
            var pb   = new ProgramBuilder(arch);
            var test = pb.Add(
                new Procedure_v1
            {
                CSignature = "void test(int a, int b)"
            },
                m => {
                var r1 = m.Reg32("r1", 1);
                var r2 = m.Reg32("r2", 2);
                var fp = m.Frame.FramePointer;
                m.Assign(r1, m.Mem32(m.IAdd(fp, 4)));
                m.Assign(r2, m.Mem32(m.IAdd(fp, 8)));
                m.Assign(r1, m.IAdd(r1, r2));
                m.MStore(m.Ptr32(0x010008), r1);
                m.Return();
            });
            var program  = pb.BuildProgram();
            var platform = new Mock <IPlatform>();

            platform.Setup(p => p.Architecture).Returns(arch);
            platform.Setup(p => p.CreateImplicitArgumentRegisters()).Returns(
                new HashSet <RegisterStorage>());
            platform.Setup(p => p.DefaultCallingConvention).Returns("__cdecl");
            platform.Setup(p => p.GetCallingConvention(null))
            .Returns(new X86CallingConvention(4, 4, 4, true, false));
            platform.Setup(p => p.GetByteSizeFromCBasicType(CBasicType.Int)).Returns(4);

            var dynamicLinker = new Mock <IDynamicLinker>().Object;

            program.Platform = platform.Object;
            var usb = new UserSignatureBuilder(program);

            usb.BuildSignatures(new FakeDecompilerEventListener());
            var dfa = new DataFlowAnalysis(program, dynamicLinker, sc);

            dfa.AnalyzeProgram();
            var sExp = @"// test
// Return size: 4
void test(int32 a, int32 b)
test_entry:
	// succ:  l1
l1:
	Mem6[0x00010008<p32>:word32] = a + b
	return
	// succ:  test_exit
test_exit:
";

            AssertProgram(sExp, pb.Program);
        }
Esempio n. 14
0
 protected override void RunTest(Program prog, TextWriter writer)
 {
     dfa = new DataFlowAnalysis(prog, new FakeDecompilerEventListener());
     dfa.AnalyzeProgram();
     foreach (Procedure proc in prog.Procedures.Values)
     {
         ProcedureFlow flow = dfa.ProgramDataFlow[proc];
         writer.Write("// ");
         flow.Signature.Emit(proc.Name, ProcedureSignature.EmitFlags.ArgumentKind | ProcedureSignature.EmitFlags.LowLevelInfo, writer);
         flow.Emit(prog.Architecture, writer);
         proc.Write(false, writer);
         writer.WriteLine();
     }
 }
Esempio n. 15
0
        protected override void RunTest(Program program, TextWriter writer)
        {
            SetCSignatures(program);
            var importResolver = new Mock <IImportResolver>();

            dfa = new DataFlowAnalysis(program, importResolver.Object, new FakeDecompilerEventListener());
            dfa.AnalyzeProgram();
            foreach (Procedure proc in program.Procedures.Values)
            {
                var flow = dfa.ProgramDataFlow[proc];
                writer.Write("// ");
                var sig = flow.Signature ?? proc.Signature;
                sig.Emit(proc.Name, FunctionType.EmitFlags.ArgumentKind | FunctionType.EmitFlags.LowLevelInfo, writer);
                flow.Emit(program.Architecture, writer);
                proc.Write(false, writer);
                writer.WriteLine();
            }
        }
Esempio n. 16
0
        protected Program RewriteFile(
            string relativePath,
            Address addrBase,
            Func <IServiceProvider, IProcessorArchitecture, IPlatform> mkPlatform)
        {
            sc = new ServiceContainer();
            var config        = new FakeDecompilerConfiguration();
            var eventListener = new FakeDecompilerEventListener();

            sc.AddService <IConfigurationService>(config);
            sc.AddService <IDecompiledFileService>(new FakeDecompiledFileService());
            sc.AddService <DecompilerEventListener>(eventListener);
            sc.AddService <IFileSystemService>(new FileSystemServiceImpl());
            var     arch    = new X86ArchitectureReal(sc, "x86-real-16");
            ILoader ldr     = new Loader(sc);
            var     program = ldr.AssembleExecutable(
                FileUnitTester.MapTestPath(relativePath),
                new X86TextAssembler(arch),
                null,
                addrBase);

            program.Platform = mkPlatform(sc, program.Architecture);

            var ep      = ImageSymbol.Procedure(arch, program.SegmentMap.BaseAddress);
            var project = new Project {
                Programs = { program }
            };
            var scan = new Scanner(
                program,
                new DynamicLinker(project, program, eventListener),
                sc);

            scan.EnqueueImageSymbol(ep, true);
            scan.ScanImage();

            var dynamicLinker = new DynamicLinker(project, program, eventListener);
            var dfa           = new DataFlowAnalysis(program, dynamicLinker, eventListener);

            dfa.AnalyzeProgram();
            return(program);
        }
Esempio n. 17
0
        private Program RewriteProgram()
        {
            var eventListener = new FakeDecompilerEventListener();
            var dynamicLinker = new Mock <IDynamicLinker>();
            var scan          = new Scanner(
                program,
                dynamicLinker.Object,
                sc);

            foreach (ImageSymbol ep in program.EntryPoints.Values)
            {
                scan.EnqueueImageSymbol(ep, true);
            }
            scan.ScanImage();

            var dfa = new DataFlowAnalysis(program, dynamicLinker.Object, sc);

            dfa.AnalyzeProgram();

            return(program);
        }
Esempio n. 18
0
        private Program RewriteProgram()
        {
            var eventListener  = new FakeDecompilerEventListener();
            var importResolver = MockRepository.GenerateStub <IImportResolver>();

            importResolver.Replay();
            var scan = new Scanner(
                program,
                importResolver,
                sc);

            foreach (ImageSymbol ep in program.EntryPoints.Values)
            {
                scan.EnqueueImageSymbol(ep, true);
            }
            scan.ScanImage();

            var dfa = new DataFlowAnalysis(program, importResolver, eventListener);

            dfa.AnalyzeProgram();

            return(program);
        }
Esempio n. 19
0
        protected Program RewriteFile(
            string relativePath,
            Address addrBase,
            Func <IServiceProvider, IProcessorArchitecture, IPlatform> mkPlatform)
        {
            var sc = new ServiceContainer();

            PopulateServiceContainer(sc);
            var     arch    = new X86ArchitectureReal(sc, "x86-real-16", new Dictionary <string, object>());
            ILoader ldr     = new Loader(sc);
            var     program = ldr.AssembleExecutable(
                ImageLocation.FromUri(FileUnitTester.MapTestPath(relativePath)),
                new X86TextAssembler(arch),
                null,
                addrBase);

            program.Platform = mkPlatform(sc, program.Architecture);

            var ep      = ImageSymbol.Procedure(arch, program.SegmentMap.BaseAddress);
            var project = new Project {
                Programs = { program }
            };
            var scan = new Scanner(
                program,
                project.LoadedMetadata,
                new DynamicLinker(project, program, eventListener),
                sc);

            scan.EnqueueImageSymbol(ep, true);
            scan.ScanImage();

            var dynamicLinker = new DynamicLinker(project, program, eventListener);
            var dfa           = new DataFlowAnalysis(program, dynamicLinker, sc);

            dfa.AnalyzeProgram();
            return(program);
        }
Esempio n. 20
0
        private Program RewriteProgram()
        {
            var project = new Project {
                Programs = { program }
            };
            var scan = new Scanner(
                program,
                new Dictionary <Address, ProcedureSignature>(),
                new ImportResolver(project),
                new FakeDecompilerEventListener());

            foreach (EntryPoint ep in program.EntryPoints)
            {
                scan.EnqueueEntryPoint(ep);
            }
            scan.ScanImage();

            DecompilerEventListener eventListener = new FakeDecompilerEventListener();
            DataFlowAnalysis        da            = new DataFlowAnalysis(program, eventListener);

            da.AnalyzeProgram();

            return(program);
        }
Esempio n. 21
0
        protected void RunHexTest(string hexFile, string outputFile)
        {
            var svc = new ServiceContainer();
            var cfg = new FakeDecompilerConfiguration();

            svc.AddService <IConfigurationService>(cfg);
            ILoader ldr       = new Loader(svc);
            var     imgLoader = new DchexLoader(FileUnitTester.MapTestPath(hexFile), svc, null);
            var     img       = imgLoader.Load(null);
            var     program   = new Program(img.Image, img.Image.CreateImageMap(), img.Architecture, img.Platform);
            var     project   = new Project {
                Programs = { program }
            };
            var ep   = new EntryPoint(program.Image.BaseAddress, program.Architecture.CreateProcessorState());
            var scan = new Scanner(program, new Dictionary <Address, ProcedureSignature>(), new ImportResolver(project), new FakeDecompilerEventListener());

            scan.EnqueueEntryPoint(ep);
            scan.ScanImage();

            var dfa = new DataFlowAnalysis(program, new FakeDecompilerEventListener());

            dfa.AnalyzeProgram();
            RunTest(program, outputFile);
        }
Esempio n. 22
0
        public void Dfa2_StackArgs_Nested()
        {
            pb = new ProgramBuilder();
            pb.Add("main", m =>
            {
                var r1 = m.Register("r1");
                var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister);
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(sp, m.ISub(sp, 4));
                m.MStore(sp, m.Mem32(m.Ptr32(0x123400)));
                m.Call("level1", 4);
                m.Assign(sp, m.IAdd(sp, 4));
                m.MStore(m.Ptr32(0x123404), r1);
                m.Return();
            });
            pb.Add("level1", m =>
            {
                var r1 = m.Register("r1");
                var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister);
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(r1, m.Mem32(m.IAdd(sp, 4)));
                m.Assign(sp, m.ISub(sp, 4));
                m.MStore(sp, r1);
                m.Call("level2", 4);
                m.Assign(sp, m.IAdd(sp, 4));
                m.Return();
            });
            pb.Add("level2", m =>
            {
                var r1 = m.Register("r1");
                var r2 = m.Register("r2");
                var sp = m.Frame.EnsureRegister(m.Architecture.StackRegister);
                m.Assign(sp, m.Frame.FramePointer);
                m.Assign(r1, m.Mem32(m.IAdd(sp, 4)));
                m.Assign(r1, m.IAdd(r1, 1));
                m.Return();
            });
            var program = pb.BuildProgram();

            var dfa = new DataFlowAnalysis(program, dynamicLinker.Object, sc);

            dfa.AnalyzeProgram();

            var sExp =
                #region Expected
                @"// main
// Return size: 0
void main()
main_entry:
	// succ:  l1
l1:
	Mem8[0x00123404<p32>:word32] = level1(Mem0[0x00123400<p32>:word32])
	return
	// succ:  main_exit
main_exit:
===
// level1
// Return size: 0
word32 level1(word32 dwArg04)
level1_entry:
	// succ:  l1
l1:
	return level2(dwArg04)
	// succ:  level1_exit
level1_exit:
===
// level2
// Return size: 0
word32 level2(word32 dwArg04)
level2_entry:
	// succ:  l1
l1:
	return dwArg04 + 1<32>
	// succ:  level2_exit
level2_exit:
";

            #endregion
            AssertProgram(sExp, pb.Program);
        }
Esempio n. 23
0
        public void Dfa2_Untangle_CallChain()
        {
            pb = new ProgramBuilder();
            pb.Add("main", m =>
            {
                var r1 = m.Register("r1");
                m.Assign(m.Frame.EnsureRegister(m.Architecture.StackRegister), m.Frame.FramePointer);
                m.Assign(r1, m.Mem32(m.Ptr32(0x00123400)));
                m.Call("level1", 0);
                m.MStore(m.Ptr32(0x00123400), r1);
                m.Return();
            });
            pb.Add("level1", m =>
            {
                m.Assign(m.Frame.EnsureRegister(m.Architecture.StackRegister), m.Frame.FramePointer);
                m.Call("level2", 0);
                m.Return();
            });
            pb.Add("level2", m =>
            {
                var r1 = m.Register("r1");
                var r2 = m.Register("r2");
                m.Assign(m.Frame.EnsureRegister(m.Architecture.StackRegister), m.Frame.FramePointer);
                m.Assign(r2, -1);
                m.Assign(r1, m.IAdd(r1, 1));
                m.Return();
            });
            var program = pb.BuildProgram();

            var dfa = new DataFlowAnalysis(program, dynamicLinker.Object, new FakeDecompilerEventListener());

            dfa.AnalyzeProgram();

            var sExp =
                #region Expected
                @"// main
// Return size: 0
void main()
main_entry:
	// succ:  l1
l1:
	Mem7[0x00123400<p32>:word32] = level1(Mem0[0x00123400<p32>:word32])
	return
	// succ:  main_exit
main_exit:
===
// level1
// Return size: 0
word32 level1(word32 r1)
level1_entry:
	// succ:  l1
l1:
	return level2(r1)
	// succ:  level1_exit
level1_exit:
===
// level2
// Return size: 0
word32 level2(word32 r1)
level2_entry:
	// succ:  l1
l1:
	return r1 + 1<32>
	// succ:  level2_exit
level2_exit:
";

            #endregion
            AssertProgram(sExp, pb.Program);
        }