internal static VTableFixupEntry Load(IBinaryAccessor accessor, PEImage pe)
        {
            var fixup = new VTableFixupEntry();

            // In this definition, RVA points to the location of the v-table slot containing the method token(s).
            uint rva = accessor.ReadUInt32();

            // Indicating the number of v-table slots grouped into one entry because their flags are identical.
            // This grouping has no effect other than saving some space�you can emit a single slot per entry,
            // but then you�ll have to emit as many v-table fixups as there are slots.
            int count = accessor.ReadUInt16();

            fixup._type = (VTableFixupType)accessor.ReadUInt16();

            bool is32Bits = ((fixup.Type & VTableFixupType.SlotSize32Bit) == VTableFixupType.SlotSize32Bit);

            // Save position
            long position = accessor.Position;

            accessor.Position = pe.ResolvePositionToSectionData(rva);
            for (int i = 0; i < count; i++)
            {
                fixup._list.Add(accessor.ReadInt32());

                if (!is32Bits)
                {
                    accessor.ReadUInt32();
                }
            }

            // Restore position
            accessor.Position = position;

            return(fixup);
        }
        private void BuildAMD64(BuildEntry entry)
        {
            int methodRID = _state.MethodDefHash.IndexOf(entry.MethodSignature) + 1;

            // Add fixup entry
            var fixup = new VTableFixupEntry();

            fixup.Type = VTableFixupType.SlotSize64Bit | VTableFixupType.FromUnmanaged;
            fixup.Add(MetadataToken.Get(MetadataTokenType.Method, methodRID));
            _state.VTableFixupTable.Add(fixup);

            int pos = _codeBlob.Length;

            if (pos > 0)
            {
                pos = pos.Align(0x10);
            }

            PE.Fixups.Add(new AMD64Fixup(_codeBlob, pos, fixup));

            // rex.w rex.b mov rax,[following address]
            _state.ExportTable.AddRVAEntry(entry.MethodName, _codeBlob, pos);
            _codeBlob.Write(ref pos, new byte[] { 0x48, 0xA1 });

            // VA of method (through VTable)
            _state.RelocTable.Add(_codeBlob, pos, BaseRelocationType.DIR64);
            _codeBlob.Write(ref pos, (ulong)0);

            // jmp [rax]
            _codeBlob.Write(ref pos, new byte[] { 0xFF, 0xE0 });
        }
        private void BuildX86(BuildEntry entry)
        {
            int methodRID = _state.MethodDefHash.IndexOf(entry.MethodSignature) + 1;

            // Add fixup entry
            var fixup = new VTableFixupEntry();

            fixup.Type = VTableFixupType.SlotSize32Bit | VTableFixupType.FromUnmanaged;
            fixup.Add(MetadataToken.Get(MetadataTokenType.Method, methodRID));
            _state.VTableFixupTable.Add(fixup);

            int pos = _codeBlob.Length;

            if (pos > 0)
            {
                pos = pos.Align(0x10);
            }

            PE.Fixups.Add(new X86Fixup(_codeBlob, pos, fixup));

            // jmp
            _state.ExportTable.AddRVAEntry(entry.MethodName, _codeBlob, pos);
            _codeBlob.Write(ref pos, new byte[] { 0xFF, 0x25 });

            // VA of method (through VTable)
            _state.RelocTable.Add(_codeBlob, pos, BaseRelocationType.HIGHLOW);
            _codeBlob.Write(ref pos, (uint)0);
        }
        public VTableFixupEntry Clone()
        {
            var copy = new VTableFixupEntry();

            CopyTo(copy);

            return(copy);
        }
        protected void CopyTo(VTableFixupEntry copy)
        {
            copy._type = _type;

            foreach (var childNode in _list)
            {
                copy._list.Add(childNode);
            }
        }
        public int GetFixupOffset(VTableFixupEntry searchFixup)
        {
            int offset = 0;

            foreach (var fixup in _table)
            {
                if (object.ReferenceEquals(fixup, searchFixup))
                {
                    return(offset);
                }

                int size = ((fixup.Type & VTableFixupType.SlotSize32Bit) == VTableFixupType.SlotSize32Bit) ? 4 : 8;
                offset += (fixup.Count * size);
            }

            throw new InvalidOperationException();
        }
        private void BuildIA64(BuildEntry entry)
        {
            int methodRID = _state.MethodDefHash.IndexOf(entry.MethodSignature) + 1;

            // Add fixup entry
            var fixup = new VTableFixupEntry();

            fixup.Type = VTableFixupType.SlotSize64Bit | VTableFixupType.FromUnmanaged;
            fixup.Add(MetadataToken.Get(MetadataTokenType.Method, methodRID));
            _state.VTableFixupTable.Add(fixup);

            int pos = _codeBlob.Length;

            if (pos > 0)
            {
                pos = pos.Align(0x10);
            }

            PE.Fixups.Add(new IA64Fixup(_codeBlob, pos, fixup));

            // IA64 stub
            // ld8    r9  = [gp]    ;;
            // ld8    r10 = [r9],8
            // nop.i                ;;
            // ld8    gp  = [r9]
            // mov    b6  = r10
            // br.cond.sptk.few  b6
            _codeBlob.Write(ref pos,
                            new byte[]
            {
                0x0B, 0x48, 0x00, 0x02, 0x18, 0x10, 0xA0, 0x40,
                0x24, 0x30, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00,
                0x10, 0x08, 0x00, 0x12, 0x18, 0x10, 0x60, 0x50,
                0x04, 0x80, 0x03, 0x00, 0x60, 0x00, 0x80, 0x00,
            });

            // VA of IA64 stub
            _state.ExportTable.AddRVAEntry(entry.MethodName, _codeBlob, pos);
            _state.RelocTable.Add(_codeBlob, pos, BaseRelocationType.DIR64);
            _codeBlob.Write(ref pos, (ulong)0);

            // VA of method (through VTable)
            _state.RelocTable.Add(_codeBlob, pos, BaseRelocationType.DIR64);
            _codeBlob.Write(ref pos, (ulong)0);
        }
 public AMD64Fixup(BuildBlob codeBlob, int codeBlobPos, VTableFixupEntry fixup)
 {
     _codeBlob    = codeBlob;
     _codeBlobPos = codeBlobPos;
     _fixup       = fixup;
 }