示例#1
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="start">The start of the memory range.</param>
        /// <param name="end">The end of the memory range.</param>
        public MemoryRange(ulong start, ulong end)
        {
            Start = start;
            End   = end;

            DebugOnly.Assert(start <= end);
        }
示例#2
0
        public DbgEngDataReader(string dumpFile)
        {
            if (!File.Exists(dumpFile))
            {
                throw new FileNotFoundException(dumpFile);
            }

            DisplayName = dumpFile;

            IntPtr pClient = CreateIDebugClient();

            CreateClient(pClient);
            HResult hr = _client.OpenDumpFile(dumpFile);

            if (hr != 0)
            {
                const int STATUS_MAPPED_FILE_SIZE_ZERO = unchecked ((int)0xC000011E);

                if (hr == HResult.E_INVALIDARG || hr == (STATUS_MAPPED_FILE_SIZE_ZERO | 0x10000000))
                {
                    throw new InvalidDataException($"'{dumpFile}' is not a crash dump.");
                }

                throw new ClrDiagnosticsException($"Could not load crash dump, HRESULT: {hr}", hr).AddData("DumpFile", dumpFile);
            }

            // This actually "attaches" to the crash dump.
            HResult result = _control.WaitForEvent(0xffffffff);

            _systemObjects.Init();
            DebugOnly.Assert(result);
        }
示例#3
0
        public bool ReadDword(ulong addr, out uint value)
        {
            uint size = 4;

            // Is addr on the current page?  If not read the page of memory addr is on.
            // If this fails, we will fall back to a raw read out of the process (which
            // is what MisalignedRead does).
            if (addr < _currPageStart || addr >= _currPageStart + (uint)_currPageSize)
            {
                if (!MoveToPage(addr))
                {
                    return(MisalignedRead(addr, out value));
                }
            }

            // If MoveToPage succeeds, we MUST be on the right page.
            DebugOnly.Assert(addr >= _currPageStart);

            // However, the amount of data requested may fall off of the page.  In that case,
            // fall back to MisalignedRead.
            ulong offset = addr - _currPageStart;

            if (offset + size > (uint)_currPageSize)
            {
                return(MisalignedRead(addr, out value));
            }

            // If we reach here we know we are on the right page of memory in the cache, and
            // that the read won't fall off of the end of the page.
            value = BitConverter.ToUInt32(_data, (int)offset);
            return(true);
        }
示例#4
0
        public IEnumerable <ModuleInfo> EnumerateModules()
        {
            EnumProcessModules(_process, null, 0, out uint needed);

            IntPtr[] modules = new IntPtr[needed / IntPtr.Size];

            if (!EnumProcessModules(_process, modules, needed, out _))
            {
                throw new InvalidOperationException("Unable to get process modules.");
            }

            List <ModuleInfo> result = new List <ModuleInfo>(modules.Length);

            for (int i = 0; i < modules.Length; i++)
            {
                IntPtr ptr = modules[i];

                StringBuilder sb  = new StringBuilder(1024);
                uint          res = GetModuleFileNameEx(_process, ptr, sb, sb.Capacity);
                DebugOnly.Assert(res != 0);

                ulong baseAddr = (ulong)ptr.ToInt64();
                GetFileProperties(baseAddr, out int filesize, out int timestamp);

                string     fileName = sb.ToString();
                ModuleInfo module   = new ModuleInfo(baseAddr, fileName, true, filesize, timestamp, ImmutableArray <byte> .Empty);
                result.Add(module);
            }

            return(result);
        }
示例#5
0
        private void Dispose(bool _)
        {
            if (!_disposed)
            {
                _suspension?.Dispose();

                if (_originalPid != 0)
                {
                    // We don't want to throw an exception when we fail to free a snapshot.  In practice we never expect this to fail.
                    // If we were able to create a snapshot we should be able to free it.  Throwing an exception here means that our
                    // DataTarget.Dispose call (normally at the end of a using statement) will throw, and that is really annoying
                    // to code around.  Instead we'll log a message to any Trace listener, but otherwise continue on.
                    int hr = PssFreeSnapshot(Process.GetCurrentProcess().Handle, _snapshotHandle);
                    DebugOnly.Assert(hr == 0);

                    if (hr != 0)
                    {
                        Trace.WriteLine($"Unable to free the snapshot of the process we took: hr={hr}");
                    }
                }

                if (_process != IntPtr.Zero)
                {
                    WindowsFunctions.NativeMethods.CloseHandle(_process);
                }

                _disposed = true;
            }
        }
