public MethodTranslator(IMethodDefinition methodDefinition, MethodBody methodBody, ClassHierarchyAnalysis CHA, ControlFlowGraph cfg, Assembly assembly, ISet <Assembly> inputAssemblies) { this.methodDefinition = methodDefinition; this.methodBody = methodBody; this.CHA = CHA; this.CFG = cfg; this.assembly = assembly; this.inputAssemblies = inputAssemblies; }
static ClassHierarchyAnalysis CreateCHAnalysis(IMetadataHost host) { foreach (var inputFile in Settings.InputFiles) { var assembly = new Assembly(host); assembly.Load(inputFile); } var CHAnalysis = new ClassHierarchyAnalysis(host); CHAnalysis.Analyze(); return(CHAnalysis); }
// 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 void GenerateCG() { GenerateCH(); if (!programInfo.Contains("CG_TEXT")) { var ch = programInfo.Get <ClassHierarchy>("CH"); var cga = new ClassHierarchyAnalysis(ch); cga.OnReachableMethodFound = method => { //GenerateIL(method); GenerateTAC(method); }; var roots = host.GetRootMethods(); var cg = cga.Analyze(host, roots); var text = DGMLSerializer.Serialize(cg); programInfo.Add("CG_TEXT", text); } }
private void CallMethodData(MethodBase methodInfo, MethodData methodData, OperationKind operationKind, CrRuntimeLibrary crRuntime) { if (HandleRuntimeHelpersMethod(methodInfo)) { methodData.ExtractNeededValuesFromStack(_evaluator); AddOperation(OperationKind.CallRuntime, methodData); return; } if (methodInfo.IsConstructor && methodInfo.DeclaringType == typeof(object)) { return; } methodData.ExtractNeededValuesFromStack(_evaluator); if (!methodData.Info.IsStatic && methodData.Parameters.Count > 0) { methodData.Info = ClassHierarchyAnalysis.GetBestVirtualMatch(methodData.Info, methodData.Parameters[0].ComputedType().ClrType); } var declaringType = methodData.Info.DeclaringType; if (declaringType.IsSubclassOf(typeof(Delegate))) { var signature = declaringType.GetMethod("Invoke"); DelegateManager.RegisterType(declaringType, signature); } if (!methodData.IsVoid) { var vreg = SetNewVReg(); vreg.FixedType = new TypeDescription(methodInfo.GetReturnType()); methodData.Result = vreg; } methodData.FixedType = new TypeDescription(methodInfo.GetReturnType()); AddOperation(operationKind, methodData); }
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 } }
public static IList <IMethodReference> PotentialCalleesUsingCHA(IMethodReference unsolvedCallee, IVariable receiver, MethodCallOperation operation, ClassHierarchyAnalysis CHA) { var result = new List <IMethodReference>(); switch (operation) { case MethodCallOperation.Static: result.Add(unsolvedCallee); break; case MethodCallOperation.Virtual: //var receiver = invocation.Arguments[0]; var type = (receiver.Type is IGenericTypeInstanceReference) ? (receiver.Type as IGenericTypeInstanceReference).GenericType : receiver.Type; if (type is IManagedPointerTypeReference) { type = (type as IManagedPointerTypeReference).TargetType; type = TypeHelper.UninstantiateAndUnspecialize(type); } var calleeTypes = new List <ITypeReference>(CHA.GetAllSubtypes(type)); calleeTypes.Add(type); var candidateCalless = calleeTypes.Select(t => t.FindMethodImplementationForGenerics(unsolvedCallee)).Where(t => t != null); var candidateCalless2 = calleeTypes.Select(t => t.FindMethodImplementation(unsolvedCallee)).Where(t => t != null); candidateCalless = candidateCalless.Union(candidateCalless2); foreach (var candidate in candidateCalless) // improved this { if (!result.Contains(candidate)) { result.Add(candidate); } } break; } result.Sort(new SubtypeComparer()); // improved this return(result); }
public static string Serialize(ClassHierarchyAnalysis ch) { using (var stringWriter = new StringWriter()) using (var xmlWriter = new XmlTextWriter(stringWriter)) { var allDefinedTypes = new Dictionary <ITypeReference, int>(new TypeDefinitionComparer()); xmlWriter.Formatting = Formatting.Indented; xmlWriter.WriteStartElement("DirectedGraph"); xmlWriter.WriteAttributeString("xmlns", "http://schemas.microsoft.com/vs/2009/dgml"); xmlWriter.WriteStartElement("Nodes"); foreach (var type in ch.Types) { allDefinedTypes.Add(type, allDefinedTypes.Count); } foreach (var entry in allDefinedTypes) { var nodeId = Convert.ToString(entry.Value); var label = TypeHelper.GetTypeName(entry.Key); xmlWriter.WriteStartElement("Node"); xmlWriter.WriteAttributeString("Id", nodeId); xmlWriter.WriteAttributeString("Label", label); xmlWriter.WriteEndElement(); } xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("Links"); foreach (var entry in allDefinedTypes) { var sourceId = Convert.ToString(entry.Value); var subtypes = ch.GetSubtypes(entry.Key); foreach (var subtype in subtypes) { var subtypeId = allDefinedTypes[subtype]; var targetId = Convert.ToString(subtypeId); xmlWriter.WriteStartElement("Link"); xmlWriter.WriteAttributeString("Source", sourceId); xmlWriter.WriteAttributeString("Target", targetId); xmlWriter.WriteEndElement(); } } xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("Styles"); xmlWriter.WriteStartElement("Style"); xmlWriter.WriteAttributeString("TargetType", "Node"); xmlWriter.WriteStartElement("Setter"); xmlWriter.WriteAttributeString("Property", "FontFamily"); xmlWriter.WriteAttributeString("Value", "Consolas"); xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("Setter"); xmlWriter.WriteAttributeString("Property", "NodeRadius"); xmlWriter.WriteAttributeString("Value", "5"); xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("Setter"); xmlWriter.WriteAttributeString("Property", "MinWidth"); xmlWriter.WriteAttributeString("Value", "0"); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement(); xmlWriter.Flush(); return(stringWriter.ToString()); } }
public static ControlFlowGraph CFG; // ugly - the thing is that if labels were erased we can't create cfg public Traverser(IMetadataHost host, ISourceLocationProvider sourceLocationProvider, ClassHierarchyAnalysis CHAnalysis) { this.host = host; this.sourceLocationProvider = sourceLocationProvider; CHA = CHAnalysis; }
public MethodTranslator(IMethodDefinition methodDefinition, MethodBody methodBody, ClassHierarchyAnalysis CHA) { this.methodDefinition = methodDefinition; this.methodBody = methodBody; this.CHA = CHA; }
public static IList <IMethodReference> PotentialCalleesUsingCHA(IMethodReference unsolvedCallee, IVariable receiver, MethodCallOperation operation, ClassHierarchyAnalysis CHA) { var result = new List <IMethodReference>(); // var unsolvedCallee = invocation.Method; if (unsolvedCallee.Name.Value.Contains("GetEnumerator")) { } switch (operation) { case MethodCallOperation.Static: result.Add(unsolvedCallee); break; case MethodCallOperation.Virtual: //var receiver = invocation.Arguments[0]; var type = (receiver.Type is IGenericTypeInstanceReference) ? (receiver.Type as IGenericTypeInstanceReference).GenericType : receiver.Type; if (type is IManagedPointerTypeReference) { type = (type as IManagedPointerTypeReference).TargetType; type = TypeHelper.UninstantiateAndUnspecialize(type); //type = (type is IGenericTypeInstanceReference) ? (type as IGenericTypeInstanceReference).GenericType : type; } var calleeTypes = new List <ITypeReference>(CHA.GetAllSubtypes(type)); //// Hack to get the type from CollectionStubs //var typeCHA = CHA.Types.SingleOrDefault(t => t.ToString() == type.ToString()); //if (typeCHA != null) // type = typeCHA; calleeTypes.Add(type); var candidateCalless = calleeTypes.Select(t => t.FindMethodImplementationForGenerics(unsolvedCallee)).Where(t => t != null); var candidateCalless2 = calleeTypes.Select(t => t.FindMethodImplementation(unsolvedCallee)).Where(t => t != null); candidateCalless = candidateCalless.Union(candidateCalless2); foreach (var candidate in candidateCalless) // improved this { if (!result.Contains(candidate)) { result.Add(candidate); } } //result.AddRange(candidateCalless); break; } result.Sort(new SubtypeComparer()); // improved this return(result); }