예제 #1
0
        private void WriteAlignedBlobHeap(BlobBuilder builder)
        {
            int alignment = BitArithmetic.Align(_blobHeapSize, 4) - _blobHeapSize;

            var writer = new BlobWriter(builder.ReserveBytes(_blobHeapSize + alignment));

            // Perf consideration: With large heap the following loop may cause a lot of cache misses
            // since the order of entries in _blobs dictionary depends on the hash of the array values,
            // which is not correlated to the heap index. If we observe such issue we should order
            // the entries by heap position before running this loop.

            int startOffset = _blobHeapStartOffset;

            foreach (var entry in _blobs)
            {
                int heapOffset = entry.Value.GetHeapOffset();
                var blob       = entry.Key;

                writer.Offset = (heapOffset == 0) ? 0 : heapOffset - startOffset;
                writer.WriteCompressedInteger(blob.Length);
                writer.WriteBytes(blob);
            }

            writer.Offset = _blobHeapSize;
            writer.WriteBytes(0, alignment);
        }
예제 #2
0
        public void EmptyWrites()
        {
            var writer = new BlobWriter(16);

            writer.WriteBytes(1, 16);
            writer.WriteBytes(new byte[] { });
            writer.WriteBytes(2, 0);
            writer.WriteUTF8("", allowUnpairedSurrogates: false);
            writer.WriteUTF16("");
            Assert.Equal(16, writer.Length);
        }
예제 #3
0
        public void SerializeMetadata(BlobBuilder builder, Func<BlobBuilder, ContentId> idProvider, out ContentId contentId)
        {
            SerializeMetadataImpl(builder, methodBodyStreamRva: 0, mappedFieldDataStreamRva: 0);

            contentId = idProvider(builder);

            // fill in the id:
            var idWriter = new BlobWriter(_pdbIdBlob);
            idWriter.WriteBytes(contentId.Guid);
            idWriter.WriteBytes(contentId.Stamp);
            Debug.Assert(idWriter.RemainingBytes == 0);
        }
예제 #4
0
        public void SerializeMetadata(BlobBuilder builder, Func <BlobBuilder, ContentId> idProvider, out ContentId contentId)
        {
            SerializeMetadataImpl(builder, methodBodyStreamRva: 0, mappedFieldDataStreamRva: 0);

            contentId = idProvider(builder);

            // fill in the id:
            var idWriter = new BlobWriter(_pdbIdBlob);

            idWriter.WriteBytes(contentId.Guid);
            idWriter.WriteBytes(contentId.Stamp);
            Debug.Assert(idWriter.RemainingBytes == 0);
        }
예제 #5
0
        public void Serialize(BlobBuilder builder, PEDirectoriesBuilder headers, out ContentId contentId)
        {
            var  serializedSections = SerializeSections();
            Blob stampFixup;

            WritePESignature(builder);
            WriteCoffHeader(builder, serializedSections, out stampFixup);
            WritePEHeader(builder, headers, serializedSections);
            WriteSectionHeaders(builder, serializedSections);
            builder.Align(FileAlignment);

            foreach (var section in serializedSections)
            {
                builder.LinkSuffix(section.Builder);
                builder.Align(FileAlignment);
            }

            contentId = IdProvider(builder);

            // patch timestamp in COFF header:
            var stampWriter = new BlobWriter(stampFixup);

            stampWriter.WriteBytes(contentId.Stamp);
            Debug.Assert(stampWriter.RemainingBytes == 0);
        }
예제 #6
0
        public void Sign(BlobBuilder peImage, Func <IEnumerable <Blob>, byte[]> signatureProvider)
        {
            if (peImage == null)
            {
                throw new ArgumentNullException(nameof(peImage));
            }

            if (signatureProvider == null)
            {
                throw new ArgumentNullException(nameof(signatureProvider));
            }

            var content = GetContentToSign(peImage);

            byte[] signature = signatureProvider(content);

            // signature may be shorter (the rest of the reserved space is padding):
            if (signature == null || signature.Length > _lazyStrongNameSignature.Length)
            {
                throw new InvalidOperationException(SR.SignatureProviderReturnedInvalidSignature);
            }

            // TODO: Native csc also calculates and fills checksum in the PE header
            // Using MapFileAndCheckSum() from imagehlp.dll.

            var writer = new BlobWriter(_lazyStrongNameSignature);

            writer.WriteBytes(signature);
        }
