/// <summary> /// Fills in stringIndexMap with data from stringIndex and write to stringWriter. /// Releases stringIndex as the stringTable is sealed after this point. /// </summary> private void SerializeStringHeap() { // Sort by suffix and remove stringIndex var sorted = new List <KeyValuePair <string, StringIdx> >(_stringIndex); sorted.Sort(new SuffixSort()); _stringIndex = null; // Create VirtIdx to Idx map and add entry for empty string _stringIndexMap = new uint[sorted.Count + 1]; _stringIndexMap[0] = 0; // Find strings that can be folded string prev = String.Empty; foreach (KeyValuePair <string, StringIdx> cur in sorted) { uint position = _stringWriter.BaseStream.Position + (uint)_stringIndexStartOffset; // It is important to use ordinal comparison otherwise we'll use the current culture! if (prev.EndsWith(cur.Key, StringComparison.Ordinal)) { // Map over the tail of prev string. Watch for null-terminator of prev string. _stringIndexMap[cur.Value.VirtIdx] = position - (uint)(s_utf8Encoding.GetByteCount(cur.Key) + 1); } else { _stringIndexMap[cur.Value.VirtIdx] = position; _stringWriter.WriteString(cur.Key, s_utf8Encoding); _stringWriter.WriteByte(0); } prev = cur.Key; } }
private static void SerializeReferenceToIteratorClass(string iteratorClassName, ArrayBuilder <MemoryStream> customDebugInfo) { if (iteratorClassName == null) { return; } MemoryStream customMetadata = new MemoryStream(); BinaryWriter cmw = new BinaryWriter(customMetadata, true); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindForwardIterator); cmw.Align(4); uint length = 10 + (uint)iteratorClassName.Length * 2; if ((length & 3) != 0) { length += 4 - (length & 3); } cmw.WriteUint(length); cmw.WriteString(iteratorClassName, true); cmw.Align(4); Debug.Assert(customMetadata.Position == length); customDebugInfo.Add(customMetadata); }
private static void SerializeReferenceToIteratorClass(string iteratorClassName, ArrayBuilder<MemoryStream> customDebugInfo) { if (iteratorClassName == null) return; MemoryStream customMetadata = new MemoryStream(); BinaryWriter cmw = new BinaryWriter(customMetadata, true); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindForwardIterator); cmw.Align(4); uint length = 10 + (uint)iteratorClassName.Length * 2; if ((length & 3) != 0) length += 4 - (length & 3); cmw.WriteUint(length); cmw.WriteString(iteratorClassName, true); cmw.Align(4); Debug.Assert(customMetadata.Position == length); customDebugInfo.Add(customMetadata); }
private void WriteDebugTable(Stream peStream, ContentId pdbContentId, MetadataSizes metadataSizes) { if (!EmitPdb) { return; } MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); // characteristics: writer.WriteUint(0); // PDB stamp writer.WriteBytes(pdbContentId.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(pdbContentId.Guid); // age writer.WriteUint(PdbWriter.Age); // UTF-8 encoded zero-terminated path to PDB writer.WriteString(_pdbPathOpt, emitNullTerminator: true); writer.BaseStream.WriteTo(peStream); stream.Free(); }