/// <summary> /// Allocates a block of memory from the default process heap. /// </summary> /// <param name="size">The size of the memory to allocate.</param> /// <param name="allocationFlags">The memory allocation flags.</param> /// <returns>A pointer to the allocated block of memory.</returns> public static IntPtr Allocate(ulong size, MemoryAllocationFlags allocationFlags) { if (hHeap == IntPtr.Zero) { InitializeHeap(); } bool zeroFill = (allocationFlags & MemoryAllocationFlags.ZeroFill) == MemoryAllocationFlags.ZeroFill; IntPtr block = SafeNativeMethods.HeapAlloc(hHeap, zeroFill ? NativeConstants.HEAP_ZERO_MEMORY : 0U, new UIntPtr(size)); if (block == IntPtr.Zero) { if ((allocationFlags & MemoryAllocationFlags.ReturnZeroOnOutOfMemory) == MemoryAllocationFlags.ReturnZeroOnOutOfMemory) { return(IntPtr.Zero); } else { throw new OutOfMemoryException(); } } if (size > 0L) { GC.AddMemoryPressure((long)size); } return(block); }
/// <summary> /// Creates a new instance of the memory block class. /// </summary> /// <param name="size">Size of the memory block in bytes</param> /// <param name="flags">Flags that controls memory block memory allocation</param> /// <exception cref="OutOfMemoryException">Throw when there's no enough memory to allocate the requested size</exception> /// <exception cref="PlatformNotSupportedException">Throw when the current platform is not supported</exception> public MemoryBlock(ulong size, MemoryAllocationFlags flags = MemoryAllocationFlags.None) { if (flags.HasFlag(MemoryAllocationFlags.Mirrorable)) { _sharedMemory = MemoryManagement.CreateSharedMemory(size, flags.HasFlag(MemoryAllocationFlags.Reserve)); _pointer = MemoryManagement.MapSharedMemory(_sharedMemory, size); _usesSharedMemory = true; } else if (flags.HasFlag(MemoryAllocationFlags.Reserve)) { _viewCompatible = flags.HasFlag(MemoryAllocationFlags.ViewCompatible); _forceWindows4KBView = flags.HasFlag(MemoryAllocationFlags.ForceWindows4KBViewMapping); _pointer = MemoryManagement.Reserve(size, _viewCompatible); } else { _pointer = MemoryManagement.Allocate(size); } Size = size; _viewStorages = new ConcurrentDictionary <MemoryBlock, byte>(); _viewStorages.TryAdd(this, 0); _viewCount = 1; }
/// <summary> /// Creates a new instance of the host mapped memory manager. /// </summary> /// <param name="backingMemory">Physical backing memory where virtual memory will be mapped to</param> /// <param name="addressSpaceSize">Size of the address space</param> /// <param name="unsafeMode">True if unmanaged access should not be masked (unsafe), false otherwise.</param> /// <param name="invalidAccessHandler">Optional function to handle invalid memory accesses</param> public MemoryManagerHostMapped(MemoryBlock backingMemory, ulong addressSpaceSize, bool unsafeMode, InvalidAccessHandler invalidAccessHandler = null) { _backingMemory = backingMemory; _pageTable = new PageTable <ulong>(); _invalidAccessHandler = invalidAccessHandler; _unsafeMode = unsafeMode; _addressSpaceSize = addressSpaceSize; ulong asSize = PageSize; int asBits = PageBits; while (asSize < addressSpaceSize) { asSize <<= 1; asBits++; } AddressSpaceBits = asBits; _pageBitmap = new ulong[1 << (AddressSpaceBits - (PageBits + PageToPteShift))]; MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible; _addressSpace = new MemoryBlock(asSize, asFlags); _addressSpaceMirror = new MemoryBlock(asSize, asFlags | MemoryAllocationFlags.ForceWindows4KBViewMapping); Tracking = new MemoryTracking(this, PageSize, invalidAccessHandler); _memoryEh = new MemoryEhMeilleure(_addressSpace, Tracking); }
/// <summary> /// Reserves a region of memory within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">The handle to a process.</param> /// <param name="allocAddress">The rough address of where the allocation should take place.</param> /// <param name="size">The size of the region of memory to allocate, in bytes.</param> /// <param name="protectionFlags">The memory protection for the region of pages to be allocated.</param> /// <param name="allocationFlags">The type of memory allocation.</param> /// <returns>The base address of the allocated region</returns> public static IntPtr Allocate( IntPtr processHandle, IntPtr allocAddress, Int32 size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit | MemoryAllocationFlags.Reserve) { if (allocAddress != IntPtr.Zero) { /* A specific address has been given. We will modify it to support the following constraints: * - Aligned by 0x10000 / 65536 * - Pointing to an unallocated region of memory * - Within +/- 2GB (using 1GB for safety) of address space of the originally specified address, such as to always be in range of a far jump instruction * Note: A retry count has been put in place because VirtualAllocEx with an allocAddress specified may be invalid by the time we request the allocation. */ IntPtr result = IntPtr.Zero; Int32 retryCount = 0; // Request all chunks of unallocated memory. These will be very large in a 64-bit process. IEnumerable <MemoryBasicInformation64> freeMemory = Memory.QueryUnallocatedMemory( processHandle, allocAddress.Subtract(Int32.MaxValue >> 1, wrapAround: false), allocAddress.Add(Int32.MaxValue >> 1, wrapAround: false)); // Convert to normalized regions IEnumerable <NormalizedRegion> regions = freeMemory.Select(x => new NormalizedRegion(x.BaseAddress, x.RegionSize.ToInt32())); // Chunk the large regions into smaller regions based on the allocation size (minimum size is the alloc alignment to prevent creating too many chunks) List <NormalizedRegion> subRegions = new List <NormalizedRegion>(); foreach (NormalizedRegion region in regions) { region.BaseAddress = region.BaseAddress.Subtract(region.BaseAddress.Mod(Memory.AllocAlignment), wrapAround: false); IEnumerable <NormalizedRegion> chunkedRegions = region.ChunkNormalizedRegion(Math.Max(size, Memory.AllocAlignment)).Take(128).Where(x => x.RegionSize >= size); subRegions.AddRange(chunkedRegions); } do { // Sample a random chunk and attempt to allocate the memory result = subRegions.ElementAt(StaticRandom.Next(0, subRegions.Count())).BaseAddress; result = NativeMethods.VirtualAllocEx(processHandle, result, size, allocationFlags, protectionFlags); if (result != IntPtr.Zero || retryCount >= Memory.AllocateRetryCount) { break; } retryCount++; }while (result == IntPtr.Zero); return(result); } else { // Allocate a memory page return(NativeMethods.VirtualAllocEx(processHandle, allocAddress, size, allocationFlags, protectionFlags)); } }
public MemoryAllocation(IntPtr handle, int size, MemoryAllocationFlags memoryAllocationFlag = MemoryAllocationFlags.Commit, MemoryProtectionFlags memoryProtectionFlag = MemoryProtectionFlags.ExecuteReadWrite) { this.Handle = handle; this.Size = size; this.MemoryAllocationFlag = memoryAllocationFlag; this.MemoryProtectionFlag = memoryProtectionFlag; }
private (MemoryBlock virt, MemoryBlock mirror, MemoryEhMeilleure exceptionHandler) GetVirtual(ulong asSize) { MemoryAllocationFlags asFlags = MemoryAllocationFlags.Reserve | MemoryAllocationFlags.ViewCompatible; var addressSpace = new MemoryBlock(asSize, asFlags); var addressSpaceMirror = new MemoryBlock(asSize, asFlags); var tracking = new MemoryTracking(new MockVirtualMemoryManager(asSize, 0x1000), 0x1000); var exceptionHandler = new MemoryEhMeilleure(addressSpace, addressSpaceMirror, tracking); return(addressSpace, addressSpaceMirror, exceptionHandler); }
/// <summary> /// Initializes a new instance of the memory block class. /// </summary> /// <param name="size">Size of the memory block</param> /// <param name="flags">Flags that controls memory block memory allocation</param> /// <exception cref="OutOfMemoryException">Throw when there's no enough memory to allocate the requested size</exception> /// <exception cref="PlatformNotSupportedException">Throw when the current platform is not supported</exception> public MemoryBlock(ulong size, MemoryAllocationFlags flags = MemoryAllocationFlags.None) { if (flags.HasFlag(MemoryAllocationFlags.Reserve)) { _pointer = MemoryManagement.Reserve(size); } else { _pointer = MemoryManagement.Allocate(size); } Size = size; }
/// <summary> /// Checks if the specified memory allocation flags are supported on the current platform. /// </summary> /// <param name="flags">Flags to be checked</param> /// <returns>True if the platform supports all the flags, false otherwise</returns> public static bool SupportsFlags(MemoryAllocationFlags flags) { if (flags.HasFlag(MemoryAllocationFlags.ViewCompatible)) { if (OperatingSystem.IsWindows()) { return(OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134)); } return(OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()); } return(true); }
/// <summary> /// Reserves a region of memory within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">The handle to a process.</param> /// <param name="size">The size of the region of memory to allocate, in bytes.</param> /// <param name="protectionFlags">The memory protection for the region of pages to be allocated.</param> /// <param name="allocationFlags">The type of memory allocation.</param> /// <returns>The base address of the allocated region.</returns> public static IntPtr Allocate(SafeMemoryHandle processHandle, int size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Allocate a memory page var ret = NativeMethods.VirtualAllocEx(processHandle, IntPtr.Zero, size, allocationFlags, protectionFlags); // Check whether the memory page is valid if (ret != IntPtr.Zero) return ret; // If the pointer isn't valid, throws an exception throw new Win32Exception(string.Format("Couldn't allocate memory of {0} byte(s).", size)); }
/// <summary> /// Reserves a region of memory within the virtual address space of a specified process. /// </summary> /// <param name="processHandle">The handle to a process.</param> /// <param name="size">The size of the region of memory to allocate, in bytes.</param> /// <param name="protectionFlags">The memory protection for the region of pages to be allocated.</param> /// <param name="allocationFlags">The type of memory allocation.</param> /// <returns>The base address of the allocated region.</returns> public static IntPtr Allocate(SafeMemoryHandle processHandle, int size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit) { // Check if the handle is valid HandleManipulator.ValidateAsArgument(processHandle, "processHandle"); // Allocate a memory page var ret = NativeMethods.VirtualAllocEx(processHandle, IntPtr.Zero, size, allocationFlags, protectionFlags); // Check whether the memory page is valid if (ret != IntPtr.Zero) { return(ret); } // If the pointer isn't valid, throws an exception throw new Win32Exception(string.Format("Couldn't allocate memory of {0} byte(s).", size)); }
public Switch(HLEConfiguration configuration) { if (configuration.GpuRenderer == null) { throw new ArgumentNullException(nameof(configuration.GpuRenderer)); } if (configuration.AudioDeviceDriver == null) { throw new ArgumentNullException(nameof(configuration.AudioDeviceDriver)); } if (configuration.UserChannelPersistence == null) { throw new ArgumentNullException(nameof(configuration.UserChannelPersistence)); } Configuration = configuration; FileSystem = Configuration.VirtualFileSystem; UiHandler = Configuration.HostUiHandler; MemoryAllocationFlags memoryAllocationFlags = configuration.MemoryManagerMode == MemoryManagerMode.SoftwarePageTable ? MemoryAllocationFlags.Reserve : MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable; AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver); Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags); Gpu = new GpuContext(Configuration.GpuRenderer); System = new Horizon(this); Statistics = new PerformanceStatistics(); Hid = new Hid(this, System.HidStorage); Application = new ApplicationLoader(this); TamperMachine = new TamperMachine(); System.State.SetLanguage(Configuration.SystemLanguage); System.State.SetRegion(Configuration.Region); EnableDeviceVsync = Configuration.EnableVsync; System.State.DockedMode = Configuration.EnableDockedMode; System.PerformanceState.PerformanceMode = System.State.DockedMode ? PerformanceMode.Boost : PerformanceMode.Default; System.EnablePtc = Configuration.EnablePtc; System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel; System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode; }
/// <summary> /// Creates a new instance of the memory block class. /// </summary> /// <param name="size">Size of the memory block in bytes</param> /// <param name="flags">Flags that controls memory block memory allocation</param> /// <exception cref="OutOfMemoryException">Throw when there's no enough memory to allocate the requested size</exception> /// <exception cref="PlatformNotSupportedException">Throw when the current platform is not supported</exception> public MemoryBlock(ulong size, MemoryAllocationFlags flags = MemoryAllocationFlags.None) { if (flags.HasFlag(MemoryAllocationFlags.Mirrorable)) { _sharedMemory = MemoryManagement.CreateSharedMemory(size, flags.HasFlag(MemoryAllocationFlags.Reserve)); _pointer = MemoryManagement.MapSharedMemory(_sharedMemory); _usesSharedMemory = true; } else if (flags.HasFlag(MemoryAllocationFlags.Reserve)) { _pointer = MemoryManagement.Reserve(size); } else { _pointer = MemoryManagement.Allocate(size); } Size = size; }
public JitMemoryBlock(ulong size, MemoryAllocationFlags flags) { _impl = new MemoryBlock(size, flags); }
public static extern IntPtr VirtualAllocEx(SafeMemoryHandle hProcess, IntPtr lpAddress, int dwSize, MemoryAllocationFlags flAllocationType, MemoryProtectionFlags flProtect);
internal static extern IntPtr VirtualAlloc(IntPtr baseAddress, UIntPtr size, MemoryAllocationFlags allocationType, MemoryProtectionFlags protection);
public static IntPtr Allocate(SafeMemoryHandle handle, int size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit) { var address = IntPtr.Zero; var regionSize = new IntPtr(size); if (NativeMethods.NtAllocateVirtualMemory(handle, ref address, 0x7FFF_FFFF, ref regionSize, allocationFlags, protectionFlags) == 0) { return(address); } return(NativeMethods.VirtualAllocEx(handle, IntPtr.Zero, size, allocationFlags, protectionFlags)); }
public static extern uint NtAllocateVirtualMemory(SafeMemoryHandle processHandle, [In, Out] ref IntPtr baseAddress, uint zeroBits, [In, Out] ref IntPtr regionSize, MemoryAllocationFlags allocationType, MemoryProtectionFlags protect);
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, Int32 dwSize, MemoryAllocationFlags flAllocationType, MemoryProtectionFlags flProtect);
public static IntPtr Allocate(SafeMemoryHandle handle, long size, MemoryProtectionFlags protectionFlags = MemoryProtectionFlags.ExecuteReadWrite, MemoryAllocationFlags allocationFlags = MemoryAllocationFlags.Commit) { return(NativeMethods.VirtualAllocEx(handle, IntPtr.Zero, size, allocationFlags, protectionFlags)); }