예제 #7
0
        private static ImmutableArray <byte> CreateSnPublicKeyBlob(
            byte type,
            byte version,
            uint algId,
            uint magic,
            uint bitLen,
            uint pubExp,
            byte[] pubKeyData)
        {
            var w = new BlobWriter(3 * sizeof(uint) + s_offsetToKeyData + pubKeyData.Length);

            w.WriteUInt32(AlgorithmId.RsaSign);
            w.WriteUInt32(AlgorithmId.Sha);
            w.WriteUInt32((uint)(s_offsetToKeyData + pubKeyData.Length));

            w.WriteByte(type);
            w.WriteByte(version);
            w.WriteUInt16(0 /* 16 bits of reserved space in the spec */);
            w.WriteUInt32(algId);

            w.WriteUInt32(magic);
            w.WriteUInt32(bitLen);

            // re-add padding for exponent
            w.WriteUInt32(pubExp);

            w.WriteBytes(pubKeyData);

            return(w.ToImmutableArray());
        }
예제 #8
0
        public void Serialize(BlobBuilder builder, out ContentId 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.WriteBytes(contentId.Stamp);
            Debug.Assert(stampWriter.RemainingBytes == 0);
        }
예제 #9
0
        /// <exception cref="ArgumentNullException"><paramref name="destination"/> is default(<see cref="BlobWriter"/>).</exception>
        /// <exception cref="InvalidOperationException">Content is not available, the builder has been linked with another one.</exception>
        public void WriteContentTo(ref BlobWriter destination)
        {
            if (destination.IsDefault)
            {
                throw new ArgumentNullException(nameof(destination));
            }

            foreach (var chunk in GetChunks())
            {
                destination.WriteBytes(chunk._buffer, 0, chunk.Length);
            }
        }
예제 #10
0
        private BlobBuilder SerializeMvidSection(SectionLocation location)
        {
            var sectionBuilder = new BlobBuilder();

            // The guid will be filled in later:
            _mvidSectionFixup = sectionBuilder.ReserveBytes(SizeOfGuid);
            var mvidWriter = new BlobWriter(_mvidSectionFixup);

            mvidWriter.WriteBytes(0, _mvidSectionFixup.Length);
            Debug.Assert(mvidWriter.RemainingBytes == 0);

            return(sectionBuilder);
        }
예제 #11
0
        public static void SerializeWin32Resources(BlobBuilder builder, ResourceSection resourceSections, int resourcesRva)
        {
            var sectionWriter = new BlobWriter(builder.ReserveBytes(resourceSections.SectionBytes.Length));

            sectionWriter.WriteBytes(resourceSections.SectionBytes);

            var readStream = new MemoryStream(resourceSections.SectionBytes);
            var reader     = new BinaryReader(readStream);

            foreach (int addressToFixup in resourceSections.Relocations)
            {
                sectionWriter.Offset       = addressToFixup;
                reader.BaseStream.Position = addressToFixup;
                sectionWriter.WriteUInt32(reader.ReadUInt32() + (uint)resourcesRva);
            }
        }
예제 #12
0
        public void ReserveBytes2()
        {
            var builder = new BlobBuilder(16);
            var writer  = new BlobWriter(builder.ReserveBytes(17));

            writer.WriteBytes(1, 17);

            var blobs = builder.GetBlobs().ToArray();

            Assert.Equal(1, blobs.Length);
            AssertEx.Equal(new byte[]
            {
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01
            }, blobs[0].GetBytes().ToArray());
        }
        private void WriteBlobHeap(BlobBuilder builder)
        {
            var writer = new BlobWriter(builder.ReserveBytes(_blobHeapSize));

            // Perf consideration: With large heap the following loop may cause a lot of cache misses
            // since the order of entries in _blobs dictionary depends on the hash of the array values,
            // which is not correlated to the heap index. If we observe such issue we should order
            // the entries by heap position before running this loop.
            foreach (var entry in _blobs)
            {
                int heapOffset = MetadataTokens.GetHeapOffset(entry.Value);
                var blob       = entry.Key;

                writer.Offset = heapOffset;
                writer.WriteCompressedInteger(blob.Length);
                writer.WriteBytes(blob);
            }
        }
예제 #14
0
        private static ImmutableArray <byte> CreateSnPublicKeyBlob(byte type, byte version, ushort reserved, uint algId, uint magic, uint bitLen, uint pubExp, byte[] pubKeyData)
        {
            var w = new BlobWriter(3 * sizeof(uint) + s_offsetToKeyData + pubKeyData.Length);

            w.WriteUInt32(AlgorithmId.RsaSign);
            w.WriteUInt32(AlgorithmId.Sha);
            w.WriteUInt32((uint)(s_offsetToKeyData + pubKeyData.Length));

            w.WriteByte(type);
            w.WriteByte(version);
            w.WriteUInt16(reserved);
            w.WriteUInt32(algId);

            w.WriteUInt32(magic);
            w.WriteUInt32(bitLen);
            w.WriteUInt32(pubExp);

            w.WriteBytes(pubKeyData);

            return(w.ToImmutableArray());
        }
