Example #1
0
        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));
            }
        }