private static void Main(string[] args)
        {
            bool removeDirectory;
            string temporaryDirectory = GetTemporaryDirectory(out removeDirectory);
            Console.WriteLine("Working directory: {0}", temporaryDirectory);

            try
            {
                IPackageRepository sourceRepository = PackageRepositoryFactory.Default.CreateRepository("https://www.nuget.org/api/v2/");
                PackageManager packageManager = new PackageManager(sourceRepository, temporaryDirectory);
                packageManager.PackageInstalled += HandlePackageInstalled;
                packageManager.InstallPackage("Microsoft.Bcl.Immutable", SemanticVersion.Parse("1.0.34"));
                packageManager.InstallPackage("System.Collections.Immutable", SemanticVersion.Parse("1.1.33-beta"));

                using (PEReader referenceAssembly = new PEReader(File.OpenRead(Path.Combine(temporaryDirectory, "Microsoft.Bcl.Immutable.1.0.34", "lib", "portable-net45+win8+wp8+wpa81", "System.Collections.Immutable.dll"))))
                {
                    using (PEReader newAssembly = new PEReader(File.OpenRead(Path.Combine(temporaryDirectory, "System.Collections.Immutable.1.1.33-beta", "lib", "portable-net45+win8+wp8+wpa81", "System.Collections.Immutable.dll"))))
                    {
                        Analyzer analyzer = new Analyzer(referenceAssembly, newAssembly, null);
                        analyzer.Run();
                    }
                }
            }
            finally
            {
                if (removeDirectory)
                    Directory.Delete(temporaryDirectory, true);
            }
        }
        static void Main(string[] args)
        {
            if (args.Length == 0 || new[] {"/?", "-?", "-h", "--help"}.Any(x => string.Equals(args[0], x, StringComparison.OrdinalIgnoreCase)))
            {
                PrintUsage();
                return;
            }

            foreach (var fileName in args)
            {
                Console.WriteLine(fileName);
                Console.WriteLine(new string('*', 80));

                try
                {
                    using (var stream = File.OpenRead(fileName))
                    using (var peFile = new PEReader(stream))
                    {
                        var metadataReader = peFile.GetMetadataReader();
                        var visualizer = new MetadataVisualizer(metadataReader, Console.Out);
                        visualizer.Visualize();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);                    
                }
            }
        }
 public InspectableAssembly(string filename, ParseContext context)
 {
     Stream = File.OpenRead(filename);
     Pe = new PEReader(Stream);
     Reader = Pe.GetMetadataReader();
     Context = context;
 }
        public static AssemblyIdentity TryGetAssemblyIdentity(string filePath)
        {
            try
            {
                using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete))
                using (var peReader = new PEReader(stream))
                {
                    var metadataReader = peReader.GetMetadataReader();

                    AssemblyDefinition assemblyDefinition = metadataReader.GetAssemblyDefinition();

                    string name = metadataReader.GetString(assemblyDefinition.Name);
                    Version version = assemblyDefinition.Version;

                    StringHandle cultureHandle = assemblyDefinition.Culture;
                    string cultureName = (!cultureHandle.IsNil) ? metadataReader.GetString(cultureHandle) : null;
                    AssemblyFlags flags = assemblyDefinition.Flags;

                    bool hasPublicKey = (flags & AssemblyFlags.PublicKey) != 0;
                    BlobHandle publicKeyHandle = assemblyDefinition.PublicKey;
                    ImmutableArray<byte> publicKeyOrToken = !publicKeyHandle.IsNil
                        ? metadataReader.GetBlobBytes(publicKeyHandle).AsImmutableOrNull()
                        : default(ImmutableArray<byte>);
                    return new AssemblyIdentity(name, version, cultureName, publicKeyOrToken, hasPublicKey);
                }
            }
            catch { }

            return null;
        }
