public void Serialize_Errors()
        {
            var mdBuilder   = new MetadataBuilder();
            var rootBuilder = new MetadataRootBuilder(mdBuilder);
            var builder     = new BlobBuilder();

            Assert.Throws <ArgumentNullException>(() => rootBuilder.Serialize(null, 0, 0));
            Assert.Throws <ArgumentOutOfRangeException>(() => rootBuilder.Serialize(builder, -1, 0));
            Assert.Throws <ArgumentOutOfRangeException>(() => rootBuilder.Serialize(builder, 0, -1));
        }
        public void Serialize_Errors()
        {
            var mdBuilder = new MetadataBuilder();
            var rootBuilder = new MetadataRootBuilder(mdBuilder);
            var builder = new BlobBuilder();

            Assert.Throws<ArgumentNullException>(() => rootBuilder.Serialize(null, 0, 0));
            Assert.Throws<ArgumentOutOfRangeException>(() => rootBuilder.Serialize(builder, -1, 0));
            Assert.Throws<ArgumentOutOfRangeException>(() => rootBuilder.Serialize(builder, 0, -1));
        }
        public void MetadataVersion_Empty()
        {
            var version = "";

            var mdBuilder = new MetadataBuilder();

            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var rootBuilder = new MetadataRootBuilder(mdBuilder, version);

            var builder = new BlobBuilder();

            rootBuilder.Serialize(builder, 0, 0);

            AssertEx.Equal(new byte[]
            {
                // padded version length:
                0x04, 0x00, 0x00, 0x00,

                // padded version:
                0x00, 0x00, 0x00, 0x00,
            }, builder.Slice(12, -132));

            Assert.Equal(version, ReadVersion(builder));
        }
Exemple #4
0
        public void MetadataVersion()
        {
            var version = "\u1234\ud800";

            var mdBuilder = new MetadataBuilder();

            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var rootBuilder = new MetadataRootBuilder(mdBuilder, version);

            var builder = new BlobBuilder();

            rootBuilder.Serialize(builder, 0, 0);

            AssertEx.Equal(new byte[]
            {
                // padded version length:
                0x08, 0x00, 0x00, 0x00,

                // padded version:
                0xE1, 0x88, 0xB4, 0xED, 0xA0, 0x80, 0x00, 0x00,
            }, builder.Slice(12, -132));

            // the default decoder replaces bad byte sequences by U+FFFD
            Assert.Equal("\u1234\ufffd\ufffd", ReadVersion(builder));
        }
        // Generate only the metadata blob as a byte[]
        public byte[] EmitToMetadataBlob()
        {
            MetadataRootBuilder metadataRootBuilder = new MetadataRootBuilder(_metadataBuilder);
            BlobBuilder         metadataBlobBuilder = new BlobBuilder();

            metadataRootBuilder.Serialize(metadataBlobBuilder, methodBodyStreamRva: 0, mappedFieldDataStreamRva: 0);

            // Clear some variables to catch any caller trying to emit data after writing the output file
            _metadataBuilder = null;

            return(metadataBlobBuilder.ToArray());
        }
