Exemplo n.º 1
0
        public void PdbStream_TypeSystemRowCounts()
        {
            var rowCounts = new int[MetadataTokens.TableCount];

            rowCounts[(int)TableIndex.MethodDef] = 0xFFFFFF;
            rowCounts[(int)TableIndex.TypeDef]   = 0x123456;

            var mdBuilder  = new MetadataBuilder();
            var pdbBuilder = new PortablePdbBuilder(
                mdBuilder,
                ImmutableArray.Create(rowCounts),
                MetadataTokens.MethodDefinitionHandle(0x123456),
                _ => new BlobContentId(new Guid("44332211-6655-8877-AA99-010203040506"), 0xFFEEDDCC));

            var builder = new BlobBuilder();

            pdbBuilder.Serialize(builder);

            AssertEx.Equal(new byte[]
            {
                // PDB ID
                0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xAA, 0x99, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
                0xCC, 0xDD, 0xEE, 0xFF,

                // EntryPoint
                0x56, 0x34, 0x12, 0x06,

                // ReferencedTypeSystemTables
                0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                // TypeSystemTableRows
                0x56, 0x34, 0x12, 0x00,
                0xFF, 0xFF, 0xFF, 0x00
            }, builder.Slice(124, -40));
        }
Exemplo n.º 2
0
        public void Hello()
        {
            var metadata = new MetadataBuilder(0, 0, 0, 0);

            var location = Assembly.GetExecutingAssembly().Location;
            var pdbPath  = Path.ChangeExtension(location, "pdb");

            using (var fileStream = new FileStream(pdbPath, FileMode.Open))
            {
                var readerProvider =
                    MetadataReaderProvider.FromPortablePdbStream(fileStream, MetadataStreamOptions.Default);

                var reader = readerProvider.GetMetadataReader(MetadataReaderOptions.ApplyWindowsRuntimeProjections, null);


                var debugDir = new DebugDirectoryBuilder();

                debugDir.AddEmbeddedPortablePdbEntry(null, 0);



                var blob = new BlobBuilder();

                var methodHandle = new MethodDefinitionHandle();

                var pdb = new PortablePdbBuilder(metadata, ImmutableArray <int> .Empty, methodHandle, null);

                var blobContentId = pdb.Serialize(blob);

                blob.ToArray();
            }
        }
Exemplo n.º 3
0
        public void Serialize_Errors()
        {
            var mdBuilder  = new MetadataBuilder();
            var pdbBuilder = new PortablePdbBuilder(mdBuilder, MetadataRootBuilder.EmptyRowCounts, default(MethodDefinitionHandle));
            var builder    = new BlobBuilder();

            Assert.Throws <ArgumentNullException>(() => pdbBuilder.Serialize(null));
        }