예제 #15
0
        internal void Sign(BlobBuilder peImage, Blob strongNameSignatureFixup, Func <IEnumerable <Blob>, byte[]> signatureProvider)
        {
            Debug.Assert(peImage != null);
            Debug.Assert(signatureProvider != null);

            int peHeadersSize = Header.ComputeSizeOfPEHeaders(GetSections().Length);

            byte[] signature = signatureProvider(GetContentToSign(peImage, peHeadersSize, Header.FileAlignment, strongNameSignatureFixup));

            // signature may be shorter (the rest of the reserved space is padding):
            if (signature == null || signature.Length > strongNameSignatureFixup.Length)
            {
                throw new InvalidOperationException(SR.SignatureProviderReturnedInvalidSignature);
            }

            uint checksum = CalculateChecksum(peImage, _lazyChecksum);

            new BlobWriter(_lazyChecksum).WriteUInt32(checksum);

            var writer = new BlobWriter(strongNameSignatureFixup);

            writer.WriteBytes(signature);
        }
예제 #16
0
파일: BlobTests.cs 프로젝트: ESgarbi/corefx
        public void ReserveBytes2()
        {
            var builder = new BlobBuilder(16);
            var writer = new BlobWriter(builder.ReserveBytes(17));
            writer.WriteBytes(1, 17);

            var blobs = builder.GetBlobs().ToArray();
            Assert.Equal(1, blobs.Length);
            AssertEx.Equal(new byte[]
            {
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                0x01
            }, blobs[0].GetBytes().ToArray());
        }
예제 #17
0
        // internal for testing
        internal static byte[] SerializeCustomDebugMetadata(ArrayBuilder<PooledBlobBuilder> recordWriters)
        {
            if (recordWriters.Count == 0)
            {
                return null;
            }

            int records = 0;
            foreach(var rec in recordWriters)
            {
                records += rec.Count;
            }

            var result = new byte[
                sizeof(byte) +                  // version
                sizeof(byte) +                  // record count
                sizeof(ushort) +                // padding
                records                         // records
            ];

            var cmw = new BlobWriter(result);
            cmw.WriteByte(CustomDebugInfoConstants.Version);
            cmw.WriteByte((byte)recordWriters.Count); // count
            cmw.WriteInt16(0);
            foreach (var recordWriter in recordWriters)
            {
                cmw.WriteBytes(recordWriter);
            }

            return result;
        }
예제 #18
0
        public void Serialize(BlobBuilder builder, PEDirectoriesBuilder headers, out ContentId contentId)
        {
            var serializedSections = SerializeSections();
            Blob stampFixup;

            WritePESignature(builder);
            WriteCoffHeader(builder, serializedSections, out stampFixup);
            WritePEHeader(builder, headers, serializedSections);
            WriteSectionHeaders(builder, serializedSections);
            builder.Align(FileAlignment);

            foreach (var section in serializedSections)
            {
                builder.LinkSuffix(section.Builder);
                builder.Align(FileAlignment);
            }

            contentId = IdProvider(builder);

            // patch timestamp in COFF header:
            var stampWriter = new BlobWriter(stampFixup);
            stampWriter.WriteBytes(contentId.Stamp);
            Debug.Assert(stampWriter.RemainingBytes == 0);
        }
예제 #19
0
파일: BlobTests.cs 프로젝트: ESgarbi/corefx
 public void EmptyWrites()
 {
     var writer = new BlobWriter(16);
     writer.WriteBytes(1, 16);
     writer.WriteBytes(new byte[] { });
     writer.WriteBytes(2, 0);
     writer.WriteUTF8("", allowUnpairedSurrogates: false);
     writer.WriteUTF16("");
     Assert.Equal(16, writer.Length);
 }
예제 #20
0
        /// <exception cref="ArgumentNullException"><paramref name="destination"/> is default(<see cref="BlobWriter"/>).</exception>
        /// <exception cref="InvalidOperationException">Content is not available, the builder has been linked with another one.</exception>
        public void WriteContentTo(ref BlobWriter destination)
        {
            if (destination.IsDefault)
            {
                throw new ArgumentNullException(nameof(destination));
            }

            foreach (var chunk in GetChunks())
            {
                destination.WriteBytes(chunk._buffer, 0, chunk.Length);
            }
        }