示例#6
0
        private IntPtr CreateIDebugClient()
        {
            Guid guid = new Guid("27fe5639-8407-4f47-8364-ee118fb08ac8");
            int hr = DebugCreate(ref guid, out IntPtr ptr);
            DebugOnly.Assert(hr == 0);

            return ptr;
        }
示例#7
0
 public static unsafe ulong AsPointer(this Span <byte> span)
 {
     DebugOnly.Assert(span.Length >= IntPtr.Size);
     DebugOnly.Assert(unchecked ((int)Unsafe.AsPointer(ref MemoryMarshal.GetReference(span))) % IntPtr.Size == 0);
     return(IntPtr.Size == 4
         ? Unsafe.As <byte, uint>(ref MemoryMarshal.GetReference(span))
         : Unsafe.As <byte, ulong>(ref MemoryMarshal.GetReference(span)));
 }
示例#8
0
        internal ClrValueType(ulong address, ClrType type, bool interior)
        {
            Address   = address;
            Type      = type;
            _interior = interior;

            DebugOnly.Assert(type.IsValueType);
        }
示例#9
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="address">The address of the object.</param>
        /// <param name="type">The concrete type of the object.</param>
        public ClrObject(ulong address, ClrType?type)
        {
            Address = address;
            Type    = type;

            DebugOnly.Assert(address == 0 || type != null);
            DebugOnly.Assert(address == 0 || (type != null && type.Heap.GetObjectType(address) == type));
        }
示例#10
0
        public IEnumerable <(ulong ReferencedObject, int Offset)> WalkObject(byte[] buffer, int size)
        {
            DebugOnly.Assert(size >= IntPtr.Size);

            int series  = GetNumSeries();
            int highest = GetHighestSeries();
            int curr    = highest;

            if (series > 0)
            {
                int lowest = GetLowestSeries();
                do
                {
                    long offset = GetSeriesOffset(curr);
                    long stop   = offset + GetSeriesSize(curr) + size;

                    while (offset < stop)
                    {
                        ulong ret = new Span <byte>(buffer).AsPointer((int)offset);
                        if (ret != 0)
                        {
                            yield return(ret, (int)offset);
                        }

                        offset += IntPtr.Size;
                    }

                    curr -= s_GCDescSize;
                } while (curr >= lowest);
            }
            else
            {
                long offset = GetSeriesOffset(curr);

                while (offset < size - IntPtr.Size)
                {
                    for (int i = 0; i > series; i--)
                    {
                        int nptrs = GetPointers(curr, i);
                        int skip  = GetSkip(curr, i);

                        long stop = offset + (nptrs * IntPtr.Size);
                        do
                        {
                            ulong ret = new Span <byte>(buffer).AsPointer((int)offset);
                            if (ret != 0)
                            {
                                yield return(ret, (int)offset);
                            }

                            offset += IntPtr.Size;
                        } while (offset < stop);

                        offset += skip;
                    }
                }
            }
        }
示例#11
0
        public IEnumerable <(ulong, int)> WalkObject(ulong addr, ulong size, Func <ulong, ulong> readPointer)
        {
            DebugOnly.Assert(size >= (ulong)IntPtr.Size);

            int series  = GetNumSeries();
            int highest = GetHighestSeries();
            int curr    = highest;

            if (series > 0)
            {
                int lowest = GetLowestSeries();
                do
                {
                    ulong ptr  = addr + GetSeriesOffset(curr);
                    ulong stop = (ulong)((long)ptr + GetSeriesSize(curr) + (long)size);

                    while (ptr < stop)
                    {
                        ulong ret = readPointer(ptr);
                        if (ret != 0)
                        {
                            yield return(ret, (int)(ptr - addr));
                        }

                        ptr += (ulong)IntPtr.Size;
                    }

                    curr -= s_GCDescSize;
                } while (curr >= lowest);
            }
            else
            {
                ulong ptr = addr + GetSeriesOffset(curr);

                while (ptr < addr + size - (ulong)IntPtr.Size)
                {
                    for (int i = 0; i > series; i--)
                    {
                        uint nptrs = GetPointers(curr, i);
                        uint skip  = GetSkip(curr, i);

                        ulong stop = ptr + (ulong)(nptrs * IntPtr.Size);
                        do
                        {
                            ulong ret = readPointer(ptr);
                            if (ret != 0)
                            {
                                yield return(ret, (int)(ptr - addr));
                            }

                            ptr += (ulong)IntPtr.Size;
                        } while (ptr < stop);

                        ptr += skip;
                    }
                }
            }
        }
