Exemple #1
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);
            }
        }
 /// <summary>
 /// Returns metadata readers for assembly PE file and portable PDB.
 /// </summary>
 /// <param name="assemblyFileName">file name of the assembly</param>
 /// <param name="peReader">PE metadata reader return</param>
 /// <param name="pdbReader">PDB metadata reader return</param>
 /// <returns>true if debugging information is available</returns>
 private static bool GetReaders(string assemblyFileName, out MetadataReader peReader, out MetadataReader pdbReader)
 {
     peReader = null;
     pdbReader = null;
     
     if (!File.Exists(assemblyFileName))
     {
         return false;
     }
     Stream peStream = File.OpenRead(assemblyFileName);
     PEReader reader = new PEReader(peStream);
     string pdbPath = null;
     
     foreach (DebugDirectoryEntry entry in reader.ReadDebugDirectory())
     {
         if (entry.Type == DebugDirectoryEntryType.CodeView)
         {
             CodeViewDebugDirectoryData codeViewData = reader.ReadCodeViewDebugDirectoryData(entry);
             pdbPath = codeViewData.Path;
             break;
         }
     }
     if (pdbPath == null)
     {
         return false;
     }
     if (!File.Exists(pdbPath))
     {
         pdbPath = Path.GetFileName(pdbPath);
         if (!File.Exists(pdbPath))
         {
             return false;
         }
     }
     
     peReader = reader.GetMetadataReader();
     Stream pdbStream = File.OpenRead(pdbPath);
     MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
     pdbReader = provider.GetMetadataReader();
     
     return true;
     
 }
Exemple #3
0
        private static void ReadPortableDebugTableEntries(PEReader peReader, out DebugDirectoryEntry codeViewEntry, out DebugDirectoryEntry embeddedPdbEntry)
        {
            // See spec: https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PE-COFF.md

            codeViewEntry = default(DebugDirectoryEntry);
            embeddedPdbEntry = default(DebugDirectoryEntry);

            foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory())
            {
                if (entry.Type == DebugDirectoryEntryType.CodeView)
                {
                    const ushort PortableCodeViewVersionMagic = 0x504d;
                    if (entry.MinorVersion != PortableCodeViewVersionMagic)
                    {
                        continue;
                    }

                    codeViewEntry = entry;
                }
                else if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb)
                {
                    embeddedPdbEntry = entry;
                }
            }
        }
        public void EmbeddedSource_InEmbeddedPdb()
        {
            string source = @"
using System;

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

            var pdbStream = new MemoryStream();
            var peBlob = c.EmitToArray(
                EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.Embedded),
                embeddedTexts: new[] { EmbeddedText.FromSource(tree.FilePath, tree.GetText()) });
            pdbStream.Position = 0;

            using (var peReader = new PEReader(peBlob))
            {
                var embeddedEntry = peReader.ReadDebugDirectory().Single(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb);

                using (var embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedEntry))
                {
                    var pdbReader = embeddedMetadataProvider.GetMetadataReader();

                    var embeddedSource =
                        (from documentHandle in pdbReader.Documents
                         let document = pdbReader.GetDocument(documentHandle)
                         select new
                         {
                             FilePath = pdbReader.GetString(document.Name),
                             Text = pdbReader.GetEmbeddedSource(documentHandle)
                         }).Single();

                    Assert.Equal(embeddedSource.FilePath, "f:/build/foo.cs");
                    Assert.Equal(source, embeddedSource.Text.ToString());
                }
            }
        }
        public void SourceLink_Embedded()
        {
            string source = @"
using System;

class C
{
    public static void Main()
    {
        Console.WriteLine();
    }
}
";
            var sourceLinkBlob = Encoding.UTF8.GetBytes(@"
{
  ""documents"": {
     ""f:/build/*"" : ""https://raw.githubusercontent.com/my-org/my-project/1111111111111111111111111111111111111111/*""
  }
}
");
            var c = CreateCompilationWithMscorlib(Parse(source, "f:/build/foo.cs"), options: TestOptions.DebugDll);

            var peBlob = c.EmitToArray(EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.Embedded), sourceLinkStream: new MemoryStream(sourceLinkBlob));

            using (var peReader = new PEReader(peBlob))
            {
                var embeddedEntry = peReader.ReadDebugDirectory().Single(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb);

                using (var embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedEntry))
                {
                    var pdbReader = embeddedMetadataProvider.GetMetadataReader();

                    var actualBlob =
                        (from cdiHandle in pdbReader.GetCustomDebugInformation(EntityHandle.ModuleDefinition)
                         let cdi = pdbReader.GetCustomDebugInformation(cdiHandle)
                         where pdbReader.GetGuid(cdi.Kind) == PortableCustomDebugInfoKinds.SourceLink
                         select pdbReader.GetBlobBytes(cdi.Value)).Single();

                    AssertEx.Equal(sourceLinkBlob, actualBlob);
                }
            }
        }
Exemple #6
0
        private bool TryReadCodeViewData(string peFilePath, out CodeViewDebugDirectoryData codeViewData, out uint stamp)
        {
            try
            {
                var peStream = PortableShim.File.OpenRead(peFilePath);
                using (var peReader = new PEReader(peStream))
                {
                    foreach (var entry in peReader.ReadDebugDirectory())
                    {
                        if (entry.Type == DebugDirectoryEntryType.CodeView)
                        {
                            codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
                            stamp = entry.Stamp;
                            return true;
                        }
                    }
                }
            }
            catch
            {
            }

            codeViewData = default(CodeViewDebugDirectoryData);
            stamp = 0;
            return false;
        }
Exemple #7
0
        /// <summary>
        /// Read the pdb file name and assembly version information from the PE file.
        /// </summary>
        /// <param name="assemblyPath">PE file path</param>
        /// <param name="loadedPeAddress">loaded PE image address or zero</param>
        /// <param name="loadedPeSize">loaded PE image size</param>
        /// <param name="age">age</param>
        /// <param name="guid">assembly guid</param>
        /// <param name="stamp">time stamp</param>
        /// <returns>pdb name or null</returns>
        /// <remarks>
        /// loadedPeAddress and loadedPeSize will be used here when/if the PEReader
        /// support runtime loaded images instead of just file images.
        /// </remarks>
        private static unsafe string GetPdbPathFromPeStream(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize, out int age, out Guid guid, out uint stamp)
        {
            if (File.Exists(assemblyPath))
            {
                Stream peStream = File.OpenRead(assemblyPath);

                using (PEReader peReader = new PEReader(peStream))
                {
                    foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory())
                    {
                        if (entry.Type == DebugDirectoryEntryType.CodeView)
                        {
                            CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);

                            stamp = entry.Stamp;
                            age = codeViewData.Age;
                            guid = codeViewData.Guid;

                            string peDirectory = Path.GetDirectoryName(assemblyPath);
                            return Path.Combine(peDirectory, Path.GetFileName(codeViewData.Path));
                        }
                    }
                }
            }

            stamp = 0;
            age = 0;
            guid = new Guid();
            return null;
        }