Esempio n. 1
0
        public static Assembly PruneAssembly(HostEnvironment host, ISlice <MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice)
        {
            Contract.Requires(host != null);
            Contract.Requires(slice != null);

            var newAssemblyName  = slice.Name;
            var originalAssembly = slice.ContainingAssembly.ResolvedAssembly;

            Contract.Assume(!(originalAssembly is Dummy));
            var methodDefsToKeep = new HashSet <uint>();

            foreach (var m in slice.Methods)
            {
                methodDefsToKeep.Add(m.reference.InternedKey);
            }


            var copier               = new MetadataDeepCopier(host);
            var thingsToKeep         = new HashSet <object>();
            var methodHashAttributes = new Dictionary <IMethodDefinition, MethodHashAttribute>();
            var me = new Prune(host, copier, thingsToKeep, methodDefsToKeep, methodHashAttributes);

            // 1. everything that is specified in the slice should definitely be kept.
            foreach (var c in slice.Chains)
            {
                me.VisitChain(c);
            }

            // 2. everything reachable from the initial set of things to keep should be kept
            Dictionary <IMethodDefinition, uint> contractOffsets;

            FindReachable.Reachable(host, slice, thingsToKeep, methodDefsToKeep, out contractOffsets);
            me.contractOffsets = contractOffsets;

            // 3. copy the original assembly --- entirely!
            var a_prime   = copier.Copy(originalAssembly);
            var nameTable = host.NameTable;

            a_prime.ModuleName = nameTable.GetNameFor(newAssemblyName + ".dll");
            a_prime.Name       = nameTable.GetNameFor(newAssemblyName);

            var mutableRoot             = (RootUnitNamespace)(a_prime.UnitNamespaceRoot);
            var methodHashAttributeType = DefineMethodHashAttributeType(host, mutableRoot);

            me.methodHashAttributeCtor = new Microsoft.Cci.MethodReference(
                host,
                methodHashAttributeType,
                CallingConvention.HasThis,
                host.PlatformType.SystemVoid,
                host.NameTable.Ctor,
                0,
                me.systemString,
                me.systemInt);

            // 4. delete all unwanted things from the mutable copy
            me.RewriteChildren(a_prime);

            var remainingTypes = new List <INamedTypeDefinition>(a_prime.AllTypes.Count); // will only shrink

            remainingTypes.Add(a_prime.AllTypes[0]);                                      // <Module> class is always kept
            for (int i = 1, n = a_prime.AllTypes.Count; i < n; i++)
            {
                var t = a_prime.AllTypes[i];
                Contract.Assume(t != null);
                Contract.Assume(copier.OriginalFor.ContainsKey(t));
                var orig = copier.OriginalFor[t];
                if (thingsToKeep.Contains(orig))
                {
                    remainingTypes.Add(t);
                }
            }
            a_prime.AllTypes = remainingTypes;
            // do this afterwards so it doesn't get visited.
            mutableRoot.Members.Add(methodHashAttributeType);
            a_prime.AllTypes.Add(methodHashAttributeType);

            return(a_prime);
        }