Exemple #6
0
        private static BlobBuilder BuildMetadataImage()
        {
            var mdBuilder = new MetadataBuilder();

            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var rootBuilder = new MetadataRootBuilder(mdBuilder, "v9.9.9.9");

            var builder = new BlobBuilder();

            rootBuilder.Serialize(builder, 0, 0);

            return(builder);
        }
        public void MetadataVersion()
        {
            var version = "\u1234\ud800";

            var mdBuilder = new MetadataBuilder();

            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var rootBuilder = new MetadataRootBuilder(mdBuilder, version);

            var builder = new BlobBuilder();

            rootBuilder.Serialize(builder, 0, 0);

            AssertEx.Equal(new byte[]
            {
                // padded version length:
                0x08, 0x00, 0x00, 0x00,

                // padded version:
                // [ E1 88 B4 ] -> U+1234
                // [ ED ] -> invalid (ED cannot be followed by A0) -> U+FFFD
                // [ A0 ] -> invalid (not ASCII, not valid leading byte) -> U+FFFD
                // [ 80 ] -> invalid (not ASCII, not valid leading byte) -> U+FFFD
                0xE1, 0x88, 0xB4, 0xED, 0xA0, 0x80, 0x00, 0x00,
            }, builder.Slice(12, -132));

            // the default decoder replaces bad byte sequences by U+FFFD
            if (PlatformDetection.IsNetCore)
            {
                Assert.Equal("\u1234\ufffd\ufffd\ufffd", ReadVersion(builder));
            }
            else
            {
                // Versions of .NET prior to Core 3.0 didn't follow Unicode recommendations for U+FFFD substitution,
                // so they sometimes emitted too few replacement chars.
                Assert.Equal("\u1234\ufffd\ufffd", ReadVersion(builder));
            }
        }
        public void GetOrAddDocumentName2()
        {
            var mdBuilder = new MetadataBuilder();

            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var n1  = mdBuilder.GetOrAddDocumentName("");
            var n2  = mdBuilder.GetOrAddDocumentName("/a/b/c");
            var n3  = mdBuilder.GetOrAddDocumentName(@"\a\b\cc");
            var n4  = mdBuilder.GetOrAddDocumentName(@"/a/b\c");
            var n5  = mdBuilder.GetOrAddDocumentName(@"/\a/\b\\//c");
            var n6  = mdBuilder.GetOrAddDocumentName(@"a/");
            var n7  = mdBuilder.GetOrAddDocumentName(@"/");
            var n8  = mdBuilder.GetOrAddDocumentName(@"\\");
            var n9  = mdBuilder.GetOrAddDocumentName("\ud800"); // unpaired surrogate
            var n10 = mdBuilder.GetOrAddDocumentName("\0");

            var root        = new MetadataRootBuilder(mdBuilder);
            var rootBuilder = new BlobBuilder();

            root.Serialize(rootBuilder, 0, 0);
            var mdImage = rootBuilder.ToImmutableArray();

            using (var provider = MetadataReaderProvider.FromMetadataImage(mdImage))
            {
                var mdReader = provider.GetMetadataReader();
                Assert.Equal("", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n1))));
                Assert.Equal("/a/b/c", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n2))));
                Assert.Equal(@"\a\b\cc", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n3))));
                Assert.Equal(@"/a/b\c", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n4))));
                Assert.Equal(@"/\a/\b\\//c", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n5))));
                Assert.Equal(@"a/", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n6))));
                Assert.Equal(@"/", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n7))));
                Assert.Equal(@"\\", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n8))));
                Assert.Equal("\uFFFd\uFFFd", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n9))));
                Assert.Equal("\0", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n10))));
            }
        }
        public void MetadataVersion_Default()
        {
            var mdBuilder = new MetadataBuilder();

            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var rootBuilder = new MetadataRootBuilder(mdBuilder);

            var builder = new BlobBuilder();

            rootBuilder.Serialize(builder, 0, 0);

            AssertEx.Equal(new byte[]
            {
                // padded version length:
                0x0C, 0x00, 0x00, 0x00,

                // padded version:
                (byte)'v', (byte)'4', (byte)'.', (byte)'0', (byte)'.', (byte)'3', (byte)'0', (byte)'3', (byte)'1', (byte)'9', 0x00, 0x00,
            }, builder.Slice(12, -132));

            Assert.Equal(rootBuilder.MetadataVersion, ReadVersion(builder));
        }
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), null, 1, null));
            }

            if (!_emissionCompleted)
            {
                foreach (ISignatureEmitter emitter in _signatureEmitters)
                {
                    emitter.MaterializeSignature();
                }

                _emissionCompleted = true;
            }

            MetadataBuilder metadataBuilder = new MetadataBuilder();

            string manifestMetadataAssemblyName = "ManifestMetadata";

            metadataBuilder.AddAssembly(
                metadataBuilder.GetOrAddString(manifestMetadataAssemblyName),
                new Version(0, 0, 0, 0),
                culture: default(StringHandle),
                publicKey: default(BlobHandle),
                flags: default(AssemblyFlags),
                hashAlgorithm: AssemblyHashAlgorithm.None);

            metadataBuilder.AddModule(
                0,
                metadataBuilder.GetOrAddString(manifestMetadataAssemblyName),
                default(GuidHandle), default(GuidHandle), default(GuidHandle));

            // Module type
            metadataBuilder.AddTypeDefinition(
                default(TypeAttributes),
                default(StringHandle),
                metadataBuilder.GetOrAddString("<Module>"),
                baseType: default(EntityHandle),
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: MetadataTokens.MethodDefinitionHandle(1));

            foreach (var idAndAssemblyName in _moduleIdToAssemblyNameMap.OrderBy(x => x.Key))
            {
                AssemblyName  assemblyName  = idAndAssemblyName.Value;
                AssemblyFlags assemblyFlags = 0;
                byte[]        publicKeyOrToken;
                if ((assemblyName.Flags & AssemblyNameFlags.PublicKey) != 0)
                {
                    assemblyFlags   |= AssemblyFlags.PublicKey;
                    publicKeyOrToken = assemblyName.GetPublicKey();
                }
                else
                {
                    publicKeyOrToken = assemblyName.GetPublicKeyToken();
                }
                if ((assemblyName.Flags & AssemblyNameFlags.Retargetable) != 0)
                {
                    assemblyFlags |= AssemblyFlags.Retargetable;
                }

                AssemblyReferenceHandle newHandle = metadataBuilder.AddAssemblyReference(
                    name: metadataBuilder.GetOrAddString(assemblyName.Name),
                    version: assemblyName.Version,
                    culture: metadataBuilder.GetOrAddString(assemblyName.CultureName),
                    publicKeyOrToken: metadataBuilder.GetOrAddBlob(publicKeyOrToken),
                    flags: assemblyFlags,
                    hashValue: default(BlobHandle) /* TODO */);
            }

            MetadataRootBuilder metadataRootBuilder = new MetadataRootBuilder(metadataBuilder);
            BlobBuilder         metadataBlobBuilder = new BlobBuilder();

            metadataRootBuilder.Serialize(metadataBlobBuilder, methodBodyStreamRva: 0, mappedFieldDataStreamRva: 0);

            return(new ObjectData(
                       data: metadataBlobBuilder.ToArray(),
                       relocs: Array.Empty <Relocation>(),
                       alignment: 1,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
Exemple #11
0
        private BlobBuilder SerializeTextSection(SectionLocation location)
        {
            var sectionBuilder  = new BlobBuilder();
            var metadataBuilder = new BlobBuilder();

            var metadataSizes = _metadataRootBuilder.Sizes;

            var textSection = new ManagedTextSection(
                imageCharacteristics: Header.ImageCharacteristics,
                machine: Header.Machine,
                ilStreamSize: _ilStream.Count,
                metadataSize: metadataSizes.MetadataSize,
                resourceDataSize: _managedResourcesOpt?.Count ?? 0,
                strongNameSignatureSize: _strongNameSignatureSize,
                debugDataSize: _debugDirectoryBuilderOpt?.Size ?? 0,
                mappedFieldDataSize: _mappedFieldDataOpt?.Count ?? 0);

            int methodBodyStreamRva      = location.RelativeVirtualAddress + textSection.OffsetToILStream;
            int mappedFieldDataStreamRva = location.RelativeVirtualAddress + textSection.CalculateOffsetToMappedFieldDataStream();

            _metadataRootBuilder.Serialize(metadataBuilder, methodBodyStreamRva, mappedFieldDataStreamRva);

            DirectoryEntry debugDirectoryEntry;
            BlobBuilder    debugTableBuilderOpt;

            if (_debugDirectoryBuilderOpt != null)
            {
                int debugDirectoryOffset = textSection.ComputeOffsetToDebugDirectory();
                debugTableBuilderOpt = new BlobBuilder(_debugDirectoryBuilderOpt.TableSize);
                _debugDirectoryBuilderOpt.Serialize(debugTableBuilderOpt, location, debugDirectoryOffset);

                // Only the size of the fixed part of the debug table goes here.
                debugDirectoryEntry = new DirectoryEntry(
                    location.RelativeVirtualAddress + debugDirectoryOffset,
                    _debugDirectoryBuilderOpt.TableSize);
            }
            else
            {
                debugTableBuilderOpt = null;
                debugDirectoryEntry  = default(DirectoryEntry);
            }

            _lazyEntryPointAddress = textSection.GetEntryPointAddress(location.RelativeVirtualAddress);

            textSection.Serialize(
                sectionBuilder,
                location.RelativeVirtualAddress,
                _entryPointOpt.IsNil ? 0 : MetadataTokens.GetToken(_entryPointOpt),
                _corFlags,
                Header.ImageBase,
                metadataBuilder,
                _ilStream,
                _mappedFieldDataOpt,
                _managedResourcesOpt,
                debugTableBuilderOpt,
                out _lazyStrongNameSignature);

            _peDirectoriesBuilder.AddressOfEntryPoint = _lazyEntryPointAddress;
            _peDirectoriesBuilder.DebugTable          = debugDirectoryEntry;
            _peDirectoriesBuilder.ImportAddressTable  = textSection.GetImportAddressTableDirectoryEntry(location.RelativeVirtualAddress);
            _peDirectoriesBuilder.ImportTable         = textSection.GetImportTableDirectoryEntry(location.RelativeVirtualAddress);
            _peDirectoriesBuilder.CorHeaderTable      = textSection.GetCorHeaderDirectoryEntry(location.RelativeVirtualAddress);

            return(sectionBuilder);
        }
        public void Headers()
        {
            var mdBuilder   = new MetadataBuilder();
            var rootBuilder = new MetadataRootBuilder(mdBuilder);

            var builder = new BlobBuilder();

            rootBuilder.Serialize(builder, 0, 0);

            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)'v', (byte)'4', (byte)'.', (byte)'0', (byte)'.', (byte)'3', (byte)'0', (byte)'3', (byte)'1', (byte)'9', 0x00, 0x00,

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

                // stream count:
                0x05, 0x00,

                // stream headers:
                0x6C, 0x00, 0x00, 0x00,
                0x1C, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'~', 0x00, 0x00,

                0x88, 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,

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

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

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

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

                // 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, 0xFA, 0x01, 0x33, 0x00, 0x16, 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());
        }
        public void MetadataVersion_Default()
        {
            var mdBuilder = new MetadataBuilder();
            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var rootBuilder = new MetadataRootBuilder(mdBuilder);

            var builder = new BlobBuilder();
            rootBuilder.Serialize(builder, 0, 0);

            AssertEx.Equal(new byte[] 
            {
                // padded version length:
                0x0C, 0x00, 0x00, 0x00,

                // padded version:
                (byte)'v', (byte)'4', (byte)'.', (byte)'0', (byte)'.', (byte)'3', (byte)'0', (byte)'3', (byte)'1', (byte)'9', 0x00, 0x00,
            }, builder.Slice(12, -132));

            Assert.Equal(rootBuilder.MetadataVersion, ReadVersion(builder));
        }
        public void MetadataVersion_MaxLength()
        {
            var version = new string('x', 254);

            var mdBuilder = new MetadataBuilder();
            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var rootBuilder = new MetadataRootBuilder(mdBuilder, version);

            var builder = new BlobBuilder();
            rootBuilder.Serialize(builder, 0, 0);

            AssertEx.Equal(new byte[]
            {
                // padded version length:
                0x00, 0x01, 0x00, 0x00,

                // padded version:
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
                0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00
            }, builder.Slice(12, -132));

            Assert.Equal(version, ReadVersion(builder));
        }
        public void EncHeaders()
        {
            var mdBuilder = new MetadataBuilder();

            mdBuilder.AddEncLogEntry(MetadataTokens.MethodDefinitionHandle(1), EditAndContinueOperation.AddMethod);

            var rootBuilder = new MetadataRootBuilder(mdBuilder);

            var builder = new BlobBuilder();

            rootBuilder.Serialize(builder, 0, 0);

            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)'v', (byte)'4', (byte)'.', (byte)'0', (byte)'.', (byte)'3', (byte)'0', (byte)'3', (byte)'1', (byte)'9', 0x00, 0x00,

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

                // stream count:
                0x06, 0x00,

                // stream headers:
                0x7C, 0x00, 0x00, 0x00,
                0x28, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'-', 0x00, 0x00,

                0xA4, 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,

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

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

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

                0xB0, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'J', (byte)'T', (byte)'D', 0x00, 0x00, 0x00, 0x00,

                // --------
                // #-
                // --------

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

                // Major Version (2)
                0x02,

                // Minor Version (0)
                0x00,

                // Heap Sizes
                0xA7,

                // Reserved (1)
                0x01,

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

                // Sorted tables
                0x00, 0xFA, 0x01, 0x33, 0x00, 0x16, 0x00, 0x00,

                // Rows
                0x01, 0x00, 0x00, 0x00,

                //
                // EncLog Table (token, operation)
                //

                0x01, 0x00, 0x00, 0x06,
                0x01, 0x00, 0x00, 0x00,

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

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

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

                // --------
                // #US
                // --------
                0x00, 0x00, 0x00, 0x00,

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

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

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

                // --------
                // #JTD
                // --------
            }, builder.ToArray());
        }
        public void EncHeaders()
        {
            var mdBuilder = new MetadataBuilder();
            mdBuilder.AddEncLogEntry(MetadataTokens.MethodDefinitionHandle(1), EditAndContinueOperation.AddMethod);

            var rootBuilder = new MetadataRootBuilder(mdBuilder);

            var builder = new BlobBuilder();
            rootBuilder.Serialize(builder, 0, 0);

            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)'v', (byte)'4', (byte)'.', (byte)'0', (byte)'.', (byte)'3', (byte)'0', (byte)'3', (byte)'1', (byte)'9', 0x00, 0x00,

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

                // stream count:
                0x06, 0x00,

                // stream headers:
                0x7C, 0x00, 0x00, 0x00,
                0x28, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'-', 0x00, 0x00,

                0xA4, 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,

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

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

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

                0xB0, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'J', (byte)'T', (byte)'D', 0x00, 0x00, 0x00, 0x00,

                // --------
                // #-
                // --------
                
                // Reserved (0)
                0x00, 0x00, 0x00, 0x00,
                
                // Major Version (2)
                0x02,

                // Minor Version (0)
                0x00,

                // Heap Sizes
                0xA7,

                // Reserved (1)
                0x01,

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

                // Sorted tables
                0x00, 0xFA, 0x01, 0x33, 0x00, 0x16, 0x00, 0x00, 

                // Rows
                0x01, 0x00, 0x00, 0x00,

                //
                // EncLog Table (token, operation)
                //

                0x01, 0x00, 0x00, 0x06,
                0x01, 0x00, 0x00, 0x00,

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

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

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

                // --------
                // #US
                // --------
                0x00, 0x00, 0x00, 0x00,

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

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

                0x00, 0x00, 0x00, 0x00,
                
                // --------
                // #JTD
                // --------
            }, builder.ToArray());
        }
        public void GetOrAddDocumentName2()
        {
            var mdBuilder = new MetadataBuilder();
            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var n1 = mdBuilder.GetOrAddDocumentName("");
            var n2 = mdBuilder.GetOrAddDocumentName("/a/b/c");
            var n3 = mdBuilder.GetOrAddDocumentName(@"\a\b\cc");
            var n4 = mdBuilder.GetOrAddDocumentName(@"/a/b\c");
            var n5 = mdBuilder.GetOrAddDocumentName(@"/\a/\b\\//c");
            var n6 = mdBuilder.GetOrAddDocumentName(@"a/");
            var n7 = mdBuilder.GetOrAddDocumentName(@"/");
            var n8 = mdBuilder.GetOrAddDocumentName(@"\\");
            var n9 = mdBuilder.GetOrAddDocumentName("\ud800"); // unpaired surrogate
            var n10 = mdBuilder.GetOrAddDocumentName("\0");

            var root = new MetadataRootBuilder(mdBuilder);
            var rootBuilder = new BlobBuilder();
            root.Serialize(rootBuilder, 0, 0);
            var mdImage = rootBuilder.ToImmutableArray();

            using (var provider = MetadataReaderProvider.FromMetadataImage(mdImage))
            {
                var mdReader = provider.GetMetadataReader();
                Assert.Equal("", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n1))));
                Assert.Equal("/a/b/c", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n2))));
                Assert.Equal(@"\a\b\cc", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n3))));
                Assert.Equal(@"/a/b\c", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n4))));
                Assert.Equal(@"/\a/\b\\//c", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n5))));
                Assert.Equal(@"a/", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n6))));
                Assert.Equal(@"/", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n7))));
                Assert.Equal(@"\\", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n8))));
                Assert.Equal("\uFFFd\uFFFd", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n9))));
                Assert.Equal("\0", mdReader.GetString(MetadataTokens.DocumentNameBlobHandle(MetadataTokens.GetHeapOffset(n10))));
            }
        }
        public void MetadataVersion()
        {
            var version = "\u1234\ud800";

            var mdBuilder = new MetadataBuilder();
            mdBuilder.AddModule(0, default(StringHandle), default(GuidHandle), default(GuidHandle), default(GuidHandle));

            var rootBuilder = new MetadataRootBuilder(mdBuilder, version);

            var builder = new BlobBuilder();
            rootBuilder.Serialize(builder, 0, 0);

            AssertEx.Equal(new byte[]
            {
                // padded version length:
                0x08, 0x00, 0x00, 0x00,

                // padded version:
                0xE1, 0x88, 0xB4, 0xED, 0xA0, 0x80, 0x00, 0x00,
            }, builder.Slice(12, -132));

            // the default decoder replaces bad byte sequences by U+FFFD
            Assert.Equal("\u1234\ufffd\ufffd", ReadVersion(builder));
        }
