private MemoryMappedView(SafeMemoryMappedViewHandle viewHandle, long pointerOffset, long size, MemoryMappedFileAccess access) { this.m_viewHandle = viewHandle; this.m_pointerOffset = pointerOffset; this.m_size = size; this.m_access = access; }
private unsafe MemoryMappedView(SafeMemoryMappedViewHandle viewHandle, long pointerOffset, long size, MemoryMappedFileAccess access) { _viewHandle = viewHandle; _pointerOffset = pointerOffset; _size = size; _access = access; }
private unsafe MemoryMappedView(SafeMemoryMappedViewHandle viewHandle, Int64 pointerOffset, Int64 size, MemoryMappedFileAccess access) { m_viewHandle = viewHandle; m_pointerOffset = pointerOffset; m_size = size; m_access = access; }
/// <summary> /// Initialization of SafeMemoryMappedViewHandle by the filePath /// </summary> /// <param name="dumpFileName">full path to dump file</param> public void Init(string dumpFileName) { using (FileStream fileStream = File.Open(dumpFileName, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read)) { _safeMemoryMappedViewHandle = MemoryMapFileHandler.MapFile(fileStream, dumpFileName); GetSystemInfo(); } }
unsafe void CreatePosix (long offset, long size, MemoryMappedFileAccess access) { int offset_diff; MemoryMappedFile.MapPosix (file_handle, offset, ref size, access, out mmap_addr, out offset_diff); handle = new SafeMemoryMappedViewHandle ((IntPtr)((long)mmap_addr + offset_diff), size); Initialize (handle, 0, size, ToFileAccess (access)); }
unsafe void Create (IntPtr handle, long offset, long size, MemoryMappedFileAccess access) { IntPtr base_address; MemoryMapImpl.Map (handle, offset, ref size, access, out mmap_handle, out base_address); safe_handle = new SafeMemoryMappedViewHandle (mmap_handle, base_address, size); Initialize (safe_handle, 0, size, ToFileAccess (access)); }
unsafe void CreatePosix (FileStream file, long offset, long size, MemoryMappedFileAccess access) { long fsize = file.Length; if (size == 0 || size > fsize) size = fsize; int offset_diff; MemoryMappedFile.MapPosix (file, offset, size, access, out mmap_addr, out offset_diff, out mmap_size); handle = new SafeMemoryMappedViewHandle ((IntPtr)((long)mmap_addr + offset_diff), size); }
internal unsafe static MemoryMappedView Create (IntPtr handle, long offset, long size, MemoryMappedFileAccess access) { IntPtr base_address; IntPtr mmap_handle; MemoryMapImpl.Map (handle, offset, ref size, access, out mmap_handle, out base_address); var safe_handle = new SafeMemoryMappedViewHandle (mmap_handle, base_address, size); // MemoryMapImpl.Map returns a base_address to the offset so MemoryMappedView is initiated // no offset. return new MemoryMappedView (safe_handle, 0, size, access); }
/// <summary> /// Initialization of SafeMemoryMappedViewHandle by PID of live process /// </summary> /// <param name="pid">PID of life process</param> public void Init(uint pid) { var handle = Kernel32.Functions.OpenProcess(Kernel32.ProcessAccessFlags.All, false, pid); RecheckDirectory(); string fileName = null; string fullfileName = GetDumpFileName(pid, ref fileName); using (FileStream fs = new FileStream(fullfileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Write)) { bool miniDumpCreated = Functions.MiniDumpWriteDump(handle, pid, fs.SafeFileHandle, MINIDUMP_TYPE.MiniDumpWithHandleData, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (miniDumpCreated) { _safeMemoryMappedViewHandle = MemoryMapFileHandler.MapFile(fs, fileName); } } }
internal extern static UIntPtr VirtualQuery(SafeMemoryMappedViewHandle lpAddress, ref MEMORY_BASIC_INFORMATION lpBuffer, UIntPtr dwLength);
private MemoryMappedView(SafeMemoryMappedViewHandle handle, long offset, long size) { this._handle = handle; this._offset = offset; this._size = size; }
internal static extern IntPtr VirtualQuery(SafeMemoryMappedViewHandle address, ref MEMORY_BASIC_INFORMATION buffer, IntPtr sizeOfBuffer);
internal static extern IntPtr VirtualAlloc(SafeMemoryMappedViewHandle address, UIntPtr numBytes, int commitOrReserve, int pageProtectionMode);
public unsafe static MemoryMappedView CreateView( SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, long requestedOffset, long requestedSize) { if (requestedOffset > memMappedFileHandle._capacity) { throw new ArgumentOutOfRangeException("offset"); } if (requestedSize > MaxProcessAddressSpace) { throw new IOException(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed); } if (requestedOffset + requestedSize > memMappedFileHandle._capacity) { throw new UnauthorizedAccessException(); } if (memMappedFileHandle.IsClosed) { throw new ObjectDisposedException(typeof(MemoryMappedFile).Name); } if (requestedSize == MemoryMappedFile.DefaultSize) { requestedSize = memMappedFileHandle._capacity - requestedOffset; } // mmap can only create views that start at a multiple of the page size. As on Windows, // we hide this restriction form the user by creating larger views than the user requested and hiding the parts // that the user did not request. extraMemNeeded is the amount of extra memory we allocate before the start of the // requested view. (mmap may round up the actual length such that it is also page-aligned; we hide that by using // the right size and not extending the size to be page-aligned.) ulong nativeSize; long extraMemNeeded, nativeOffset; long pageSize = Interop.Sys.SysConf(Interop.Sys.SysConfName._SC_PAGESIZE); Debug.Assert(pageSize > 0); ValidateSizeAndOffset( requestedSize, requestedOffset, pageSize, out nativeSize, out extraMemNeeded, out nativeOffset); // Determine whether to create the pages as private or as shared; the former is used for copy-on-write. Interop.Sys.MemoryMappedFlags flags = (memMappedFileHandle._access == MemoryMappedFileAccess.CopyOnWrite || access == MemoryMappedFileAccess.CopyOnWrite) ? Interop.Sys.MemoryMappedFlags.MAP_PRIVATE : Interop.Sys.MemoryMappedFlags.MAP_SHARED; // If we have a file handle, get the file descriptor from it. If the handle is null, // we'll use an anonymous backing store for the map. SafeFileHandle fd; if (memMappedFileHandle._fileStream != null) { // Get the file descriptor from the SafeFileHandle fd = memMappedFileHandle._fileStream.SafeFileHandle; Debug.Assert(!fd.IsInvalid); } else { fd = new SafeFileHandle(new IntPtr(-1), false); flags |= Interop.Sys.MemoryMappedFlags.MAP_ANONYMOUS; } // Nothing to do for options.DelayAllocatePages, since we're only creating the map // with mmap when creating the view. // Verify that the requested view permissions don't exceed the map's permissions Interop.Sys.MemoryMappedProtections viewProtForVerification = GetProtections(access, forVerification: true); Interop.Sys.MemoryMappedProtections mapProtForVerification = GetProtections(memMappedFileHandle._access, forVerification: true); if ((viewProtForVerification & mapProtForVerification) != viewProtForVerification) { throw new UnauthorizedAccessException(); } // viewProtections is strictly less than mapProtections, so use viewProtections for actually creating the map. Interop.Sys.MemoryMappedProtections viewProtForCreation = GetProtections(access, forVerification: false); // Create the map IntPtr addr = IntPtr.Zero; if (nativeSize > 0) { addr = Interop.Sys.MMap( IntPtr.Zero, // don't specify an address; let the system choose one nativeSize, // specify the rounded-size we computed so as to page align; size + extraMemNeeded viewProtForCreation, flags, fd, // mmap adds a ref count to the fd, so there's no need to dup it. nativeOffset); // specify the rounded-offset we computed so as to page align; offset - extraMemNeeded } else { // There are some corner cases where the .NET API allows the requested size to be zero, e.g. the caller is // creating a map at the end of the capacity. We can't pass 0 to mmap, as that'll fail with EINVAL, nor can // we create a map that extends beyond the end of the underlying file, as that'll fail on some platforms at the // time of the map's creation. Instead, since there's no data to be read/written, it doesn't actually matter // what backs the view, so we just create an anonymous mapping. addr = Interop.Sys.MMap( IntPtr.Zero, 1, // any length that's greater than zero will suffice viewProtForCreation, flags | Interop.Sys.MemoryMappedFlags.MAP_ANONYMOUS, new SafeFileHandle(new IntPtr(-1), false), // ignore the actual fd even if there was one 0); requestedSize = 0; extraMemNeeded = 0; } if (addr == IntPtr.Zero) // note that shim uses null pointer, not non-null MAP_FAILED sentinel { throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo()); } // Based on the HandleInheritability, try to prevent the memory-mapped region // from being inherited by a forked process if (memMappedFileHandle._inheritability == HandleInheritability.None) { DisableForkingIfPossible(addr, nativeSize); } // Create and return the view handle var viewHandle = new SafeMemoryMappedViewHandle(addr, ownsHandle: true); viewHandle.Initialize((ulong)nativeSize); return new MemoryMappedView( viewHandle, extraMemNeeded, // the view points to offset - extraMemNeeded, so we need to shift back by extraMemNeeded requestedSize, // only allow access to the actual size requested access); }
void Dispose(bool disposeManagedResources) { if (this._handle != null && !this._handle.IsClosed) this._handle.Dispose(); this._handle = null; }
private Win32MemoryMappedFile(FileStream fs, SafeMemoryMappedFileHandle handle, ulong size) { Contract.Requires(fs != null && handle != null && !handle.IsInvalid && !handle.IsClosed); m_mapHandle = handle; m_file = fs; m_size = size; // verify that it fits on 32 bit OS... if (IntPtr.Size == 4 && size > uint.MaxValue) { // won't work with 32-bit pointers throw new InvalidOperationException("Memory mapped file size is too big to be opened on a 32-bit system."); } // verifiy that it will fit in the virtual address space of the process var totalVirtual = UnsafeNativeMethods.GetTotalVirtualAddressSpaceSize(); if (size > totalVirtual) { throw new InvalidOperationException("Memory mapped file size is too big to fit in the current process virtual address space"); } SafeMemoryMappedViewHandle view = null; byte* baseAddress = null; try { view = UnsafeNativeMethods.MapViewOfFile(m_mapHandle, UnsafeNativeMethods.FileMapAccess.FileMapRead, 0, 0, new UIntPtr(size)); if (view.IsInvalid) throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); view.Initialize(size); m_viewHandle = view; view.AcquirePointer(ref baseAddress); m_baseAddress = baseAddress; } catch { if (baseAddress != null) view.ReleasePointer(); if (view != null) view.Dispose(); m_file = null; m_viewHandle = null; m_mapHandle = null; m_baseAddress = null; throw; } }
private void Test(SafeMemoryMappedViewHandle mappedFileView) { MINIDUMP_HANDLE_DATA_STREAM handleData; IntPtr streamPointer; IntPtr baseOfView; uint streamSize; var readStrem = SafeMemoryMappedViewStreamHandler.ReadStream(MINIDUMP_STREAM_TYPE.HandleDataStream, out handleData, out streamPointer, out streamSize, mappedFileView, out baseOfView); Assert.AreNotEqual(streamPointer, IntPtr.Zero); Assert.AreNotEqual(baseOfView, IntPtr.Zero); Assert.AreNotEqual(handleData.SizeOfHeader, 0); Assert.IsNotNull(handleData); var descriptor2 = handleData.SizeOfDescriptor == Marshal.SizeOf(typeof(MINIDUMP_HANDLE_DESCRIPTOR_2)); var descriptor = handleData.SizeOfDescriptor == Marshal.SizeOf(typeof(MINIDUMP_HANDLE_DESCRIPTOR)); if(!descriptor && !descriptor2) { Assert.Fail($"SizeOfDescriptor isn't as expected {handleData.SizeOfDescriptor }"); } }
public unsafe static MemoryMappedView CreateView( SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, long requestedOffset, long requestedSize) { // If the requested size is either the default or if it's larger than the capacity // of the mapped file, reset it to be the capacity set when creating the mapped file. if (requestedSize == MemoryMappedFile.DefaultSize || requestedSize > memMappedFileHandle._capacity) { requestedSize = memMappedFileHandle._capacity; } Debug.Assert(requestedSize > 0); // mmap can only create views that start at a multiple of the page size. As on Windows, // we hide this restriction form the user by creating larger views than the user requested and hiding the parts // that the user did not request. extraMemNeeded is the amount of extra memory we allocate before the start of the // requested view. (mmap may round up the actual length such that it is also page-aligned; we hide that by using // the right size and not extending the size to be page-aligned.) ulong nativeSize, extraMemNeeded, nativeOffset; ValidateSizeAndOffset( requestedSize, requestedOffset, Interop.libc.sysconf(Interop.libc.SysConfNames._SC_PAGESIZE), out nativeSize, out extraMemNeeded, out nativeOffset); bool gotRefOnHandle = false; try { // Determine whether to create the pages as private or as shared; the former is used for copy-on-write. Interop.libc.MemoryMappedFlags flags = (memMappedFileHandle._access == MemoryMappedFileAccess.CopyOnWrite) ? Interop.libc.MemoryMappedFlags.MAP_PRIVATE : Interop.libc.MemoryMappedFlags.MAP_SHARED; // If we have a file handle, get the file descriptor from it. If the handle is null, // we'll use an anonymous backing store for the map. int fd; if (memMappedFileHandle._fileHandle != null) { // Get the file descriptor from the SafeFileHandle memMappedFileHandle._fileHandle.DangerousAddRef(ref gotRefOnHandle); Debug.Assert(gotRefOnHandle); fd = (int)memMappedFileHandle._fileHandle.DangerousGetHandle(); Debug.Assert(fd >= 0); } else { Debug.Assert(!gotRefOnHandle); fd = -1; flags |= Interop.libc.MemoryMappedFlags.MAP_ANONYMOUS; } // Nothing to do for options.DelayAllocatePages, since we're only creating the map // with mmap when creating the view. // Intersect the permissions from the creation of the MMF and the MMV. Interop.libc.MemoryMappedProtections prot = GetProtections(memMappedFileHandle._access); prot &= GetProtections(access); if (prot == 0) { throw new ArgumentOutOfRangeException("access"); } // Create the map IntPtr addr = Interop.libc.mmap( IntPtr.Zero, // don't specify an address; let the system choose one (IntPtr)nativeSize, // specify the rounded-size we computed so as to page align; size + extraMemNeeded prot, flags, fd, // mmap adds a ref count to the fd, so there's no need to dup it. (long)nativeOffset); // specify the rounded-offset we computed so as to page align; offset - extraMemNeeded if ((long)addr < 0) { throw Interop.GetExceptionForIoErrno(Marshal.GetLastWin32Error()); } // Based on the HandleInheritability, try to prevent the memory-mapped region // from being inherited by a forked process if (memMappedFileHandle._inheritability == HandleInheritability.None) { int adviseResult = Interop.libc.madvise(addr, (IntPtr)nativeSize, Interop.libc.MemoryMappedAdvice.MADV_DONTFORK); Debug.Assert(adviseResult == 0); // In release, ignore failures from advise; it's just a hint, anyway. } // Create and return the view handle var viewHandle = new SafeMemoryMappedViewHandle(addr, ownsHandle: true); viewHandle.Initialize(nativeSize); return new MemoryMappedView( viewHandle, (long)extraMemNeeded, // the view points to offset - extraMemNeeded, so we need to shift back by extraMemNeeded requestedSize, // only allow access to the actual size requested access); } finally { if (gotRefOnHandle) { memMappedFileHandle._fileHandle.DangerousRelease(); } } }