Exemplo n.º 4
0
        public void Serialize_Errors()
        {
            var mdBuilder = new MetadataBuilder();
            var pdbBuilder = new PortablePdbBuilder(mdBuilder, MetadataRootBuilder.EmptyRowCounts, default(MethodDefinitionHandle));
            var builder = new BlobBuilder();

            Assert.Throws<ArgumentNullException>(() => pdbBuilder.Serialize(null));
        }
        public static void Convert(Stream peStream, Stream sourcePdbStream, Stream targetPdbStream)
        {
            var metadataBuilder = new MetadataBuilder();
            ImmutableArray <int> typeSystemRowCounts;
            var debugEntryPointToken = default(MethodDefinitionHandle);
            var pdbId = default(BlobContentId);

            try
            {
                using (var peReader = new PEReader(peStream))
                {
                    pdbId = ReadPdbId(peReader);

                    var symReader = SymReaderFactory.CreateWindowsPdbReader(sourcePdbStream, peReader);

                    var metadataReader = peReader.GetMetadataReader();
                    var metadataModel  = new MetadataModel(metadataReader);

                    typeSystemRowCounts  = metadataModel.GetRowCounts();
                    debugEntryPointToken = ReadEntryPointHandle(symReader);

                    // documents:
                    var documentIndex = new Dictionary <string, DocumentHandle>(StringComparer.Ordinal);
                    var documents     = symReader.GetDocuments();
                    metadataBuilder.SetCapacity(TableIndex.Document, documents.Length);

                    bool vbSemantics = false;

                    foreach (var document in documents)
                    {
                        string name     = document.GetName();
                        Guid   language = document.GetLanguage();

                        // TODO:
                        // won't work for IL-merged assmemblies
                        vbSemantics |= language == SymReaderHelpers.VisualBasicLanguageGuid;

                        var rid = metadataBuilder.AddDocument(
                            name: metadataBuilder.GetOrAddDocumentName(name),
                            hashAlgorithm: metadataBuilder.GetOrAddGuid(document.GetHashAlgorithm()),
                            hash: metadataBuilder.GetOrAddBlob(document.GetChecksum()),
                            language: metadataBuilder.GetOrAddGuid(language));

                        documentIndex.Add(name, rid);
                    }

                    var lastLocalVariableHandle = default(LocalVariableHandle);
                    var lastLocalConstantHandle = default(LocalConstantHandle);

                    var importStringsByMethod = new Dictionary <int, ImmutableArray <string> >();
                    var importScopesByMethod  = new Dictionary <int, ImportScopeHandle>();

                    // Maps import scope content to import scope handles
                    var importScopeIndex = new Dictionary <ImportScopeInfo, ImportScopeHandle>();
                    var importScopes     = new List <ImportScopeInfo>();

                    // reserve slot for module import scope:
                    importScopes.Add(default(ImportScopeInfo));

                    var externAliasImports   = new List <ImportInfo>();
                    var externAliasStringSet = new HashSet <string>(StringComparer.Ordinal);

                    string vbDefaultNamespace    = null;
                    var    vbProjectLevelImports = new List <ImportInfo>();

                    // first pass:
                    foreach (var methodHandle in metadataReader.MethodDefinitions)
                    {
                        int methodToken = MetadataTokens.GetToken(methodHandle);
                        ImmutableArray <ImmutableArray <ImportInfo> > importGroups;

                        if (vbSemantics)
                        {
                            var importStrings = CustomDebugInfoReader.GetVisualBasicImportStrings(
                                methodToken,
                                symReader,
                                getMethodImportStrings: (token, sr) => GetImportStrings(token, importStringsByMethod, sr));

                            if (importStrings.IsEmpty)
                            {
                                // no debug info
                                continue;
                            }

                            var vbFileLevelImports = ArrayBuilder <ImportInfo> .GetInstance();

                            foreach (var importString in importStrings)
                            {
                                if (TryParseImportString(importString, out var import, vbSemantics: true))
                                {
                                    if (import.Kind == ImportTargetKind.DefaultNamespace)
                                    {
                                        vbDefaultNamespace = import.Target;
                                    }
                                    else if (import.Scope == VBImportScopeKind.Project)
                                    {
                                        vbProjectLevelImports.Add(import);
                                    }
                                    else
                                    {
                                        vbFileLevelImports.Add(import);
                                    }
                                }
                            }

                            importGroups = ImmutableArray.Create(vbFileLevelImports.ToImmutableAndFree());
                        }
                        else
                        {
                            var importStringGroups = CustomDebugInfoReader.GetCSharpGroupedImportStrings(
                                methodToken,
                                symReader,
                                getMethodCustomDebugInfo: (token, sr) => sr.GetCustomDebugInfo(token, methodVersion: 1),
                                getMethodImportStrings: (token, sr) => GetImportStrings(token, importStringsByMethod, sr),
                                externAliasStrings: out var localExternAliasStrings);

                            if (importStringGroups.IsDefault)
                            {
                                // no debug info
                                continue;
                            }

                            if (!localExternAliasStrings.IsDefault)
                            {
                                foreach (var externAlias in localExternAliasStrings)
                                {
                                    if (externAliasStringSet.Add(externAlias) &&
                                        TryParseImportString(externAlias, out var import, vbSemantics: false))
                                    {
                                        externAliasImports.Add(import);
                                    }
                                }
                            }

                            importGroups = ImmutableArray.CreateRange(importStringGroups.Select(g => ParseImportStrings(g, vbSemantics: false)));
                        }

                        var importScopeHandle = DefineImportScope(importGroups, importScopeIndex, importScopes);
                        importScopesByMethod.Add(methodToken, importScopeHandle);
                    }

                    // import scopes:
                    metadataBuilder.AddImportScope(
                        parentScope: default(ImportScopeHandle),
                        imports: SerializeModuleImportScope(metadataBuilder, externAliasImports, vbProjectLevelImports, vbDefaultNamespace, metadataModel));

                    for (int i = 1; i < importScopes.Count; i++)
                    {
                        metadataBuilder.AddImportScope(
                            parentScope: importScopes[i].Parent,
                            imports: SerializeImportsBlob(metadataBuilder, importScopes[i].Imports, metadataModel));
                    }

                    var dynamicNames = new Dictionary <string, DynamicLocalInfo>();
                    var dynamicSlots = new Dictionary <int, DynamicLocalInfo>();

                    // methods:
                    metadataBuilder.SetCapacity(TableIndex.MethodDebugInformation, metadataReader.MethodDefinitions.Count);
                    foreach (var methodHandle in metadataReader.MethodDefinitions)
                    {
                        var methodDef   = metadataReader.GetMethodDefinition(methodHandle);
                        int methodToken = MetadataTokens.GetToken(methodHandle);

                        var symMethod = symReader.GetMethod(methodToken);
                        if (symMethod == null)
                        {
                            metadataBuilder.AddMethodDebugInformation(default(DocumentHandle), sequencePoints: default(BlobHandle));
                            continue;
                        }

                        // method debug info:
                        int localSignatureRowId;
                        if (methodDef.RelativeVirtualAddress != 0)
                        {
                            var methodBody = peReader.GetMethodBody(methodDef.RelativeVirtualAddress);
                            localSignatureRowId = methodBody.LocalSignature.IsNil ? 0 : MetadataTokens.GetRowNumber(methodBody.LocalSignature);
                        }
                        else
                        {
                            localSignatureRowId = 0;
                        }

                        var symSequencePoints = symMethod.GetSequencePoints().ToImmutableArray();

                        DocumentHandle singleDocumentHandle;
                        BlobHandle     sequencePointsBlob = SerializeSequencePoints(metadataBuilder, localSignatureRowId, symSequencePoints, documentIndex, out singleDocumentHandle);

                        metadataBuilder.AddMethodDebugInformation(
                            document: singleDocumentHandle,
                            sequencePoints: sequencePointsBlob);

                        // state machine and async info:
                        var symAsyncMethod = symMethod.AsAsyncMethod();
                        if (symAsyncMethod != null)
                        {
                            var kickoffToken = MetadataTokens.Handle(symAsyncMethod.GetKickoffMethod());
                            metadataBuilder.AddStateMachineMethod(
                                moveNextMethod: methodHandle,
                                kickoffMethod: (MethodDefinitionHandle)kickoffToken);

                            metadataBuilder.AddCustomDebugInformation(
                                parent: methodHandle,
                                kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.AsyncMethodSteppingInformationBlob),
                                value: SerializeAsyncMethodSteppingInfo(metadataBuilder, symAsyncMethod, MetadataTokens.GetRowNumber(methodHandle)));
                        }

                        // custom debug information:
                        var dynamicLocals = default(ImmutableArray <DynamicLocalInfo>);

                        byte[] customDebugInfoBytes = symReader.GetCustomDebugInfo(methodToken, methodVersion: 1);
                        if (customDebugInfoBytes != null)
                        {
                            foreach (var record in CustomDebugInfoReader.GetCustomDebugInfoRecords(customDebugInfoBytes))
                            {
                                switch (record.Kind)
                                {
                                case CustomDebugInfoKind.DynamicLocals:
                                    dynamicLocals = CustomDebugInfoReader.DecodeDynamicLocalsRecord(record.Data);
                                    break;

                                case CustomDebugInfoKind.StateMachineHoistedLocalScopes:
                                    metadataBuilder.AddCustomDebugInformation(
                                        parent: methodHandle,
                                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.EncLocalSlotMap),
                                        value: SerializeStateMachineHoistedLocalsBlob(metadataBuilder, CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(record.Data)));
                                    break;

                                case CustomDebugInfoKind.EditAndContinueLocalSlotMap:
                                    metadataBuilder.AddCustomDebugInformation(
                                        parent: methodHandle,
                                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.EncLocalSlotMap),
                                        value: metadataBuilder.GetOrAddBlob(record.Data));
                                    break;

                                case CustomDebugInfoKind.EditAndContinueLambdaMap:
                                    metadataBuilder.AddCustomDebugInformation(
                                        parent: methodHandle,
                                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.EncLambdaAndClosureMap),
                                        value: metadataBuilder.GetOrAddBlob(record.Data));
                                    break;
                                }
                            }
                        }

                        var rootScope = symMethod.GetRootScope();
                        if (rootScope.GetNamespaces().Length == 0 || rootScope.GetLocals().Length == 0 || rootScope.GetConstants().Length == 0)
                        {
                            dynamicNames.Clear();
                            dynamicSlots.Clear();

                            foreach (var dynamicLocal in dynamicLocals)
                            {
                                if (dynamicLocal.SlotId == 0)
                                {
                                    // All dynamic constants have slot id == 0,
                                    // but a variable can also have slot id == 0
                                    if (!dynamicNames.ContainsKey(dynamicLocal.LocalName))
                                    {
                                        dynamicNames.Add(dynamicLocal.LocalName, dynamicLocal);
                                    }
                                    else
                                    {
                                        // TODO: warning
                                    }
                                }
                                else if (!dynamicSlots.ContainsKey(dynamicLocal.SlotId))
                                {
                                    dynamicSlots.Add(dynamicLocal.SlotId, dynamicLocal);
                                }
                                else
                                {
                                    // TODO: warning
                                }
                            }

                            foreach (ISymUnmanagedScope scope in rootScope.GetChildren())
                            {
                                SerializeScope(
                                    metadataBuilder,
                                    metadataModel,
                                    methodHandle,
                                    importScopesByMethod[methodToken],
                                    scope,
                                    dynamicSlots,
                                    dynamicNames,
                                    vbSemantics,
                                    ref lastLocalVariableHandle,
                                    ref lastLocalConstantHandle);
                            }
                        }
                        else
                        {
                            // TODO: warning:
                            // "Root scope must be empty (method 0x{0:x8})", MetadataTokens.GetToken(methodHandle))
                        }
                    }
                }
            }
            catch (COMException e)
            {
                // TODO: loc
                throw new BadImageFormatException("Invalid PDB format: " + e.Message, e);
            }

            var         serializer  = new PortablePdbBuilder(metadataBuilder, typeSystemRowCounts, debugEntryPointToken, idProvider: _ => pdbId);
            BlobBuilder blobBuilder = new BlobBuilder();

            serializer.Serialize(blobBuilder);
            blobBuilder.WriteContentTo(targetPdbStream);
        }
