private static void WritePEImage( Stream peStream, MetadataBuilder metadataBuilder, BlobBuilder ilBuilder, MethodDefinitionHandle entryPointHandle ) { // Create executable with the managed metadata from the specified MetadataBuilder. var peHeaderBuilder = new PEHeaderBuilder( imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll ); var peBuilder = new ManagedPEBuilder( peHeaderBuilder, new MetadataRootBuilder(metadataBuilder), ilBuilder, entryPoint: entryPointHandle, flags: CorFlags.ILOnly, deterministicIdProvider: content => s_contentId); // Write executable into the specified stream. var peBlob = new BlobBuilder(); BlobContentId contentId = peBuilder.Serialize(peBlob); peBlob.WriteContentTo(peStream); }
public void TryOpenAssociatedPortablePdb_ExpectedExceptionFromStreamProvider_NoFallback() { var pdbBuilder = new BlobBuilder(); pdbBuilder.WriteBytes(PortablePdbs.DocumentsPdb); var id = new BlobContentId(Guid.Parse("18091B06-32BB-46C2-9C3B-7C9389A2F6C6"), 0x12345678); var ddBuilder = new DebugDirectoryBuilder(); ddBuilder.AddCodeViewEntry(@"/a/b/a.pdb", id, portablePdbVersion: 0x0100); var peStream = new MemoryStream(TestBuilders.BuildPEWithDebugDirectory(ddBuilder)); using (var reader = new PEReader(peStream)) { MetadataReaderProvider pdbProvider; string pdbPath; Assert.Throws <IOException>(() => reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), _ => { throw new IOException(); }, out pdbProvider, out pdbPath)); AssertEx.Throws <BadImageFormatException>(() => reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), _ => { throw new BadImageFormatException("Bang!"); }, out pdbProvider, out pdbPath), e => Assert.Equal("Bang!", e.Message)); // file doesn't exist and no embedded => return false Assert.False(reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), _ => { throw new FileNotFoundException(); }, out pdbProvider, out pdbPath)); } }
public void TryOpenAssociatedPortablePdb_ExpectedExceptionFromStreamProvider_FallbackOnEmbedded_Valid() { var pdbBuilder = new BlobBuilder(); pdbBuilder.WriteBytes(PortablePdbs.DocumentsPdb); var id = new BlobContentId(Guid.Parse("18091B06-32BB-46C2-9C3B-7C9389A2F6C6"), 0x12345678); var ddBuilder = new DebugDirectoryBuilder(); ddBuilder.AddCodeViewEntry(@"/a/b/a.pdb", id, portablePdbVersion: 0x0100); ddBuilder.AddEmbeddedPortablePdbEntry(pdbBuilder, portablePdbVersion: 0x0100); var peStream = new MemoryStream(TestBuilders.BuildPEWithDebugDirectory(ddBuilder)); using (var reader = new PEReader(peStream)) { MetadataReaderProvider pdbProvider; string pdbPath; Assert.True(reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), _ => { throw new IOException(); }, out pdbProvider, out pdbPath)); Assert.Null(pdbPath); Assert.Equal(13, pdbProvider.GetMetadataReader().Documents.Count); Assert.True(reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), _ => { throw new BadImageFormatException(); }, out pdbProvider, out pdbPath)); Assert.Null(pdbPath); Assert.Equal(13, pdbProvider.GetMetadataReader().Documents.Count); Assert.True(reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), _ => { throw new FileNotFoundException(); }, out pdbProvider, out pdbPath)); Assert.Null(pdbPath); Assert.Equal(13, pdbProvider.GetMetadataReader().Documents.Count); } }
public override IEnumerable <SymbolStoreKey> GetKeys(KeyTypeFlags flags) { if ((flags & KeyTypeFlags.IdentityKey) != 0) { SymbolStoreKey key = null; try { _file.Stream.Position = 0; using (MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(_file.Stream, MetadataStreamOptions.LeaveOpen)) { MetadataReader reader = provider.GetMetadataReader(); var blob = new BlobContentId(reader.DebugMetadataHeader.Id); if ((flags & KeyTypeFlags.ForceWindowsPdbs) == 0) { key = GetKey(_file.FileName, blob.Guid); } else { // Force the Windows PDB index key = PDBFileKeyGenerator.GetKey(_file.FileName, blob.Guid, 1); } } } catch (BadImageFormatException ex) { Tracer.Warning("PortablePDBFileKeyGenerator {0}", ex.Message); } if (key != null) { yield return(key); } } }
public void TryOpenAssociatedPortablePdb_BadStreamProvider() { var pdbBuilder = new BlobBuilder(); pdbBuilder.WriteBytes(PortablePdbs.DocumentsPdb); var id = new BlobContentId(Guid.Parse("18091B06-32BB-46C2-9C3B-7C9389A2F6C6"), 0x12345678); var ddBuilder = new DebugDirectoryBuilder(); ddBuilder.AddCodeViewEntry(@"/a/b/a.pdb", id, portablePdbVersion: 0x0100); var peStream = new MemoryStream(TestBuilders.BuildPEWithDebugDirectory(ddBuilder)); using (var reader = new PEReader(peStream)) { MetadataReaderProvider pdbProvider; string pdbPath; // pass-thru: AssertExtensions.Throws <ArgumentException>(null, () => reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), _ => { throw new ArgumentException(); }, out pdbProvider, out pdbPath)); Assert.Throws <InvalidOperationException>(() => reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), _ => { return(new TestStream(canRead: false, canWrite: true, canSeek: true)); }, out pdbProvider, out pdbPath)); Assert.Throws <InvalidOperationException>(() => reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), _ => { return(new TestStream(canRead: true, canWrite: true, canSeek: false)); }, out pdbProvider, out pdbPath)); } }
public void MultipleEntries() { var b = new DebugDirectoryBuilder(); var id = new BlobContentId(new Guid("3C88E66E-E0B9-4508-9290-11E0DB51A1C5"), 0x12345678); b.AddReproducibleEntry(); b.AddCodeViewEntry("x", id, 0); b.AddReproducibleEntry(); b.AddCodeViewEntry("y", id, 0xABCD); var blob = new BlobBuilder(); b.Serialize(blob, new SectionLocation(0x1000, 0x2000), 0x50); AssertEx.Equal(new byte[] { 0x00, 0x00, 0x00, 0x00, // Characteristics 0x00, 0x00, 0x00, 0x00, // Stamp 0x00, 0x00, 0x00, 0x00, // Version 0x10, 0x00, 0x00, 0x00, // Type 0x00, 0x00, 0x00, 0x00, // SizeOfData 0x00, 0x00, 0x00, 0x00, // AddressOfRawData 0x00, 0x00, 0x00, 0x00, // PointerToRawData 0x00, 0x00, 0x00, 0x00, // Characteristics 0x78, 0x56, 0x34, 0x12, // Stamp 0x00, 0x00, 0x00, 0x00, // Version 0x02, 0x00, 0x00, 0x00, // Type 0x1A, 0x00, 0x00, 0x00, // SizeOfData 0xC0, 0x10, 0x00, 0x00, // AddressOfRawData 0xC0, 0x20, 0x00, 0x00, // PointerToRawData 0x00, 0x00, 0x00, 0x00, // Characteristics 0x00, 0x00, 0x00, 0x00, // Stamp 0x00, 0x00, 0x00, 0x00, // Version 0x10, 0x00, 0x00, 0x00, // Type 0x00, 0x00, 0x00, 0x00, // SizeOfData 0x00, 0x00, 0x00, 0x00, // AddressOfRawData 0x00, 0x00, 0x00, 0x00, // PointerToRawData 0x00, 0x00, 0x00, 0x00, // Characteristics 0x78, 0x56, 0x34, 0x12, // Stamp 0xCD, 0xAB, 0x4D, 0x50, // Version 0x02, 0x00, 0x00, 0x00, // Type 0x1A, 0x00, 0x00, 0x00, // SizeOfData 0xDA, 0x10, 0x00, 0x00, // AddressOfRawData 0xDA, 0x20, 0x00, 0x00, // PointerToRawData // data (byte)'R', (byte)'S', (byte)'D', (byte)'S', 0x6E, 0xE6, 0x88, 0x3C, 0xB9, 0xE0, 0x08, 0x45, 0x92, 0x90, 0x11, 0xE0, 0xDB, 0x51, 0xA1, 0xC5, // GUID 0x01, 0x00, 0x00, 0x00, // age (byte)'x', 0x00, // path // data (byte)'R', (byte)'S', (byte)'D', (byte)'S', 0x6E, 0xE6, 0x88, 0x3C, 0xB9, 0xE0, 0x08, 0x45, 0x92, 0x90, 0x11, 0xE0, 0xDB, 0x51, 0xA1, 0xC5, // GUID 0x01, 0x00, 0x00, 0x00, // age (byte)'y', 0x00, // path }, blob.ToArray()); }
public void Serialize(BlobBuilder builder, out BlobContentId contentId) { // Define and serialize sections in two steps. // We need to know about all sections before serializing them. var serializedSections = SerializeSections(); // The positions and sizes of directories are calculated during section serialization. var directories = GetDirectories(); Blob stampFixup; WritePESignature(builder); WriteCoffHeader(builder, serializedSections, out stampFixup); WritePEHeader(builder, directories, serializedSections); WriteSectionHeaders(builder, serializedSections); builder.Align(Header.FileAlignment); foreach (var section in serializedSections) { builder.LinkSuffix(section.Builder); builder.Align(Header.FileAlignment); } contentId = IdProvider(builder.GetBlobs()); // patch timestamp in COFF header: var stampWriter = new BlobWriter(stampFixup); stampWriter.WriteUInt32(contentId.Stamp); Debug.Assert(stampWriter.RemainingBytes == 0); }
/// <summary> /// Adds a CodeView entry. /// </summary> /// <param name="pdbPath">Path to the PDB. Shall not be empty.</param> /// <param name="pdbContentId">Unique id of the PDB content.</param> /// <param name="portablePdbVersion">Version of Portable PDB format (e.g. 0x0100 for 1.0), or 0 if the PDB is not portable.</param> /// <param name="age">Age (iteration) of the PDB. Shall be 1 for Portable PDBs.</param> /// <exception cref="ArgumentNullException"><paramref name="pdbPath"/> is null.</exception> /// <exception cref="ArgumentException"><paramref name="pdbPath"/> contains NUL character.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="age"/> is less than 1.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="portablePdbVersion"/> is smaller than 0x0100.</exception> internal void AddCodeViewEntry( string pdbPath, BlobContentId pdbContentId, ushort portablePdbVersion, int age) { if (pdbPath == null) { Throw.ArgumentNull(nameof(pdbPath)); } if (age < 1) { Throw.ArgumentOutOfRange(nameof(age)); } // We allow NUL characters to allow for padding for backward compat purposes. if (pdbPath.Length == 0 || pdbPath.IndexOf('\0') == 0) { Throw.InvalidArgument(SR.ExpectedNonEmptyString, nameof(pdbPath)); } if (portablePdbVersion > 0 && portablePdbVersion < PortablePdbVersions.MinFormatVersion) { Throw.ArgumentOutOfRange(nameof(portablePdbVersion)); } int dataSize = WriteCodeViewData(_dataBuilder, pdbPath, pdbContentId.Guid, age); AddEntry( type: DebugDirectoryEntryType.CodeView, version: (portablePdbVersion == 0) ? 0 : PortablePdbVersions.DebugDirectoryEntryVersion(portablePdbVersion), stamp: pdbContentId.Stamp, dataSize); }
/// <summary> /// Adds a CodeView entry. /// </summary> /// <param name="pdbPath">Path to the PDB. Shall not be empty.</param> /// <param name="pdbContentId">Unique id of the PDB content.</param> /// <param name="portablePdbVersion">Version of Portable PDB format (e.g. 0x0100 for 1.0), or 0 if the PDB is not portable.</param> /// <exception cref="ArgumentNullException"><paramref name="pdbPath"/> is null.</exception> /// <exception cref="ArgumentException"><paramref name="pdbPath"/> contains NUL character.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="portablePdbVersion"/> is smaller than 0x0100.</exception> public void AddCodeViewEntry( string pdbPath, BlobContentId pdbContentId, ushort portablePdbVersion) { AddCodeViewEntry(pdbPath, pdbContentId, portablePdbVersion, age: 1); }
private bool TryOpenCodeViewPortablePdb(DebugDirectoryEntry codeViewEntry, string peImageDirectory, Func <string, Stream?> pdbFileStreamProvider, out MetadataReaderProvider?provider, out string?pdbPath, ref Exception?errorToReport) { pdbPath = null; provider = null; CodeViewDebugDirectoryData data; try { data = ReadCodeViewDebugDirectoryData(codeViewEntry); } catch (Exception e) when(e is BadImageFormatException || e is IOException) { errorToReport = errorToReport ?? e; return(false); } var id = new BlobContentId(data.Guid, codeViewEntry.Stamp); // The interpretation os the path in the CodeView needs to be platform agnostic, // so that PDBs built on Windows work on Unix-like systems and vice versa. // System.IO.Path.GetFileName() on Unix-like systems doesn't treat '\' as a file name separator, // so we need a custom implementation. Also avoid throwing an exception if the path contains invalid characters, // they might not be invalid on the other platform. It's up to the FS APIs to deal with that when opening the stream. string collocatedPdbPath = PathUtilities.CombinePathWithRelativePath(peImageDirectory, PathUtilities.GetFileName(data.Path)); if (TryOpenPortablePdbFile(collocatedPdbPath, id, pdbFileStreamProvider, out provider, ref errorToReport)) { pdbPath = collocatedPdbPath; return(true); } return(false); }
private static unsafe void ValidatePortablePdbId(MetadataReader pdbReader, uint stampInDebugDirectory, Guid guidInDebugDirectory) { var expectedId = new BlobContentId(guidInDebugDirectory, stampInDebugDirectory); var actualId = new BlobContentId(pdbReader.DebugMetadataHeader.Id); Assert.Equal(expectedId, actualId); }
public void TryOpenAssociatedPortablePdb_DuplicateEntries_CodeView() { var id = new BlobContentId(Guid.Parse("18091B06-32BB-46C2-9C3B-7C9389A2F6C6"), 0x12345678); var ddBuilder = new DebugDirectoryBuilder(); ddBuilder.AddCodeViewEntry(@"/a/b/a.pdb", id, portablePdbVersion: 0); ddBuilder.AddReproducibleEntry(); ddBuilder.AddCodeViewEntry(@"/a/b/c.pdb", id, portablePdbVersion: 0x0100, age: 0x1234); ddBuilder.AddCodeViewEntry(@"/a/b/d.pdb", id, portablePdbVersion: 0x0100); var peStream = new MemoryStream(TestBuilders.BuildPEWithDebugDirectory(ddBuilder)); using (var reader = new PEReader(peStream)) { string pathQueried = null; Func <string, Stream> streamProvider = p => { Assert.Null(pathQueried); pathQueried = p; return(null); }; MetadataReaderProvider pdbProvider; string pdbPath; Assert.False(reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), streamProvider, out pdbProvider, out pdbPath)); Assert.Equal(PathUtilities.CombinePathWithRelativePath("pedir", "c.pdb"), pathQueried); } }
public void TryOpenAssociatedPortablePdb_WindowsSpecificPath() { var id = new BlobContentId(Guid.Parse("18091B06-32BB-46C2-9C3B-7C9389A2F6C6"), 0x12345678); var ddBuilder = new DebugDirectoryBuilder(); ddBuilder.AddCodeViewEntry(@"C:def.xyz", id, portablePdbVersion: 0x0100); var peStream = new MemoryStream(TestBuilders.BuildPEWithDebugDirectory(ddBuilder)); using (var reader = new PEReader(peStream)) { string pathQueried = null; Func <string, Stream> streamProvider = p => { Assert.Null(pathQueried); pathQueried = p; return(null); }; MetadataReaderProvider pdbProvider; string pdbPath; Assert.False(reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), streamProvider, out pdbProvider, out pdbPath)); Assert.Equal(Path.Combine("pedir", "def.xyz"), pathQueried); } }
public void AddCodeViewEntry2() { var b = new DebugDirectoryBuilder(); var id = new BlobContentId(new Guid("3C88E66E-E0B9-4508-9290-11E0DB51A1C5"), 0x12345678); b.AddCodeViewEntry("foo.pdb" + new string('\0', 260 - "foo.pdb".Length - 1), id, 0xABCD, 0x99); var blob = new BlobBuilder(); b.Serialize(blob, new SectionLocation(0x1000, 0x2000), 0x50); var bytes = blob.ToArray(); AssertEx.Equal(new byte[] { 0x00, 0x00, 0x00, 0x00, // Characteristics 0x78, 0x56, 0x34, 0x12, // Stamp 0xCD, 0xAB, 0x4D, 0x50, // Version 0x02, 0x00, 0x00, 0x00, // Type 0x1C, 0x01, 0x00, 0x00, // SizeOfData 0x6C, 0x10, 0x00, 0x00, // AddressOfRawData 0x6C, 0x20, 0x00, 0x00, // PointerToRawData // data (byte)'R', (byte)'S', (byte)'D', (byte)'S', 0x6E, 0xE6, 0x88, 0x3C, 0xB9, 0xE0, 0x08, 0x45, 0x92, 0x90, 0x11, 0xE0, 0xDB, 0x51, 0xA1, 0xC5, // GUID 0x99, 0x00, 0x00, 0x00, // age (byte)'f', (byte)'o', (byte)'o', (byte)'.', (byte)'p', (byte)'d', (byte)'b', 0x00, // path // path padding: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, bytes); using (var pinned = new PinnedBlob(bytes)) { var actual = PEReader.ReadDebugDirectoryEntries(pinned.CreateReader(0, DebugDirectoryEntry.Size)); Assert.Equal(1, actual.Length); Assert.Equal(id.Stamp, actual[0].Stamp); Assert.Equal(0xABCD, actual[0].MajorVersion); Assert.Equal(0x504d, actual[0].MinorVersion); Assert.Equal(DebugDirectoryEntryType.CodeView, actual[0].Type); Assert.True(actual[0].IsPortableCodeView); Assert.Equal(0x0000011c, actual[0].DataSize); Assert.Equal(0x0000106c, actual[0].DataRelativeVirtualAddress); Assert.Equal(0x0000206c, actual[0].DataPointer); } }
public void EmbeddedPortablePdb() { string source = @" using System; class C { public static void Main() { Console.WriteLine(); } } "; var c = CreateCompilation(Parse(source, "goo.cs"), options: TestOptions.DebugDll); var peBlob = c.EmitToArray(EmitOptions.Default. WithDebugInformationFormat(DebugInformationFormat.Embedded). WithPdbFilePath(@"a/b/c/d.pdb"). WithPdbChecksumAlgorithm(HashAlgorithmName.SHA512)); using (var peReader = new PEReader(peBlob)) { var entries = peReader.ReadDebugDirectory(); AssertEx.Equal(new[] { DebugDirectoryEntryType.CodeView, DebugDirectoryExtensions.PdbChecksumEntryType, DebugDirectoryEntryType.EmbeddedPortablePdb }, entries.Select(e => e.Type)); var codeView = entries[0]; var checksum = entries[1]; var embedded = entries[2]; // 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[] { "goo.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); // Checksum entry: var checksumData = peReader.ReadPdbChecksumDebugDirectoryData(checksum); Assert.Equal("SHA512", checksumData.AlgorithmName); Assert.Equal(64, checksumData.Checksum.Length); } }
private string ReadFromProgramDatabaseStream(Stream pdbStream) { var metadataProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); var metadataReader = metadataProvider.GetMetadataReader(); var id = new BlobContentId(metadataReader.DebugMetadataHeader.Id); var guid = id.Guid.ToString("N"); return($"{guid}FFFFFFFF".ToUpper()); }
public void EmbeddedPortablePdb_Deterministic() { string source = @" using System; class C { public static void Main() { Console.WriteLine(); } } "; var c = CreateCompilationWithMscorlib(Parse(source, "foo.cs"), options: TestOptions.DebugDll.WithDeterministic(true)); 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.Reproducible, DebugDirectoryEntryType.EmbeddedPortablePdb }, entries.Select(e => e.Type)); var codeView = entries[0]; var reproducible = entries[1]; var embedded = entries[2]; // 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); // Reproducible entry: Assert.Equal(0, reproducible.MajorVersion); Assert.Equal(0, reproducible.MinorVersion); Assert.Equal(0U, reproducible.Stamp); Assert.Equal(0, reproducible.DataSize); } }
public void Empty() { var b = new DebugDirectoryBuilder(); var id = new BlobContentId(new Guid("3C88E66E-E0B9-4508-9290-11E0DB51A1C5"), 0x12345678); var blob = new BlobBuilder(); b.Serialize(blob, new SectionLocation(0x1000, 0x2000), 0x50); AssertEx.Equal(new byte[0], blob.ToArray()); }
public StandaloneDebugMetadataSerializer( MetadataBuilder builder, ImmutableArray <int> typeSystemRowCounts, MethodDefinitionHandle entryPoint, bool isMinimalDelta, Func <IEnumerable <Blob>, BlobContentId> deterministicIdProvider = null) : base(builder, CreateSizes(builder, typeSystemRowCounts, isMinimalDelta, isStandaloneDebugMetadata: true), DebugMetadataVersionString) { _entryPoint = entryPoint; IdProvider = deterministicIdProvider ?? BlobContentId.GetTimeBasedProvider(); }
internal bool MatchesModule(Guid guid, uint stamp, int age) { if (age != 1) { return(false); } var id = new BlobContentId(MetadataReader.DebugMetadataHeader.Id); return(id.Guid == guid && id.Stamp == stamp); }
protected PEBuilder(PEHeaderBuilder header, Func <IEnumerable <Blob>, BlobContentId>?deterministicIdProvider) { if (header is null) { Throw.ArgumentNull(nameof(header)); } IdProvider = deterministicIdProvider ?? BlobContentId.GetTimeBasedProvider(); IsDeterministic = deterministicIdProvider != null; Header = header; _lazySections = new Lazy <ImmutableArray <Section> >(CreateSections); }
private bool TryOpenPortablePdbFile(string path, BlobContentId id, Func <string, Stream?> pdbFileStreamProvider, out MetadataReaderProvider?provider, ref Exception?errorToReport) { provider = null; MetadataReaderProvider?candidate = null; try { Stream?pdbStream; try { pdbStream = pdbFileStreamProvider(path); } catch (FileNotFoundException) { // Not an unexpected IO exception, continue witout reporting the error. pdbStream = null; } if (pdbStream == null) { return(false); } if (!pdbStream.CanRead || !pdbStream.CanSeek) { throw new InvalidOperationException(SR.StreamMustSupportReadAndSeek); } candidate = MetadataReaderProvider.FromPortablePdbStream(pdbStream); // Validate that the PDB matches the assembly version if (new BlobContentId(candidate.GetMetadataReader().DebugMetadataHeader !.Id) != id) { return(false); } provider = candidate; return(true); } catch (Exception e) when(e is BadImageFormatException || e is IOException) { errorToReport = errorToReport ?? e; return(false); } finally { if (provider == null) { candidate?.Dispose(); } } }
public void SerializeMetadata(BlobBuilder builder, out BlobContentId contentId) { SerializeMetadataImpl(builder, methodBodyStreamRva: 0, mappedFieldDataStreamRva: 0); contentId = IdProvider(builder.GetBlobs()); // fill in the id: var idWriter = new BlobWriter(_pdbIdBlob); idWriter.WriteGuid(contentId.Guid); idWriter.WriteUInt32(contentId.Stamp); Debug.Assert(idWriter.RemainingBytes == 0); }
public void Ctor() { var id1 = new BlobContentId(default(Guid), 1); Assert.Equal(default(Guid), id1.Guid); Assert.Equal(1u, id1.Stamp); Assert.False(id1.IsDefault); var id2 = new BlobContentId(new Guid("D6D61CDE-5BAF-4E77-ADDD-3B80F4020BF2"), 0x12345678); Assert.Equal(new Guid("D6D61CDE-5BAF-4E77-ADDD-3B80F4020BF2"), id2.Guid); Assert.Equal(0x12345678u, id2.Stamp); Assert.False(id2.IsDefault); Assert.True(default(BlobContentId).IsDefault); }
// // Symbols // private PdbSymbolReader OpenAssociatedSymbolFile(string peFilePath, PEReader peReader) { string pdbFileName = null; BlobContentId pdbContentId = default; foreach (DebugDirectoryEntry debugEntry in peReader.ReadDebugDirectory()) { if (debugEntry.Type != DebugDirectoryEntryType.CodeView) { continue; } CodeViewDebugDirectoryData debugDirectoryData = peReader.ReadCodeViewDebugDirectoryData(debugEntry); string candidatePath = debugDirectoryData.Path; if (!Path.IsPathRooted(candidatePath) || !File.Exists(candidatePath)) { // Also check next to the PE file candidatePath = Path.Combine(Path.GetDirectoryName(peFilePath), Path.GetFileName(candidatePath)); if (!File.Exists(candidatePath)) { continue; } } pdbFileName = candidatePath; pdbContentId = new BlobContentId(debugDirectoryData.Guid, debugEntry.Stamp); break; } if (pdbFileName == null) { return(null); } // Try to open the symbol file as portable pdb first PdbSymbolReader reader = PortablePdbSymbolReader.TryOpen(pdbFileName, GetMetadataStringDecoder(), pdbContentId); if (reader == null) { // Fallback to the diasymreader for non-portable pdbs reader = UnmanagedPdbSymbolReader.TryOpenSymbolReaderForMetadataFile(peFilePath, Path.GetDirectoryName(pdbFileName)); } return(reader); }
public static bool TryReadPdbId(PEReader peReader, out BlobContentId id, out int age) { var codeViewEntry = peReader.ReadDebugDirectory().FirstOrDefault(entry => entry.Type == DebugDirectoryEntryType.CodeView); if (codeViewEntry.DataSize == 0) { id = default(BlobContentId); age = 0; return(false); } var codeViewData = peReader.ReadCodeViewDebugDirectoryData(codeViewEntry); id = new BlobContentId(codeViewData.Guid, codeViewEntry.Stamp); age = codeViewData.Age; return(true); }
public void AddCodeViewEntry( string pdbPath, BlobContentId pdbContentId, ushort portablePdbVersion) { if (pdbPath == null) { Throw.ArgumentNull(nameof(pdbPath)); } int dataSize = WriteCodeViewData(_dataBuilder, pdbPath, pdbContentId.Guid); AddEntry( type: DebugDirectoryEntryType.CodeView, stamp: pdbContentId.Stamp, version: (portablePdbVersion == 0) ? 0 : ('P' << 24 | 'M' << 16 | (uint)portablePdbVersion), dataSize: dataSize); }
public void Ctor() { var id1 = new BlobContentId(default(Guid), 1); Assert.Equal(default(Guid), id1.Guid); Assert.Equal(1u, id1.Stamp); Assert.False(id1.IsDefault); var id2 = new BlobContentId(new Guid("D6D61CDE-5BAF-4E77-ADDD-3B80F4020BF2"), 0x12345678); Assert.Equal(new Guid("D6D61CDE-5BAF-4E77-ADDD-3B80F4020BF2"), id2.Guid); Assert.Equal(0x12345678u, id2.Stamp); Assert.False(id2.IsDefault); var id3 = new BlobContentId(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14 }); Assert.Equal(new Guid("04030201-0605-0807-090a-0b0c0d0e0f10"), id3.Guid); Assert.Equal(0x14131211u, id3.Stamp); Assert.False(id3.IsDefault); Assert.True(default(BlobContentId).IsDefault); }
private async Task <PortablePdb> ExtractPortablePdbAsync( PackageArchiveReader symbolPackage, string pdbPath, CancellationToken cancellationToken) { // TODO: Validate that the PDB has a corresponding DLL // See: https://github.com/NuGet/NuGet.Jobs/blob/master/src/Validation.Symbols/SymbolsValidatorService.cs#L170 Stream pdbStream = null; PortablePdb result = null; try { using (var rawPdbStream = await symbolPackage.GetStreamAsync(pdbPath, cancellationToken)) { pdbStream = await rawPdbStream.AsTemporaryFileStreamAsync(); string signature; using (var pdbReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream, MetadataStreamOptions.LeaveOpen)) { var reader = pdbReaderProvider.GetMetadataReader(); var id = new BlobContentId(reader.DebugMetadataHeader.Id); signature = id.Guid.ToString("N").ToUpperInvariant(); } var fileName = Path.GetFileName(pdbPath).ToLowerInvariant(); var key = $"{signature}ffffffff"; pdbStream.Position = 0; result = new PortablePdb(fileName, key, pdbStream); } } finally { if (result == null) { pdbStream?.Dispose(); } } return(result); }
public static PdbSymbolReader TryOpen(string pdbFilename, MetadataStringDecoder stringDecoder, BlobContentId expectedContentId) { MemoryMappedViewAccessor mappedViewAccessor; MetadataReader reader = TryOpenMetadataFile(pdbFilename, stringDecoder, out mappedViewAccessor); if (reader == null) { return(null); } var foundContentId = new BlobContentId(reader.DebugMetadataHeader.Id); if (foundContentId != expectedContentId) { mappedViewAccessor.Dispose(); return(null); } return(new PortablePdbSymbolReader(reader, mappedViewAccessor)); }
/// <summary> /// This gets format for the VSTS symbol server indexed files. This format is /// based off of the PDB name and the signature present in the PDB /// </summary> /// <param name="pdbFullPath">Path to the PDB file</param> /// <returns>The indexed format of PDB file for the VSTS symbol server</returns> public static string GetIndex(string pdbFullPath) { if (pdbFullPath == null) { throw new ArgumentNullException(nameof(pdbFullPath)); } var indexingPath = string.Empty; using (var stream = File.OpenRead(pdbFullPath)) using (var pdbReaderProvider = MetadataReaderProvider.FromPortablePdbStream(stream, MetadataStreamOptions.LeaveOpen)) { var pdbReader = pdbReaderProvider.GetMetadataReader(); var pdbSignature = new BlobContentId(pdbReader.DebugMetadataHeader.Id).Guid; var pdbFileName = Path.GetFileName(pdbFullPath).ToLowerInvariant(); var pdbAge = "FFFFFFFF"; indexingPath = $"{pdbFileName}/{pdbSignature.ToString("N")}{pdbAge}/{pdbFileName}"; } return(indexingPath); }