public int GetHashCode(RawMethodRow obj) => (int)obj.RVA + rol(obj.ImplFlags, 3) + rol(obj.Flags, 7) + rol(obj.Name, 11) + rol(obj.Signature, 15) + rol(obj.ParamList, 19);
/// <summary> /// Reads a raw <c>Method</c> row or returns false if the row doesn't exist /// </summary> /// <param name="rid">Row ID</param> /// <param name="row">Row data</param> /// <returns></returns> public bool TryReadMethodRow(uint rid, out RawMethodRow row) { var table = MethodTable; if (table.IsInvalidRID(rid)) { row = default; return(false); } var mrr = methodRowReader; if (mrr != null && mrr.TryReadRow(rid, out row)) { return(true); } var reader = table.DataReader; reader.Position = (rid - 1) * (uint)table.TableInfo.RowSize; row = new RawMethodRow( reader.Unsafe_ReadUInt32(), reader.Unsafe_ReadUInt16(), reader.Unsafe_ReadUInt16(), table.Column3.Unsafe_Read24(ref reader), table.Column4.Unsafe_Read24(ref reader), table.Column5.Unsafe_Read24(ref reader)); return(true); }
public bool Equals(RawMethodRow x, RawMethodRow y) => x.RVA == y.RVA && x.ImplFlags == y.ImplFlags && x.Flags == y.Flags && x.Name == y.Name && x.Signature == y.Signature && x.ParamList == y.ParamList;
public DmdMethodDefMD(DmdEcma335MetadataReader reader, RawMethodRow row, uint rid, string name, DmdType declaringType, DmdType reflectedType) : base(rid, declaringType, reflectedType) { this.reader = reader ?? throw new ArgumentNullException(nameof(reader)); MethodImplementationFlags = (DmdMethodImplAttributes)row.ImplFlags; Attributes = (DmdMethodAttributes)row.Flags; Name = name ?? throw new ArgumentNullException(nameof(name)); methodSignature = reader.ReadMethodSignature(row.Signature, DeclaringType.GetGenericArguments(), GetGenericArguments(), isProperty: false); }
void InitializeRawRow() { if (rawRow != null) { return; } rawRow = readerModule.TablesStream.ReadMethodRow(rid); }
public static void Erase(NativeModuleWriter writer, ModuleDefMD module) { if (writer == null || module == null) { return; } List <Tuple <uint, uint, byte[]> > sections = new List <Tuple <uint, uint, byte[]> >(); MemoryStream s = new MemoryStream(); foreach (NativeModuleWriter.OrigSection origSect in writer.OrigSections) { var oldChunk = origSect.Chunk; ImageSectionHeader sectHdr = origSect.PESection; s.SetLength(0L); oldChunk.WriteTo(new BinaryWriter(s)); byte[] buf = s.ToArray(); var newChunk = new BinaryReaderChunk(MemoryImageStream.Create(buf), oldChunk.GetVirtualSize()); newChunk.SetOffset(oldChunk.FileOffset, oldChunk.RVA); origSect.Chunk = newChunk; sections.Add(Tuple.Create <uint, uint, byte[]>(sectHdr.PointerToRawData, sectHdr.PointerToRawData + sectHdr.SizeOfRawData, buf)); } var md = module.MetaData; uint row = md.TablesStream.MethodTable.Rows; for (uint i = 1u; i <= row; i += 1u) { RawMethodRow method = md.TablesStream.ReadMethodRow(i); if ((method.ImplFlags & 3) == 0) { Erase(sections, (uint)md.PEImage.ToFileOffset((RVA)method.RVA)); } } ImageDataDirectory res = md.ImageCor20Header.Resources; if (res.Size > 0u) { Erase(sections, (uint)res.StartOffset, res.Size); } Erase(sections, md.ImageCor20Header); Erase(sections, md.MetaDataHeader);// md.MetadataHeader); foreach (DotNetStream stream in md.AllStreams) { Erase(sections, stream); } }
void InjectNativeCode(object sender, ModuleWriterEventArgs e) { var writer = (ModuleWriterBase)sender; if (e.Event == ModuleWriterEvent.MDEndWriteMethodBodies) { for (int n = 0; n < nativeCodes.Count; n++) nativeCodes[n] = new Tuple<MethodDef, byte[], MethodBody>( nativeCodes[n].Item1, nativeCodes[n].Item2, writer.MethodBodies.Add(new MethodBody(nativeCodes[n].Item2))); } else if (e.Event == ModuleWriterEvent.EndCalculateRvasAndFileOffsets) { foreach (var native in nativeCodes) { uint rid = writer.Metadata.GetRid(native.Item1); RawMethodRow methodRow = writer.Metadata.TablesHeap.MethodTable[rid]; writer.Metadata.TablesHeap.MethodTable[rid] = new RawMethodRow( (uint)native.Item3.RVA, methodRow.ImplFlags, methodRow.Flags, methodRow.Name, methodRow.Signature, methodRow.ParamList); } } }
/// <summary> /// Patches all columns and blob signatures that reference a moved TypeDef so they reference the new TypeRef /// </summary> void PatchTypeTokenReferences(TypeDef nonNestedEditedType) { if (remappedTypeTokens.Count == 0) { return; } // NOTE: We don't patch the following: // - Method bodies // - All MemberRefs referenced by method bodies // - StandAloneSig.Signature. It's only used by method bodies // - MethodSpec.Instantiation. It's only used by method bodies // - Custom attribute blobs. Could reference the edited type but not likely to cause a problem. // - Marshal blobs. Could reference the edited type but not likely to cause a problem. // The MD writer doesn't write the FieldMarshal table. var tablesHeap = mdEditor.TablesHeap; var typeSigDict = new Dictionary <uint, uint>(); var callConvSigDict = new Dictionary <uint, uint>(); MDTable table; byte * p; int rowSize; ColumnInfo column, column2; uint i, codedToken, newToken, sig, newSig, rid; MDToken token; // Patch the TypeDef table { table = mdEditor.RealMetadata.TablesStream.TypeDefTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[3]; p += column.Offset; for (i = 0; i < table.Rows; i++, p += rowSize) { codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p; if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token)) { continue; } if (remappedTypeTokens.TryGetValue(token.Raw, out newToken)) { var row = tablesHeap.TypeDefTable.Get(i + 1); row = new RawTypeDefRow(row.Flags, row.Name, row.Namespace, CodedToken.TypeDefOrRef.Encode(newToken), row.FieldList, row.MethodList); tablesHeap.TypeDefTable.Set(i + 1, ref row); } } } // Patch the Field table { table = mdEditor.RealMetadata.TablesStream.FieldTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[2]; p += column.Offset; for (i = 0; i < table.Rows; i++, p += rowSize) { sig = column.Size == 2 ? *(ushort *)p : *(uint *)p; newSig = PatchCallingConventionSignature(callConvSigDict, sig); if (newSig != sig) { var row = tablesHeap.FieldTable.Get(i + 1); row = new RawFieldRow(row.Flags, row.Name, newSig); tablesHeap.FieldTable.Set(i + 1, ref row); } } } // Patch the Method table { table = mdEditor.RealMetadata.TablesStream.MethodTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[4]; p += column.Offset; for (i = 0; i < table.Rows; i++, p += rowSize) { sig = column.Size == 2 ? *(ushort *)p : *(uint *)p; newSig = PatchCallingConventionSignature(callConvSigDict, sig); if (newSig != sig) { var row = tablesHeap.MethodTable.Get(i + 1); row = new RawMethodRow(row.RVA, row.ImplFlags, row.Flags, row.Name, newSig, row.ParamList); tablesHeap.MethodTable.Set(i + 1, ref row); } } } // Patch the InterfaceImpl table { table = mdEditor.RealMetadata.TablesStream.InterfaceImplTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[1]; p += column.Offset; for (i = 0; i < table.Rows; i++, p += rowSize) { codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p; if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token)) { continue; } if (remappedTypeTokens.TryGetValue(token.Raw, out newToken)) { var row = tablesHeap.InterfaceImplTable.Get(i + 1); row = new RawInterfaceImplRow(row.Class, CodedToken.TypeDefOrRef.Encode(newToken)); tablesHeap.InterfaceImplTable.Set(i + 1, ref row); } } } //TODO: PERF: If needed, this table could mostly be skipped. We only need to update refs from: // CustomAttribute.Type, MethodImpl.MethodBody, MethodImpl.MethodDeclaration // CustomAttribute.Type almost never references the edited type, and if it does, the // edited type, or any of its nested types, is an attribute. Quick test: this block // took ~25% of the total time (patch file, write new MD, test file was dnSpy.exe = 3.3MB). // Patch the MemberRef table { table = mdEditor.RealMetadata.TablesStream.MemberRefTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[0]; column2 = table.Columns[2]; for (i = 0; i < table.Rows; i++, p += rowSize) { codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p; if (!CodedToken.MemberRefParent.Decode(codedToken, out token)) { continue; } rid = i + 1; RawMemberRefRow row; switch (token.Table) { case Table.TypeRef: case Table.TypeDef: case Table.TypeSpec: if (remappedTypeTokens.TryGetValue(token.Raw, out newToken)) { row = tablesHeap.MemberRefTable.Get(rid); row = new RawMemberRefRow(CodedToken.MemberRefParent.Encode(newToken), row.Name, row.Signature); tablesHeap.MemberRefTable.Set(rid, ref row); } break; case Table.ModuleRef: if (nonNestedEditedType.IsGlobalModuleType && CheckResolutionScopeIsSameModule(token, nonNestedEditedType.Module)) { if (remappedTypeTokens.TryGetValue(nonNestedEditedType.MDToken.Raw, out newToken)) { row = tablesHeap.MemberRefTable.Get(rid); row = new RawMemberRefRow(CodedToken.MemberRefParent.Encode(newToken), row.Name, row.Signature); tablesHeap.MemberRefTable.Set(rid, ref row); } } break; case Table.Method: break; default: Debug.Fail("Impossible"); break; } sig = column2.Size == 2 ? *(ushort *)(p + column2.Offset) : *(uint *)(p + column2.Offset); newSig = PatchCallingConventionSignature(callConvSigDict, sig); if (sig != newSig) { row = tablesHeap.MemberRefTable.Get(rid); row = new RawMemberRefRow(row.Class, row.Name, newSig); tablesHeap.MemberRefTable.Set(rid, ref row); } } } // Patch the Event table { table = mdEditor.RealMetadata.TablesStream.EventTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[2]; p += column.Offset; for (i = 0; i < table.Rows; i++, p += rowSize) { codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p; if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token)) { continue; } if (remappedTypeTokens.TryGetValue(token.Raw, out newToken)) { var row = tablesHeap.EventTable.Get(i + 1); row = new RawEventRow(row.EventFlags, row.Name, CodedToken.TypeDefOrRef.Encode(newToken)); tablesHeap.EventTable.Set(i + 1, ref row); } } } // Patch the Property table { table = mdEditor.RealMetadata.TablesStream.PropertyTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[2]; p += column.Offset; for (i = 0; i < table.Rows; i++, p += rowSize) { sig = column.Size == 2 ? *(ushort *)p : *(uint *)p; newSig = PatchCallingConventionSignature(callConvSigDict, sig); if (newSig != sig) { var row = tablesHeap.PropertyTable.Get(i + 1); row = new RawPropertyRow(row.PropFlags, row.Name, newSig); tablesHeap.PropertyTable.Set(i + 1, ref row); } } } // Patch the TypeSpec table { table = mdEditor.RealMetadata.TablesStream.TypeSpecTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[0]; for (i = 0; i < table.Rows; i++, p += rowSize) { sig = column.Size == 2 ? *(ushort *)p : *(uint *)p; newSig = PatchTypeSignature(typeSigDict, sig); if (newSig != sig) { var row = new RawTypeSpecRow(newSig); tablesHeap.TypeSpecTable.Set(i + 1, ref row); } } } // Patch the GenericParam table if (mdEditor.RealMetadata.TablesStream.GenericParamTable.Columns.Count == 5) { table = mdEditor.RealMetadata.TablesStream.GenericParamTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[4]; p += column.Offset; for (i = 0; i < table.Rows; i++, p += rowSize) { codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p; if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token)) { continue; } if (remappedTypeTokens.TryGetValue(token.Raw, out newToken)) { var row = tablesHeap.GenericParamTable.Get(i + 1); row = new RawGenericParamRow(row.Number, row.Flags, row.Owner, row.Name, CodedToken.TypeDefOrRef.Encode(newToken)); tablesHeap.GenericParamTable.Set(i + 1, ref row); } } } // Patch the GenericParamConstraint table { table = mdEditor.RealMetadata.TablesStream.GenericParamConstraintTable; p = peFile + (int)table.StartOffset; rowSize = (int)table.RowSize; column = table.Columns[1]; p += column.Offset; for (i = 0; i < table.Rows; i++, p += rowSize) { codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p; if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token)) { continue; } if (remappedTypeTokens.TryGetValue(token.Raw, out newToken)) { var row = tablesHeap.GenericParamConstraintTable.Get(i + 1); row = new RawGenericParamConstraintRow(row.Owner, CodedToken.TypeDefOrRef.Encode(newToken)); tablesHeap.GenericParamConstraintTable.Set(i + 1, ref row); } } } }
/// <inheritdoc/> protected override void AllocateMemberDefRids() { int numTypes = allTypeDefs.Count; int typeNum = 0; int notifyNum = 0; const int numNotifyEvents = 5; // AllocateMemberDefRids0 - AllocateMemberDefRids4 int notifyAfter = numTypes / numNotifyEvents; uint fieldListRid = 1, methodListRid = 1; uint eventListRid = 1, propertyListRid = 1; uint paramListRid = 1; foreach (var type in allTypeDefs) { if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents) { Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids0 + notifyNum++); notifyAfter += numTypes / numNotifyEvents; } if (type == null) { continue; } uint typeRid = GetRid(type); var typeRow = tablesHeap.TypeDefTable[typeRid]; typeRow.FieldList = fieldListRid; typeRow.MethodList = methodListRid; foreach (var field in type.Fields) { if (field == null) { continue; } uint rid = fieldListRid++; if (rid != tablesHeap.FieldTable.Create(new RawFieldRow())) { throw new ModuleWriterException("Invalid field rid"); } fieldDefInfos.Add(field, rid); } foreach (var method in type.Methods) { if (method == null) { continue; } uint rid = methodListRid++; var row = new RawMethodRow(0, 0, 0, 0, 0, paramListRid); if (rid != tablesHeap.MethodTable.Create(row)) { throw new ModuleWriterException("Invalid method rid"); } methodDefInfos.Add(method, rid); foreach (var pd in Sort(method.ParamDefs)) { if (pd == null) { continue; } uint pdRid = paramListRid++; if (pdRid != tablesHeap.ParamTable.Create(new RawParamRow())) { throw new ModuleWriterException("Invalid param rid"); } paramDefInfos.Add(pd, pdRid); } } if (!IsEmpty(type.Events)) { uint eventMapRid = tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, eventListRid)); eventMapInfos.Add(type, eventMapRid); foreach (var evt in type.Events) { if (evt == null) { continue; } uint rid = eventListRid++; if (rid != tablesHeap.EventTable.Create(new RawEventRow())) { throw new ModuleWriterException("Invalid event rid"); } eventDefInfos.Add(evt, rid); } } if (!IsEmpty(type.Properties)) { uint propertyMapRid = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, propertyListRid)); propertyMapInfos.Add(type, propertyMapRid); foreach (var prop in type.Properties) { if (prop == null) { continue; } uint rid = propertyListRid++; if (rid != tablesHeap.PropertyTable.Create(new RawPropertyRow())) { throw new ModuleWriterException("Invalid property rid"); } propertyDefInfos.Add(prop, rid); } } } while (notifyNum < numNotifyEvents) { Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids0 + notifyNum++); } }
/// <inheritdoc/> protected override void AllocateMemberDefRids() { uint fieldListRid = 1, methodListRid = 1; uint eventListRid = 1, propertyListRid = 1; uint paramListRid = 1; foreach (var type in allTypeDefs) { if (type == null) { continue; } uint typeRid = GetRid(type); var typeRow = tablesHeap.TypeDefTable[typeRid]; typeRow.FieldList = fieldListRid; typeRow.MethodList = methodListRid; foreach (var field in type.Fields) { if (field == null) { continue; } uint rid = fieldListRid++; if (rid != tablesHeap.FieldTable.Create(new RawFieldRow())) { throw new ModuleWriterException("Invalid field rid"); } fieldDefInfos.Add(field, rid); } foreach (var method in type.Methods) { if (method == null) { continue; } uint rid = methodListRid++; var row = new RawMethodRow(0, 0, 0, 0, 0, paramListRid); if (rid != tablesHeap.MethodTable.Create(row)) { throw new ModuleWriterException("Invalid method rid"); } methodDefInfos.Add(method, rid); foreach (var pd in Sort(method.ParamDefs)) { if (pd == null) { continue; } uint pdRid = paramListRid++; if (pdRid != tablesHeap.ParamTable.Create(new RawParamRow())) { throw new ModuleWriterException("Invalid param rid"); } paramDefInfos.Add(pd, pdRid); } } if (!IsEmpty(type.Events)) { uint eventMapRid = tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, eventListRid)); eventMapInfos.Add(type, eventMapRid); foreach (var evt in type.Events) { if (evt == null) { continue; } uint rid = eventListRid++; if (rid != tablesHeap.EventTable.Create(new RawEventRow())) { throw new ModuleWriterException("Invalid event rid"); } eventDefInfos.Add(evt, rid); } } if (!IsEmpty(type.Properties)) { uint propertyMapRid = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, propertyListRid)); propertyMapInfos.Add(type, propertyMapRid); foreach (var prop in type.Properties) { if (prop == null) { continue; } uint rid = propertyListRid++; if (rid != tablesHeap.PropertyTable.Create(new RawPropertyRow())) { throw new ModuleWriterException("Invalid property rid"); } propertyDefInfos.Add(prop, rid); } } } }
static uint ReadMethodColumnMethod(ref RawMethodRow row, int index) => row[index];
/// <inheritdoc/> protected override void AllocateMemberDefRids() { int numTypes = allTypeDefs.Length; int typeNum = 0; int notifyNum = 0; const int numNotifyEvents = 5; int notifyAfter = numTypes / numNotifyEvents; uint fieldListRid = 1, methodListRid = 1; uint eventListRid = 1, propertyListRid = 1; uint paramListRid = 1; int count; foreach (var type in allTypeDefs) { if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents) { RaiseProgress(Writer.MetadataEvent.AllocateMemberDefRids, (double)typeNum / numTypes); notifyNum++; notifyAfter = (int)((double)numTypes / numNotifyEvents * (notifyNum + 1)); } if (type == null) { continue; } uint typeRid = GetRid(type); var typeRow = tablesHeap.TypeDefTable[typeRid]; typeRow = new RawTypeDefRow(typeRow.Flags, typeRow.Name, typeRow.Namespace, typeRow.Extends, fieldListRid, methodListRid); tablesHeap.TypeDefTable[typeRid] = typeRow; var fields = type.Fields; count = fields.Count; for (int i = 0; i < count; i++) { var field = fields[i]; if (field == null) { continue; } uint rid = fieldListRid++; if (rid != tablesHeap.FieldTable.Create(new RawFieldRow())) { throw new ModuleWriterException("Invalid field rid"); } fieldDefInfos.Add(field, rid); } var methods = type.Methods; count = methods.Count; for (int i = 0; i < count; i++) { var method = methods[i]; if (method == null) { continue; } uint rid = methodListRid++; var row = new RawMethodRow(0, 0, 0, 0, 0, paramListRid); if (rid != tablesHeap.MethodTable.Create(row)) { throw new ModuleWriterException("Invalid method rid"); } methodDefInfos.Add(method, rid); foreach (var pd in Sort(method.ParamDefs)) { if (pd == null) { continue; } uint pdRid = paramListRid++; if (pdRid != tablesHeap.ParamTable.Create(new RawParamRow())) { throw new ModuleWriterException("Invalid param rid"); } paramDefInfos.Add(pd, pdRid); } } if (!IsEmpty(type.Events)) { uint eventMapRid = tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, eventListRid)); eventMapInfos.Add(type, eventMapRid); var events = type.Events; count = events.Count; for (int i = 0; i < count; i++) { var evt = events[i]; if (evt == null) { continue; } uint rid = eventListRid++; if (rid != tablesHeap.EventTable.Create(new RawEventRow())) { throw new ModuleWriterException("Invalid event rid"); } eventDefInfos.Add(evt, rid); } } if (!IsEmpty(type.Properties)) { uint propertyMapRid = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, propertyListRid)); propertyMapInfos.Add(type, propertyMapRid); var properties = type.Properties; count = properties.Count; for (int i = 0; i < count; i++) { var prop = properties[i]; if (prop == null) { continue; } uint rid = propertyListRid++; if (rid != tablesHeap.PropertyTable.Create(new RawPropertyRow())) { throw new ModuleWriterException("Invalid property rid"); } propertyDefInfos.Add(prop, rid); } } } }
void CreateSection(ModuleWriterBase writer) { // move some PE parts to separate section to prevent it from being hashed var peSection = new PESection("", 0x60000020); bool moved = false; uint alignment; if (writer.StrongNameSignature != null) { alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value; peSection.Add(writer.StrongNameSignature, alignment); moved = true; } var managedWriter = writer as ModuleWriter; if (managedWriter != null) { if (managedWriter.ImportAddressTable != null) { alignment = writer.TextSection.Remove(managedWriter.ImportAddressTable).Value; peSection.Add(managedWriter.ImportAddressTable, alignment); moved = true; } if (managedWriter.StartupStub != null) { alignment = writer.TextSection.Remove(managedWriter.StartupStub).Value; peSection.Add(managedWriter.StartupStub, alignment); moved = true; } } if (moved) { writer.Sections.AddBeforeReloc(peSection); } // create section var nameBuffer = new byte[8]; nameBuffer[0] = (byte)(name1 >> 0); nameBuffer[1] = (byte)(name1 >> 8); nameBuffer[2] = (byte)(name1 >> 16); nameBuffer[3] = (byte)(name1 >> 24); nameBuffer[4] = (byte)(name2 >> 0); nameBuffer[5] = (byte)(name2 >> 8); nameBuffer[6] = (byte)(name2 >> 16); nameBuffer[7] = (byte)(name2 >> 24); var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040); writer.Sections.InsertBeforeReloc(random.NextInt32(writer.Sections.Count), newSection); // random padding at beginning to prevent revealing hash key newSection.Add(new ByteArrayChunk(random.NextBytes(0x10)), 0x10); // create index var bodyIndex = new JITBodyIndex(methods.Select(method => writer.Metadata.GetToken(method).Raw)); newSection.Add(bodyIndex, 0x10); // save methods foreach (MethodDef method in methods.WithProgress(context.Logger)) { if (!method.HasBody) { continue; } MDToken token = writer.Metadata.GetToken(method); var jitBody = new JITMethodBody(); var bodyWriter = new JITMethodBodyWriter(writer.Metadata, method.Body, jitBody, random.NextUInt32(), writer.Metadata.KeepOldMaxStack || method.Body.KeepOldMaxStack); bodyWriter.Write(); jitBody.Serialize(token.Raw, key, fieldLayout); bodyIndex.Add(token.Raw, jitBody); method.Body = NopBody; RawMethodRow methodRow = writer.Metadata.TablesHeap.MethodTable[token.Rid]; writer.Metadata.TablesHeap.MethodTable[token.Rid] = new RawMethodRow( methodRow.RVA, (ushort)(methodRow.ImplFlags | (ushort)MethodImplAttributes.NoInlining), methodRow.Flags, methodRow.Name, methodRow.Signature, methodRow.ParamList); context.CheckCancellation(); } bodyIndex.PopulateSection(newSection); // padding to prevent bad size due to shift division newSection.Add(new ByteArrayChunk(new byte[4]), 4); }