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); }
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); }
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); }
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); }
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); }
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); }
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()); }
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); }
/// <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); } }
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); }
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); } }
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); } }
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()); }
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); }
// 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; }
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; }