Exemplo n.º 6
0
        public void Headers()
        {
            var mdBuilder  = new MetadataBuilder();
            var pdbBuilder = new PortablePdbBuilder(
                mdBuilder,
                MetadataRootBuilder.EmptyRowCounts,
                MetadataTokens.MethodDefinitionHandle(0x123456),
                _ => new BlobContentId(new Guid("44332211-6655-8877-AA99-010203040506"), 0xFFEEDDCC));

            var builder = new BlobBuilder();

            pdbBuilder.Serialize(builder);

            AssertEx.Equal(new byte[]
            {
                // signature:
                0x42, 0x53, 0x4A, 0x42,
                // major version (1)
                0x01, 0x00,
                // minor version (1)
                0x01, 0x00,
                // reserved (0)
                0x00, 0x00, 0x00, 0x00,

                // padded version length:
                0x0C, 0x00, 0x00, 0x00,

                // padded version:
                (byte)'P', (byte)'D', (byte)'B', (byte)' ', (byte)'v', (byte)'1', (byte)'.', (byte)'0', 0x00, 0x00, 0x00, 0x00,

                // flags (0):
                0x00, 0x00,

                // stream count:
                0x06, 0x00,

                // stream headers (offset, size, padded name)
                0x7C, 0x00, 0x00, 0x00,
                0x20, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'P', (byte)'d', (byte)'b', 0x00, 0x00, 0x00, 0x00,

                0x9C, 0x00, 0x00, 0x00,
                0x1C, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'~', 0x00, 0x00,

                0xB8, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'S', (byte)'t', (byte)'r', (byte)'i', (byte)'n', (byte)'g', (byte)'s', 0x00, 0x00, 0x00, 0x00,

                0xBC, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'U', (byte)'S', 0x00,

                0xC0, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'G', (byte)'U', (byte)'I', (byte)'D', 0x00, 0x00, 0x00,

                0xC0, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'B', (byte)'l', (byte)'o', (byte)'b', 0x00, 0x00, 0x00,

                // --------
                // #Pdb
                // --------

                // PDB ID
                0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xAA, 0x99, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
                0xCC, 0xDD, 0xEE, 0xFF,

                // EntryPoint
                0x56, 0x34, 0x12, 0x06,

                // ReferencedTypeSystemTables
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                // TypeSystemTableRows (empty)

                // --------
                // #~
                // --------

                // Reserved (0)
                0x00, 0x00, 0x00, 0x00,

                // Major Version (2)
                0x02,

                // Minor Version (0)
                0x00,

                // Heap Sizes
                0x00,

                // Reserved (1)
                0x01,

                // Present tables
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                // Sorted tables
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                // Rows (empty)
                // Tables (empty)

                // Padding and alignment
                0x00, 0x00, 0x00, 0x00,

                // --------
                // #Strings
                // --------

                0x00, 0x00, 0x00, 0x00,

                // --------
                // #US
                // --------

                0x00, 0x00, 0x00, 0x00,

                // --------
                // #GUID
                // --------

                // --------
                // #Blob
                // --------

                0x00, 0x00, 0x00, 0x00,
            }, builder.ToArray());
        }
