// 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(CDI.CdiVersion); cmw.WriteByte((byte)recordWriters.Count); // count cmw.WriteInt16(0); foreach (var recordWriter in recordWriters) { cmw.WriteBytes(recordWriter); } return(result); }
/// <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); }
internal int GetBlobIndex(ImmutableArray <byte> blob) { int result = 0; if (blob.Length == 0 || _blobIndex.TryGetValue(blob, out result)) { return(result); } Debug.Assert(!_streamsAreComplete); result = _blobWriter.Position + _blobIndexStartOffset; _blobIndex.Add(blob, result); _blobWriter.WriteCompressedUInt((uint)blob.Length); _blobWriter.WriteBytes(blob); return(result); }
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); } }
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); } }
public int AllocateGuid(Guid guid) { Debug.Assert(!_streamsAreComplete); // The only GUIDs that are serialized are MVID, EncId, and EncBaseId in the // Module table. Each of those GUID offsets are relative to the local heap, // even for deltas, so there's no need for a GetGuidStreamPosition() method // to offset the positions by the size of the original heap in delta metadata. // Unlike #Blob, #String and #US streams delta #GUID stream is padded to the // size of the previous generation #GUID stream before new GUIDs are added. // Metadata Spec: // The Guid heap is an array of GUIDs, each 16 bytes wide. // Its first element is numbered 1, its second 2, and so on. int result = (_guidWriter.Length >> 4) + 1; _guidIndex.Add(guid, result); _guidWriter.WriteBytes(guid.ToByteArray()); return(result); }
private void WriteDirectory(Directory directory, BlobWriter writer, uint offset, uint level, uint sizeOfDirectoryTree, uint virtualAddressBase, BlobWriter dataWriter) { writer.WriteUint(0); // Characteristics writer.WriteUint(0); // Timestamp writer.WriteUint(0); // Version writer.WriteUshort(directory.NumberOfNamedEntries); writer.WriteUshort(directory.NumberOfIdEntries); uint n = (uint)directory.Entries.Count; uint k = offset + 16 + n * 8; for (int i = 0; i < n; i++) { int id; string name; uint nameOffset = (uint)dataWriter.Position + sizeOfDirectoryTree; uint directoryOffset = k; Directory subDir = directory.Entries[i] as Directory; if (subDir != null) { id = subDir.ID; name = subDir.Name; if (level == 0) { k += SizeOfDirectory(subDir); } else { k += 16 + 8 * (uint)subDir.Entries.Count; } } else { //EDMAURER write out an IMAGE_RESOURCE_DATA_ENTRY followed //immediately by the data that it refers to. This results //in a layout different than that produced by pulling the resources //from an OBJ. In that case all of the data bits of a resource are //contiguous in .rsrc$02. After processing these will end up at //the end of .rsrc following all of the directory //info and IMAGE_RESOURCE_DATA_ENTRYs IWin32Resource r = (IWin32Resource)directory.Entries[i]; id = level == 0 ? r.TypeId : level == 1 ? r.Id : (int)r.LanguageId; name = level == 0 ? r.TypeName : level == 1 ? r.Name : null; dataWriter.WriteUint(virtualAddressBase + sizeOfDirectoryTree + 16 + (uint)dataWriter.Position); byte[] data = new List<byte>(r.Data).ToArray(); dataWriter.WriteUint((uint)data.Length); dataWriter.WriteUint(r.CodePage); dataWriter.WriteUint(0); dataWriter.WriteBytes(data); while ((dataWriter.Length % 4) != 0) { dataWriter.WriteByte(0); } } if (id >= 0) { writer.WriteInt(id); } else { if (name == null) { name = string.Empty; } writer.WriteUint(nameOffset | 0x80000000); dataWriter.WriteUshort((ushort)name.Length); dataWriter.WriteUTF16(name); } if (subDir != null) { writer.WriteUint(directoryOffset | 0x80000000); } else { writer.WriteUint(nameOffset); } } k = offset + 16 + n * 8; for (int i = 0; i < n; i++) { Directory subDir = directory.Entries[i] as Directory; if (subDir != null) { this.WriteDirectory(subDir, writer, k, level + 1, sizeOfDirectoryTree, virtualAddressBase, dataWriter); if (level == 0) { k += SizeOfDirectory(subDir); } else { k += 16 + 8 * (uint)subDir.Entries.Count; } } } }
private void WriteDebugTable(Stream peStream, ContentId nativePdbContentId, MetadataSizes metadataSizes) { if (!EmitPdb) { return; } var writer = new BlobWriter(); // characteristics: writer.WriteUint(0); // PDB stamp writer.WriteBytes(nativePdbContentId.Stamp); // version writer.WriteUint(0); // type: const int ImageDebugTypeCodeView = 2; writer.WriteUint(ImageDebugTypeCodeView); // size of data: writer.WriteUint((uint)ComputeSizeOfDebugDirectoryData()); uint dataOffset = (uint)ComputeOffsetToDebugTable(metadataSizes) + ImageDebugDirectoryBaseSize; // PointerToRawData (RVA of the data): writer.WriteUint(_textSection.RelativeVirtualAddress + dataOffset); // AddressOfRawData (position of the data in the PE stream): writer.WriteUint(_textSection.PointerToRawData + dataOffset); writer.WriteByte((byte)'R'); writer.WriteByte((byte)'S'); writer.WriteByte((byte)'D'); writer.WriteByte((byte)'S'); // PDB id: writer.WriteBytes(nativePdbContentId.Guid); // age writer.WriteUint(PdbWriter.Age); // UTF-8 encoded zero-terminated path to PDB writer.WriteUTF8(_pdbPathOpt); writer.WriteByte(0); writer.WriteTo(peStream); writer.Free(); }
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); }
internal void WriteTo(BlobWriter stream) { stream.WriteBytes(_buffer, 0, _length); }
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); }
public void WriteBytes1() { var writer = new BlobWriter(4); writer.WriteBytes(new byte[] { 1, 2, 3, 4 }); writer.WriteBytes(new byte[] { }); writer.WriteBytes(new byte[] { }, 0, 0); writer.WriteBytes(new byte[] { 5, 6, 7, 8 }); writer.WriteBytes(new byte[] { 9 }); writer.WriteBytes(new byte[] { 0x0a }, 0, 0); writer.WriteBytes(new byte[] { 0x0b }, 0, 1); writer.WriteBytes(new byte[] { 0x0c }, 1, 0); writer.WriteBytes(new byte[] { 0x0d, 0x0e }, 1, 1); AssertEx.Equal(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0b, 0x0e }, writer.ToArray()); }
private void WriteHeaders(Stream peStream, NtHeader ntHeader, CoffHeader coffHeader, List<SectionHeader> sectionHeaders, out long ntHeaderTimestampPosition) { var writer = new BlobWriter(1024); // MS-DOS stub (128 bytes) writer.WriteBytes(s_dosHeader); // PE Signature "PE\0\0" writer.WriteUint(0x00004550); // COFF Header (20 bytes) writer.WriteUshort((ushort)coffHeader.Machine); writer.WriteUshort((ushort)coffHeader.NumberOfSections); ntHeaderTimestampPosition = writer.Position + peStream.Position; writer.WriteUint((uint)coffHeader.TimeDateStamp); writer.WriteUint((uint)coffHeader.PointerToSymbolTable); writer.WriteUint((uint)coffHeader.NumberOfSymbols); writer.WriteUshort((ushort)(_is32bit ? 224 : 240)); // SizeOfOptionalHeader writer.WriteUshort((ushort)coffHeader.Characteristics); // PE Headers: writer.WriteUshort((ushort)(_is32bit ? PEMagic.PE32 : PEMagic.PE32Plus)); // 2 writer.WriteByte(ntHeader.MajorLinkerVersion); // 3 writer.WriteByte(ntHeader.MinorLinkerVersion); // 4 writer.WriteUint((uint)ntHeader.SizeOfCode); // 8 writer.WriteUint((uint)ntHeader.SizeOfInitializedData); // 12 writer.WriteUint((uint)ntHeader.SizeOfUninitializedData); // 16 writer.WriteUint((uint)ntHeader.AddressOfEntryPoint); // 20 writer.WriteUint((uint)ntHeader.BaseOfCode); // 24 if (_is32bit) { writer.WriteUint((uint)ntHeader.BaseOfData); // 28 writer.WriteUint((uint)ntHeader.ImageBase); // 32 } else { writer.WriteUlong(ntHeader.ImageBase); // 32 } // NT additional fields: writer.WriteUint((uint)ntHeader.SectionAlignment); // 36 writer.WriteUint((uint)ntHeader.FileAlignment); // 40 writer.WriteUshort(ntHeader.MajorOperatingSystemVersion); // 42 writer.WriteUshort(ntHeader.MinorOperatingSystemVersion); // 44 writer.WriteUshort(ntHeader.MajorImageVersion); // 46 writer.WriteUshort(ntHeader.MinorImageVersion); // 48 writer.WriteUshort(ntHeader.MajorSubsystemVersion); // MajorSubsystemVersion 50 writer.WriteUshort(ntHeader.MinorSubsystemVersion); // MinorSubsystemVersion 52 // Win32VersionValue (reserved, should be 0) writer.WriteUint(0); // 56 writer.WriteUint((uint)ntHeader.SizeOfImage); // 60 writer.WriteUint((uint)ntHeader.SizeOfHeaders); // 64 writer.WriteUint(ntHeader.Checksum); // 68 writer.WriteUshort((ushort)ntHeader.Subsystem); // 70 writer.WriteUshort((ushort)ntHeader.DllCharacteristics); if (_is32bit) { writer.WriteUint((uint)ntHeader.SizeOfStackReserve); // 76 writer.WriteUint((uint)ntHeader.SizeOfStackCommit); // 80 writer.WriteUint((uint)ntHeader.SizeOfHeapReserve); // 84 writer.WriteUint((uint)ntHeader.SizeOfHeapCommit); // 88 } else { writer.WriteUlong(ntHeader.SizeOfStackReserve); // 80 writer.WriteUlong(ntHeader.SizeOfStackCommit); // 88 writer.WriteUlong(ntHeader.SizeOfHeapReserve); // 96 writer.WriteUlong(ntHeader.SizeOfHeapCommit); // 104 } // LoaderFlags writer.WriteUint(0); // 92|108 // The number of data-directory entries in the remainder of the header. writer.WriteUint(16); // 96|112 // directory entries: writer.WriteUint((uint)ntHeader.ExportTable.RelativeVirtualAddress); // 100|116 writer.WriteUint((uint)ntHeader.ExportTable.Size); // 104|120 writer.WriteUint((uint)ntHeader.ImportTable.RelativeVirtualAddress); // 108|124 writer.WriteUint((uint)ntHeader.ImportTable.Size); // 112|128 writer.WriteUint((uint)ntHeader.ResourceTable.RelativeVirtualAddress); // 116|132 writer.WriteUint((uint)ntHeader.ResourceTable.Size); // 120|136 writer.WriteUint((uint)ntHeader.ExceptionTable.RelativeVirtualAddress); // 124|140 writer.WriteUint((uint)ntHeader.ExceptionTable.Size); // 128|144 writer.WriteUint((uint)ntHeader.CertificateTable.RelativeVirtualAddress); // 132|148 writer.WriteUint((uint)ntHeader.CertificateTable.Size); // 136|152 writer.WriteUint((uint)ntHeader.BaseRelocationTable.RelativeVirtualAddress); // 140|156 writer.WriteUint((uint)ntHeader.BaseRelocationTable.Size); // 144|160 writer.WriteUint((uint)ntHeader.DebugTable.RelativeVirtualAddress); // 148|164 writer.WriteUint((uint)ntHeader.DebugTable.Size); // 152|168 writer.WriteUint((uint)ntHeader.CopyrightTable.RelativeVirtualAddress); // 156|172 writer.WriteUint((uint)ntHeader.CopyrightTable.Size); // 160|176 writer.WriteUint((uint)ntHeader.GlobalPointerTable.RelativeVirtualAddress); // 164|180 writer.WriteUint((uint)ntHeader.GlobalPointerTable.Size); // 168|184 writer.WriteUint((uint)ntHeader.ThreadLocalStorageTable.RelativeVirtualAddress); // 172|188 writer.WriteUint((uint)ntHeader.ThreadLocalStorageTable.Size); // 176|192 writer.WriteUint((uint)ntHeader.LoadConfigTable.RelativeVirtualAddress); // 180|196 writer.WriteUint((uint)ntHeader.LoadConfigTable.Size); // 184|200 writer.WriteUint((uint)ntHeader.BoundImportTable.RelativeVirtualAddress); // 188|204 writer.WriteUint((uint)ntHeader.BoundImportTable.Size); // 192|208 writer.WriteUint((uint)ntHeader.ImportAddressTable.RelativeVirtualAddress); // 196|212 writer.WriteUint((uint)ntHeader.ImportAddressTable.Size); // 200|216 writer.WriteUint((uint)ntHeader.DelayImportTable.RelativeVirtualAddress); // 204|220 writer.WriteUint((uint)ntHeader.DelayImportTable.Size); // 208|224 writer.WriteUint((uint)ntHeader.CliHeaderTable.RelativeVirtualAddress); // 212|228 writer.WriteUint((uint)ntHeader.CliHeaderTable.Size); // 216|232 writer.WriteUlong(0); // 224|240 // Section Headers foreach (var sectionHeader in sectionHeaders) { WriteSectionHeader(sectionHeader, writer); } writer.WriteTo(peStream); }
private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder<BlobWriter> customDebugInfo) { if (!methodBody.HasDynamicLocalVariables) { return; //There are no dynamic locals } var dynamicLocals = ArrayBuilder<ILocalDefinition>.GetInstance(); foreach (ILocalDefinition local in methodBody.LocalVariables) { if (local.IsDynamic) { dynamicLocals.Add(local); } } int dynamicVariableCount = dynamicLocals.Count; foreach (var currentScope in methodBody.LocalScopes) { foreach (var localConstant in currentScope.Constants) { if (localConstant.IsDynamic) { dynamicLocals.Add(localConstant); } } } Debug.Assert(dynamicLocals.Any()); // There must be at least one dynamic local if this point is reached const int blobSize = 200;//DynamicAttribute - 64, DynamicAttributeLength - 4, SlotIndex -4, IdentifierName - 128 var cmw = new BlobWriter(); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindDynamicLocals); cmw.Align(4); // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob)) cmw.WriteUint(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block cmw.WriteUint((uint)dynamicLocals.Count); int localIndex = 0; foreach (ILocalDefinition local in dynamicLocals) { if (local.Name.Length > 63)//Ignore and push empty information { cmw.WriteBytes(0, blobSize); continue; } var dynamicTransformFlags = local.DynamicTransformFlags; if (!dynamicTransformFlags.IsDefault && dynamicTransformFlags.Length <= 64) { byte[] flag = new byte[64]; for (int k = 0; k < dynamicTransformFlags.Length; k++) { if ((bool)dynamicTransformFlags[k].Value) { flag[k] = 1; } } cmw.WriteBytes(flag); //Written Flag cmw.WriteUint((uint)dynamicTransformFlags.Length); //Written Length } else { cmw.WriteBytes(0, 68); //Empty flag array and size. } if (localIndex < dynamicVariableCount) { // Dynamic variable cmw.WriteUint((uint)local.SlotIndex); } else { // Dynamic constant cmw.WriteUint(0); } char[] localName = new char[64]; local.Name.CopyTo(0, localName, 0, local.Name.Length); cmw.WriteUTF16(localName); localIndex++; } dynamicLocals.Free(); customDebugInfo.Add(cmw); }
/// <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); } }
// 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(CDI.CdiVersion); cmw.WriteByte((byte)recordWriters.Count); // count cmw.WriteInt16(0); foreach (var recordWriter in recordWriters) { cmw.WriteBytes(recordWriter); } return result; }
public void WriteBytes2() { var writer = new BlobWriter(4); writer.WriteBytes(0xff, 0); writer.WriteBytes(1, 4); writer.WriteBytes(0xff, 0); writer.WriteBytes(2, 10); writer.WriteBytes(0xff, 0); writer.WriteBytes(3, 1); AssertEx.Equal(new byte[] { 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03 }, writer.ToArray()); }
private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder <BlobWriter> customDebugInfo) { if (!methodBody.HasDynamicLocalVariables) { return; //There are no dynamic locals } var dynamicLocals = ArrayBuilder <ILocalDefinition> .GetInstance(); foreach (ILocalDefinition local in methodBody.LocalVariables) { if (local.IsDynamic) { dynamicLocals.Add(local); } } int dynamicVariableCount = dynamicLocals.Count; foreach (var currentScope in methodBody.LocalScopes) { foreach (var localConstant in currentScope.Constants) { if (localConstant.IsDynamic) { dynamicLocals.Add(localConstant); } } } Debug.Assert(dynamicLocals.Any()); // There must be at least one dynamic local if this point is reached const int blobSize = 200; //DynamicAttribute - 64, DynamicAttributeLength - 4, SlotIndex -4, IdentifierName - 128 var cmw = new BlobWriter(); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindDynamicLocals); cmw.Align(4); // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob)) cmw.WriteUint(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block cmw.WriteUint((uint)dynamicLocals.Count); int localIndex = 0; foreach (ILocalDefinition local in dynamicLocals) { if (local.Name.Length > 63)//Ignore and push empty information { cmw.WriteBytes(0, blobSize); continue; } var dynamicTransformFlags = local.DynamicTransformFlags; if (!dynamicTransformFlags.IsDefault && dynamicTransformFlags.Length <= 64) { byte[] flag = new byte[64]; for (int k = 0; k < dynamicTransformFlags.Length; k++) { if ((bool)dynamicTransformFlags[k].Value) { flag[k] = 1; } } cmw.WriteBytes(flag); //Written Flag cmw.WriteUint((uint)dynamicTransformFlags.Length); //Written Length } else { cmw.WriteBytes(0, 68); //Empty flag array and size. } if (localIndex < dynamicVariableCount) { // Dynamic variable cmw.WriteUint((uint)local.SlotIndex); } else { // Dynamic constant cmw.WriteUint(0); } char[] localName = new char[64]; local.Name.CopyTo(0, localName, 0, local.Name.Length); cmw.WriteUTF16(localName); localIndex++; } dynamicLocals.Free(); customDebugInfo.Add(cmw); }