示例#12
0
        public void GetVersionInfo(ulong addr, out VersionInfo version)
        {
            StringBuilder fileName = new StringBuilder(1024);
            uint          res      = GetModuleFileNameEx(_process, addr.AsIntPtr(), fileName, fileName.Capacity);

            DebugOnly.Assert(res != 0);

            if (DataTarget.PlatformFunctions.GetFileVersion(fileName.ToString(), out int major, out int minor, out int revision, out int patch))
            {
                version = new VersionInfo(major, minor, revision, patch, true);
            }
示例#13
0
        public static ulong AsPointer(this Span <byte> span, int index = 0)
        {
            if (index != 0)
            {
                span = span.Slice(index * IntPtr.Size, IntPtr.Size);
            }

            DebugOnly.Assert(span.Length >= IntPtr.Size);
            return(IntPtr.Size == 4
                ? MemoryMarshal.Read <uint>(span)
                : MemoryMarshal.Read <ulong>(span));
        }
示例#14
0
        public bool Read(ulong address, Span <byte> buffer, out int bytesRead)
        {
            DebugOnly.Assert(!buffer.IsEmpty);
            if (address > long.MaxValue)
            {
                bytesRead = 0;
                return(false);
            }

            bytesRead = _core.ReadMemory((long)address, buffer);
            return(bytesRead > 0);
        }
示例#15
0
        public ClrException(IExceptionHelpers helpers, ClrThread?thread, ClrObject obj)
        {
            if (obj.IsNull)
            {
                throw new InvalidOperationException($"Cannot construct a ClrException from a null object.");
            }

            _helpers = helpers ?? throw new ArgumentNullException(nameof(helpers));
            _object  = obj;
            Thread   = thread;

            DebugOnly.Assert(obj.IsException);
        }
示例#16
0
        public override int Read(ulong address, ref byte buffer, uint length)
        {
            DebugOnly.Assert(length != 0);
            try
            {
                fixed(byte *ptr = &buffer)
                {
                    int res = ReadProcessMemory(_process, new IntPtr((nint)address), ptr, new IntPtr(length), out var read);

                    return((int)read);
                }
            }
            catch (OverflowException) {
                return(0);
            }
        }
示例#17
0
        public bool GetVersionInfo(ulong addr, out Version version)
        {
            var  fileName = new StringBuilder(1024);
            uint res      = GetModuleFileNameEx(_process, new IntPtr((nint)addr), fileName, fileName.Capacity);

            DebugOnly.Assert(res != 0);

            if (DataTarget.PlatformFunctions.GetFileVersion(fileName.ToString(), out int major, out int minor, out int build, out int revision))
            {
                version = new Version(major, minor, build, revision);
                return(true);
            }

            version = new Version(0, 0, 0, 0);
            return(false);
        }
示例#18
0
        /// <summary>
        /// Creates a ClrFieldReference from an actual field.
        /// </summary>
        /// <param name="reference">The object referenced.</param>
        /// <param name="containingType">The type of the object which points to <paramref name="reference"/>.</param>
        /// <param name="offset">The offset within the source object where <paramref name="reference"/> was located.</param>
        public static ClrReference CreateFromFieldOrArray(ClrObject reference, ClrType containingType, int offset)
        {
            if (containingType == null)
            {
                throw new ArgumentNullException(nameof(containingType));
            }

            offset -= IntPtr.Size;
            DebugOnly.Assert(offset >= 0);

            ClrInstanceField?field = containingType.IsArray ? null : containingType.Fields.First(f => f.Offset <= offset && offset < f.Offset + f.Size);

            unchecked
            {
                return(new ClrReference(reference, field, OffsetFlag | (uint)offset));
            }
        }
示例#19
0
        public override int Read(ulong address, Span <byte> buffer)
        {
            DebugOnly.Assert(!buffer.IsEmpty);
            try
            {
                fixed(byte *ptr = buffer)
                {
                    int res = ReadProcessMemory(_process, address.AsIntPtr(), ptr, new IntPtr(buffer.Length), out IntPtr read);

                    return((int)read);
                }
            }
            catch (OverflowException)
            {
                return(0);
            }
        }
示例#20
0
        public DbgEngDataReader(string dumpFile)
        {
            if (!File.Exists(dumpFile))
                throw new FileNotFoundException(dumpFile);

            IntPtr pClient = CreateIDebugClient();
            CreateClient(pClient);
            int hr = _client.OpenDumpFile(dumpFile);
            if (hr != 0)
            {
                var kind = (uint)hr == 0x80004005 ? ClrDiagnosticsExceptionKind.CorruptedFileOrUnknownFormat : ClrDiagnosticsExceptionKind.DebuggerError;
                throw new ClrDiagnosticsException($"Could not load crash dump, HRESULT: 0x{hr:x8}", kind, hr).AddData("DumpFile", dumpFile);
            }

            // This actually "attaches" to the crash dump.
            bool result = _control.WaitForEvent(0xffffffff);
            DebugOnly.Assert(result);
        }
        public bool Read(ulong address, Span <byte> buffer, out int bytesRead)
        {
            DebugOnly.Assert(!buffer.IsEmpty);
            try
            {
                fixed(byte *ptr = buffer)
                {
                    int res = ReadProcessMemory(_process, address.AsIntPtr(), ptr, new IntPtr(buffer.Length), out IntPtr read);

                    bytesRead = (int)read;
                    return(res != 0);
                }
            }
            catch
            {
                bytesRead = 0;
                return(false);
            }
        }
示例#22
0
        /// <summary>
        /// Creates a ClrFieldReference from an actual field.
        /// </summary>
        /// <param name="reference">The object referenced.</param>
        /// <param name="containingType">The type of the object which points to <paramref name="reference"/>.</param>
        /// <param name="offset">The offset within the source object where <paramref name="reference"/> was located.</param>
        public static ClrReference CreateFromFieldOrArray(ClrObject reference, ClrType containingType, int offset)
        {
            if (containingType == null)
            {
                throw new ArgumentNullException(nameof(containingType));
            }

            offset -= IntPtr.Size;
            DebugOnly.Assert(offset >= 0);

            ClrInstanceField?field = null;

            foreach (ClrInstanceField curr in containingType.Fields)
            {
                // If we found the correct field, stop searching
                if (curr.Offset <= offset && offset <= curr.Offset + curr.Size)
                {
                    field = curr;
                    break;
                }

                // Sometimes .Size == 0 if we failed to properly determine the type of the field,
                // instead search for the field closest to the offset we are searching for.
                if (curr.Offset <= offset)
                {
                    if (field == null)
                    {
                        field = curr;
                    }
                    else if (field.Offset < curr.Offset)
                    {
                        field = curr;
                    }
                }
            }

            unchecked
            {
                return(new ClrReference(reference, field, OffsetFlag | (uint)offset));
            }
        }
示例#23
0
        public IEnumerable <ModuleInfo> EnumerateModules()
        {
            EnumProcessModules(_process, null, 0, out uint needed);

            IntPtr[] modules = new IntPtr[needed / IntPtr.Size];

            if (!EnumProcessModules(_process, modules, needed, out _))
            {
                throw new InvalidOperationException("Unable to get process modules.");
            }

            List <ModuleInfo> result = new List <ModuleInfo>(modules.Length);

            for (int i = 0; i < modules.Length; i++)
            {
                IntPtr ptr = modules[i];

                StringBuilder sb  = new StringBuilder(1024);
                uint          res = GetModuleFileNameEx(_process, ptr, sb, sb.Capacity);
                DebugOnly.Assert(res != 0);

                ulong baseAddr = (ulong)ptr.ToInt64();
                GetFileProperties(baseAddr, out int filesize, out int timestamp);

                string fileName = sb.ToString();


                Version?version = null;
                if (DataTarget.PlatformFunctions.GetFileVersion(fileName, out int major, out int minor, out int revision, out int patch))
                {
                    version = new Version(major, minor, revision, patch);
                }

                ModuleInfo module = new PEModuleInfo(this, baseAddr, fileName, true, timestamp, filesize, version);
                result.Add(module);
            }

            return(result);
        }
示例#24
0
        public IEnumerable <ModuleInfo> EnumerateModules()
        {
            List <ModuleInfo> result = new List <ModuleInfo>();

            EnumProcessModules(_process, null, 0, out uint needed);

            IntPtr[] modules = new IntPtr[needed / 4];
            uint     size    = (uint)modules.Length * sizeof(uint);

            if (!EnumProcessModules(_process, modules, size, out _))
            {
                throw new ClrDiagnosticsException("Unable to get process modules.", ClrDiagnosticsExceptionKind.DataRequestError);
            }

            for (int i = 0; i < modules.Length; i++)
            {
                IntPtr ptr = modules[i];

                if (ptr == IntPtr.Zero)
                {
                    break;
                }

                StringBuilder sb  = new StringBuilder(1024);
                uint          res = GetModuleFileNameExA(_process, ptr, sb, sb.Capacity);
                DebugOnly.Assert(res != 0);

                ulong baseAddr = (ulong)ptr.ToInt64();
                GetFileProperties(baseAddr, out int filesize, out int timestamp);

                string     fileName = sb.ToString();
                ModuleInfo module   = new ModuleInfo(this, baseAddr, filesize, timestamp, fileName);
                result.Add(module);
            }

            return(result);
        }
示例#25
0
        private void GetFileProperties(ulong moduleBase, out int filesize, out int timestamp)
        {
            filesize  = 0;
            timestamp = 0;

            Span <byte> buffer = stackalloc byte[sizeof(uint)];

            if (Read(moduleBase + 0x3c, buffer) == buffer.Length)
            {
                uint sigOffset = buffer.AsUInt32();
                int  sigLength = 4;

                if (Read(moduleBase + sigOffset, buffer) == buffer.Length)
                {
                    uint header = buffer.AsUInt32();

                    // Ensure the module contains the magic "PE" value at the offset it says it does.  This check should
                    // never fail unless we have the wrong base address for CLR.
                    DebugOnly.Assert(header == 0x4550);
                    if (header == 0x4550)
                    {
                        const int timeDataOffset  = 4;
                        const int imageSizeOffset = 0x4c;
                        if (Read(moduleBase + sigOffset + (ulong)sigLength + timeDataOffset, buffer) == buffer.Length)
                        {
                            timestamp = buffer.AsInt32();
                        }

                        if (Read(moduleBase + sigOffset + (ulong)sigLength + imageSizeOffset, buffer) == buffer.Length)
                        {
                            filesize = buffer.AsInt32();
                        }
                    }
                }
            }
        }
示例#26
0
 public static unsafe uint AsUInt32(this Span <byte> span)
 {
     DebugOnly.Assert(span.Length >= sizeof(uint));
     DebugOnly.Assert(unchecked ((int)Unsafe.AsPointer(ref MemoryMarshal.GetReference(span))) % sizeof(uint) == 0);
     return(Unsafe.As <byte, uint>(ref MemoryMarshal.GetReference(span)));
 }
示例#27
0
 public override int Read(ulong address, Span <byte> buffer)
 {
     DebugOnly.Assert(!buffer.IsEmpty);
     return(address > long.MaxValue ? 0 : _core.ReadMemory(address, buffer));
 }
示例#28
0
        /// <summary>
        /// Constructs a <see cref="ClrDelegate"/> from a <see cref="ClrObject"/>.  Note that obj.IsDelegate
        /// must be true.
        /// </summary>
        /// <param name="obj">A delegate object</param>
        public ClrDelegate(ClrObject obj)
        {
            DebugOnly.Assert(obj.IsDelegate);

            Object = obj;
        }
示例#29
0
 public static uint AsUInt32(this Span <byte> span)
 {
     DebugOnly.Assert(span.Length >= sizeof(uint));
     return(MemoryMarshal.Read <uint>(span));
 }
示例#30
0
 public static ulong AsUInt64(this Span <byte> span)
 {
     DebugOnly.Assert(span.Length >= sizeof(ulong));
     return(MemoryMarshal.Read <ulong>(span));
 }