File: CompilationVerifier.EmitOutput.cs
Web Access
Project: src\src\Compilers\Test\Core\Microsoft.CodeAnalysis.Test.Utilities.csproj (Microsoft.CodeAnalysis.Test.Utilities)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis;
 
namespace Microsoft.CodeAnalysis.Test.Utilities
{
    public sealed partial class CompilationVerifier
    {
        internal readonly struct EmitOutput
        {
            internal ImmutableArray<byte> Assembly { get; }
            internal ImmutableArray<byte> Pdb { get; }
            internal EmitOutput(ImmutableArray<byte> assembly, ImmutableArray<byte> pdb)
            {
                if (pdb.IsDefault)
                {
                    // We didn't emit a discrete PDB file, so we'll look for an embedded PDB instead.
                    using (var peReader = new PEReader(assembly))
                    {
                        DebugDirectoryEntry portablePdbEntry = peReader.ReadDebugDirectory().FirstOrDefault(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb);
                        if (portablePdbEntry.DataSize != 0)
                        {
                            using (var embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(portablePdbEntry))
                            {
                                var mdReader = embeddedMetadataProvider.GetMetadataReader();
                                pdb = readMetadata(mdReader);
                            }
                        }
                    }
                }
 
                Assembly = assembly;
                Pdb = pdb;
 
                unsafe ImmutableArray<byte> readMetadata(MetadataReader mdReader)
                {
                    var length = mdReader.MetadataLength;
                    var bytes = new byte[length];
                    Marshal.Copy((IntPtr)mdReader.MetadataPointer, bytes, 0, length);
                    return ImmutableArray.Create(bytes);
                }
            }
        }
    }
}