Esempio n. 2
0
        public bool WriteSliceToFile(ISlice <MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice, string directory, out string dll)
        {
#if TRACE_PERFORMANCE
            var stopWatch = new Stopwatch();
            stopWatch.Start();
#endif

            var newAssembly = Prune.PruneAssembly(host, slice);

#if TRACE_PERFORMANCE
            Console.WriteLine("Time to prune the assembly: {0}", stopWatch.Elapsed);
#endif

            var errors = ValidateAssembly(host, newAssembly);
            if (/*errors != null && */ 0 < errors.Count)
            {
#if !DEBUG_SLICE
                dll = null;
                return(false);
#endif
            }

            //Get a PDB reader if there is a PDB file.
            PdbReader /*?*/ pdbReader = null;
            string          pdbFile   = slice.ContainingAssembly.ResolvedAssembly.DebugInformationLocation;
            if (string.IsNullOrEmpty(pdbFile) || !File.Exists(pdbFile))
            {
                pdbFile = Path.ChangeExtension(slice.ContainingAssembly.ResolvedAssembly.Location, "pdb");
            }
            if (File.Exists(pdbFile))
            {
                using (var pdbStream = File.OpenRead(pdbFile)) {
                    pdbReader = new PdbReader(pdbStream, host);
                }
            }
            using (pdbReader) {
                ISourceLocationProvider sourceLocationProvider = pdbReader;
                ILocalScopeProvider     localScopeProvider     = pdbReader;

                Contract.Assume(sourceLocationProvider != null, "why??");
                if (!MakeSureSliceHasAtLeastMethodSourceLocation(slice, sourceLocationProvider))
                {
                    dll = null;
                    return(false);
                }

                dll = Path.Combine(directory, slice.Name + ".dll");

#if TRACE_PERFORMANCE
                stopWatch.Reset();
#endif

                using (var peStream = File.Create(dll)) {
                    if (pdbReader == null)
                    {
                        PeWriter.WritePeToStream(newAssembly, host, peStream);
                    }
                    else
                    {
                        using (var pdbWriter = new PdbWriter(dll.Replace(".dll", ".pdb"), pdbReader, emitTokenSourceInfo: true)) {
                            PeWriter.WritePeToStream(newAssembly, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter);
                        }
                    }
                }

#if TRACE_PERFORMANCE
                Console.WriteLine("Time spent to write on the disk: {0}", stopWatch.Elapsed);
#endif
            }

#if !DEBUG_SLICE
            if (errors != null && 0 < errors.Count)
            {
                using (var tw = new StreamWriter(File.Create(Path.Combine(directory, slice.Name + ".errors.txt"))))
                {
                    // something is performed asynchronously and may not be terminated here, that is wrong!
                    lock (errors)
                    {
                        foreach (var err in errors)
                        {
                            tw.WriteLine(err.Location);
                            foreach (var e in err.Errors)
                            {
                                tw.WriteLine("{0} {1} {2}", e.IsWarning ? "WARNING" : "ERROR ", e.Code, e.Message);
                            }
                            tw.WriteLine();
                        }
                    }
                }

                return(false);
            }
#endif

            // Can this be checked before writing it out?
            if (newAssembly.AssemblyReferences.Any(ar => ar.AssemblyIdentity.Equals(slice.ContainingAssembly.AssemblyIdentity)))
            {
            }

            return(true);
        }
Esempio n. 3
0
    public static Assembly PruneAssembly(HostEnvironment host, ISlice<MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice) {
      Contract.Requires(host != null);
      Contract.Requires(slice != null);

      var newAssemblyName = slice.Name;
      var originalAssembly = slice.ContainingAssembly.ResolvedAssembly;
      Contract.Assume(!(originalAssembly is Dummy));
      var methodDefsToKeep = new HashSet<uint>();
      foreach (var m in slice.Methods) {
        methodDefsToKeep.Add(m.reference.InternedKey);
      }


      var copier = new MetadataDeepCopier(host);
      var thingsToKeep = new HashSet<object>();
      var methodHashAttributes = new Dictionary<IMethodDefinition, MethodHashAttribute>();
      var me = new Prune(host, copier, thingsToKeep, methodDefsToKeep, methodHashAttributes);

      // 1. everything that is specified in the slice should definitely be kept.
      foreach (var c in slice.Chains) {
        me.VisitChain(c);
      }

      // 2. everything reachable from the initial set of things to keep should be kept
      Dictionary<IMethodDefinition, uint> contractOffsets;
      FindReachable.Reachable(host, slice, thingsToKeep, methodDefsToKeep, out contractOffsets);
      me.contractOffsets = contractOffsets;

      // 3. copy the original assembly --- entirely!
      var a_prime = copier.Copy(originalAssembly);
      var nameTable = host.NameTable;
      a_prime.ModuleName = nameTable.GetNameFor(newAssemblyName + ".dll");
      a_prime.Name = nameTable.GetNameFor(newAssemblyName);

      var mutableRoot = (RootUnitNamespace)(a_prime.UnitNamespaceRoot);
      var methodHashAttributeType = DefineMethodHashAttributeType(host, mutableRoot);
      me.methodHashAttributeCtor = new Microsoft.Cci.MethodReference(
          host,
          methodHashAttributeType,
          CallingConvention.HasThis,
          host.PlatformType.SystemVoid,
          host.NameTable.Ctor,
          0,
          me.systemString,
          me.systemInt);

      // 4. delete all unwanted things from the mutable copy
      me.RewriteChildren(a_prime);

      var remainingTypes = new List<INamedTypeDefinition>(a_prime.AllTypes.Count); // will only shrink
      remainingTypes.Add(a_prime.AllTypes[0]); // <Module> class is always kept
      for (int i = 1, n = a_prime.AllTypes.Count; i < n; i++) {
        var t = a_prime.AllTypes[i];
        Contract.Assume(t!= null);
        Contract.Assume(copier.OriginalFor.ContainsKey(t));
        var orig = copier.OriginalFor[t];
        if (thingsToKeep.Contains(orig))
          remainingTypes.Add(t);
      }
      a_prime.AllTypes = remainingTypes;
      // do this afterwards so it doesn't get visited.
      mutableRoot.Members.Add(methodHashAttributeType);
      a_prime.AllTypes.Add(methodHashAttributeType);

      return a_prime;
    }