Builds ProcedureSignatures from user-supplied signatures.
Exemple #1
0
        /// <summary>
        /// Summarizes the net effect each procedure has on registers,
        /// then removes trashed registers that aren't live-out.
        /// </summary>
        public List <SsaTransform> UntangleProcedures()
        {
            eventListener.ShowProgress("Rewriting procedures.", 0, program.Procedures.Count);

            IntraBlockDeadRegisters.Apply(program, eventListener);

            AdjacentBranchCollector.Transform(program, eventListener);

            var ssts = RewriteProceduresToSsa();

            // Recreate user-defined signatures. It should prevent type
            // inference between user-defined parameters and other expressions
            var usb = new UserSignatureBuilder(program);

            usb.BuildSignatures(eventListener);

            // Discover ssaId's that are live out at each call site.
            // Delete all others.
            var uvr = new UnusedOutValuesRemover(
                program,
                ssts.Select(sst => sst.SsaState),
                this.flow,
                dynamicLinker,
                eventListener);

            uvr.Transform();

            // At this point, the exit blocks contain only live out registers.
            // We can create signatures from that.
            CallRewriter.Rewrite(program.Platform, ssts, this.flow, eventListener);
            return(ssts);
        }
        public void Usb_EmptyUserSignature()
        {
            Given_Procedure(0x1000);

            var oldSig = proc.Signature;
            var usb = new UserSignatureBuilder(program);
            usb.BuildSignatures(new FakeDecompilerEventListener());
            Assert.AreSame(oldSig, proc.Signature);
        }
        public void Usb_EmptyUserSignature()
        {
            Given_Procedure(0x1000);

            var oldSig = proc.Signature;
            var usb = new UserSignatureBuilder(program);
            usb.BuildSignatures();
            Assert.AreSame(oldSig, proc.Signature);
        }
Exemple #4
0
        // EXPERIMENTAL - consult uxmal before using
        /// <summary>
        /// Analyizes the procedures of a program by finding all strongly
        /// connected components (SCCs) and processing the SCCs one by one.
        /// </summary>
        public void AnalyzeProgram2()
        {
            var usb = new UserSignatureBuilder(program);

            usb.BuildSignatures();

            var sscf = new SccFinder <Procedure>(new ProcedureGraph(program), UntangleProcedureScc);

            foreach (var procedure in program.Procedures.Values)
            {
                sscf.Find(procedure);
            }
        }
        public void Usb_BuildSignature()
        {
            Given_Procedure(0x1000);
            var ser = mr.Stub<ProcedureSerializer>(arch, null, "cdecl");
            platform.Expect(s => s.CreateProcedureSerializer(null, null)).IgnoreArguments().Return(ser);
            ser.Expect(s => s.Deserialize(
                Arg<SerializedSignature>.Is.NotNull,
                Arg<Frame>.Is.NotNull)).Return(new ProcedureSignature());
            mr.ReplayAll();

            var usb = new UserSignatureBuilder(program);
            var sig = usb.BuildSignature("int foo(char *)", proc.Frame);
            mr.ReplayAll();
        }