예제 #21
0
파일: PeWriter.cs 프로젝트: Rookieek/roslyn
        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);

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

            var properties = context.Module.Properties;

            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));

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

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

            MethodDefinitionHandle entryPointHandle;
            MethodDefinitionHandle debugEntryPointHandle;
            mdWriter.GetEntryPoints(out entryPointHandle, out debugEntryPointHandle);
            
            if (!debugEntryPointHandle.IsNil)
            {
                nativePdbWriterOpt?.SetEntryPoint((uint)MetadataTokens.GetToken(debugEntryPointHandle));
            }

            if (nativePdbWriterOpt != null)
            {
                var assembly = mdWriter.Module.AsAssembly;
                if (assembly != null && assembly.Kind == 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
                }
            }

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

            ContentId nativePdbContentId = nativePdbWriterOpt?.GetContentId() ?? default(ContentId);

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

            var metadataSerializer = mdWriter.GetTypeSystemMetadataSerializer();

            var peBuilder = new PEBuilder(
                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,
                deterministicIdProvider: isDeterministic ? new Func<BlobBuilder, ContentId>(content => ContentId.FromHash(CryptographicHashProvider.ComputeSha1(content))) : null);

            ContentId portablePdbContentId;
            if (mdWriter.EmitStandaloneDebugMetadata)
            {
                Debug.Assert(getPortablePdbStreamOpt != null);

                var debugMetadataBuilder = new BlobBuilder();
                var debugMetadataSerializer = mdWriter.GetStandaloneDebugMetadataSerializer(metadataSerializer.MetadataSizes, debugEntryPointHandle);
                debugMetadataSerializer.SerializeMetadata(debugMetadataBuilder, peBuilder.IdProvider, out portablePdbContentId);

                // write to Portable PDB stream:
                Stream portablePdbStream = getPortablePdbStreamOpt();
                if (portablePdbStream != null)
                {
                    debugMetadataBuilder.WriteContentTo(portablePdbStream);
                }
            }
            else
            {
                portablePdbContentId = default(ContentId);
            }

            var peDirectoriesBuilder = new PEDirectoriesBuilder();

            peBuilder.AddManagedSections(
                peDirectoriesBuilder,
                metadataSerializer,
                ilBuilder,
                mappedFieldDataBuilder,
                managedResourceBuilder,
                CreateNativeResourceSectionSerializer(context.Module),
                CalculateStrongNameSignatureSize(context.Module),
                entryPointHandle,
                pdbPathOpt,
                nativePdbContentId,
                portablePdbContentId,
                properties.CorFlags);

            var peBlob = new BlobBuilder();
            ContentId peContentId;
            peBuilder.Serialize(peBlob, peDirectoriesBuilder, out peContentId);

            // Patch MVID
            if (!mvidFixup.IsDefault)
            {
                var mvidWriter = new BlobWriter(mvidFixup);
                mvidWriter.WriteBytes(peContentId.Guid);
                Debug.Assert(mvidWriter.RemainingBytes == 0);
            }

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

            return true;
        }
        private void WriteBlobHeap(BlobBuilder builder)
        {
            var writer = new BlobWriter(builder.ReserveBytes(_blobHeapSize));

            // Perf consideration: With large heap the following loop may cause a lot of cache misses
            // since the order of entries in _blobs dictionary depends on the hash of the array values,
            // which is not correlated to the heap index. If we observe such issue we should order
            // the entries by heap position before running this loop.
            foreach (var entry in _blobs)
            {
                int heapOffset = MetadataTokens.GetHeapOffset(entry.Value);
                var blob = entry.Key;

                writer.Offset = heapOffset;
                writer.WriteCompressedInteger(blob.Length);
                writer.WriteBytes(blob);
            }
        }
예제 #23
0
        public static void SerializeWin32Resources(BlobBuilder builder, ResourceSection resourceSections, int resourcesRva)
        {
            var sectionWriter = new BlobWriter(builder.ReserveBytes(resourceSections.SectionBytes.Length));
            sectionWriter.WriteBytes(resourceSections.SectionBytes);

            var readStream = new MemoryStream(resourceSections.SectionBytes);
            var reader = new BinaryReader(readStream);

            foreach (int addressToFixup in resourceSections.Relocations)
            {
                sectionWriter.Offset = addressToFixup;
                reader.BaseStream.Position = addressToFixup;
                sectionWriter.WriteUInt32(reader.ReadUInt32() + (uint)resourcesRva);
            }
        }