private void SerializeStateMachineLocalScopes(IMethodBody methodBody, MethodDefinitionHandle method) { var scopes = methodBody.StateMachineHoistedLocalScopes; if (scopes.IsDefaultOrEmpty) { return; } var writer = new BlobBuilder(); foreach (var scope in scopes) { writer.WriteUInt32((uint)scope.StartOffset); writer.WriteUInt32((uint)scope.Length); } _debugMetadataOpt.AddCustomDebugInformation( parent: method, kind: _debugMetadataOpt.GetOrAddGuid(PortableCustomDebugInfoKinds.StateMachineHoistedLocalScopes), value: _debugMetadataOpt.GetOrAddBlob(writer)); }
private void SerializeAsyncMethodSteppingInfo(AsyncMethodBodyDebugInfo asyncInfo, int moveNextMethodRid) { Debug.Assert(asyncInfo.ResumeOffsets.Length == asyncInfo.YieldOffsets.Length); Debug.Assert(asyncInfo.CatchHandlerOffset >= -1); var writer = new BlobBuilder(); writer.WriteUInt32((uint)((long)asyncInfo.CatchHandlerOffset + 1)); for (int i = 0; i < asyncInfo.ResumeOffsets.Length; i++) { writer.WriteUInt32((uint)asyncInfo.YieldOffsets[i]); writer.WriteUInt32((uint)asyncInfo.ResumeOffsets[i]); writer.WriteCompressedInteger((uint)moveNextMethodRid); } _customDebugInformationTable.Add(new CustomDebugInformationRow { Parent = HasCustomDebugInformation(HasCustomDebugInformationTag.MethodDef, moveNextMethodRid), Kind = (uint)_debugHeapsOpt.GetGuidIndex(PortableCustomDebugInfoKinds.AsyncMethodSteppingInformationBlob), Value = _debugHeapsOpt.GetBlobIndex(writer), }); }
private void SerializeStateMachineLocalScopes(IMethodBody methodBody, int methodRowId) { var scopes = methodBody.StateMachineHoistedLocalScopes; if (scopes.IsDefaultOrEmpty) { return; } var writer = new BlobBuilder(); foreach (var scope in scopes) { writer.WriteUInt32((uint)scope.StartOffset); writer.WriteUInt32((uint)scope.Length); } _customDebugInformationTable.Add(new CustomDebugInformationRow { Parent = HasCustomDebugInformation(HasCustomDebugInformationTag.MethodDef, methodRowId), Kind = (uint)_debugHeapsOpt.GetGuidIndex(PortableCustomDebugInfoKinds.StateMachineHoistedLocalScopes), Value = _debugHeapsOpt.GetBlobIndex(writer), }); }
private void SerializeNamespaceScopeMetadata(EmitContext context, IMethodBody methodBody, ArrayBuilder <BlobBuilder> customDebugInfo) { if (context.Module.GenerateVisualBasicStylePdb) { return; } if (ShouldForwardToPreviousMethodWithUsingInfo(context, methodBody)) { Debug.Assert(!ReferenceEquals(_previousMethodBodyWithUsingInfo, methodBody)); SerializeReferenceToPreviousMethodWithUsingInfo(customDebugInfo); return; } List <ushort> usingCounts = new List <ushort>(); var cmw = new BlobBuilder(); for (IImportScope scope = methodBody.ImportScope; scope != null; scope = scope.Parent) { usingCounts.Add((ushort)scope.GetUsedNamespaces().Length); } // ACASEY: This originally wrote (uint)12, (ushort)1, (ushort)0 in the // case where usingCounts was empty, but I'm not sure why. if (usingCounts.Count > 0) { uint streamLength; cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindUsingInfo); cmw.Align(4); cmw.WriteUInt32(streamLength = BitArithmeticUtilities.Align((uint)usingCounts.Count * 2 + 10, 4)); cmw.WriteUInt16((ushort)usingCounts.Count); foreach (ushort uc in usingCounts) { cmw.WriteUInt16(uc); } cmw.Align(4); Debug.Assert(streamLength == cmw.Count); customDebugInfo.Add(cmw); } if (_methodBodyWithModuleInfo != null && !ReferenceEquals(_methodBodyWithModuleInfo, methodBody)) { SerializeReferenceToMethodWithModuleInfo(customDebugInfo); } }
public void WritePrimitive() { var writer = new BlobBuilder(4); writer.WriteUInt32(0x11223344); writer.WriteUInt16(0x5566); writer.WriteByte(0x77); writer.WriteUInt64(0x8899aabbccddeeff); writer.WriteInt32(-1); writer.WriteInt16(-2); writer.WriteSByte(-3); writer.WriteBoolean(true); writer.WriteBoolean(false); writer.WriteInt64(unchecked((long)0xfedcba0987654321)); writer.WriteDateTime(new DateTime(0x1112223334445556)); writer.WriteDecimal(102030405060.70m); writer.WriteDouble(double.NaN); writer.WriteSingle(float.NegativeInfinity); AssertEx.Equal(new byte[] { 0x44, 0x33, 0x22, 0x11, 0x66, 0x55, 0x77, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfd, 0x01, 0x00, 0x21, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE, 0x56, 0x55, 0x44, 0x34, 0x33, 0x22, 0x12, 0x11, 0x02, 0xD6, 0xE0, 0x9A, 0x94, 0x47, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x80, 0xFF }, writer.ToArray()); }
private static void SerializeReferenceToIteratorClass(string iteratorClassName, ArrayBuilder <BlobBuilder> customDebugInfo) { if (iteratorClassName == null) { return; } var cmw = new BlobBuilder(); 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.WriteUInt32(length); cmw.WriteUTF16(iteratorClassName); cmw.WriteInt16(0); cmw.Align(4); Debug.Assert(cmw.Position == length); customDebugInfo.Add(cmw); }
private void WriteRuntimeStartupStub(Stream peStream, int importAddressTableRva) { var writer = new BlobBuilder(16); // entry point code, consisting of a jump indirect to _CorXXXMain if (_is32bit) { //emit 0's (nops) to pad the entry point code so that the target address is aligned on a 4 byte boundary. for (uint i = 0, n = (uint)(BitArithmeticUtilities.Align((uint)peStream.Position, 4) - peStream.Position); i < n; i++) { writer.WriteByte(0); } writer.WriteUInt16(0); writer.WriteByte(0xff); writer.WriteByte(0x25); //4 writer.WriteUInt32((uint)importAddressTableRva + (uint)_properties.BaseAddress); //8 } else { //emit 0's (nops) to pad the entry point code so that the target address is aligned on a 8 byte boundary. for (uint i = 0, n = (uint)(BitArithmeticUtilities.Align((uint)peStream.Position, 8) - peStream.Position); i < n; i++) { writer.WriteByte(0); } writer.WriteUInt32(0); writer.WriteUInt16(0); writer.WriteByte(0xff); writer.WriteByte(0x25); //8 writer.WriteUInt64((ulong)importAddressTableRva + _properties.BaseAddress); //16 } writer.WriteTo(peStream); }
private static void WriteCorHeader(Stream peStream, CorHeader corHeader) { var writer = new BlobBuilder(CorHeaderSize); writer.WriteUInt32(CorHeaderSize); writer.WriteUInt16(corHeader.MajorRuntimeVersion); writer.WriteUInt16(corHeader.MinorRuntimeVersion); writer.WriteUInt32((uint)corHeader.MetadataDirectory.RelativeVirtualAddress); writer.WriteUInt32((uint)corHeader.MetadataDirectory.Size); writer.WriteUInt32((uint)corHeader.Flags); writer.WriteUInt32((uint)corHeader.EntryPointTokenOrRelativeVirtualAddress); writer.WriteUInt32((uint)(corHeader.ResourcesDirectory.Size == 0 ? 0 : corHeader.ResourcesDirectory.RelativeVirtualAddress)); // 28 writer.WriteUInt32((uint)corHeader.ResourcesDirectory.Size); writer.WriteUInt32((uint)(corHeader.StrongNameSignatureDirectory.Size == 0 ? 0 : corHeader.StrongNameSignatureDirectory.RelativeVirtualAddress)); // 36 writer.WriteUInt32((uint)corHeader.StrongNameSignatureDirectory.Size); writer.WriteUInt32((uint)corHeader.CodeManagerTableDirectory.RelativeVirtualAddress); writer.WriteUInt32((uint)corHeader.CodeManagerTableDirectory.Size); writer.WriteUInt32((uint)corHeader.VtableFixupsDirectory.RelativeVirtualAddress); writer.WriteUInt32((uint)corHeader.VtableFixupsDirectory.Size); writer.WriteUInt32((uint)corHeader.ExportAddressTableJumpsDirectory.RelativeVirtualAddress); writer.WriteUInt32((uint)corHeader.ExportAddressTableJumpsDirectory.Size); writer.WriteUInt64(0); Debug.Assert(writer.Length == CorHeaderSize); Debug.Assert(writer.Length % 4 == 0); writer.WriteTo(peStream); }
private void SerializeNamespaceScopeMetadata(EmitContext context, IMethodBody methodBody, ArrayBuilder<BlobBuilder> customDebugInfo) { if (context.Module.GenerateVisualBasicStylePdb) { return; } if (ShouldForwardToPreviousMethodWithUsingInfo(context, methodBody)) { Debug.Assert(!ReferenceEquals(_previousMethodBodyWithUsingInfo, methodBody)); SerializeReferenceToPreviousMethodWithUsingInfo(customDebugInfo); return; } List<ushort> usingCounts = new List<ushort>(); var cmw = new BlobBuilder(); for (IImportScope scope = methodBody.ImportScope; scope != null; scope = scope.Parent) { usingCounts.Add((ushort)scope.GetUsedNamespaces().Length); } // ACASEY: This originally wrote (uint)12, (ushort)1, (ushort)0 in the // case where usingCounts was empty, but I'm not sure why. if (usingCounts.Count > 0) { uint streamLength; cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindUsingInfo); cmw.Align(4); cmw.WriteUInt32(streamLength = BitArithmeticUtilities.Align((uint)usingCounts.Count * 2 + 10, 4)); cmw.WriteUInt16((ushort)usingCounts.Count); foreach (ushort uc in usingCounts) { cmw.WriteUInt16(uc); } cmw.Align(4); Debug.Assert(streamLength == cmw.Length); customDebugInfo.Add(cmw); } if (_methodBodyWithModuleInfo != null && !ReferenceEquals(_methodBodyWithModuleInfo, methodBody)) { SerializeReferenceToMethodWithModuleInfo(customDebugInfo); } }
private static void SerializeStateMachineLocalScopes(IMethodBody methodBody, ArrayBuilder<BlobBuilder> customDebugInfo) { var scopes = methodBody.StateMachineHoistedLocalScopes; if (scopes.IsDefaultOrEmpty) { return; } uint numberOfScopes = (uint)scopes.Length; var cmw = new BlobBuilder(); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindStateMachineHoistedLocalScopes); cmw.Align(4); cmw.WriteUInt32(12 + numberOfScopes * 8); cmw.WriteUInt32(numberOfScopes); foreach (var scope in scopes) { if (scope.IsDefault) { cmw.WriteUInt32(0); cmw.WriteUInt32(0); } else { // Dev12 C# emits end-inclusive range cmw.WriteUInt32((uint)scope.StartOffset); cmw.WriteUInt32((uint)scope.EndOffset - 1); } } customDebugInfo.Add(cmw); }
public void ToImmutableArray() { var builder = new BlobBuilder(16); AssertEx.Equal(new byte[] { }, builder.ToArray(0, 0)); for (int i = 0; i < 13; i++) { builder.WriteByte((byte)i); } builder.WriteUInt32(0xaabbccdd); AssertEx.Equal(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0xDD, 0xCC, 0xBB, 0xAA }, builder.ToImmutableArray()); AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(0, 0)); AssertEx.Equal(new byte[] { 0 }, builder.ToImmutableArray(0, 1)); AssertEx.Equal(new byte[] { 1 }, builder.ToImmutableArray(1, 1)); AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(14, 0)); AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(15, 0)); AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(16, 0)); AssertEx.Equal(new byte[] { }, builder.ToImmutableArray(17, 0)); AssertEx.Equal(new byte[] { 0xdd }, builder.ToImmutableArray(13, 1)); AssertEx.Equal(new byte[] { 0xcc }, builder.ToImmutableArray(14, 1)); AssertEx.Equal(new byte[] { 0xbb }, builder.ToImmutableArray(15, 1)); AssertEx.Equal(new byte[] { 0xaa }, builder.ToImmutableArray(16, 1)); AssertEx.Equal(new byte[] { 0xdd, 0xcc }, builder.ToImmutableArray(13, 2)); AssertEx.Equal(new byte[] { 0xcc, 0xbb }, builder.ToImmutableArray(14, 2)); AssertEx.Equal(new byte[] { 0xbb, 0xaa }, builder.ToImmutableArray(15, 2)); AssertEx.Equal(new byte[] { 0xdd, 0xcc, 0xbb }, builder.ToImmutableArray(13, 3)); AssertEx.Equal(new byte[] { 0xcc, 0xbb, 0xaa }, builder.ToImmutableArray(14, 3)); AssertEx.Equal(new byte[] { 0xdd, 0xcc, 0xbb, 0xaa }, builder.ToImmutableArray(13, 4)); }
internal static void WriteConstant(BlobBuilder writer, object value) { if (value == null) { // The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 32-bit. writer.WriteUInt32(0); return; } var type = value.GetType(); if (type.GetTypeInfo().IsEnum) { type = Enum.GetUnderlyingType(type); } if (type == typeof(bool)) { writer.WriteBoolean((bool)value); } else if (type == typeof(int)) { writer.WriteInt32((int)value); } else if (type == typeof(string)) { writer.WriteUTF16((string)value); } else if (type == typeof(byte)) { writer.WriteByte((byte)value); } else if (type == typeof(char)) { writer.WriteUInt16((char)value); } else if (type == typeof(double)) { writer.WriteDouble((double)value); } else if (type == typeof(short)) { writer.WriteInt16((short)value); } else if (type == typeof(long)) { writer.WriteInt64((long)value); } else if (type == typeof(sbyte)) { writer.WriteSByte((sbyte)value); } else if (type == typeof(float)) { writer.WriteSingle((float)value); } else if (type == typeof(ushort)) { writer.WriteUInt16((ushort)value); } else if (type == typeof(uint)) { writer.WriteUInt32((uint)value); } else if (type == typeof(ulong)) { writer.WriteUInt64((ulong)value); } else { // TODO: message throw new ArgumentException(); } }
private void SerializeManifestResourceTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (ManifestResourceRow manifestResource in _manifestResourceTable) { writer.WriteUInt32(manifestResource.Offset); writer.WriteUInt32(manifestResource.Flags); writer.WriteReference((uint)_heaps.ResolveStringIndex(manifestResource.Name), metadataSizes.StringIndexSize); writer.WriteReference(manifestResource.Implementation, metadataSizes.ImplementationCodedIndexSize); } }
private void SerializeEncLogTable(BlobBuilder writer) { foreach (EncLogRow encLog in _encLogTable) { writer.WriteUInt32(encLog.Token); writer.WriteUInt32(encLog.FuncCode); } }
private void SerializeTablesHeader(BlobBuilder writer, MetadataSizes metadataSizes) { int startPosition = writer.Position; HeapSizeFlag heapSizes = 0; if (metadataSizes.StringIndexSize > 2) { heapSizes |= HeapSizeFlag.StringHeapLarge; } if (metadataSizes.GuidIndexSize > 2) { heapSizes |= HeapSizeFlag.GuidHeapLarge; } if (metadataSizes.BlobIndexSize > 2) { heapSizes |= HeapSizeFlag.BlobHeapLarge; } if (metadataSizes.IsMinimalDelta) { heapSizes |= (HeapSizeFlag.EnCDeltas | HeapSizeFlag.DeletedMarks); } ulong sortedDebugTables = metadataSizes.PresentTablesMask & MetadataSizes.SortedDebugTables; // Consider filtering out type system tables that are not present: ulong sortedTables = sortedDebugTables | (metadataSizes.IsStandaloneDebugMetadata ? 0UL : 0x16003301fa00); writer.WriteUInt32(0); // reserved writer.WriteByte(MetadataFormatMajorVersion); writer.WriteByte(MetadataFormatMinorVersion); writer.WriteByte((byte)heapSizes); writer.WriteByte(1); // reserved writer.WriteUInt64(metadataSizes.PresentTablesMask); writer.WriteUInt64(sortedTables); SerializeRowCounts(writer, metadataSizes.RowCounts, metadataSizes.PresentTablesMask); int endPosition = writer.Position; Debug.Assert(metadataSizes.CalculateTableStreamHeaderSize() == endPosition - startPosition); }
private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder <BlobBuilder> 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 BlobBuilder(); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindDynamicLocals); cmw.Align(4); // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob)) cmw.WriteUInt32(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block cmw.WriteUInt32((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.WriteUInt32((uint)dynamicTransformFlags.Length); //Written Length } else { cmw.WriteBytes(0, 68); //Empty flag array and size. } if (localIndex < dynamicVariableCount) { // Dynamic variable cmw.WriteUInt32((uint)local.SlotIndex); } else { // Dynamic constant cmw.WriteUInt32(0); } char[] localName = new char[64]; local.Name.CopyTo(0, localName, 0, local.Name.Length); cmw.WriteUTF16(localName); localIndex++; } dynamicLocals.Free(); customDebugInfo.Add(cmw); }
private void SerializeReferenceToPreviousMethodWithUsingInfo(ArrayBuilder<BlobBuilder> customDebugInfo) { BlobBuilder cmw = new BlobBuilder(12); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindForwardInfo); cmw.Align(4); cmw.WriteUInt32(12); cmw.WriteUInt32((uint)_previousMethodTokenWithUsingInfo); customDebugInfo.Add(cmw); }
private void WriteDirectory(Directory directory, BlobBuilder writer, uint offset, uint level, uint sizeOfDirectoryTree, int virtualAddressBase, BlobBuilder dataWriter) { writer.WriteUInt32(0); // Characteristics writer.WriteUInt32(0); // Timestamp writer.WriteUInt32(0); // Version writer.WriteUInt16(directory.NumberOfNamedEntries); writer.WriteUInt16(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.WriteUInt32((uint)(virtualAddressBase + sizeOfDirectoryTree + 16 + dataWriter.Position)); byte[] data = new List<byte>(r.Data).ToArray(); dataWriter.WriteUInt32((uint)data.Length); dataWriter.WriteUInt32(r.CodePage); dataWriter.WriteUInt32(0); dataWriter.WriteBytes(data); while ((dataWriter.Length % 4) != 0) { dataWriter.WriteByte(0); } } if (id >= 0) { writer.WriteInt32(id); } else { if (name == null) { name = string.Empty; } writer.WriteUInt32(nameOffset | 0x80000000); dataWriter.WriteUInt16((ushort)name.Length); dataWriter.WriteUTF16(name); } if (subDir != null) { writer.WriteUInt32(directoryOffset | 0x80000000); } else { writer.WriteUInt32(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 static void SerializeReferenceToIteratorClass(string iteratorClassName, ArrayBuilder<BlobBuilder> customDebugInfo) { if (iteratorClassName == null) return; var cmw = new BlobBuilder(); 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.WriteUInt32(length); cmw.WriteUTF16(iteratorClassName); cmw.WriteInt16(0); cmw.Align(4); Debug.Assert(cmw.Position == length); customDebugInfo.Add(cmw); }
private void SerializeEncMapTable(BlobBuilder writer) { foreach (EncMapRow encMap in _encMapTable) { writer.WriteUInt32(encMap.Token); } }
private void SerializeLocalScopeTable(BlobBuilder writer, MetadataSizes metadataSizes) { #if DEBUG // Spec: The table is required to be sorted first by Method in ascending order, then by StartOffset in ascending order, then by Length in descending order. for (int i = 1; i < _localScopeTable.Count; i++) { Debug.Assert(_localScopeTable[i - 1].Method <= _localScopeTable[i].Method); if (_localScopeTable[i - 1].Method == _localScopeTable[i].Method) { Debug.Assert(_localScopeTable[i - 1].StartOffset <= _localScopeTable[i].StartOffset); if (_localScopeTable[i - 1].StartOffset == _localScopeTable[i].StartOffset) { Debug.Assert(_localScopeTable[i - 1].Length >= _localScopeTable[i].Length); } } } #endif foreach (var row in _localScopeTable) { writer.WriteReference(row.Method, metadataSizes.MethodDefIndexSize); writer.WriteReference(row.ImportScope, metadataSizes.ImportScopeIndexSize); writer.WriteReference(row.VariableList, metadataSizes.LocalVariableIndexSize); writer.WriteReference(row.ConstantList, metadataSizes.LocalConstantIndexSize); writer.WriteUInt32(row.StartOffset); writer.WriteUInt32(row.Length); } }
private void SerializeTypeDefTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (TypeDefRow typeDef in _typeDefTable) { writer.WriteUInt32(typeDef.Flags); writer.WriteReference((uint)_heaps.ResolveStringIndex(typeDef.Name), metadataSizes.StringIndexSize); writer.WriteReference((uint)_heaps.ResolveStringIndex(typeDef.Namespace), metadataSizes.StringIndexSize); writer.WriteReference(typeDef.Extends, metadataSizes.TypeDefOrRefCodedIndexSize); writer.WriteReference(typeDef.FieldList, metadataSizes.FieldDefIndexSize); writer.WriteReference(typeDef.MethodList, metadataSizes.MethodDefIndexSize); } }
private void SerializeMethodDefTable(BlobBuilder writer, MetadataSizes metadataSizes, int methodBodyStreamRva) { foreach (MethodRow method in _methodDefTable) { if (method.Rva == -1) { writer.WriteUInt32(0); } else { writer.WriteUInt32((uint)(methodBodyStreamRva + method.Rva)); } writer.WriteUInt16(method.ImplFlags); writer.WriteUInt16(method.Flags); writer.WriteReference((uint)_heaps.ResolveStringIndex(method.Name), metadataSizes.StringIndexSize); writer.WriteReference((uint)_heaps.ResolveBlobIndex(method.Signature), metadataSizes.BlobIndexSize); writer.WriteReference(method.ParamList, metadataSizes.ParameterIndexSize); } }
private void WriteHeaders(Stream peStream, NtHeader ntHeader, CoffHeader coffHeader, List<SectionHeader> sectionHeaders, out long ntHeaderTimestampPosition) { var writer = new BlobBuilder(1024); // MS-DOS stub (128 bytes) writer.WriteBytes(s_dosHeader); // PE Signature "PE\0\0" writer.WriteUInt32(0x00004550); // COFF Header (20 bytes) writer.WriteUInt16((ushort)coffHeader.Machine); writer.WriteUInt16((ushort)coffHeader.NumberOfSections); ntHeaderTimestampPosition = writer.Position + peStream.Position; writer.WriteUInt32((uint)coffHeader.TimeDateStamp); writer.WriteUInt32((uint)coffHeader.PointerToSymbolTable); writer.WriteUInt32((uint)coffHeader.NumberOfSymbols); writer.WriteUInt16((ushort)(_is32bit ? 224 : 240)); // SizeOfOptionalHeader writer.WriteUInt16((ushort)coffHeader.Characteristics); // PE Headers: writer.WriteUInt16((ushort)(_is32bit ? PEMagic.PE32 : PEMagic.PE32Plus)); // 2 writer.WriteByte(ntHeader.MajorLinkerVersion); // 3 writer.WriteByte(ntHeader.MinorLinkerVersion); // 4 writer.WriteUInt32((uint)ntHeader.SizeOfCode); // 8 writer.WriteUInt32((uint)ntHeader.SizeOfInitializedData); // 12 writer.WriteUInt32((uint)ntHeader.SizeOfUninitializedData); // 16 writer.WriteUInt32((uint)ntHeader.AddressOfEntryPoint); // 20 writer.WriteUInt32((uint)ntHeader.BaseOfCode); // 24 if (_is32bit) { writer.WriteUInt32((uint)ntHeader.BaseOfData); // 28 writer.WriteUInt32((uint)ntHeader.ImageBase); // 32 } else { writer.WriteUInt64(ntHeader.ImageBase); // 32 } // NT additional fields: writer.WriteUInt32((uint)ntHeader.SectionAlignment); // 36 writer.WriteUInt32((uint)ntHeader.FileAlignment); // 40 writer.WriteUInt16(ntHeader.MajorOperatingSystemVersion); // 42 writer.WriteUInt16(ntHeader.MinorOperatingSystemVersion); // 44 writer.WriteUInt16(ntHeader.MajorImageVersion); // 46 writer.WriteUInt16(ntHeader.MinorImageVersion); // 48 writer.WriteUInt16(ntHeader.MajorSubsystemVersion); // MajorSubsystemVersion 50 writer.WriteUInt16(ntHeader.MinorSubsystemVersion); // MinorSubsystemVersion 52 // Win32VersionValue (reserved, should be 0) writer.WriteUInt32(0); // 56 writer.WriteUInt32((uint)ntHeader.SizeOfImage); // 60 writer.WriteUInt32((uint)ntHeader.SizeOfHeaders); // 64 writer.WriteUInt32(ntHeader.Checksum); // 68 writer.WriteUInt16((ushort)ntHeader.Subsystem); // 70 writer.WriteUInt16((ushort)ntHeader.DllCharacteristics); if (_is32bit) { writer.WriteUInt32((uint)ntHeader.SizeOfStackReserve); // 76 writer.WriteUInt32((uint)ntHeader.SizeOfStackCommit); // 80 writer.WriteUInt32((uint)ntHeader.SizeOfHeapReserve); // 84 writer.WriteUInt32((uint)ntHeader.SizeOfHeapCommit); // 88 } else { writer.WriteUInt64(ntHeader.SizeOfStackReserve); // 80 writer.WriteUInt64(ntHeader.SizeOfStackCommit); // 88 writer.WriteUInt64(ntHeader.SizeOfHeapReserve); // 96 writer.WriteUInt64(ntHeader.SizeOfHeapCommit); // 104 } // LoaderFlags writer.WriteUInt32(0); // 92|108 // The number of data-directory entries in the remainder of the header. writer.WriteUInt32(16); // 96|112 // directory entries: writer.WriteUInt32((uint)ntHeader.ExportTable.RelativeVirtualAddress); // 100|116 writer.WriteUInt32((uint)ntHeader.ExportTable.Size); // 104|120 writer.WriteUInt32((uint)ntHeader.ImportTable.RelativeVirtualAddress); // 108|124 writer.WriteUInt32((uint)ntHeader.ImportTable.Size); // 112|128 writer.WriteUInt32((uint)ntHeader.ResourceTable.RelativeVirtualAddress); // 116|132 writer.WriteUInt32((uint)ntHeader.ResourceTable.Size); // 120|136 writer.WriteUInt32((uint)ntHeader.ExceptionTable.RelativeVirtualAddress); // 124|140 writer.WriteUInt32((uint)ntHeader.ExceptionTable.Size); // 128|144 writer.WriteUInt32((uint)ntHeader.CertificateTable.RelativeVirtualAddress); // 132|148 writer.WriteUInt32((uint)ntHeader.CertificateTable.Size); // 136|152 writer.WriteUInt32((uint)ntHeader.BaseRelocationTable.RelativeVirtualAddress); // 140|156 writer.WriteUInt32((uint)ntHeader.BaseRelocationTable.Size); // 144|160 writer.WriteUInt32((uint)ntHeader.DebugTable.RelativeVirtualAddress); // 148|164 writer.WriteUInt32((uint)ntHeader.DebugTable.Size); // 152|168 writer.WriteUInt32((uint)ntHeader.CopyrightTable.RelativeVirtualAddress); // 156|172 writer.WriteUInt32((uint)ntHeader.CopyrightTable.Size); // 160|176 writer.WriteUInt32((uint)ntHeader.GlobalPointerTable.RelativeVirtualAddress); // 164|180 writer.WriteUInt32((uint)ntHeader.GlobalPointerTable.Size); // 168|184 writer.WriteUInt32((uint)ntHeader.ThreadLocalStorageTable.RelativeVirtualAddress); // 172|188 writer.WriteUInt32((uint)ntHeader.ThreadLocalStorageTable.Size); // 176|192 writer.WriteUInt32((uint)ntHeader.LoadConfigTable.RelativeVirtualAddress); // 180|196 writer.WriteUInt32((uint)ntHeader.LoadConfigTable.Size); // 184|200 writer.WriteUInt32((uint)ntHeader.BoundImportTable.RelativeVirtualAddress); // 188|204 writer.WriteUInt32((uint)ntHeader.BoundImportTable.Size); // 192|208 writer.WriteUInt32((uint)ntHeader.ImportAddressTable.RelativeVirtualAddress); // 196|212 writer.WriteUInt32((uint)ntHeader.ImportAddressTable.Size); // 200|216 writer.WriteUInt32((uint)ntHeader.DelayImportTable.RelativeVirtualAddress); // 204|220 writer.WriteUInt32((uint)ntHeader.DelayImportTable.Size); // 208|224 writer.WriteUInt32((uint)ntHeader.CliHeaderTable.RelativeVirtualAddress); // 212|228 writer.WriteUInt32((uint)ntHeader.CliHeaderTable.Size); // 216|232 writer.WriteUInt64(0); // 224|240 // Section Headers foreach (var sectionHeader in sectionHeaders) { WriteSectionHeader(sectionHeader, writer); } writer.WriteTo(peStream); }
private static void WriteDirectory( Directory directory, BlobBuilder writer, uint offset, uint level, uint sizeOfDirectoryTree, int virtualAddressBase, BlobBuilder dataWriter ) { writer.WriteUInt32(0); // Characteristics writer.WriteUInt32(0); // Timestamp writer.WriteUInt32(0); // Version writer.WriteUInt16(directory.NumberOfNamedEntries); writer.WriteUInt16(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.Count + 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.WriteUInt32( (uint)(virtualAddressBase + sizeOfDirectoryTree + 16 + dataWriter.Count) ); byte[] data = new List <byte>(r.Data).ToArray(); dataWriter.WriteUInt32((uint)data.Length); dataWriter.WriteUInt32(r.CodePage); dataWriter.WriteUInt32(0); dataWriter.WriteBytes(data); while ((dataWriter.Count % 4) != 0) { dataWriter.WriteByte(0); } } if (id >= 0) { writer.WriteInt32(id); } else { if (name == null) { name = string.Empty; } writer.WriteUInt32(nameOffset | 0x80000000); dataWriter.WriteUInt16((ushort)name.Length); dataWriter.WriteUTF16(name); } if (subDir != null) { writer.WriteUInt32(directoryOffset | 0x80000000); } else { writer.WriteUInt32(nameOffset); } } k = offset + 16 + n * 8; for (int i = 0; i < n; i++) { Directory subDir = directory.Entries[i] as Directory; if (subDir != null) { 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 WriteImportAddressTable(Stream peStream, int importTableRva) { var writer = new BlobBuilder(SizeOfImportAddressTable); int ilRVA = importTableRva + 40; int hintRva = ilRVA + (_is32bit ? 12 : 16); // Import Address Table if (_is32bit) { writer.WriteUInt32((uint)hintRva); // 4 writer.WriteUInt32(0); // 8 } else { writer.WriteUInt64((uint)hintRva); // 8 writer.WriteUInt64(0); // 16 } Debug.Assert(writer.Length == SizeOfImportAddressTable); writer.WriteTo(peStream); }
private void SerializeClassLayoutTable(BlobBuilder writer, MetadataSizes metadataSizes) { #if DEBUG for (int i = 1; i < _classLayoutTable.Count; i++) { Debug.Assert(_classLayoutTable[i - 1].Parent < _classLayoutTable[i].Parent); } #endif foreach (ClassLayoutRow classLayout in _classLayoutTable) { writer.WriteUInt16(classLayout.PackingSize); writer.WriteUInt32(classLayout.ClassSize); writer.WriteReference(classLayout.Parent, metadataSizes.TypeDefIndexSize); } }
private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder<BlobBuilder> 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 BlobBuilder(); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(CDI.CdiKindDynamicLocals); cmw.Align(4); // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob)) cmw.WriteUInt32(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block cmw.WriteUInt32((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.WriteUInt32((uint)dynamicTransformFlags.Length); //Written Length } else { cmw.WriteBytes(0, 68); //Empty flag array and size. } if (localIndex < dynamicVariableCount) { // Dynamic variable cmw.WriteUInt32((uint)local.SlotIndex); } else { // Dynamic constant cmw.WriteUInt32(0); } char[] localName = new char[64]; local.Name.CopyTo(0, localName, 0, local.Name.Length); cmw.WriteUTF16(localName); localIndex++; } dynamicLocals.Free(); customDebugInfo.Add(cmw); }
private static void WriteSectionHeader(SectionHeader sectionHeader, BlobBuilder writer) { if (sectionHeader.VirtualSize == 0) { return; } for (int j = 0, m = sectionHeader.Name.Length; j < 8; j++) { if (j < m) { writer.WriteByte((byte)sectionHeader.Name[j]); } else { writer.WriteByte(0); } } writer.WriteUInt32((uint)sectionHeader.VirtualSize); writer.WriteUInt32((uint)sectionHeader.RelativeVirtualAddress); writer.WriteUInt32((uint)sectionHeader.SizeOfRawData); writer.WriteUInt32((uint)sectionHeader.PointerToRawData); writer.WriteUInt32((uint)sectionHeader.PointerToRelocations); writer.WriteUInt32((uint)sectionHeader.PointerToLinenumbers); writer.WriteUInt16(sectionHeader.NumberOfRelocations); writer.WriteUInt16(sectionHeader.NumberOfLinenumbers); writer.WriteUInt32((uint)sectionHeader.Characteristics); }
private void SerializeFieldLayoutTable(BlobBuilder writer, MetadataSizes metadataSizes) { #if DEBUG for (int i = 1; i < _fieldLayoutTable.Count; i++) { Debug.Assert(_fieldLayoutTable[i - 1].Field < _fieldLayoutTable[i].Field); } #endif foreach (FieldLayoutRow fieldLayout in _fieldLayoutTable) { writer.WriteUInt32(fieldLayout.Offset); writer.WriteReference(fieldLayout.Field, metadataSizes.FieldDefIndexSize); } }
private void WriteImportTable(Stream peStream, int importTableRva, int importAddressTableRva) { var writer = new BlobBuilder(SizeOfImportTable); int ilRVA = importTableRva + 40; int hintRva = ilRVA + (_is32bit ? 12 : 16); int nameRva = hintRva + 12 + 2; // Import table writer.WriteUInt32((uint)ilRVA); // 4 writer.WriteUInt32(0); // 8 writer.WriteUInt32(0); // 12 writer.WriteUInt32((uint)nameRva); // 16 writer.WriteUInt32((uint)importAddressTableRva); // 20 writer.WriteBytes(0, 20); // 40 // Import Lookup table if (_is32bit) { writer.WriteUInt32((uint)hintRva); // 44 writer.WriteUInt32(0); // 48 writer.WriteUInt32(0); // 52 } else { writer.WriteUInt64((uint)hintRva); // 48 writer.WriteUInt64(0); // 56 } // Hint table writer.WriteUInt16(0); // Hint 54|58 foreach (char ch in CorEntryPointName) { writer.WriteByte((byte)ch); // 65|69 } writer.WriteByte(0); // 66|70 Debug.Assert(writer.Length == SizeOfImportTable); writer.WriteTo(peStream); }
private void SerializeFieldRvaTable(BlobBuilder writer, MetadataSizes metadataSizes, int mappedFieldDataStreamRva) { #if DEBUG for (int i = 1; i < _fieldRvaTable.Count; i++) { Debug.Assert(_fieldRvaTable[i - 1].Field < _fieldRvaTable[i].Field); } #endif foreach (FieldRvaRow fieldRva in _fieldRvaTable) { writer.WriteUInt32((uint)mappedFieldDataStreamRva + fieldRva.Offset); writer.WriteReference(fieldRva.Field, metadataSizes.FieldDefIndexSize); } }
private void WriteDebugTable(Stream peStream, SectionHeader textSection, ContentId nativePdbContentId, ContentId portablePdbContentId, MetadataSizes metadataSizes) { Debug.Assert(nativePdbContentId.IsDefault ^ portablePdbContentId.IsDefault); var writer = new BlobBuilder(); // characteristics: writer.WriteUInt32(0); // PDB stamp & version if (portablePdbContentId.IsDefault) { writer.WriteBytes(nativePdbContentId.Stamp); writer.WriteUInt32(0); } else { writer.WriteBytes(portablePdbContentId.Stamp); writer.WriteUInt32('P' << 24 | 'M' << 16 | 0x00 << 8 | 0x01); } // type: const int ImageDebugTypeCodeView = 2; writer.WriteUInt32(ImageDebugTypeCodeView); // size of data: writer.WriteUInt32((uint)ComputeSizeOfDebugDirectoryData()); uint dataOffset = (uint)ComputeOffsetToDebugTable(metadataSizes) + ImageDebugDirectoryBaseSize; // PointerToRawData (RVA of the data): writer.WriteUInt32((uint)textSection.RelativeVirtualAddress + dataOffset); // AddressOfRawData (position of the data in the PE stream): writer.WriteUInt32((uint)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 ?? portablePdbContentId.Guid); // age writer.WriteUInt32(PdbWriter.Age); // UTF-8 encoded zero-terminated path to PDB writer.WriteUTF8(_pdbPathOpt); writer.WriteByte(0); writer.WriteTo(peStream); writer.Free(); }
private void SerializeAssemblyRefTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (AssemblyRefTableRow row in _assemblyRefTable) { writer.WriteUInt16((ushort)row.Version.Major); writer.WriteUInt16((ushort)row.Version.Minor); writer.WriteUInt16((ushort)row.Version.Build); writer.WriteUInt16((ushort)row.Version.Revision); writer.WriteUInt32(row.Flags); writer.WriteReference((uint)_heaps.ResolveBlobIndex(row.PublicKeyToken), metadataSizes.BlobIndexSize); writer.WriteReference((uint)_heaps.ResolveStringIndex(row.Name), metadataSizes.StringIndexSize); writer.WriteReference((uint)_heaps.ResolveStringIndex(row.Culture), metadataSizes.StringIndexSize); writer.WriteReference((uint)_heaps.ResolveBlobIndex(row.HashValue), metadataSizes.BlobIndexSize); } }
private void WriteRelocSection(Stream peStream, SectionHeader relocSection, int entryPointAddress) { peStream.Position = relocSection.PointerToRawData; var writer = new BlobBuilder(relocSection.SizeOfRawData); writer.WriteUInt32((((uint)entryPointAddress + 2) / 0x1000) * 0x1000); writer.WriteUInt32(_properties.Requires64bits && !_properties.RequiresAmdInstructionSet ? 14u : 12u); uint offsetWithinPage = ((uint)entryPointAddress + 2) % 0x1000; uint relocType = _properties.Requires64bits ? 10u : 3u; ushort s = (ushort)((relocType << 12) | offsetWithinPage); writer.WriteUInt16(s); if (_properties.Requires64bits && !_properties.RequiresAmdInstructionSet) { writer.WriteUInt32(relocType << 12); } writer.WriteUInt16(0); // next chunk's RVA writer.PadTo(relocSection.SizeOfRawData); writer.WriteTo(peStream); }
private void SerializeFileTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (FileTableRow fileReference in _fileTable) { writer.WriteUInt32(fileReference.Flags); writer.WriteReference((uint)_heaps.ResolveStringIndex(fileReference.FileName), metadataSizes.StringIndexSize); writer.WriteReference((uint)_heaps.ResolveBlobIndex(fileReference.HashValue), metadataSizes.BlobIndexSize); } }
private void SerializeExportedTypeTable(BlobBuilder writer, MetadataSizes metadataSizes) { foreach (ExportedTypeRow exportedType in _exportedTypeTable) { writer.WriteUInt32((uint)exportedType.Flags); writer.WriteUInt32(exportedType.TypeDefId); writer.WriteReference((uint)_heaps.ResolveStringIndex(exportedType.TypeName), metadataSizes.StringIndexSize); writer.WriteReference((uint)_heaps.ResolveStringIndex(exportedType.TypeNamespace), metadataSizes.StringIndexSize); writer.WriteReference(exportedType.Implementation, metadataSizes.ImplementationCodedIndexSize); } }
private static BlobBuilder SerializeRecord(byte kind, Action<BlobBuilder> data) { var cmw = new BlobBuilder(); cmw.WriteByte(CDI.CdiVersion); cmw.WriteByte(kind); cmw.WriteByte(0); // alignment size (will be patched) int alignmentSizeAndLengthPosition = cmw.Position; cmw.WriteByte(0); // length (will be patched) cmw.WriteUInt32(0); data(cmw); int length = cmw.Position; int alignedLength = 4 * ((length + 3) / 4); byte alignmentSize = (byte)(alignedLength - length); for (int i = 0; i < alignmentSize; i++) { cmw.WriteByte(0); } cmw.SetPosition(alignmentSizeAndLengthPosition); cmw.WriteByte(alignmentSize); cmw.WriteUInt32((uint)alignedLength); cmw.SetPosition(length); return cmw; }