Exemple #5
0
         + sizeof(Int64); // metadata directory

        private static bool ExecuteCore(string assemblyPath)
        {
            if (Directory.Exists(assemblyPath))
            {
                Console.Error.WriteLine($"Expected file, not a directory: {assemblyPath}");
                return false;
            }

            if (!File.Exists(assemblyPath))
            {
                Console.Error.WriteLine($"File not found: {assemblyPath}");
                return false;
            }

            using (var stream = OpenFile(assemblyPath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
            using (var reader = new PEReader(stream))
            using (var writer = new BinaryWriter(stream))
            {
                if (!Validate(reader))
                {
                    Console.Error.WriteLine($"Unable to sign {assemblyPath}");
                    return false;
                }

                stream.Position = reader.PEHeaders.CorHeaderStartOffset + OffsetFromStartOfCorHeaderToFlags;
                writer.Write((UInt32)(reader.PEHeaders.CorHeader.Flags | CorFlags.StrongNameSigned));
            }

            return true;
        }
Exemple #6
0
        public PE(string fileName)
        {
            FileName = Path.GetFullPath(fileName);
            Uri = new Uri(FileName);
            IsPEFile = false;
            try
            {
                _fs = File.OpenRead(FileName);

                byte byteRead = (byte)_fs.ReadByte();
                if (byteRead != 'M') { return; }

                byteRead = (byte)_fs.ReadByte();
                if (byteRead != 'Z') { return; }
                _fs.Seek(0, SeekOrigin.Begin);

                _peReader = new PEReader(_fs);
                PEHeaders = _peReader.PEHeaders;
                IsPEFile = true;
            }
            catch (IOException e) { LoadException = e; }
            catch (BadImageFormatException e) { LoadException = e; }
            catch (UnauthorizedAccessException e) { LoadException = e; }

            if (IsPEFile)
            {
                m_pImage = new SafePointer(_peReader.GetEntireImage().GetContent().ToBuilder().ToArray());

                if (IsManaged)
                {
                    _metadataReader = _peReader.GetMetadataReader();
                }
            }
        }
        /// <summary>
        /// Returns true if the PE file meets all of the pre-conditions to be Open Source Signed.
        /// Returns false and logs msbuild errors otherwise.
        /// </summary>
        private bool Validate(PEReader peReader)
        {
            if (!peReader.HasMetadata)
            {
                LogError("PE file is not a managed module.");
                return false;
            }

            var mdReader = peReader.GetMetadataReader();
            if (!mdReader.IsAssembly)
            {
                LogError("PE file is not an assembly.");
                return false;
            }

            CorHeader header = peReader.PEHeaders.CorHeader;
            if ((header.Flags & CorFlags.StrongNameSigned) == CorFlags.StrongNameSigned)
            {
                LogError("PE file is already strong-name signed.");
                return false;
            }

            if ((header.StrongNameSignatureDirectory.Size <= 0) || mdReader.GetAssemblyDefinition().PublicKey.IsNil)
            {
                LogError("PE file is not a delay-signed assembly.");
                return false;
            }

            return true;
        }
        public static EcmaModule Create(TypeSystemContext context, PEReader peReader, PdbSymbolReader pdbReader)
        {
            MetadataReader metadataReader = CreateMetadataReader(context, peReader);

            if (metadataReader.IsAssembly)
                return new EcmaAssembly(context, peReader, metadataReader, pdbReader);
            else
                return new EcmaModule(context, peReader, metadataReader, pdbReader);
        }
Exemple #9
0
 public void OpenNativeImage()
 {
     using (var reader = new PEReader(File.OpenRead(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "kernel32.dll"))))
     {
         Assert.False(reader.HasMetadata);
         Assert.True(reader.PEHeaders.IsDll);
         Assert.False(reader.PEHeaders.IsExe);
         Assert.Throws<InvalidOperationException>(() => reader.GetMetadataReader());
     }
 }
 public static ISymUnmanagedReader CreateReader(Stream pdbStream, Stream peStreamOpt = null)
 {
     if (peStreamOpt != null)
     {
         var peReader = new PEReader(peStreamOpt);
         return CreateReader(pdbStream, peReader.GetMetadataReader(), peReader);
     }
     else
     {
         return CreateReader(pdbStream, null, null);
     }
 }
        public override bool Execute()
        {
            if (Assemblies == null || Assemblies.Length == 0)
                return true;

            List<ITaskItem> references = new List<ITaskItem>();
            List<ITaskItem> nativeLibs = new List<ITaskItem>();

            foreach (var assemblyItem in Assemblies)
            {
                try
                {
                    if (!File.Exists(assemblyItem.ItemSpec))
                    {
                        Log.LogError($"File {assemblyItem.ItemSpec} does not exist, ensure you have built libraries before building the package.");
                        continue;
                    }

                    using (PEReader peReader = new PEReader(new FileStream(assemblyItem.ItemSpec, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read)))
                    {
                        MetadataReader reader = peReader.GetMetadataReader();
                        foreach (var handle in reader.AssemblyReferences)
                        {
                            AssemblyReference reference = reader.GetAssemblyReference(handle);
                            TaskItem referenceItem = new TaskItem(reader.GetString(reference.Name));
                            assemblyItem.CopyMetadataTo(referenceItem);
                            referenceItem.SetMetadata("Version", reference.Version.ToString());
                            referenceItem.SetMetadata("AssemblyVersion", reference.Version.ToString());
                            references.Add(referenceItem);
                        }

                        for (int i = 1, count = reader.GetTableRowCount(TableIndex.ModuleRef); i <= count; i++)
                        {
                            var moduleRef = reader.GetModuleReference(MetadataTokens.ModuleReferenceHandle(i));
                            var moduleName = reader.GetString(moduleRef.Name);

                            TaskItem nativeLib = new TaskItem(moduleName);
                            assemblyItem.CopyMetadataTo(nativeLib);
                            nativeLibs.Add(nativeLib);
                        }
                    }
                }
                catch (InvalidOperationException)
                {
                    // Ignore invalid assemblies
                }
            }

            ReferencedAssemblies = references.ToArray();
            ReferencedNativeLibraries = nativeLibs.ToArray();

            return true;
        }
Exemple #12
0
        public void IL_EagerLoad()
        {
            var peStream = new MemoryStream(TestResources.Misc.Members);
            using (var reader = new PEReader(peStream, PEStreamOptions.LeaveOpen | PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage))
            {
                var md = reader.GetMetadataReader();
                var il = reader.GetMethodBody(md.GetMethodDefinition(MetadataTokens.MethodDefinitionHandle(1)).RelativeVirtualAddress);

                Assert.Equal(new byte[] { 0, 42 }, il.GetILBytes());
                Assert.Equal(8, il.MaxStack);
            }
        }
        public static ReadOnlyCollection<Message> AnalyzeAssemblies(string referenceAssemblyFile, string newAssemblyFile)
        {
            using (PEReader referenceAssembly = new PEReader(File.OpenRead(referenceAssemblyFile)))
            {
                using (PEReader newAssembly = new PEReader(File.OpenRead(newAssemblyFile)))
                {
                    TestMessageLogger logger = new TestMessageLogger();
                    Analyzer analyzer = new Analyzer(referenceAssembly, newAssembly, logger);
                    analyzer.Run();

                    return logger.RawMessages;
                }
            }
        }
        public override bool Execute()
        {
            Log.LogMessage(MessageImportance.High, "About to inspect {0} test assemblies.", TestBinaries.Length);
            var perfTests = new List<ITaskItem>();

            foreach (var testBinary in TestBinaries)
            {
                Log.LogMessage(MessageImportance.Low, "Inspecting assembly {0}.", testBinary.ItemSpec);

                using (var stream = File.OpenRead(testBinary.ItemSpec))
                {
                    using (var peFile = new PEReader(stream))
                    {
                        if(!peFile.HasMetadata){
                            continue;
                        }
                        var mdReader = peFile.GetMetadataReader();

                        foreach (var asmRefHandle in mdReader.AssemblyReferences)
                        {
                            var asmRef = mdReader.GetAssemblyReference(asmRefHandle);
                            var asmRefName = mdReader.GetString(asmRef.Name);

                            // if an assembly contains a reference to xunit.performance.core
                            // then it contains at least one performance test.

                            if (string.Compare(asmRefName, "xunit.performance.core", StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                var fileName = (GetFullPaths) ? Path.GetFullPath(testBinary.ItemSpec) : Path.GetFileNameWithoutExtension(testBinary.ItemSpec);
                                perfTests.Add(new TaskItem(fileName));
                                Log.LogMessage("+ Assembly {0} contains one or more performance tests.", fileName);
                                break;
                            }
                        }
                    }
                }
            }

            if (perfTests.Count > 0)
            {
                PerfTestAssemblies = perfTests.ToArray();
                Log.LogMessage(MessageImportance.High, "Found {0} assemblies containing performance tests.", perfTests.Count);
            }
            else
            {
                Log.LogWarning("Didn't find any performance tests.");
            }

            return true;
        }
Exemple #15
0
        public void Dispose()
        {
            if (_peReader != null)
            {
                _peReader.Dispose();
                _peReader = null;
            }

            if (_fs != null)
            {
                _fs.Dispose();
                _fs = null;
            }
        }
        public static AssemblyInfo GetAssemblyInfo(string path)
        {
            using (var peReader = new PEReader(new FileStream(path, FileMode.Open, FileAccess.Read)))
            {
                var contractReader = peReader.GetMetadataReader();
                var assembly = contractReader.GetAssemblyDefinition();

                var name = contractReader.GetString(assembly.Name);
                var version = assembly.Version;
                var references = GetAssemblyReferences(contractReader);

                return new AssemblyInfo(path, name, version, references);
            }
        }
        /// <summary>
        /// Given a path to an assembly, returns its MVID (Module Version ID).
        /// May throw.
        /// </summary>
        /// <exception cref="IOException">If the file at <paramref name="filePath"/> does not exist or cannot be accessed.</exception>
        /// <exception cref="BadImageFormatException">If the file is not an assembly or is somehow corrupted.</exception>
        public static Guid ReadMvid(string filePath)
        {
            Debug.Assert(filePath != null);
            Debug.Assert(PathUtilities.IsAbsolute(filePath));

            using (var reader = new PEReader(FileUtilities.OpenRead(filePath)))
            {
                var metadataReader = reader.GetMetadataReader();
                var mvidHandle = metadataReader.GetModuleDefinition().Mvid;
                var fileMvid = metadataReader.GetGuid(mvidHandle);

                return fileMvid;
            }
        }
Exemple #18
0
        public void EmbeddedPortablePdb()
        {
            string source = @"
            using System;

            class C
            {
            public static void Main()
            {
            Console.WriteLine();
            }
            }
            ";
            var c = CreateCompilationWithMscorlib(Parse(source, "foo.cs"), options: TestOptions.DebugDll);

            var peBlob = c.EmitToArray(EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.Embedded).WithPdbFilePath(@"a/b/c/d.pdb"));

            using (var peReader = new PEReader(peBlob))
            {
                var entries = peReader.ReadDebugDirectory();

                AssertEx.Equal(new[] { DebugDirectoryEntryType.CodeView, DebugDirectoryEntryType.EmbeddedPortablePdb }, entries.Select(e => e.Type));

                var codeView = entries[0];
                var embedded = entries[1];

                // EmbeddedPortablePdb entry:
                Assert.Equal(0x0100, embedded.MajorVersion);
                Assert.Equal(0x0100, embedded.MinorVersion);
                Assert.Equal(0u, embedded.Stamp);

                BlobContentId pdbId;
                using (var embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embedded))
                {
                    var mdReader = embeddedMetadataProvider.GetMetadataReader();
                    AssertEx.Equal(new[] { "foo.cs" }, mdReader.Documents.Select(doc => mdReader.GetString(mdReader.GetDocument(doc).Name)));

                    pdbId = new BlobContentId(mdReader.DebugMetadataHeader.Id);
                }

                // CodeView entry:
                var codeViewData = peReader.ReadCodeViewDebugDirectoryData(codeView);
                Assert.Equal(0x0100, codeView.MajorVersion);
                Assert.Equal(0x504D, codeView.MinorVersion);
                Assert.Equal(pdbId.Stamp, codeView.Stamp);
                Assert.Equal(pdbId.Guid, codeViewData.Guid);
                Assert.Equal("d.pdb", codeViewData.Path);
            }
        }
        public void TestSpansPresentInResource()
        {
            var c = CreateCompilationWithMscorlib(Parse(ExampleSource + InstrumentationHelperSource, @"C:\myproject\doc1.cs"));
            var peImage = c.EmitToArray(EmitOptions.Default.WithInstrumentationKinds(ImmutableArray.Create(InstrumentationKind.TestCoverage)));
       
            var peReader = new PEReader(peImage);
            var reader = DynamicAnalysisDataReader.TryCreateFromPE(peReader, "<DynamicAnalysisData>");

            VerifyDocuments(reader, reader.Documents,
                @"'C:\myproject\doc1.cs' FF-9A-1F-F4-03-A5-A1-F7-8D-CD-00-15-67-0E-BA-F7-23-9D-3F-0F (SHA1)");

            Assert.Equal(12, reader.Methods.Length);

            string[] sourceLines = ExampleSource.Split('\n');

            VerifySpans(reader, reader.Methods[0], sourceLines,                         // Main
                new SpanResult(5, 4, 9, 5, "public static void Main()"),
                new SpanResult(7, 8, 7, 31, "Console.WriteLine(123)"),
                new SpanResult(8, 8, 8, 31, "Console.WriteLine(123)"));

            VerifySpans(reader, reader.Methods[1], sourceLines,                         // Fred get
                new SpanResult(11, 4, 11, 32, "public static int Fred => 3"),
                new SpanResult(11, 30, 11, 31, "3"));

            VerifySpans(reader, reader.Methods[2], sourceLines,                         // Barney
                new SpanResult(13, 4, 13, 41, "public static int Barney(int x) => x"),
                new SpanResult(13, 39, 13, 40, "x"));

            VerifySpans(reader, reader.Methods[3], sourceLines,                         // Wilma get
                new SpanResult(17, 8, 17, 26, "get { return 12; }"),
                new SpanResult(17, 14, 17, 24, "return 12"));

            VerifySpans(reader, reader.Methods[4], sourceLines,                         // Wilma set
                new SpanResult(18, 8, 18, 15, "set { }"));

            VerifySpans(reader, reader.Methods[5], sourceLines,                         // Betty get
                new SpanResult(21, 4, 21, 36, "public static int Betty { get; }"),
                new SpanResult(21, 30, 21, 34, "get"));

            VerifySpans(reader, reader.Methods[6], sourceLines,                         // Pebbles get
                new SpanResult(23, 4, 23, 43, "public static int Pebbles { get; set; }"),
                new SpanResult(23, 32, 23, 36, "get"));

            VerifySpans(reader, reader.Methods[7], sourceLines,                         // Pebbles set
                new SpanResult(23, 4, 23, 43, "public static int Pebbles { get; set; }"),
                new SpanResult(23, 37, 23, 41, "set"));

            VerifySpans(reader, reader.Methods[8]);
        }