Exemple #6
0
        /// <summary>
        /// Finds all interprocedural register dependencies (in- and out-parameters) and
        /// abstracts them away by rewriting as calls.
        /// </summary>
        /// <returns>A RegisterLiveness object that summarizes the interprocedural register
        /// liveness analysis. This information can be used to generate SSA form.
        /// </returns>
        public void UntangleProcedures()
        {
            eventListener.ShowStatus("Eliminating intra-block dead registers.");
            var usb = new UserSignatureBuilder(program);

            usb.BuildSignatures(eventListener);
            CallRewriter.Rewrite(program, eventListener);
            IntraBlockDeadRegisters.Apply(program, eventListener);
            eventListener.ShowStatus("Finding terminating procedures.");
            var term = new TerminationAnalysis(flow, eventListener);

            term.Analyze(program);
            eventListener.ShowStatus("Finding trashed registers.");
            var trf = new TrashedRegisterFinder(program, program.Procedures.Values, flow, eventListener);

            trf.Compute();
            eventListener.ShowStatus("Rewriting affine expressions.");
            trf.RewriteBasicBlocks();
            eventListener.ShowStatus("Computing register liveness.");
            RegisterLiveness.Compute(program, flow, eventListener);
            eventListener.ShowStatus("Rewriting calls.");
            GlobalCallRewriter.Rewrite(program, flow, eventListener);
        }
        public void Usb_BuildSignatures_UserDefinedTypes()
        {
            var platformTypes = new Dictionary<string, DataType>()
            {
                { "PLATFORMDEF", PrimitiveType.Create(PrimitiveType.Byte.Domain, 1) },
            };
            var userDefinedTypes = new Dictionary<string, DataType>()
            {
                { "USRDEF", PrimitiveType.Create( PrimitiveType.Int16.Domain, 2 ) },
            };
            mockFactory.Given_PlatformTypes(platformTypes);
            mockFactory.Given_UserDefinedMetafile("mod", userDefinedTypes, null, null);
            Given_Procedure(0x1000);
            Given_UserSignature(0x01000, "int test(PLATFORMDEF a, USRDEF b)");

            var usb = new UserSignatureBuilder(program);
            usb.BuildSignatures();

            var sigExp =
@"Register int32 ()(Stack PLATFORMDEF a, Stack USRDEF b)
// stackDelta: 4; fpuStackDelta: 0; fpuMaxParam: -1
";

            Assert.AreEqual(sigExp, proc.Signature.ToString());

            Assert.AreEqual(2, proc.Signature.Parameters.Length);
            Assert.AreEqual("int32", proc.Signature.ReturnValue.DataType.ToString());
            Assert.AreEqual("a", proc.Signature.Parameters[0].Name);
            Assert.AreEqual("byte", (proc.Signature.Parameters[0].DataType as TypeReference).Referent.ToString());
            Assert.AreEqual("b", proc.Signature.Parameters[1].Name);
            Assert.AreEqual("int16", (proc.Signature.Parameters[1].DataType as TypeReference).Referent.ToString());
        }
        public void Usb_ParseFunctionDeclaration_UserDefinedTypes()
        {
            var platformTypes = new Dictionary<string, DataType>()
            {
                { "BYTE", PrimitiveType.Create(PrimitiveType.Byte.Domain, 1) },
            };
            var userDefinedTypes1 = new Dictionary<string, DataType>()
            {
                { "USRDEF1", PrimitiveType.Create( PrimitiveType.Int16.Domain, 2 ) },
            };
            var userDefinedTypes2 = new Dictionary<string, DataType>()
            {
                { "USRDEF2", PrimitiveType.Create( PrimitiveType.Int16.Domain, 2 ) },
            };
            mockFactory.Given_PlatformTypes(platformTypes);
            Given_Procedure(0x1000);

            var usb = new UserSignatureBuilder(program);

            //should accept user defined type USRDEF1
            mockFactory.Given_UserDefinedMetafile("mod1", userDefinedTypes1, null, null);

            var sProc = usb.ParseFunctionDeclaration("BYTE foo(USRDEF1 a, BYTE b)", proc.Frame);

            Assert.AreEqual(
                "fn(arg(BYTE),(arg(a,USRDEF1)arg(b,BYTE))",
                sProc.Signature.ToString());

            //should not accept undefined type USRDEF2
            sProc = usb.ParseFunctionDeclaration("BYTE foo(USRDEF1 a, USRDEF2 b)", proc.Frame);

            Assert.AreEqual(null, sProc);

            //define USRDEF2 so parser should accept it
            mockFactory.Given_UserDefinedMetafile("mod2", userDefinedTypes2, null, null);

            sProc = usb.ParseFunctionDeclaration("BYTE foo(USRDEF1 a, USRDEF2 b)", proc.Frame);

            Assert.AreEqual(
                "fn(arg(BYTE),(arg(a,USRDEF1)arg(b,USRDEF2))",
                sProc.Signature.ToString());
        }
        public void Usb_ParseFunctionDeclaration_PlatfromTypes()
        {
            program.EnvironmentMetadata.Types.Add(
                "BYTE",
                PrimitiveType.Create(PrimitiveType.Byte.Domain, 1));
            Given_Procedure(0x1000);

            var usb = new UserSignatureBuilder(program);
            var sProc = usb.ParseFunctionDeclaration("BYTE foo(BYTE a, BYTE b)");

            Assert.AreEqual(
                "fn(arg(BYTE),(arg(a,BYTE),arg(b,BYTE))",
                sProc.Signature.ToString());
        }
 protected void Signature_TextChanged(object sender, EventArgs e)
 {
     // Attempt to parse the signature.
     var CSignature = dlg.Signature.Text.Trim();
     ProcedureBase_v1 sProc = null;
     bool isValid;
     if (!string.IsNullOrEmpty(CSignature))
     {
         var usb = new UserSignatureBuilder(program);
         sProc = usb.ParseFunctionDeclaration(CSignature);
         isValid = (sProc != null);
     } else
     {
         CSignature = null;
         isValid = true;
     }
     EnableControls(isValid);
     if (isValid)
     {
         if (sProc != null)
             dlg.ProcedureName.Text = sProc.Name;
         EnableProcedureName();
     }
 }
 public void Usb_ParseGlobalDeclaration_PointerToUnsignedInt()
 {
     var usb = new UserSignatureBuilder(program);
     var gbl = usb.ParseGlobalDeclaration("unsigned int *uiPtr");
     Assert.AreEqual("uiPtr", gbl.Name);
     Assert.AreEqual("ptr(prim(UnsignedInt,4))", gbl.DataType.ToString());
 }
        private bool TryParseGlobal(string txtGlobal, out GlobalDataItem_v2 global)
        {
            global = null;
            if (program == null || program.Platform == null)
            {
                return false;
            }

            // Attempt to parse the global declaration.
            var usb = new UserSignatureBuilder(program);
            global = usb.ParseGlobalDeclaration(txtGlobal);
            return global != null;
        }
