/// <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); }
// 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(); }
/// <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; }
/// <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); } }
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; }
/// <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()); }
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; }