Exemple #20
0
        internal override void RemovePublicSign(string assemblyPath)
        {
            using (var stream = new FileStream(assemblyPath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
            using (var peReader = new PEReader(stream))
            using (var writer = new BinaryWriter(stream))
            {
                if (!IsPublicSigned(peReader))
                {
                    return;
                }

                stream.Position = peReader.PEHeaders.CorHeaderStartOffset + OffsetFromStartOfCorHeaderToFlags;
                writer.Write((UInt32)(peReader.PEHeaders.CorHeader.Flags | CorFlags.StrongNameSigned));
            }
        }
Exemple #21
0
        public void BasicValidation()
        {
            using (var peStream = new MemoryStream())
            {
                var ilBuilder = new BlobBuilder();
                var metadataBuilder = new MetadataBuilder();
                var entryPoint = BasicValidationEmit(metadataBuilder, ilBuilder);
                WritePEImage(peStream, metadataBuilder, ilBuilder, entryPoint);

                peStream.Position = 0;
                var r = new PEReader(peStream);
                var h = r.PEHeaders;
                var mdReader = r.GetMetadataReader();
            }
        }
Exemple #22
0
         + sizeof(Int64); // metadata directory

        private static bool ExecuteCore(string assemblyPath, bool unSign = false, bool force = false)
        {
            if (Directory.Exists(assemblyPath))
            {
                Console.Error.WriteLine($"Expected file, not a directory: {assemblyPath}");
                return false;
            }

            if (!File.Exists(assemblyPath))
            {
                Console.Error.WriteLine($"File not found: {assemblyPath}");
                return false;
            }

            using (var stream = OpenFile(assemblyPath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
            using (var reader = new PEReader(stream))
            using (var writer = new BinaryWriter(stream))
            {
                var mdReader = ValidateManagedAssemblyAndGetMetadataReader(reader);
                if (mdReader == null)
                {
                    Console.Error.WriteLine($"Cannot {(unSign ? "un-sign" : "sign")} {assemblyPath}.");
                    return false;
                }

                if (!force && !Validate(reader, mdReader, unSign))
                {
                    Console.Error.WriteLine($"Use the -f (force) option to {(unSign ? "un-sign" : "sign")} {assemblyPath} anyway.");
                    return false;
                }

                stream.Position = reader.PEHeaders.CorHeaderStartOffset + OffsetFromStartOfCorHeaderToFlags;

                var flags = reader.PEHeaders.CorHeader.Flags;
                if (unSign)
                {
                    flags &= ~CorFlags.StrongNameSigned;
                }
                else
                {
                    flags |= CorFlags.StrongNameSigned;
                }

                writer.Write((UInt32)flags);
            }

            return true;
        }
        public static ImmutableArray<DebugDirectoryEntry> ReadDebugDirectory(PEReader peReader, Stream peStream)
        {
            var debugDirectory = peReader.PEHeaders.PEHeader.DebugTableDirectory;

            // TODO: Add API to PEReader to get a memory block for a directory

            int position;
            if (!peReader.PEHeaders.TryGetDirectoryOffset(debugDirectory, out position))
            {
                throw new BadImageFormatException();
            }

            const int entrySize = 0x1c;

            if (debugDirectory.Size % entrySize != 0)
            {
                throw new BadImageFormatException();
            }

            peStream.Position = position;
            var reader = new BinaryReader(peStream);

            int entryCount = debugDirectory.Size / entrySize;
            var builder = ImmutableArray.CreateBuilder<DebugDirectoryEntry>(entryCount);
            for (int i = 0; i < entryCount; i++)
            {
                // Reserved, must be zero.
                int characteristics = reader.ReadInt32();
                if (characteristics != 0)
                {
                    throw new BadImageFormatException();
                }

                uint stamp = reader.ReadUInt32();
                ushort majorVersion = reader.ReadUInt16();
                ushort minorVersion = reader.ReadUInt16();

                var type = (DebugDirectoryEntryType)reader.ReadInt32();

                int dataSize = reader.ReadInt32();
                int dataRva = reader.ReadInt32();
                int dataPointer = reader.ReadInt32();

                builder.Add(new DebugDirectoryEntry(stamp, majorVersion, minorVersion, type, dataSize, dataRva, dataPointer));
            }

            return builder.MoveToImmutable();
        }
Exemple #24
0
        /// <summary>
        /// Returns true if the PE file meets all of the pre-conditions to be Open Source Signed.
        /// Returns false and logs msbuild errors otherwise.
        /// </summary>
        private static bool IsPublicSigned(PEReader peReader)
        {
            if (!peReader.HasMetadata)
            {
                return false;
            }

            var mdReader = peReader.GetMetadataReader();
            if (!mdReader.IsAssembly)
            {
                return false;
            }

            CorHeader header = peReader.PEHeaders.CorHeader;
            return (header.Flags & CorFlags.StrongNameSigned) == CorFlags.StrongNameSigned;
        }
Exemple #25
0
        public static bool HasMetadata(string pathToFile)
        {
            try
            {
                using (var inStream = File.OpenRead(pathToFile))
                {
                    using (var peReader = new PEReader(inStream))
                    {
                        return peReader.HasMetadata;
                    }
                }
            }
            catch (BadImageFormatException) { }

            return false;
        }
Exemple #26
0
        private static unsafe byte[] GetEmbeddedResourceContents(PEReader peReader, ManifestResource resource)
        {
            if (!resource.Implementation.IsNil)
            {
                throw new ArgumentException("Resource is not embedded in the PE file.", "resource");
            }

            checked // arithmetic overflow here could cause AV
            {
                // Locate start and end of PE image in unmanaged memory.
                var block = peReader.GetEntireImage();
                int peImageSize = block.Length;
                byte* peImageStart = block.Pointer;
                byte* peImageEnd = peImageStart + peImageSize;
                Debug.Assert(peImageStart != null && peImageSize > 0);

                // Locate offset to resources within PE image.
                int offsetToResources;
                if (!peReader.PEHeaders.TryGetDirectoryOffset(peReader.PEHeaders.CorHeader.ResourcesDirectory, out offsetToResources))
                {
                    throw new InvalidDataException("Failed to get offset to resources in PE file.");
                }
                Debug.Assert(offsetToResources > 0);
                byte* resourceStart = peImageStart + offsetToResources + resource.Offset;

                // Get the length of the the resource from the first 4 bytes.
                if (resourceStart >= peImageEnd - sizeof(int))
                {
                    throw new InvalidDataException("resource offset out of bounds.");
                }
                int resourceLength = *(int*)(resourceStart);
                resourceStart += sizeof(int);
                if (resourceLength < 0 || resourceStart >= peImageEnd - resourceLength)
                {
                    throw new InvalidDataException("resource offset or length out of bounds.");
                }

                // TODO: Use UmanagedMemoryStream when available on core clr
                var buffer = new byte[resourceLength];
                for (int i = 0; i < resourceLength; i++)
                {
                    buffer[i] = *(resourceStart + i);
                }

                return buffer;
            }
        }
        private bool ExecuteCore()
        {
            using (var stream = OpenFile(this.AssemblyPath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
            using (var reader = new PEReader(stream))
            using (var writer = new BinaryWriter(stream))
            {
                if (!Validate(reader))
                {
                    return false;
                }

                stream.Position = reader.PEHeaders.CorHeaderStartOffset + OffsetFromStartOfCorHeaderToFlags;
                writer.Write((UInt32)(reader.PEHeaders.CorHeader.Flags | CorFlags.StrongNameSigned));
            }

            return true;
        }
Exemple #28
0
        private static MetadataReader ValidateManagedAssemblyAndGetMetadataReader(PEReader peReader)
        {
            if (!peReader.HasMetadata)
            {
                Console.Error.WriteLine("PE file is not a managed module.");
                return null;
            }

            var mdReader = peReader.GetMetadataReader();
            if (!mdReader.IsAssembly)
            {
                Console.Error.WriteLine("PE file is not an assembly.");
                return null;
            }

            return mdReader;
        }
        /// <remarks>
        /// Based on https://gist.github.com/nguerrera/72444715c7ea0b40addb
        /// </remarks>
        public static byte[] GetILBytes(this MethodInfo methodInfo)
        {
#if NET45
            return methodInfo.GetMethodBody().GetILAsByteArray();
#else
            var metadataToken = methodInfo.GetMetadataToken();
            
            using (var stream = File.OpenRead(methodInfo.DeclaringType.GetTypeInfo().Assembly.Location))
            using (var peReader = new PEReader(stream))
            {
                var metadataReader = peReader.GetMetadataReader();
                var methodHandle = MetadataTokens.MethodDefinitionHandle(metadataToken);
                var methodDefinition = metadataReader.GetMethodDefinition(methodHandle);
                var methodBody = peReader.GetMethodBody(methodDefinition.RelativeVirtualAddress);
                return methodBody.GetILBytes();
            }
#endif
        }
        /// <summary>
        /// Given a path to an assembly, identifies files in the same directory
        /// that could satisfy the assembly's dependencies. May throw.
        /// </summary>
        /// <remarks>
        /// Dependencies are identified by simply checking the name of an assembly
        /// reference against a file name; if they match the file is considered a
        /// dependency. Other factors, such as version, culture, public key, etc., 
        /// are not considered, and so the returned collection may include items that
        /// cannot in fact satisfy the original assembly's dependencies.
        /// </remarks>
        /// <exception cref="IOException">If the file at <paramref name="filePath"/> does not exist or cannot be accessed.</exception>
        /// <exception cref="BadImageFormatException">If the file is not an assembly or is somehow corrupted.</exception>
        public static ImmutableArray<string> FindAssemblySet(string filePath)
        {
            Debug.Assert(filePath != null);
            Debug.Assert(PathUtilities.IsAbsolute(filePath));

            Queue<string> workList = new Queue<string>();
            HashSet<string> assemblySet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

            workList.Enqueue(filePath);

            while (workList.Count > 0)
            {
                string assemblyPath = workList.Dequeue();

                if (!assemblySet.Add(assemblyPath))
                {
                    continue;
                }

                var directory = Path.GetDirectoryName(assemblyPath);

                using (var reader = new PEReader(FileUtilities.OpenRead(assemblyPath)))
                {
                    var metadataReader = reader.GetMetadataReader();
                    var assemblyReferenceHandles = metadataReader.AssemblyReferences;

                    foreach (var handle in assemblyReferenceHandles)
                    {
                        var reference = metadataReader.GetAssemblyReference(handle);
                        var referenceName = metadataReader.GetString(reference.Name);

                        string referencePath = Path.Combine(directory, referenceName + ".dll");

                        if (!assemblySet.Contains(referencePath) &&
                            File.Exists(referencePath))
                        {
                            workList.Enqueue(referencePath);
                        }
                    }
                }
            }

            return ImmutableArray.CreateRange(assemblySet);
        }
Exemple #31
0
        static int InnerProcessTraceFileMain(CommandLineOptions commandLineOptions)
        {
            if (commandLineOptions.TraceFile == null)
            {
                PrintUsage(commandLineOptions, "--trace must be specified");
                return(-8);
            }

            if (commandLineOptions.OutputFileName == null)
            {
                PrintUsage(commandLineOptions, "--output must be specified");
                return(-8);
            }

            if (commandLineOptions.OutputFileName != null)
            {
                if (!commandLineOptions.FileType.HasValue)
                {
                    PrintUsage(commandLineOptions, $"--pgo-file-type must be specified");
                    return(-9);
                }
                if ((commandLineOptions.FileType.Value != PgoFileType.jittrace) && (commandLineOptions.FileType != PgoFileType.mibc))
                {
                    PrintUsage(commandLineOptions, $"Invalid output pgo type {commandLineOptions.FileType} specified.");
                    return(-9);
                }
                if (commandLineOptions.FileType == PgoFileType.jittrace)
                {
                    if (!commandLineOptions.OutputFileName.Name.EndsWith(".jittrace"))
                    {
                        PrintUsage(commandLineOptions, $"jittrace output file name must end with .jittrace");
                        return(-9);
                    }
                }
                if (commandLineOptions.FileType == PgoFileType.mibc)
                {
                    if (!commandLineOptions.OutputFileName.Name.EndsWith(".mibc"))
                    {
                        PrintUsage(commandLineOptions, $"mibc output file name must end with .mibc");
                        return(-9);
                    }
                }
            }

            string etlFileName = commandLineOptions.TraceFile.FullName;

            foreach (string nettraceExtension in new string[] { ".netperf", ".netperf.zip", ".nettrace" })
            {
                if (commandLineOptions.TraceFile.FullName.EndsWith(nettraceExtension))
                {
                    etlFileName = commandLineOptions.TraceFile.FullName.Substring(0, commandLineOptions.TraceFile.FullName.Length - nettraceExtension.Length) + ".etlx";
                    PrintMessage($"Creating ETLX file {etlFileName} from {commandLineOptions.TraceFile.FullName}");
                    TraceLog.CreateFromEventPipeDataFile(commandLineOptions.TraceFile.FullName, etlFileName);
                }
            }

            string lttngExtension = ".trace.zip";

            if (commandLineOptions.TraceFile.FullName.EndsWith(lttngExtension))
            {
                etlFileName = commandLineOptions.TraceFile.FullName.Substring(0, commandLineOptions.TraceFile.FullName.Length - lttngExtension.Length) + ".etlx";
                PrintMessage($"Creating ETLX file {etlFileName} from {commandLineOptions.TraceFile.FullName}");
                TraceLog.CreateFromLttngTextDataFile(commandLineOptions.TraceFile.FullName, etlFileName);
            }

            UnZipIfNecessary(ref etlFileName, commandLineOptions.BasicProgressMessages ? Console.Out : new StringWriter());

            using (var traceLog = TraceLog.OpenOrConvert(etlFileName))
            {
                if ((!commandLineOptions.Pid.HasValue && commandLineOptions.ProcessName == null) && traceLog.Processes.Count != 1)
                {
                    PrintError("Trace file contains multiple processes to distinguish between");
                    PrintOutput("Either a pid or process name from the following list must be specified");
                    foreach (TraceProcess proc in traceLog.Processes)
                    {
                        PrintOutput($"Procname = {proc.Name} Pid = {proc.ProcessID}");
                    }
                    return(1);
                }

                if (commandLineOptions.Pid.HasValue && (commandLineOptions.ProcessName != null))
                {
                    PrintError("--pid and --process-name cannot be specified together");
                    return(-1);
                }

                // For a particular process
                TraceProcess p;
                if (commandLineOptions.Pid.HasValue)
                {
                    p = traceLog.Processes.LastProcessWithID(commandLineOptions.Pid.Value);
                }
                else if (commandLineOptions.ProcessName != null)
                {
                    List <TraceProcess> matchingProcesses = new List <TraceProcess>();
                    foreach (TraceProcess proc in traceLog.Processes)
                    {
                        if (String.Compare(proc.Name, commandLineOptions.ProcessName, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            matchingProcesses.Add(proc);
                        }
                    }

                    if (matchingProcesses.Count == 0)
                    {
                        PrintError("Unable to find matching process in trace");
                        return(-1);
                    }
                    if (matchingProcesses.Count > 1)
                    {
                        StringBuilder errorMessage = new StringBuilder();

                        errorMessage.AppendLine("Found multiple matching processes in trace");
                        foreach (TraceProcess proc in matchingProcesses)
                        {
                            errorMessage.AppendLine($"{proc.Name}\tpid={proc.ProcessID}\tCPUMSec={proc.CPUMSec}");
                        }
                        PrintError(errorMessage.ToString());
                        return(-2);
                    }
                    p = matchingProcesses[0];
                }
                else
                {
                    p = traceLog.Processes.First();
                }

                if (!p.EventsInProcess.ByEventType <MethodDetailsTraceData>().Any())
                {
                    PrintError($"No MethodDetails\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?");
                    return(-3);
                }

                if (!p.EventsInProcess.ByEventType <GCBulkTypeTraceData>().Any())
                {
                    PrintError($"No BulkType data\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?");
                    return(-4);
                }

                if (!p.EventsInProcess.ByEventType <ModuleLoadUnloadTraceData>().Any())
                {
                    PrintError($"No managed module load data\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?");
                    return(-5);
                }

                if (!p.EventsInProcess.ByEventType <MethodJittingStartedTraceData>().Any())
                {
                    PrintError($"No managed jit starting data\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?");
                    return(-5);
                }

                PgoTraceProcess pgoProcess    = new PgoTraceProcess(p);
                int?            clrInstanceId = commandLineOptions.ClrInstanceId;
                if (!clrInstanceId.HasValue)
                {
                    HashSet <int> clrInstanceIds         = new HashSet <int>();
                    HashSet <int> examinedClrInstanceIds = new HashSet <int>();
                    foreach (var assemblyLoadTrace in p.EventsInProcess.ByEventType <AssemblyLoadUnloadTraceData>())
                    {
                        if (examinedClrInstanceIds.Add(assemblyLoadTrace.ClrInstanceID))
                        {
                            if (pgoProcess.ClrInstanceIsCoreCLRInstance(assemblyLoadTrace.ClrInstanceID))
                            {
                                clrInstanceIds.Add(assemblyLoadTrace.ClrInstanceID);
                            }
                        }
                    }

                    if (clrInstanceIds.Count != 1)
                    {
                        if (clrInstanceIds.Count == 0)
                        {
                            PrintError($"No managed CLR in target process, or per module information could not be loaded from the trace.");
                        }
                        else
                        {
                            // There are multiple clr processes... search for the one that implements
                            int[] clrInstanceIdsArray = clrInstanceIds.ToArray();
                            Array.Sort(clrInstanceIdsArray);
                            StringBuilder errorMessage = new StringBuilder();
                            errorMessage.AppendLine("Multiple CLR instances used in process. Choose one to examine with -clrInstanceID:<id> Valid ids:");
                            foreach (int instanceID in clrInstanceIds)
                            {
                                errorMessage.AppendLine(instanceID.ToString());
                            }
                            PrintError(errorMessage.ToString());
                        }
                        return(-10);
                    }
                    else
                    {
                        clrInstanceId = clrInstanceIds.First();
                    }
                }

                var tsc = new TraceTypeSystemContext(pgoProcess, clrInstanceId.Value, s_logger);

                if (commandLineOptions.VerboseWarnings)
                {
                    PrintWarning($"{traceLog.EventsLost} Lost events");
                }

                bool filePathError = false;
                if (commandLineOptions.Reference != null)
                {
                    foreach (FileInfo fileReference in commandLineOptions.Reference)
                    {
                        if (!File.Exists(fileReference.FullName))
                        {
                            PrintError($"Unable to find reference '{fileReference.FullName}'");
                            filePathError = true;
                        }
                        else
                        {
                            tsc.GetModuleFromPath(fileReference.FullName);
                        }
                    }
                }

                if (filePathError)
                {
                    return(-6);
                }

                if (!tsc.Initialize())
                {
                    return(-12);
                }

                TraceRuntimeDescToTypeSystemDesc idParser = new TraceRuntimeDescToTypeSystemDesc(p, tsc, clrInstanceId.Value);

                SortedDictionary <int, ProcessedMethodData> methodsToAttemptToPrepare = new SortedDictionary <int, ProcessedMethodData>();

                if (commandLineOptions.ProcessR2REvents)
                {
                    foreach (var e in p.EventsInProcess.ByEventType <R2RGetEntryPointTraceData>())
                    {
                        int    parenIndex = e.MethodSignature.IndexOf('(');
                        string retArg     = e.MethodSignature.Substring(0, parenIndex);
                        string paramsArgs = e.MethodSignature.Substring(parenIndex);
                        string methodNameFromEventDirectly = retArg + e.MethodNamespace + "." + e.MethodName + paramsArgs;
                        if (e.ClrInstanceID != clrInstanceId.Value)
                        {
                            if (!commandLineOptions.Warnings)
                            {
                                continue;
                            }

                            PrintWarning($"Skipped R2REntryPoint {methodNameFromEventDirectly} due to ClrInstanceID of {e.ClrInstanceID}");
                            continue;
                        }
                        MethodDesc method           = null;
                        string     extraWarningText = null;
                        try
                        {
                            method = idParser.ResolveMethodID(e.MethodID, commandLineOptions.VerboseWarnings);
                        }
                        catch (Exception exception)
                        {
                            extraWarningText = exception.ToString();
                        }

                        if (method == null)
                        {
                            if ((e.MethodNamespace == "dynamicClass") || !commandLineOptions.Warnings)
                            {
                                continue;
                            }

                            PrintWarning($"Unable to parse {methodNameFromEventDirectly} when looking up R2R methods");
                            if (extraWarningText != null)
                            {
                                PrintWarning(extraWarningText);
                            }
                            continue;
                        }

                        if ((e.TimeStampRelativeMSec >= commandLineOptions.ExcludeEventsBefore) && (e.TimeStampRelativeMSec <= commandLineOptions.ExcludeEventsAfter))
                        {
                            methodsToAttemptToPrepare.Add((int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, method, "R2RLoad"));
                        }
                    }
                }

                // Find all the jitStart events.
                if (commandLineOptions.ProcessJitEvents)
                {
                    foreach (var e in p.EventsInProcess.ByEventType <MethodJittingStartedTraceData>())
                    {
                        int    parenIndex = e.MethodSignature.IndexOf('(');
                        string retArg     = e.MethodSignature.Substring(0, parenIndex);
                        string paramsArgs = e.MethodSignature.Substring(parenIndex);
                        string methodNameFromEventDirectly = retArg + e.MethodNamespace + "." + e.MethodName + paramsArgs;
                        if (e.ClrInstanceID != clrInstanceId.Value)
                        {
                            if (!commandLineOptions.Warnings)
                            {
                                continue;
                            }

                            PrintWarning($"Skipped {methodNameFromEventDirectly} due to ClrInstanceID of {e.ClrInstanceID}");
                            continue;
                        }

                        MethodDesc method           = null;
                        string     extraWarningText = null;
                        try
                        {
                            method = idParser.ResolveMethodID(e.MethodID, commandLineOptions.VerboseWarnings);
                        }
                        catch (Exception exception)
                        {
                            extraWarningText = exception.ToString();
                        }

                        if (method == null)
                        {
                            if ((e.MethodNamespace == "dynamicClass") || !commandLineOptions.Warnings)
                            {
                                continue;
                            }

                            PrintWarning($"Unable to parse {methodNameFromEventDirectly}");
                            if (extraWarningText != null)
                            {
                                PrintWarning(extraWarningText);
                            }
                            continue;
                        }

                        if ((e.TimeStampRelativeMSec >= commandLineOptions.ExcludeEventsBefore) && (e.TimeStampRelativeMSec <= commandLineOptions.ExcludeEventsAfter))
                        {
                            methodsToAttemptToPrepare.Add((int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, method, "JitStart"));
                        }
                    }
                }

                Dictionary <MethodDesc, Dictionary <MethodDesc, int> > callGraph = null;
                Dictionary <MethodDesc, int> exclusiveSamples = null;
                if (commandLineOptions.GenerateCallGraph)
                {
                    HashSet <MethodDesc> methodsListedToPrepare = new HashSet <MethodDesc>();
                    foreach (var entry in methodsToAttemptToPrepare)
                    {
                        methodsListedToPrepare.Add(entry.Value.Method);
                    }

                    callGraph        = new Dictionary <MethodDesc, Dictionary <MethodDesc, int> >();
                    exclusiveSamples = new Dictionary <MethodDesc, int>();
                    // Capture the addresses of jitted code
                    List <ValueTuple <InstructionPointerRange, MethodDesc> > codeLocations = new List <(InstructionPointerRange, MethodDesc)>();
                    foreach (var e in p.EventsInProcess.ByEventType <MethodLoadUnloadTraceData>())
                    {
                        if (e.ClrInstanceID != clrInstanceId.Value)
                        {
                            continue;
                        }

                        MethodDesc method = null;
                        try
                        {
                            method = idParser.ResolveMethodID(e.MethodID, commandLineOptions.VerboseWarnings);
                        }
                        catch (Exception)
                        {
                        }

                        if (method != null)
                        {
                            codeLocations.Add((new InstructionPointerRange(e.MethodStartAddress, e.MethodSize), method));
                        }
                    }
                    foreach (var e in p.EventsInProcess.ByEventType <MethodLoadUnloadVerboseTraceData>())
                    {
                        if (e.ClrInstanceID != clrInstanceId.Value)
                        {
                            continue;
                        }

                        MethodDesc method = null;
                        try
                        {
                            method = idParser.ResolveMethodID(e.MethodID, commandLineOptions.VerboseWarnings);
                        }
                        catch (Exception)
                        {
                        }

                        if (method != null)
                        {
                            codeLocations.Add((new InstructionPointerRange(e.MethodStartAddress, e.MethodSize), method));
                        }
                    }

                    var sigProvider = new R2RSignatureTypeProvider(tsc);
                    foreach (var module in p.LoadedModules)
                    {
                        if (module.FilePath == "")
                        {
                            continue;
                        }

                        if (!File.Exists(module.FilePath))
                        {
                            continue;
                        }

                        try
                        {
                            byte[] image = File.ReadAllBytes(module.FilePath);
                            using (FileStream fstream = new FileStream(module.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                            {
                                var r2rCheckPEReader = new System.Reflection.PortableExecutable.PEReader(fstream, System.Reflection.PortableExecutable.PEStreamOptions.LeaveOpen);

                                if (!ILCompiler.Reflection.ReadyToRun.ReadyToRunReader.IsReadyToRunImage(r2rCheckPEReader))
                                {
                                    continue;
                                }
                            }

                            var reader = new ILCompiler.Reflection.ReadyToRun.ReadyToRunReader(tsc, module.FilePath);
                            foreach (var methodEntry in reader.GetCustomMethodToRuntimeFunctionMapping <TypeDesc, MethodDesc, R2RSigProviderContext>(sigProvider))
                            {
                                foreach (var runtimeFunction in methodEntry.Value.RuntimeFunctions)
                                {
                                    codeLocations.Add((new InstructionPointerRange(module.ImageBase + (ulong)runtimeFunction.StartAddress, runtimeFunction.Size), methodEntry.Key));
                                }
                            }
                        }
                        catch { }
                    }

                    InstructionPointerRange[] instructionPointerRanges = new InstructionPointerRange[codeLocations.Count];
                    MethodDesc[] methods = new MethodDesc[codeLocations.Count];
                    for (int i = 0; i < codeLocations.Count; i++)
                    {
                        instructionPointerRanges[i] = codeLocations[i].Item1;
                        methods[i] = codeLocations[i].Item2;
                    }

                    Array.Sort(instructionPointerRanges, methods);

                    foreach (var e in p.EventsInProcess.ByEventType <SampledProfileTraceData>())
                    {
                        var callstack = e.CallStack();
                        if (callstack == null)
                        {
                            continue;
                        }

                        ulong      address1         = callstack.CodeAddress.Address;
                        MethodDesc topOfStackMethod = LookupMethodByAddress(address1);
                        MethodDesc nextMethod       = null;
                        if (callstack.Caller != null)
                        {
                            ulong address2 = callstack.Caller.CodeAddress.Address;
                            nextMethod = LookupMethodByAddress(address2);
                        }

                        if (topOfStackMethod != null)
                        {
                            if (!methodsListedToPrepare.Contains(topOfStackMethod))
                            {
                                methodsListedToPrepare.Add(topOfStackMethod);
                                methodsToAttemptToPrepare.Add((int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, topOfStackMethod, "SampleMethod"));
                            }

                            if (exclusiveSamples.TryGetValue(topOfStackMethod, out int count))
                            {
                                exclusiveSamples[topOfStackMethod] = count + 1;
                            }
                            else
                            {
                                exclusiveSamples[topOfStackMethod] = 1;
                            }
                        }

                        if (topOfStackMethod != null && nextMethod != null)
                        {
                            if (!methodsListedToPrepare.Contains(nextMethod))
                            {
                                methodsListedToPrepare.Add(nextMethod);
                                methodsToAttemptToPrepare.Add((int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, nextMethod, "SampleMethodCaller"));
                            }

                            if (!callGraph.TryGetValue(nextMethod, out var innerDictionary))
                            {
                                innerDictionary       = new Dictionary <MethodDesc, int>();
                                callGraph[nextMethod] = innerDictionary;
                            }
                            if (innerDictionary.TryGetValue(topOfStackMethod, out int count))
                            {
                                innerDictionary[topOfStackMethod] = count + 1;
                            }
                            else
                            {
                                innerDictionary[topOfStackMethod] = 1;
                            }
                        }
                    }

                    MethodDesc LookupMethodByAddress(ulong address)
                    {
                        int index = Array.BinarySearch(instructionPointerRanges, new InstructionPointerRange(address, 1));

                        if (index >= 0)
                        {
                            return(methods[index]);
                        }
                        else
                        {
                            index = ~index;
                            if (index >= instructionPointerRanges.Length)
                            {
                                return(null);
                            }

                            if (instructionPointerRanges[index].StartAddress < address)
                            {
                                if (instructionPointerRanges[index].EndAddress > address)
                                {
                                    return(methods[index]);
                                }
                            }

                            if (index == 0)
                            {
                                return(null);
                            }

                            index--;

                            if (instructionPointerRanges[index].StartAddress < address)
                            {
                                if (instructionPointerRanges[index].EndAddress > address)
                                {
                                    return(methods[index]);
                                }
                            }

                            return(null);
                        }
                    }
                }

                Dictionary <MethodDesc, MethodChunks> instrumentationDataByMethod = new Dictionary <MethodDesc, MethodChunks>();

                foreach (var e in p.EventsInProcess.ByEventType <JitInstrumentationDataVerboseTraceData>())
                {
                    AddToInstrumentationData(e.ClrInstanceID, e.MethodID, e.MethodFlags, e.Data);
                }
                foreach (var e in p.EventsInProcess.ByEventType <JitInstrumentationDataTraceData>())
                {
                    AddToInstrumentationData(e.ClrInstanceID, e.MethodID, e.MethodFlags, e.Data);
                }

                // Local function used with the above two loops as the behavior is supposed to be identical
                void AddToInstrumentationData(int eventClrInstanceId, long methodID, int methodFlags, byte[] data)
                {
                    if (eventClrInstanceId != clrInstanceId.Value)
                    {
                        return;
                    }

                    MethodDesc method = null;

                    try
                    {
                        method = idParser.ResolveMethodID(methodID, commandLineOptions.VerboseWarnings);
                    }
                    catch (Exception)
                    {
                    }

                    if (method != null)
                    {
                        if (!instrumentationDataByMethod.TryGetValue(method, out MethodChunks perMethodChunks))
                        {
                            perMethodChunks = new MethodChunks();
                            instrumentationDataByMethod.Add(method, perMethodChunks);
                        }
                        const int FinalChunkFlag = unchecked ((int)0x80000000);
                        int       chunkIndex     = methodFlags & ~FinalChunkFlag;
                        if ((chunkIndex != (perMethodChunks.LastChunk + 1)) || perMethodChunks.Done)
                        {
                            instrumentationDataByMethod.Remove(method);
                            return;
                        }
                        perMethodChunks.LastChunk = perMethodChunks.InstrumentationData.Count;
                        perMethodChunks.InstrumentationData.Add(data);
                        if ((methodFlags & FinalChunkFlag) == FinalChunkFlag)
                        {
                            perMethodChunks.Done = true;
                        }
                    }
                }

                if (commandLineOptions.DisplayProcessedEvents)
                {
                    foreach (var entry in methodsToAttemptToPrepare)
                    {
                        MethodDesc method = entry.Value.Method;
                        string     reason = entry.Value.Reason;
                        PrintOutput($"{entry.Value.Millisecond.ToString("F4")} {reason} {method}");
                    }
                }

                PrintMessage($"Done processing input file");

                if (commandLineOptions.OutputFileName == null)
                {
                    return(0);
                }

                // Deduplicate entries
                HashSet <MethodDesc>       methodsInListAlready = new HashSet <MethodDesc>();
                List <ProcessedMethodData> methodsUsedInProcess = new List <ProcessedMethodData>();

                PgoDataLoader pgoDataLoader = new PgoDataLoader(idParser);

                foreach (var entry in methodsToAttemptToPrepare)
                {
                    if (methodsInListAlready.Add(entry.Value.Method))
                    {
                        var methodData = entry.Value;
                        if (commandLineOptions.GenerateCallGraph)
                        {
                            exclusiveSamples.TryGetValue(methodData.Method, out methodData.ExclusiveWeight);
                            callGraph.TryGetValue(methodData.Method, out methodData.WeightedCallData);
                        }
                        if (instrumentationDataByMethod.TryGetValue(methodData.Method, out MethodChunks chunks))
                        {
                            int size = 0;
                            foreach (byte[] arr in chunks.InstrumentationData)
                            {
                                size += arr.Length;
                            }

                            byte[] instrumentationData = new byte[size];
                            int    offset = 0;

                            foreach (byte[] arr in chunks.InstrumentationData)
                            {
                                arr.CopyTo(instrumentationData, offset);
                                offset += arr.Length;
                            }

                            var intDecompressor = new PgoProcessor.PgoEncodedCompressedIntParser(instrumentationData, 0);
                            methodData.InstrumentationData = PgoProcessor.ParsePgoData <TypeSystemEntityOrUnknown>(pgoDataLoader, intDecompressor, true).ToArray();
                        }
                        methodsUsedInProcess.Add(methodData);
                    }
                }

                if (commandLineOptions.FileType.Value == PgoFileType.jittrace)
                {
                    GenerateJittraceFile(commandLineOptions.OutputFileName, methodsUsedInProcess, commandLineOptions.JitTraceOptions);
                }
                else if (commandLineOptions.FileType.Value == PgoFileType.mibc)
                {
                    ILCompiler.MethodProfileData[] methodProfileData = new ILCompiler.MethodProfileData[methodsUsedInProcess.Count];
                    for (int i = 0; i < methodProfileData.Length; i++)
                    {
                        ProcessedMethodData processedData = methodsUsedInProcess[i];
                        methodProfileData[i] = new ILCompiler.MethodProfileData(processedData.Method, ILCompiler.MethodProfilingDataFlags.ReadMethodCode, processedData.ExclusiveWeight, processedData.WeightedCallData, 0xFFFFFFFF, processedData.InstrumentationData);
                    }
                    return(MibcEmitter.GenerateMibcFile(tsc, commandLineOptions.OutputFileName, methodProfileData, commandLineOptions.ValidateOutputFile, commandLineOptions.Uncompressed));
                }
            }
            return(0);
        }