Exemple #13
0
 /// <summary>
 /// Finds all interprocedural register dependencies (in- and out-parameters) and
 /// abstracts them away by rewriting as calls.
 /// </summary>
 /// <returns>A RegisterLiveness object that summarizes the interprocedural register
 /// liveness analysis. This information can be used to generate SSA form.
 /// </returns>
 public void UntangleProcedures()
 {
     eventListener.ShowStatus("Eliminating intra-block dead registers.");
     var usb = new UserSignatureBuilder(program);
     usb.BuildSignatures();
     CallRewriter.Rewrite(program);
     IntraBlockDeadRegisters.Apply(program);
     eventListener.ShowStatus("Finding terminating procedures.");
     var term = new TerminationAnalysis(flow);
     term.Analyze(program);
     eventListener.ShowStatus("Finding trashed registers.");
     var trf = new TrashedRegisterFinder(program, program.Procedures.Values, flow, eventListener);
     trf.Compute();
     eventListener.ShowStatus("Rewriting affine expressions.");
     trf.RewriteBasicBlocks();
     eventListener.ShowStatus("Computing register liveness.");
     var rl = RegisterLiveness.Compute(program, flow, eventListener);
     eventListener.ShowStatus("Rewriting calls.");
     GlobalCallRewriter.Rewrite(program, flow);
 }
        public void Usb_ParseFunctionDeclaration()
        {
            Given_Procedure(0x1000);

            var usb = new UserSignatureBuilder(program);
            var sProc = usb.ParseFunctionDeclaration("int foo(char *)", proc.Frame);

            Assert.AreEqual(
                "fn(arg(prim(SignedInt,4)),(arg(ptr(prim(Character,1))))",
                sProc.Signature.ToString());
        }
        public void Usb_ParseFunctionDeclaration_UserDefinedTypes()
        {
            program.EnvironmentMetadata.Types.Add(
                "BYTE", PrimitiveType.Create(PrimitiveType.Byte.Domain, 1));
         
            Given_Procedure(0x1000);

            var usb = new UserSignatureBuilder(program);

            //should accept user defined type USRDEF1
            program.EnvironmentMetadata.Types.Add(
                "USRDEF1", PrimitiveType.Create(PrimitiveType.Int16.Domain, 2));

            var sProc = usb.ParseFunctionDeclaration("BYTE foo(USRDEF1 a, BYTE b)");

            Assert.AreEqual(
                "fn(arg(BYTE),(arg(a,USRDEF1),arg(b,BYTE))",
                sProc.Signature.ToString());

            //should not accept undefined type USRDEF2
            sProc = usb.ParseFunctionDeclaration("BYTE foo(USRDEF1 a, USRDEF2 b)");
            Assert.AreEqual(null, sProc);

            //define USRDEF2 so parser should accept it

            program.EnvironmentMetadata.Types.Add(
               "USRDEF2", PrimitiveType.Create(PrimitiveType.Int16.Domain, 2));

            sProc = usb.ParseFunctionDeclaration("BYTE foo(USRDEF1 a, USRDEF2 b)");

            Assert.AreEqual(
                "fn(arg(BYTE),(arg(a,USRDEF1),arg(b,USRDEF2))",
                sProc.Signature.ToString());
        }
        // EXPERIMENTAL - consult uxmal before using
        /// <summary>
        /// Analyizes the procedures of a program by finding all strongly 
        /// connected components (SCCs) and processing the SCCs one by one.
        /// </summary>
        public void AnalyzeProgram2()
        {
            var usb = new UserSignatureBuilder(program);
            usb.BuildSignatures();

            var sscf = new SccFinder<Procedure>(new ProcedureGraph(program), UntangleProcedureScc);
            foreach (var procedure in program.Procedures.Values)
            {
                sscf.Find(procedure);
            }
        }