Exemple #19
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), null, 1, null));
            }

            ComputeLastSetOfModuleIndices();

            MetadataBuilder metadataBuilder = new MetadataBuilder();

            AssemblyHashAlgorithm hashAlgorithm         = AssemblyHashAlgorithm.None;
            BlobHandle            publicKeyBlob         = default(BlobHandle);
            AssemblyFlags         manifestAssemblyFlags = default(AssemblyFlags);
            Version manifestAssemblyVersion             = new Version(0, 0, 0, 0);

            if ((factory.CompositeImageSettings != null) && factory.CompilationModuleGroup.IsCompositeBuildMode)
            {
                if (factory.CompositeImageSettings.PublicKey != null)
                {
                    hashAlgorithm          = AssemblyHashAlgorithm.Sha1;
                    publicKeyBlob          = metadataBuilder.GetOrAddBlob(factory.CompositeImageSettings.PublicKey);
                    manifestAssemblyFlags |= AssemblyFlags.PublicKey;
                }

                if (factory.CompositeImageSettings.AssemblyVersion != null)
                {
                    manifestAssemblyVersion = factory.CompositeImageSettings.AssemblyVersion;
                }
            }

            string manifestMetadataAssemblyName = "ManifestMetadata";

            metadataBuilder.AddAssembly(
                metadataBuilder.GetOrAddString(manifestMetadataAssemblyName),
                manifestAssemblyVersion,
                culture: default(StringHandle),
                publicKey: publicKeyBlob,
                flags: manifestAssemblyFlags,
                hashAlgorithm: hashAlgorithm);

            metadataBuilder.AddModule(
                0,
                metadataBuilder.GetOrAddString(manifestMetadataAssemblyName),
                default(GuidHandle), default(GuidHandle), default(GuidHandle));

            // Module type
            metadataBuilder.AddTypeDefinition(
                default(TypeAttributes),
                default(StringHandle),
                metadataBuilder.GetOrAddString("<Module>"),
                baseType: default(EntityHandle),
                fieldList: MetadataTokens.FieldDefinitionHandle(1),
                methodList: MetadataTokens.MethodDefinitionHandle(1));

            foreach (var idAndAssemblyName in _moduleIdToAssemblyNameMap.OrderBy(x => x.Key))
            {
                AssemblyName  assemblyName  = idAndAssemblyName.Value;
                AssemblyFlags assemblyFlags = 0;
                byte[]        publicKeyOrToken;
                if ((assemblyName.Flags & AssemblyNameFlags.PublicKey) != 0)
                {
                    assemblyFlags   |= AssemblyFlags.PublicKey;
                    publicKeyOrToken = assemblyName.GetPublicKey();
                }
                else
                {
                    publicKeyOrToken = assemblyName.GetPublicKeyToken();
                }
                if ((assemblyName.Flags & AssemblyNameFlags.Retargetable) != 0)
                {
                    assemblyFlags |= AssemblyFlags.Retargetable;
                }

                AssemblyReferenceHandle newHandle = metadataBuilder.AddAssemblyReference(
                    name: metadataBuilder.GetOrAddString(assemblyName.Name),
                    version: assemblyName.Version,
                    culture: metadataBuilder.GetOrAddString(assemblyName.CultureName),
                    publicKeyOrToken: metadataBuilder.GetOrAddBlob(publicKeyOrToken),
                    flags: assemblyFlags,
                    hashValue: default(BlobHandle) /* TODO */);
            }

            MetadataRootBuilder metadataRootBuilder = new MetadataRootBuilder(metadataBuilder);
            BlobBuilder         metadataBlobBuilder = new BlobBuilder();

            metadataRootBuilder.Serialize(metadataBlobBuilder, methodBodyStreamRva: 0, mappedFieldDataStreamRva: 0);

            return(new ObjectData(
                       data: metadataBlobBuilder.ToArray(),
                       relocs: Array.Empty <Relocation>(),
                       alignment: 1,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
        public void Headers()
        {
            var mdBuilder = new MetadataBuilder();
            var rootBuilder = new MetadataRootBuilder(mdBuilder);

            var builder = new BlobBuilder();
            rootBuilder.Serialize(builder, 0, 0);

            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)'v', (byte)'4', (byte)'.', (byte)'0', (byte)'.', (byte)'3', (byte)'0', (byte)'3', (byte)'1', (byte)'9', 0x00, 0x00,

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

                // stream count:
                0x05, 0x00,

                // stream headers:
                0x6C, 0x00, 0x00, 0x00,
                0x1C, 0x00, 0x00, 0x00,
                (byte)'#', (byte)'~', 0x00, 0x00,

                0x88, 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,

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

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

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

                // --------
                // #~
                // --------
                
                // 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, 0xFA, 0x01, 0x33, 0x00, 0x16, 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());
        }