public int ReserveDynamicEntry(ulong ownerGuestAddress, bool isJump) { int entry = DynTable.AllocateEntry(); ExpandIfNeededDynamicTable(entry); // Keep track of ownership for jump table entries. List <int> ownerEntries = Owners.GetOrAdd(ownerGuestAddress, (addr) => new List <int>()); lock (ownerEntries) { ownerEntries.Add(entry | DynamicEntryTag); } // Initialize all host function pointers to the indirect call stub. IntPtr addr = GetEntryAddressDynamicTable(entry); long stubPtr = DirectCallStubs.IndirectCallStub(isJump).ToInt64(); for (int i = 0; i < DynamicTableElems; i++) { Marshal.WriteInt64(addr, i * JumpTableStride + 8, stubPtr); } return(entry); }
public void ReadJumpTable(JumpTable jumpTable) { // Reads in-memory jump table state and store internally for PtcJumpTable serialization. _jumpTable.Clear(); IEnumerable <int> entries = jumpTable.Table.GetEntries(); foreach (int entry in entries) { IntPtr addr = jumpTable.GetEntryAddressJumpTable(entry); long guestAddress = Marshal.ReadInt64(addr, 0); long hostAddress = Marshal.ReadInt64(addr, 8); DirectHostAddress directHostAddress; if (hostAddress == DirectCallStubs.DirectCallStub(false).ToInt64()) { directHostAddress = DirectHostAddress.CallStub; } else if (hostAddress == DirectCallStubs.DirectCallStub(true).ToInt64()) { directHostAddress = DirectHostAddress.TailCallStub; } else { directHostAddress = DirectHostAddress.Host; } _jumpTable.Add(new TableEntry <DirectHostAddress>(entry, guestAddress, directHostAddress)); } }
public void ReadDynamicTable(JumpTable jumpTable) { if (JumpTable.DynamicTableElems > 1) { throw new NotSupportedException(); } _dynamicTable.Clear(); for (int entry = 1; entry <= jumpTable.DynTableEnd; entry++) { IntPtr addr = jumpTable.GetEntryAddressDynamicTable(entry); long guestAddress = Marshal.ReadInt64(addr, 0); long hostAddress = Marshal.ReadInt64(addr, 8); IndirectHostAddress indirectHostAddress; if (hostAddress == DirectCallStubs.IndirectCallStub(false).ToInt64()) { indirectHostAddress = IndirectHostAddress.CallStub; } else if (hostAddress == DirectCallStubs.IndirectCallStub(true).ToInt64()) { indirectHostAddress = IndirectHostAddress.TailCallStub; } else { throw new InvalidOperationException($"({nameof(hostAddress)} = 0x{hostAddress:X16})"); } _dynamicTable.Add(new KeyValuePair <long, IndirectHostAddress>(guestAddress, indirectHostAddress)); } }
public void ReadJumpTable(JumpTable jumpTable) { _jumpTable.Clear(); for (int entry = 1; entry <= jumpTable.TableEnd; entry++) { IntPtr addr = jumpTable.GetEntryAddressJumpTable(entry); long guestAddress = Marshal.ReadInt64(addr, 0); long hostAddress = Marshal.ReadInt64(addr, 8); DirectHostAddress directHostAddress; if (hostAddress == DirectCallStubs.DirectCallStub(false).ToInt64()) { directHostAddress = DirectHostAddress.CallStub; } else if (hostAddress == DirectCallStubs.DirectCallStub(true).ToInt64()) { directHostAddress = DirectHostAddress.TailCallStub; } else { directHostAddress = DirectHostAddress.Host; } _jumpTable.Add(new KeyValuePair <long, DirectHostAddress>(guestAddress, directHostAddress)); } }
public void WriteJumpTable(JumpTable jumpTable, ConcurrentDictionary <ulong, TranslatedFunction> funcs) { // Writes internal state to jump table in-memory, after PtcJumpTable was deserialized. foreach (var tableEntry in _jumpTable) { long guestAddress = tableEntry.GuestAddress; DirectHostAddress directHostAddress = tableEntry.HostAddress; long hostAddress; if (directHostAddress == DirectHostAddress.CallStub) { hostAddress = DirectCallStubs.DirectCallStub(false).ToInt64(); } else if (directHostAddress == DirectHostAddress.TailCallStub) { hostAddress = DirectCallStubs.DirectCallStub(true).ToInt64(); } else if (directHostAddress == DirectHostAddress.Host) { if (funcs.TryGetValue((ulong)guestAddress, out TranslatedFunction func)) { hostAddress = func.FuncPtr.ToInt64(); } else { if (!PtcProfiler.ProfiledFuncs.TryGetValue((ulong)guestAddress, out var value) || !value.HighCq) { throw new KeyNotFoundException($"({nameof(guestAddress)} = 0x{(ulong)guestAddress:X16})"); } hostAddress = 0L; } } else { throw new InvalidOperationException(nameof(directHostAddress)); } int entry = tableEntry.EntryIndex; jumpTable.Table.SetEntry(entry); jumpTable.ExpandIfNeededJumpTable(entry); IntPtr addr = jumpTable.GetEntryAddressJumpTable(entry); Marshal.WriteInt64(addr, 0, guestAddress); Marshal.WriteInt64(addr, 8, hostAddress); } }
public void WriteJumpTable(JumpTable jumpTable, ConcurrentDictionary <ulong, TranslatedFunction> funcs) { jumpTable.ExpandIfNeededJumpTable(TableEnd); int entry = 0; foreach (var item in _jumpTable) { entry += 1; long guestAddress = item.Key; DirectHostAddress directHostAddress = item.Value; long hostAddress; if (directHostAddress == DirectHostAddress.CallStub) { hostAddress = DirectCallStubs.DirectCallStub(false).ToInt64(); } else if (directHostAddress == DirectHostAddress.TailCallStub) { hostAddress = DirectCallStubs.DirectCallStub(true).ToInt64(); } else if (directHostAddress == DirectHostAddress.Host) { if (funcs.TryGetValue((ulong)guestAddress, out TranslatedFunction func)) { hostAddress = func.FuncPtr.ToInt64(); } else { throw new KeyNotFoundException($"({nameof(guestAddress)} = 0x{(ulong)guestAddress:X16})"); } } else { throw new InvalidOperationException(nameof(directHostAddress)); } IntPtr addr = jumpTable.GetEntryAddressJumpTable(entry); Marshal.WriteInt64(addr, 0, guestAddress); Marshal.WriteInt64(addr, 8, hostAddress); } }
public void WriteDynamicTable(JumpTable jumpTable) { // Writes internal state to jump table in-memory, after PtcJumpTable was deserialized. if (JumpTable.DynamicTableElems > 1) { throw new NotSupportedException(); } foreach (var tableEntry in _dynamicTable) { long guestAddress = tableEntry.GuestAddress; IndirectHostAddress indirectHostAddress = tableEntry.HostAddress; long hostAddress; if (indirectHostAddress == IndirectHostAddress.CallStub) { hostAddress = DirectCallStubs.IndirectCallStub(false).ToInt64(); } else if (indirectHostAddress == IndirectHostAddress.TailCallStub) { hostAddress = DirectCallStubs.IndirectCallStub(true).ToInt64(); } else { throw new InvalidOperationException(nameof(indirectHostAddress)); } int entry = tableEntry.EntryIndex; jumpTable.DynTable.SetEntry(entry); jumpTable.ExpandIfNeededDynamicTable(entry); IntPtr addr = jumpTable.GetEntryAddressDynamicTable(entry); Marshal.WriteInt64(addr, 0, guestAddress); Marshal.WriteInt64(addr, 8, hostAddress); } }
public void WriteDynamicTable(JumpTable jumpTable) { if (JumpTable.DynamicTableElems > 1) { throw new NotSupportedException(); } jumpTable.ExpandIfNeededDynamicTable(DynTableEnd); int entry = 0; foreach (var item in _dynamicTable) { entry += 1; long guestAddress = item.Key; IndirectHostAddress indirectHostAddress = item.Value; long hostAddress; if (indirectHostAddress == IndirectHostAddress.CallStub) { hostAddress = DirectCallStubs.IndirectCallStub(false).ToInt64(); } else if (indirectHostAddress == IndirectHostAddress.TailCallStub) { hostAddress = DirectCallStubs.IndirectCallStub(true).ToInt64(); } else { throw new InvalidOperationException(nameof(indirectHostAddress)); } IntPtr addr = jumpTable.GetEntryAddressDynamicTable(entry); Marshal.WriteInt64(addr, 0, guestAddress); Marshal.WriteInt64(addr, 8, hostAddress); } }
public void ReadDynamicTable(JumpTable jumpTable) { // Reads in-memory jump table state and store internally for PtcJumpTable serialization. if (JumpTable.DynamicTableElems > 1) { throw new NotSupportedException(); } _dynamicTable.Clear(); IEnumerable <int> entries = jumpTable.DynTable.GetEntries(); foreach (int entry in entries) { IntPtr addr = jumpTable.GetEntryAddressDynamicTable(entry); long guestAddress = Marshal.ReadInt64(addr, 0); long hostAddress = Marshal.ReadInt64(addr, 8); IndirectHostAddress indirectHostAddress; if (hostAddress == DirectCallStubs.IndirectCallStub(false).ToInt64()) { indirectHostAddress = IndirectHostAddress.CallStub; } else if (hostAddress == DirectCallStubs.IndirectCallStub(true).ToInt64()) { indirectHostAddress = IndirectHostAddress.TailCallStub; } else { throw new InvalidOperationException($"({nameof(hostAddress)} = 0x{hostAddress:X16})"); } _dynamicTable.Add(new TableEntry <IndirectHostAddress>(entry, guestAddress, indirectHostAddress)); } }
public int ReserveTableEntry(ulong ownerGuestAddress, ulong address, bool isJump) { int entry = Table.AllocateEntry(); ExpandIfNeededJumpTable(entry); // Is the address we have already registered? If so, put the function address in the jump table. // If not, it will point to the direct call stub. long value = DirectCallStubs.DirectCallStub(isJump).ToInt64(); if (Targets.TryGetValue(address, out TranslatedFunction func)) { value = func.FuncPtr.ToInt64(); } // Make sure changes to the function at the target address update this jump table entry. List <int> targetDependants = Dependants.GetOrAdd(address, (addr) => new List <int>()); lock (targetDependants) { targetDependants.Add(entry); } // Keep track of ownership for jump table entries. List <int> ownerEntries = Owners.GetOrAdd(ownerGuestAddress, (addr) => new List <int>()); lock (ownerEntries) { ownerEntries.Add(entry); } IntPtr addr = GetEntryAddressJumpTable(entry); Marshal.WriteInt64(addr, 0, (long)address); Marshal.WriteInt64(addr, 8, value); return(entry); }