Exemple #17
0
 private bool TryGetNoDecompiledParsedProcedure(Address addr, out Procedure_v1 parsedProc)
 {
     Procedure_v1 sProc;
     if (!TryGetNoDecompiledProcedure(addr, out sProc))
     {
         parsedProc = null;
         return false;
     }
     if (noDecompiledProcs.TryGetValue(addr, out parsedProc))
         return true;
     parsedProc = new Procedure_v1()
     {
         Name = sProc.Name,
     };
     noDecompiledProcs[addr] = parsedProc;
     if (string.IsNullOrEmpty(sProc.CSignature))
     {
         Warn(addr, "The user-defined procedure at address {0} did not have a signature.", addr);
         return true;
     }
     var usb = new UserSignatureBuilder(program);
     var procDecl = usb.ParseFunctionDeclaration(sProc.CSignature);
     if (procDecl == null)
     {
         Warn(addr, "The user-defined procedure signature at address {0} could not be parsed.", addr);
         return true;
     }
     parsedProc.Signature = procDecl.Signature;
     return true;
 }
Exemple #18
0
        /// <summary>
        /// Performs a scan of the blocks that constitute a procedure named <paramref name="procedureName"/>
        /// </summary>
        /// <param name="addr">Address of the code from which we will start scanning.</param>
        /// <param name="procedureName"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public ProcedureBase ScanProcedure(Address addr, string procedureName, ProcessorState state)
        {
            TerminateAnyBlockAt(addr);
            ExternalProcedure ep;
            if (TryGetNoDecompiledProcedure(addr, out ep))
                return ep;
            if (program.InterceptedCalls.TryGetValue(addr, out ep))
                return ep;
            var trampoline = GetTrampoline(addr);
            if (trampoline != null)
                return trampoline;

            var imp = GetImportedProcedure(addr, addr);
            if (imp != null)
                return imp;
            Procedure proc = EnsureProcedure(addr, procedureName);
            if (visitedProcs.Contains(proc))
                return proc;

            visitedProcs.Add(proc);
            Debug.WriteLineIf(trace.TraceInfo, string.Format("Scanning procedure at {0}", addr));

            var st = state.Clone();
            EstablishInitialState(addr, st, proc);

            //$REFACTOR: make the stack explicit?
            var oldQueue = queue;
            queue = new PriorityQueue<WorkItem>();
            var block = EnqueueJumpTarget(addr, addr, proc, st);
            proc.ControlGraph.AddEdge(proc.EntryBlock, block);
            ProcessQueue();

            queue = oldQueue;

            InjectProcedureEntryInstructions(addr, proc);
            var usb = new UserSignatureBuilder(program);
            usb.BuildSignature(addr, proc);
            return proc;
        }
        public void Usb_ParseFunctionDeclaration_WithRegisterArgs()
        {
            var arch = new FakeArchitecture();
            var m = new ProcedureBuilder(arch, "test");
            var r1 = m.Reg32("r1", 1);
            var r2 = m.Reg32("r2", 2);
            m.Store(m.Word32(0x123400), m.Cast(PrimitiveType.Byte, r1));
            m.Store(m.Word32(0x123404), m.Cast(PrimitiveType.Real32, r2));
            m.Return();

            var usb = new UserSignatureBuilder(program);
            usb.ApplySignatureToProcedure(
                Address.Create(PrimitiveType.Pointer32, 0x1000),
                new ProcedureSignature(
                    null,
                    new Identifier("r2", PrimitiveType.Char, r1.Storage),  // perverse but legal.
                    new Identifier("r1", PrimitiveType.Real32, r2.Storage)),
                m.Procedure);
            var sExp = @"// test
// Return size: 0
void test(char r2, real32 r1)
test_entry:
	// succ:  l1
l1:
	r1 = r2
	r2 = r1
	Mem0[0x00123400:byte] = (byte) r1
	Mem0[0x00123404:real32] = (real32) r2
	return
	// succ:  test_exit
test_exit:
";
            var sb = new StringWriter();
            m.Procedure.Write(false, sb);
            Assert.AreEqual(sExp, sb.ToString());
        }
        public void Usb_BuildSignature_KeepRegisterType()
        {
            Given_Procedure(0x1000);
            Given_UserSignature(0x01000, "void test([[reko::arg(register,\"ecx\")]] float f)");

            var usb = new UserSignatureBuilder(program);
            usb.BuildSignature(Address.Ptr32(0x1000), proc);

            var ass = proc.Statements
                .Select(stm => stm.Instruction as Assignment)
                .Where(instr => instr != null)
                .Single();
            Assert.AreEqual("ecx = f", ass.ToString());
            // verify that data type of register was not overwritten
            Assert.AreEqual("word32", ass.Dst.DataType.ToString());
            Assert.AreEqual("real32", ass.Src.DataType.ToString());
        }
        public void Usb_BuildSignatures_UserDefinedTypes()
        {
            program.EnvironmentMetadata.Types.Add(
                "PLATFORMDEF",
                PrimitiveType.Create(PrimitiveType.Byte.Domain, 1));
            program.EnvironmentMetadata.Types.Add(
                "USRDEF",
                PrimitiveType.Create(PrimitiveType.Int16.Domain, 2));
            Given_Procedure(0x1000);
            Given_UserSignature(0x01000, "int test(PLATFORMDEF a, USRDEF b)");

            var usb = new UserSignatureBuilder(program);
            usb.BuildSignatures(new FakeDecompilerEventListener());

            var sigExp =
@"Register int32 test(Stack PLATFORMDEF a, Stack USRDEF b)
// stackDelta: 4; fpuStackDelta: 0; fpuMaxParam: -1
";
            Assert.AreEqual(sigExp, proc.Signature.ToString("test", FunctionType.EmitFlags.AllDetails));

            Assert.AreEqual(2, proc.Signature.Parameters.Length);
            Assert.AreEqual("int32", proc.Signature.ReturnValue.DataType.ToString());
            Assert.AreEqual("a", proc.Signature.Parameters[0].Name);
            Assert.AreEqual("byte", (proc.Signature.Parameters[0].DataType as TypeReference).Referent.ToString());
            Assert.AreEqual("b", proc.Signature.Parameters[1].Name);
            Assert.AreEqual("int16", (proc.Signature.Parameters[1].DataType as TypeReference).Referent.ToString());
        }
        private bool TryParseSignature(string txtSignature, out ProcedureBase_v1 sProc)
        {
            sProc = null;
            if (program == null || program.Platform == null)
            {
                return false;
            }

            // Attempt to parse the signature.
            var usb = new UserSignatureBuilder(program);
            sProc = usb.ParseFunctionDeclaration(txtSignature);
            return sProc != null;
        }
        public void Usb_ParseFunctionDeclaration_PlatfromTypes()
        {
            var platformTypes = new Dictionary<string, DataType>()
            {
                { "BYTE", PrimitiveType.Create(PrimitiveType.Byte.Domain, 1) },
            };
            mockFactory.Given_PlatformTypes(platformTypes);
            Given_Procedure(0x1000);

            var usb = new UserSignatureBuilder(program);
            var sProc = usb.ParseFunctionDeclaration("BYTE foo(BYTE a, BYTE b)", proc.Frame);

            Assert.AreEqual(
                "fn(arg(BYTE),(arg(a,BYTE)arg(b,BYTE))",
                sProc.Signature.ToString());
        }
 public void Usb_ParseGlobalDeclaration_Int()
 {
     var usb = new UserSignatureBuilder(program);
     var gbl = usb.ParseGlobalDeclaration("int test123");
     Assert.AreEqual("test123", gbl.Name);
     Assert.AreEqual("prim(SignedInt,4)", gbl.DataType.ToString());
 }
 public void Usb_ParseGlobalDeclaration_ArrayOfDouble()
 {
     var usb = new UserSignatureBuilder(program);
     var gbl = usb.ParseGlobalDeclaration("double dArr[12]");
     Assert.AreEqual("dArr", gbl.Name);
     Assert.AreEqual("arr(prim(Real,8),12)", gbl.DataType.ToString());
 }
Exemple #26
0
        private bool TryGetNoDecompiledProcedure(Address addr, out ExternalProcedure ep)
        {
            Procedure_v1 sProc;
            if (!program.User.Procedures.TryGetValue(addr, out sProc) ||
                sProc.Decompile)
            {
                ep = null;
                return false;
            }

            FunctionType sig = null;
            if (!string.IsNullOrEmpty(sProc.CSignature))
            {
                var usb = new UserSignatureBuilder(program);
                var procDecl = usb.ParseFunctionDeclaration(sProc.CSignature);
                if (procDecl != null)
                {
                    var ser = program.CreateProcedureSerializer();
                    sig = ser.Deserialize(
                        procDecl.Signature,
                        program.Architecture.CreateFrame());
                }
            }
            else
            {
                Warn(addr, "The user-defined procedure at address {0} did not have a signature.", addr); 
            }

            ep = new ExternalProcedure(sProc.Name, sig);
            return true;
        }