public void AddVTableHeader(VTableHeader header) { if (!header.Is32Bit && !header.Is64Bit) { throw new ArgumentException("VTable header must be marked either 32 bits or 64 bits."); } if (header.Is32Bit && header.Is64Bit) { throw new ArgumentException("VTable header cannot be 32 bits and 64 bits simultanuously."); } var rawTable = new byte[header.Table.Count * (header.Is32Bit ? sizeof(uint) : sizeof(ulong))]; for (int index = 0; index < header.Table.Count; index++) { var entry = header.Table[index]; var rawEntry = header.Is64Bit ? BitConverter.GetBytes((ulong)entry.MetadataToken.ToUInt32()) : BitConverter.GetBytes(entry.MetadataToken.ToUInt32()); Buffer.BlockCopy(rawEntry, 0, rawTable, index * rawEntry.Length, rawEntry.Length); } var tableSegment = new DataSegment(rawTable); _entriesTable.Segments.Add(tableSegment); _headerToTables[header] = tableSegment; }
public void PersistentVTables() { var assembly = CreateTempAssembly(); var header = assembly.NetDirectory.MetadataHeader; var importer = new ReferenceImporter(header.Image); var type = new TypeDefinition(null, "SomeType", TypeAttributes.Public, importer.ImportType(typeof(object))); for (int i = 0; i < 10; i++) { var method = new MethodDefinition("Method" + i, MethodAttributes.Public | MethodAttributes.Virtual, new MethodSignature(header.Image.TypeSystem.Void)); method.MethodBody = new CilMethodBody(method) { Instructions = { CilInstruction.Create(CilOpCodes.Ret) } }; type.Methods.Add(method); } header.Image.Assembly.Modules[0].TopLevelTypes.Add(type); var mapping = header.UnlockMetadata(); var directory = new VTablesDirectory(); var vTableHeader = new VTableHeader() { Attributes = VTableAttributes.Is32Bit, }; foreach (var method in type.Methods) { vTableHeader.Table.Add(header.GetStream <TableStream>().ResolveRow(mapping[method])); } directory.VTableHeaders.Add(vTableHeader); assembly.NetDirectory.VTablesDirectory = directory; using (var stream = new MemoryStream()) { assembly.Write(new BinaryStreamWriter(stream), new CompactNetAssemblyBuilder(assembly)); assembly = WindowsAssembly.FromBytes(stream.ToArray()); directory = assembly.NetDirectory.VTablesDirectory; Assert.NotNull(directory); Assert.Equal(1, directory.VTableHeaders.Count); Assert.Equal(type.Methods.Select(x => mapping[x]), directory.VTableHeaders[0].Table.Select(x => x.MetadataToken)); } }