Exemplo n.º 7
0
        public void Headers()
        {
            var mdBuilder = new MetadataBuilder();
            var pdbBuilder = new PortablePdbBuilder(
                mdBuilder,
                MetadataRootBuilder.EmptyRowCounts,
                MetadataTokens.MethodDefinitionHandle(0x123456),
                _ => new BlobContentId(new Guid("44332211-6655-8877-AA99-010203040506"), 0xFFEEDDCC));

            var builder = new BlobBuilder();
            pdbBuilder.Serialize(builder);

            AssertEx.Equal(new byte[]
            {
                // signature:
                0x42, 0x53, 0x4A, 0x42,
                // major version (1)
                0x01, 0x00,
                // minor version (1)
                0x01, 0x00,
                // reserved (0)
                0x00, 0x00, 0x00, 0x00,

                // padded version length:
                0x0C, 0x00, 0x00, 0x00,

                // padded version:
                (byte)'P', (byte)'D', (byte)'B', (byte)' ', (byte)'v', (byte)'1', (byte)'.', (byte)'0', 0x00, 0x00, 0x00, 0x00,
                
                // flags (0):
                0x00, 0x00,

                // stream count:
                0x06, 0x00,

                // stream headers (offset, size, padded name)
                0x7C, 0x00, 0x00, 0x00,
                0x20, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'P', (byte)'d', (byte)'b', 0x00, 0x00, 0x00, 0x00,

                0x9C, 0x00, 0x00, 0x00,
                0x1C, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'~', 0x00, 0x00,

                0xB8, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'S', (byte)'t', (byte)'r', (byte)'i', (byte)'n', (byte)'g', (byte)'s', 0x00, 0x00, 0x00, 0x00,

                0xBC, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'U', (byte)'S', 0x00,

                0xC0, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'G', (byte)'U', (byte)'I', (byte)'D', 0x00, 0x00, 0x00,

                0xC0, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'B', (byte)'l', (byte)'o', (byte)'b', 0x00, 0x00, 0x00,

                // --------
                // #Pdb
                // --------

                // PDB ID
                0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xAA, 0x99, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
                0xCC, 0xDD, 0xEE, 0xFF,

                // EntryPoint
                0x56, 0x34, 0x12, 0x06,

                // ReferencedTypeSystemTables
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                // TypeSystemTableRows (empty)

                // --------
                // #~
                // --------
                
                // Reserved (0)
                0x00, 0x00, 0x00, 0x00,

                // Major Version (2)
                0x02,

                // Minor Version (0)
                0x00,

                // Heap Sizes
                0x00,

                // Reserved (1)
                0x01,

                // Present tables
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                // Sorted tables
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                // Rows (empty)
                // Tables (empty)

                // Padding and alignment
                0x00, 0x00, 0x00, 0x00,
                
                // --------
                // #Strings
                // --------

                0x00, 0x00, 0x00, 0x00,

                // --------
                // #US
                // --------

                0x00, 0x00, 0x00, 0x00,

                // --------
                // #GUID
                // --------

                // --------
                // #Blob
                // --------

                0x00, 0x00, 0x00, 0x00,

            }, builder.ToArray());
        }
