public static string CreateInitializeGlobals() { StringBuilder sb = new StringBuilder(); sb.AppendLine("procedure {:ProgramInitialization} $initialize_globals()"); sb.AppendLine("{"); sb.AppendLine("\t//this procedure initializes global exception variables and calls static constructors"); sb.AppendLine("\t$Exception := null;"); sb.AppendLine("\t$ExceptionType := null;"); sb.AppendLine("\t$ExceptionInCatchHandler := null;"); sb.AppendLine("\t$ExceptionInCatchHandlerType := null;"); foreach (var staticConstructor in staticConstructors) { var signature = BoogieMethod.From(staticConstructor).Name; sb.AppendLine(String.Format("\tcall {0}();", signature)); sb.AppendLine("\tif ($Exception != null)"); sb.AppendLine("\t{"); sb.AppendLine("\t\treturn;"); sb.AppendLine("\t}"); } sb.AppendLine("}"); return(sb.ToString()); }
public static Boolean IsCurrentlyMissing(IMethodReference methodReference) { // The value of this condition can change throughout the execution of the translation. // For that reason, it should be called at the end of the translation again to confirm // the method is actually missing from the binary. return(!methodsTranslated.Contains(BoogieMethod.From(methodReference).Name)); }
public static void CreateAsyncStartMethod(StreamWriter sw) { StatementList stmts = new StatementList(); var boogieGetTypeRes = BoogieVariable.GetTempVar(Helpers.ObjectType(), null /* need dict with used var names*/, prefix: "asyncType"); var stateMachineVar = BoogieVariable.GetTempVar(Helpers.ObjectType(), null /* need dict with used var names*/, prefix: "stateMachineCopy"); stmts.Add(BoogieStatement.VariableDeclaration(stateMachineVar)); stmts.Add(BoogieStatement.VariableDeclaration(boogieGetTypeRes)); stmts.Add(BoogieStatement.FromString($"{stateMachineVar.Expr} := stateMachine;")); foreach (var asyncMethod in Helpers.asyncMoveNexts) { var asyncType = asyncMethod.ContainingTypeDefinition; var bg = BoogieGenerator.Instance(); stmts.Add(bg.ProcedureCall(BoogieMethod.GetTypeMethod, new List <Expression> { stateMachineVar }, boogieGetTypeRes)); StatementList ifStmts = new StatementList(); ifStmts.Add(BoogieGenerator.Instance().ProcedureCall(BoogieMethod.From(asyncMethod), new List <Expression> { stateMachineVar })); stmts.Add(BoogieStatement.If(Expression.Subtype(boogieGetTypeRes, asyncType), ifStmts)); } stmts.Add(BoogieStatement.FromString($"v0$out := {stateMachineVar.Expr};")); sw.WriteLine(@"procedure {:extern} System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Start``1$``0$(this : Ref,stateMachine : Ref) returns (v0$out : Ref) {"); foreach (var stmt in stmts) { sw.WriteLine(stmt.Stmt); } sw.WriteLine("}"); }
public static string CreateMainWrappers() { StringBuilder sb = new StringBuilder(); foreach (var mainMethodTuple in mainMethods) { var mainMethod = mainMethodTuple.Item1; var assembly = mainMethodTuple.Item2; var disassembler = new Disassembler(assembly.Host, mainMethod, assembly.PdbReader); disassembler.Execute(); var methodName = BoogieMethod.From(mainMethod).Name; var parameters = Helpers.GetParametersWithBoogieType(disassembler.MethodBody.Parameters); var returnType = Helpers.GetMethodBoogieReturnType(mainMethod).Equals(Helpers.BoogieType.Void) ? String.Empty : ("returns ($result :" + Helpers.GetMethodBoogieReturnType(mainMethod) + ")"); sb.AppendLine(String.Format("procedure {{:entrypoint}} $Main_Wrapper_{0}({1}) {2}", methodName, parameters, returnType)); sb.AppendLine("{"); var variables = String.Empty; IMethodDefinition methodDef = mainMethod as IMethodDefinition; if (methodDef != null) { variables = String.Join(",", methodDef.Parameters.Select(v => v.Name)); } else { variables = String.Join(",", mainMethod.Parameters.Select(v => String.Format("param{0}", v.Index))); } if (mainMethod.CallingConvention.HasFlag(Microsoft.Cci.CallingConvention.HasThis)) { variables = String.Format("this", mainMethod.ParameterCount > 0 ? "," : String.Empty, parameters); } variables = Helpers.Strings.NormalizeStringForCorral(variables); sb.AppendLine("\tcall $allocate_static_fields();"); sb.AppendLine("\tcall $default_values_static_fields();"); sb.AppendLine("\tcall $initialize_globals();"); sb.AppendLine("\tcall $call_static_constructors();"); if (String.IsNullOrEmpty(returnType)) { sb.AppendLine(String.Format("\tcall {0}({1});", methodName, variables)); } else { sb.AppendLine(String.Format("\tcall $result := {0}({1});", methodName, variables)); } sb.AppendLine("\tif ($Exception != null)"); sb.AppendLine("\t{"); sb.AppendLine("\t\treturn;"); sb.AppendLine("\t}"); sb.AppendLine("}"); } return(sb.ToString()); }
public static String GetExternalMethodDefinition(IMethodReference methodRef) { var methodName = BoogieMethod.From(methodRef).Name; if (Helpers.IsCurrentlyMissing(methodRef)) { // TODO(rcastano): Add logger. Print this as INFO or WARNING level. Console.WriteLine("WARNING: Creating non-deterministic definition for missing method: " + methodName); } var parameters = Helpers.GetParametersWithBoogieType(methodRef); var returnType = String.Empty; if (Settings.NewAddrModelling) { #region Return variables in NewAddrModelling. We should only add the return variable type from CCI if (Helpers.GetMethodBoogieReturnType(methodRef).Equals(Helpers.BoogieType.Void)) { returnType = "returns ()"; } else { var returnVariables = new List <String>(); returnVariables.Add(String.Format("$result : {0}", Helpers.GetMethodBoogieReturnType(methodRef))); returnType = String.Format("returns ({0})", String.Join(",", returnVariables)); } #endregion } else { #region Return variables in old memory model. We need to add 'ref' parameters as return variables (in addition to the return variable from CCI). if (Helpers.GetMethodBoogieReturnType(methodRef).Equals(Helpers.BoogieType.Void)) { if (methodRef.Parameters.Any(p => p.IsByReference)) { var returnVariables = new List <String>(); returnVariables = methodRef.Parameters.Where(p => p.IsByReference).Select(p => String.Format("v{0}$out : {1}", p.Index, Helpers.GetBoogieType(p))).ToList(); returnType = String.Format("returns ({0})", String.Join(",", returnVariables)); } } else { var returnVariables = new List <String>(); returnVariables = methodRef.Parameters.Where(p => p.IsByReference).Select(p => String.Format("v{0}$out : {1}", p.Index, Helpers.GetBoogieType(p))).ToList(); returnVariables.Add(String.Format("$result : {0}", Helpers.GetMethodBoogieReturnType(methodRef))); returnType = String.Format("returns ({0})", String.Join(",", returnVariables)); } #endregion } var t = new BoogieProcedureTemplate(methodName, " {:extern} ", StatementList.Empty, StatementList.Empty, parameters, returnType, true); return(t.TransformText()); }
public string SetProcedureStub(IMethodReference method) { FieldTranslator field = new FieldTranslator(); var boogieName = field.BoogieNameForField(method.ContainingType, GetFieldName(method)); var paramType = Helpers.GetBoogieType(method.Parameters.ElementAt(0)); var get = new StatementList(); get.Add(BoogieStatement.FromString(boogieName + "[obj] := " + "val;")); var t = new BoogieProcedureTemplate(BoogieMethod.From(method).Name, "", StatementList.Empty, get, "obj : Ref, val : " + paramType, String.Empty, false); return(t.TransformText()); }
public string GetProcedureStub(IMethodReference method) { FieldTranslator field = new FieldTranslator(); var boogieName = field.BoogieNameForField(method.ContainingType, GetFieldName(method)); var boogieType = Helpers.GetBoogieType(method.Type); var get = new StatementList(); get.Add(BoogieStatement.FromString("$result := " + boogieName + "[obj];")); var t = new BoogieProcedureTemplate(BoogieMethod.From(method).Name, "", StatementList.Empty, get, "obj : Ref", String.Format(" returns ( $result : {0})", boogieType.ToString()), false); return(t.TransformText()); }
public String Translate() { // instructions must be translated before local variables // modification to local variables can ocurr while instruction translation is done // for example when delegate creation is detected some local variables are deleted. var ins = TranslateInstructions(out Dictionary <string, BoogieVariable> temporalVariables); var localVariables = TranslateLocalVariables(temporalVariables); var methodName = BoogieMethod.From(methodDefinition).Name; var attr = TranslateAttr(); var parametersWithTypes = Helpers.GetParametersWithBoogieType(methodDefinition); var returnTypeIfAny = TranslateReturnTypeIfAny(); var boogieProcedureTemplate = new BoogieProcedureTemplate(methodName, attr, localVariables, ins, parametersWithTypes, returnTypeIfAny, Helpers.IsExternal(methodDefinition)); return(boogieProcedureTemplate.TransformText()); }
// workaround public static Boolean IsExternal(IMethodDefinition methodDefinition) { if (methodDefinition.IsConstructor) { var methodName = BoogieMethod.From(methodDefinition).Name; if (methodName.Equals("System.Object.#ctor")) { return(true); } } if (methodDefinition.IsExternal) { return(true); } return(false); }
public static string CreateStaticConstructorsCallsProcedure() { StatementList body = new StatementList(); foreach (var staticConstructor in staticConstructors) { var ctor = BoogieMethod.From(staticConstructor); body.Add(BoogieGenerator.Instance().ProcedureCall(ctor, new List <Expression>(), null)); } string procedureName = "$call_static_constructors"; string attributes = String.Empty; StatementList localVariables = new StatementList(); String parametersWithTypes = String.Empty; String returnTypeIfAny = String.Empty; BoogieProcedureTemplate temp = new BoogieProcedureTemplate(procedureName, attributes, localVariables, body, parametersWithTypes, returnTypeIfAny, false); return(temp.TransformText()); }
private StatementList Invoke(IMethodDefinition member, BoogieVariable receiver) { Expression receiverObject = receiver; if (receiver.Type.Equals(Helpers.BoogieType.Addr)) { AddressExpression addrExpr = new AddressExpression(member.ContainingType, receiver); receiverObject = BoogieGenerator.Instance().ReadAddr(addrExpr); } Expression subtype = Expression.Subtype(Expression.DynamicType(receiverObject), member.ContainingType); StatementList body = new StatementList(); List <Expression> argumentList = new List <Expression>(); argumentList.Add(receiverObject); body.Add(BoogieGenerator.Instance().ProcedureCall(BoogieMethod.From(member), argumentList)); body.Add(BoogieStatement.ReturnStatement); var ifExpr = BoogieStatement.If(subtype, body); return(ifExpr); }
// called from Traverser // set in Main public static void TranslateAssemblies(ISet <Assembly> assemblies, ClassHierarchyAnalysis CHA) { foreach (Assembly assembly in assemblies) { foreach (IMethodDefinition methodDefinition in assembly.GetAllDefinedMethods()) { if (!methodDefinition.IsExternal) { try { var disassembler = new Disassembler(assembly.Host, methodDefinition, assembly.PdbReader); disassembler.Execute(); MethodBody mB = disassembler.MethodBody; ControlFlowGraph cfg = disassembler.ControlFlowGraph; // it would be faster to do this while we do // the global search for field references if (Settings.MemoryModel == ProgramOptions.MemoryModelOption.Mixed) { ReferenceFinder reference = new ReferenceFinder(); reference.CollectLocalVariables(mB); } MethodTranslator methodTranslator = new MethodTranslator(methodDefinition, mB, CHA, cfg, assembly, assemblies); // todo: improve this piece of code StreamWriter streamWriter = Program.streamWriter; streamWriter.WriteLine(methodTranslator.Translate()); Helpers.addTranslatedMethod(methodDefinition); } catch (InvalidOperationException ex) { Console.WriteLine("WARNING: Exception thrown while translating method (omitting): " + BoogieMethod.From(methodDefinition).Name); if (!Settings.SilentExceptionsForMethods) { throw ex; } } } } } }
public static void addTranslatedMethod(IMethodDefinition methodDefinition) { methodsTranslated.Add(BoogieMethod.From(methodDefinition).Name); }
// this method returns all method references that have been stubbed public IEnumerable <IMethodReference> Stub(ISet <Assembly> inputAssemblies, StreamWriter streamWriter) { PropertiesFinder propertiesFinder = new PropertiesFinder(); var nonExternMethods = inputAssemblies.GetAllDefinedMethods().Where(m => m.Body.Size > 0); var usedProperties = propertiesFinder.FindPropertiesCalls(inputAssemblies).Except(nonExternMethods); if (Settings.StubGettersSettersWhitelist.Count > 0) { usedProperties = usedProperties.Where(p => Settings.StubGettersSettersWhitelist.Contains(BoogieMethod.From(p).Name)); } var propertyFields = usedProperties.Select(propertyMethod => GetFieldDef(propertyMethod)).ToList().Distinct(); foreach (var propertyDefinition in propertyFields) { streamWriter.WriteLine(propertyDefinition); } foreach (var property in usedProperties) { //streamWriter.WriteLine(GetFieldDef(property)); var proc = property.Name.Value.StartsWith("get_") ? GetProcedureStub(property) : SetProcedureStub(property); streamWriter.WriteLine(proc); } return(usedProperties); }
// called from Traverser // set in Main public static void IMethodDefinitionTraverse(IMethodDefinition mD, IMetadataHost host, ISourceLocationProvider sourceLocationProvider) { // TODO: Hack to for treating a method as nondet var method = mD.ResolvedMethod; var methodName = method.ContainingType.FullName() + "." + method.Name.Value; if (methodName.Equals("SVX.ContractBase.getNondet")) { InstructionTranslator.AddToExternalMethods(method); return; } // End Hack if (!mD.IsExternal) { try { if (whitelistContains(mD.ContainingType.FullName())) { var disassembler = new Disassembler(host, mD, sourceLocationProvider); MethodBody mB = disassembler.Execute(); transformBody(mB); MethodTranslator methodTranslator = new MethodTranslator(mD, mB, Traverser.CHA); // todo: improve this piece of code StreamWriter streamWriter = Program.streamWriter; streamWriter.WriteLine(methodTranslator.Translate()); Helpers.addTranslatedMethod(mD); } } catch (InvalidOperationException ex) { Console.WriteLine("WARNING: Exception thrown while translating method (omitting): " + BoogieMethod.From(mD).Name); if (!Settings.SilentExceptionsForMethods) { throw ex; } } } }
public static void Start(ProgramOptions programOptions) { Console.WriteLine(programOptions); Settings.SetProgramOptions(programOptions); var outputPath = SetupOutputFile(); streamWriter.WriteLine(Resource.GetResourceAsString("TinyBCT.Resources.Prelude.bpl")); if (Settings.AsyncSupport || Settings.AsyncSupportGenerics) { streamWriter.WriteLine(Resource.GetResourceAsString("TinyBCT.Resources.CommonAsyncPrelude.bpl")); } if (Settings.AsyncSupport) { streamWriter.WriteLine(Resource.GetResourceAsString("TinyBCT.Resources.AsyncPrelude.bpl")); } if (Settings.AsyncSupportGenerics) { streamWriter.WriteLine(Resource.GetResourceAsString("TinyBCT.Resources.AsyncPreludeGeneric.bpl")); } using (var host = new PeReader.DefaultHost()) { #region Load assemblies ISet <Assembly> inputAssemblies = new HashSet <Assembly>(); foreach (string inputFile in Settings.InputFiles) { Assembly assembly = new Assembly(host); assembly.Load(inputFile); inputAssemblies.Add(assembly); } #endregion #region Execute CHA var CHAnalysis = new ClassHierarchyAnalysis(host); CHAnalysis.Analyze(); #endregion #region Initialize host types Types.Initialize(host); #endregion // TODO(diegog): Analysis not integrated yet // This can be used to obtain the allocated types and delegates //var allocationsAndDelelegatesAnalysis = new TypesAndDelegatesCollector(host); #region Write three address code for debugging TACWriter.WriteTAC(inputAssemblies); #endregion #region Look for references (used in mixed memory model) if (Settings.MemoryModel == ProgramOptions.MemoryModelOption.Mixed) { ReferenceFinder.TraverseForFields(inputAssemblies); } #endregion #region Translate defined types and add axioms about subtyping TypeDefinitionTranslator.TranslateTypes(inputAssemblies); #endregion #region Translate defined methods MethodTranslator.TranslateAssemblies(inputAssemblies, CHAnalysis); #endregion #region Create main wrapper with static fields initialization and static constructors calls StaticInitializer.SearchStaticConstructorsAndMain(inputAssemblies); streamWriter.WriteLine(StaticInitializer.CreateInitializeGlobals()); streamWriter.WriteLine(StaticInitializer.CreateMainWrappers()); streamWriter.WriteLine(StaticInitializer.CreateStaticVariablesAllocProcedure()); streamWriter.WriteLine(StaticInitializer.CreateDefaultValuesStaticVariablesProcedure()); streamWriter.WriteLine(StaticInitializer.CreateStaticConstructorsCallsProcedure()); #endregion #region Translate types that are referenced but not defined in the input assemblies TypeDefinitionTranslator.DefineUndeclaredSuperClasses(); TypeDefinitionTranslator.ParametricTypeDeclarations(); #endregion #region Translate string constants BoogieLiteral.Strings.WriteStringConsts(streamWriter); #endregion #region Translate delegates streamWriter.WriteLine(DelegateStore.DefineMethodsIdentifiers()); streamWriter.WriteLine(DelegateStore.CreateDelegateMethod()); streamWriter.WriteLine(DelegateStore.InvokeDelegateMethod()); #endregion // CreateAllAsyncMethods(streamWriter); #region Heuristic to catch getters & setters. If they are in our input assemblies we generate a body using a field associated to that property IEnumerable <IMethodReference> usedProperties = new List <IMethodReference>(); if (Settings.StubGettersSetters || Settings.StubGettersSettersWhitelist.Count > 0) { GetterSetterStub getterSetterStub = new GetterSetterStub(); usedProperties = getterSetterStub.Stub(inputAssemblies, streamWriter); } #endregion #region Generate stubs for async methods if (Settings.AsyncSupport) { AsyncStubs asyncStubs = new AsyncStubs(inputAssemblies); streamWriter.WriteLine(asyncStubs.AsyncMethodBuilderStartStub(false)); streamWriter.WriteLine(asyncStubs.AsyncStubsScheduleTask(false)); } if (Settings.AsyncSupportGenerics) { AsyncStubs asyncStubs = new AsyncStubs(inputAssemblies); streamWriter.WriteLine(asyncStubs.AsyncMethodBuilderStartStub(true)); streamWriter.WriteLine(asyncStubs.AsyncStubsScheduleTask(true)); } if (!Settings.AsyncSupport && Settings.AsyncSupportGenerics) { // this is only in AsyncSupport prelude // we can't add it to AsyncSupportGenerics because we are not always sure there will be all defined types and functions bool hasEventually = inputAssemblies.GetAllDefinedMethods().Any(m => m.Name.Value.Equals("Eventually")); if (hasEventually) { AsyncStubs asyncStubs = new AsyncStubs(inputAssemblies); streamWriter.WriteLine(asyncStubs.EventuallyStub()); } } #endregion streamWriter.WriteLine(StringTranslator.Stubs()); #region Translate called methods as extern (bodyless methods or methods not present in our input assemblies) var externMethods = InstructionTranslator.CalledMethods.Except(inputAssemblies.GetAllDefinedMethods().Where(m => m.Body.Size > 0)).Except(usedProperties); externMethods = externMethods.Where(m => !StringTranslator.GetBoogieNamesForStubs().Contains(BoogieMethod.From(m).Name)); foreach (var methodRef in externMethods) { var head = Helpers.GetExternalMethodDefinition(Helpers.GetUnspecializedVersion(methodRef)); streamWriter.WriteLine(head); } #endregion #region Translate class fields // we declare read or written fields foreach (var field in FieldTranslator.GetFieldDefinitions()) { streamWriter.WriteLine(field); } #endregion streamWriter.Close(); #region Append bpl input files foreach (var bplInputFile in Settings.BplInputFiles) { var output = new FileStream(outputPath, FileMode.Append, FileAccess.Write); using (var inputStream = File.OpenRead(bplInputFile)) { inputStream.CopyTo(output); } output.Close(); } #endregion } }
// called from Traverser // set in Main public static void IMethodDefinitionTraverse(IMethodDefinition mD, IMetadataHost host, ISourceLocationProvider sourceLocationProvider) { if (!mD.IsExternal) { try { var disassembler = new Disassembler(host, mD, sourceLocationProvider); MethodBody mB = disassembler.Execute(); MethodTranslator.transformBody(mB); TACWriter.AddMethod(mB); TACWriter.Write(); } catch (InvalidOperationException ex) { Console.WriteLine("WARNING: Exception thrown while translating method (omitting): " + BoogieMethod.From(mD).Name); if (!Settings.SilentExceptionsForMethods) { throw ex; } } } }