Exemplo n.º 8
0
        public void PdbStream_TypeSystemRowCounts()
        {
            var rowCounts = new int[MetadataTokens.TableCount];
            rowCounts[(int)TableIndex.MethodDef] = 0xFFFFFF;
            rowCounts[(int)TableIndex.TypeDef] = 0x123456;

            var mdBuilder = new MetadataBuilder();
            var pdbBuilder = new PortablePdbBuilder(
                mdBuilder,
                ImmutableArray.Create(rowCounts),
                MetadataTokens.MethodDefinitionHandle(0x123456),
                _ => new BlobContentId(new Guid("44332211-6655-8877-AA99-010203040506"), 0xFFEEDDCC));

            var builder = new BlobBuilder();
            pdbBuilder.Serialize(builder);

            AssertEx.Equal(new byte[]
            {
                // PDB ID
                0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0xAA, 0x99, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
                0xCC, 0xDD, 0xEE, 0xFF,

                // EntryPoint
                0x56, 0x34, 0x12, 0x06,

                // ReferencedTypeSystemTables
                0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

                // TypeSystemTableRows
                0x56, 0x34, 0x12, 0x00,
                0xFF, 0xFF, 0xFF, 0x00

            }, builder.Slice(124, -40));
        }
Exemplo n.º 9
0
        public static bool WritePeToStream(
            EmitContext context,
            CommonMessageProvider messageProvider,
            Func <Stream> getPeStream,
            Func <Stream> getPortablePdbStreamOpt,
            PdbWriter nativePdbWriterOpt,
            string pdbPathOpt,
            bool allowMissingMethodBodies,
            bool isDeterministic,
            CancellationToken cancellationToken)
        {
            // If PDB writer is given, we have to have PDB path.
            Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null);

            MetadataWriter mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken);

            ModulePropertiesForSerialization properties = context.Module.SerializationProperties;

            nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

            // Since we are producing a full assembly, we should not have a module version ID
            // imposed ahead-of time. Instead we will compute a deterministic module version ID
            // based on the contents of the generated stream.
            Debug.Assert(properties.PersistentIdentifier == default(Guid));

            BlobBuilder ilBuilder = new BlobBuilder(32 * 1024);
            BlobBuilder mappedFieldDataBuilder = new BlobBuilder();
            BlobBuilder managedResourceBuilder = new BlobBuilder(1024);

            mdWriter.BuildMetadataAndIL(
                nativePdbWriterOpt,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                out Blob mvidFixup,
                out Blob mvidStringFixup);

            mdWriter.GetEntryPoints(out MethodDefinitionHandle entryPointHandle, out MethodDefinitionHandle debugEntryPointHandle);

            if (!debugEntryPointHandle.IsNil)
            {
                nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle));
            }

            if (nativePdbWriterOpt != null)
            {
                if (mdWriter.Module.OutputKind == OutputKind.WindowsRuntimeMetadata)
                {
                    // Dev12: If compiling to winmdobj, we need to add to PDB source spans of
                    //        all types and members for better error reporting by WinMDExp.
                    nativePdbWriterOpt.WriteDefinitionLocations(mdWriter.Module.GetSymbolToLocationMap());
                }
                else
                {
#if DEBUG
                    // validate that all definitions are writable
                    // if same scenario would happen in an winmdobj project
                    nativePdbWriterOpt.AssertAllDefinitionsHaveTokens(mdWriter.Module.GetSymbolToLocationMap());
#endif
                }

                // embedded text not currently supported for native PDB and we should have validated that
                Debug.Assert(!mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments.Any());
            }

            Stream peStream = getPeStream();
            if (peStream == null)
            {
                return(false);
            }

            BlobContentId pdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(BlobContentId);

            // the writer shall not be used after this point for writing:
            nativePdbWriterOpt = null;

            ushort portablePdbVersion = 0;
            MetadataRootBuilder metadataRootBuilder = mdWriter.GetRootBuilder();

            PEHeaderBuilder peHeaderBuilder = new PEHeaderBuilder(
                machine: properties.Machine,
                sectionAlignment: properties.SectionAlignment,
                fileAlignment: properties.FileAlignment,
                imageBase: properties.BaseAddress,
                majorLinkerVersion: properties.LinkerMajorVersion,
                minorLinkerVersion: properties.LinkerMinorVersion,
                majorOperatingSystemVersion: 4,
                minorOperatingSystemVersion: 0,
                majorImageVersion: 0,
                minorImageVersion: 0,
                majorSubsystemVersion: properties.MajorSubsystemVersion,
                minorSubsystemVersion: properties.MinorSubsystemVersion,
                subsystem: properties.Subsystem,
                dllCharacteristics: properties.DllCharacteristics,
                imageCharacteristics: properties.ImageCharacteristics,
                sizeOfStackReserve: properties.SizeOfStackReserve,
                sizeOfStackCommit: properties.SizeOfStackCommit,
                sizeOfHeapReserve: properties.SizeOfHeapReserve,
                sizeOfHeapCommit: properties.SizeOfHeapCommit);

            Func <IEnumerable <Blob>, BlobContentId> deterministicIdProvider = isDeterministic ?
                                                                               new Func <IEnumerable <Blob>, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) :
                                                                               null;

            BlobBuilder portablePdbToEmbed = null;
            if (mdWriter.EmitStandaloneDebugMetadata)
            {
                mdWriter.AddRemainingEmbeddedDocuments(mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments);

                BlobBuilder        portablePdbBlob    = new BlobBuilder();
                PortablePdbBuilder portablePdbBuilder = mdWriter.GetPortablePdbBuilder(metadataRootBuilder.Sizes.RowCounts, debugEntryPointHandle, deterministicIdProvider);
                pdbContentId       = portablePdbBuilder.Serialize(portablePdbBlob);
                portablePdbVersion = portablePdbBuilder.FormatVersion;

                if (getPortablePdbStreamOpt == null)
                {
                    // embed to debug directory:
                    portablePdbToEmbed = portablePdbBlob;
                }
                else
                {
                    // write to Portable PDB stream:
                    Stream portablePdbStream = getPortablePdbStreamOpt();
                    if (portablePdbStream != null)
                    {
                        portablePdbBlob.WriteContentTo(portablePdbStream);
                    }
                }
            }

            DebugDirectoryBuilder debugDirectoryBuilder;
            if (pdbPathOpt != null || isDeterministic || portablePdbToEmbed != null)
            {
                debugDirectoryBuilder = new DebugDirectoryBuilder();
                if (pdbPathOpt != null)
                {
                    string paddedPath = isDeterministic ? pdbPathOpt : PadPdbPath(pdbPathOpt);
                    debugDirectoryBuilder.AddCodeViewEntry(paddedPath, pdbContentId, portablePdbVersion);
                }

                if (isDeterministic)
                {
                    debugDirectoryBuilder.AddReproducibleEntry();
                }

                if (portablePdbToEmbed != null)
                {
                    debugDirectoryBuilder.AddEmbeddedPortablePdbEntry(portablePdbToEmbed, portablePdbVersion);
                }
            }
            else
            {
                debugDirectoryBuilder = null;
            }

            ManagedPEBuilder peBuilder = new ManagedPEBuilder(
                peHeaderBuilder,
                metadataRootBuilder,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                CreateNativeResourceSectionSerializer(context.Module),
                debugDirectoryBuilder,
                CalculateStrongNameSignatureSize(context.Module),
                entryPointHandle,
                properties.CorFlags,
                deterministicIdProvider);

            BlobBuilder   peBlob      = new BlobBuilder();
            BlobContentId peContentId = peBuilder.Serialize(peBlob);

            PatchModuleVersionIds(mvidFixup, mvidStringFixup, peContentId.Guid);

            try
            {
                peBlob.WriteContentTo(peStream);
            }
            catch (Exception e) when(!(e is OperationCanceledException))
            {
                throw new PeWritingException(e);
            }

            return(true);
        }