diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs index 1d6a369c4a..efc0975de2 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs @@ -2,9 +2,11 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; using System.Text; using System.Text.RegularExpressions; +using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; @@ -24,7 +26,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads Process debuggedProcess; List> memoryAddresses = new List>(); - Dictionary addressesMapping = new Dictionary(); + Dictionary addressesMapping = new Dictionary(); public MemoryPad() { @@ -64,11 +66,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads long addr = Int64.Parse(address, NumberStyles.AllowHexSpecifier); + memoryAddresses = debuggedProcess.GetMemoryAddresses(); // find index for the address or the near addess - currentAddressIndex = memoryAddresses.Search(addr); + currentAddressIndex = memoryAddresses.BinarySearch(addr); if (currentAddressIndex == -1) { MessageService.ShowMessage( - string.Format(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.AddressNotFound"), address), + string.Format(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.AddressNotFound"), address), ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad")); currentAddressIndex = 0; @@ -76,13 +79,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } // refresh pad - Refresh(); + if (!Refresh()) + return; // find line long mod = addr % addressStep; int line; - if (addressesMapping.ContainsKey(addr - mod)) - line = addressesMapping[addr - mod]; + string key = (addr - mod).ToString("X8"); + if (addressesMapping.ContainsKey(key)) + line = addressesMapping[key]; else line = 1; @@ -97,15 +102,41 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - public void Refresh() + public bool Refresh() { - if (debuggedProcess == null || debugger.IsProcessRunning) - return; + console.Clear(); - if (memoryAddresses.Count == 0) - return; + if (debuggedProcess == null || debugger.IsProcessRunning) { + console.Append("Not debugging or process is running!"); + return false; + } + + if (currentAddressIndex <= -1) { + console.Append("No mappings for memory addresses!"); + currentAddressIndex = -1; + return false; + } + + memoryAddresses = debuggedProcess.GetMemoryAddresses(); + if (memoryAddresses.Count == 0) { + console.Append("No mappings for memory addresses!"); + return false; + } - console.Clear();addressesMapping.Clear(); + if (currentAddressIndex >= memoryAddresses.Count) { + console.Append("No mappings for memory addresses!"); + currentAddressIndex = memoryAddresses.Count ; + return false; + } + + console.Append(DoWork()); + return true; + } + + string DoWork() + { + // refresh data + addressesMapping.Clear(); // get current address var item = memoryAddresses[currentAddressIndex]; @@ -115,25 +146,25 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads byte[] memory = debuggedProcess.ReadProcessMemory(address, size); System.Diagnostics.Debug.Assert(memory != null); - int div = memory.Length / addressStep; + int numberOfLines = memory.Length / addressStep; int mod = memory.Length % addressStep; - int index = 0; + int currentLine = 0; + StringBuilder sb = new StringBuilder(); - while (index < div) { - StringBuilder sb = new StringBuilder(); - addressesMapping.Add(address, index + 1); + while (currentLine < numberOfLines) { + addressesMapping.Add(address.ToString("X8"), currentLine + 1); // write address sb.Append(address.ToString("X8")); address += (long)addressStep; sb.Append(" "); // write bytes for (int i = 0; i < addressStep; ++i) { - sb.Append(memory[index * addressStep + i].ToString("X2") + " "); + sb.Append(memory[currentLine * addressStep + i].ToString("X2") + " "); } // write chars StringBuilder sb1 = new StringBuilder(); for (int i = 0; i < addressStep; ++i) { - sb1.Append(((char)memory[index * addressStep + i]).ToString()); + sb1.Append(((char)memory[currentLine * addressStep + i]).ToString()); } string s = sb1.ToString(); s = Regex.Replace(s, @"\r\n", string.Empty); @@ -142,61 +173,43 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads sb.Append(s); sb.Append(Environment.NewLine); - // start writing in console - console.Append(sb.ToString()); - index++; + currentLine++; } if (mod != 0) { // write the rest of memory - StringBuilder sb = new StringBuilder(); - addressesMapping.Add(address, index + 1); + addressesMapping.Add(address.ToString("X8"), currentLine + 1); // write address sb.Append(address.ToString("X8")); sb.Append(" "); // write bytes for (int i = 0; i < mod; ++i) { - sb.Append(memory[index * addressStep + i].ToString("X2") + " "); + sb.Append(memory[currentLine * addressStep + i].ToString("X2") + " "); } // write chars StringBuilder sb1 = new StringBuilder(); for (int i = 0; i < mod; ++i) { - sb1.Append(((char)memory[index * addressStep + i]).ToString()); + sb1.Append(((char)memory[currentLine * addressStep + i]).ToString()); } string s = sb1.ToString(); s = Regex.Replace(s, @"\r\n", string.Empty); s = Regex.Replace(s, @"\n", string.Empty); s = Regex.Replace(s, @"\r", string.Empty); sb.Append(s); - - sb.Append(Environment.NewLine); - - // start writing in console - console.Append(sb.ToString()); } + + return sb.ToString(); } public void MoveToPreviousAddress() { - if (debuggedProcess == null || debugger.IsProcessRunning) - return; - - if (currentAddressIndex == 0) - return; - currentAddressIndex--; Refresh(); } public void MoveToNextAddress() { - if (debuggedProcess == null || debugger.IsProcessRunning) - return; - - if (currentAddressIndex == memoryAddresses.Count) - return; - currentAddressIndex++; Refresh(); } @@ -204,19 +217,41 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads internal static class MemoryPadExtensions { - internal static int Search(this List> source, long item1) + /// + /// Does a binary search when the Item1 from Tuple is sorted. + /// + /// Source of data. + /// Item to search. + /// The nearast index. + internal static int BinarySearch(this List> source, long item1) { + // base checks if (source == null) throw new NullReferenceException("Source is null!"); - for (int i = 0; i < source.Count - 1; i++) { - if (source[i + 1].Item1 < item1) - continue; - - return i; + if (source.Count == 0) + return -1; + + if (item1 < source[0].Item1) + return 0; + + if (item1 > source[source.Count - 1].Item1) + return source.Count; + + // do a binary search since the source is sorted + int first = 0; int last = source.Count; + while (first < last - 1) { + int middle = (first + last) / 2; + if (source[middle].Item1 == item1) + return middle; + else + if (source[middle].Item1 < item1) + first = middle; + else + last = middle; } - return -1; + return first; } } } diff --git a/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs b/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs index cfa343243b..02acbede0e 100644 --- a/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs +++ b/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs @@ -97,7 +97,7 @@ namespace Debugger.Interop public static class NativeMethods { - [DllImport("kernel32.dll")] + [DllImport("kernel32.dll", SetLastError = true)] public static extern bool CloseHandle(IntPtr handle); [DllImport("mscoree.dll", CharSet=CharSet.Unicode, PreserveSig=false)] @@ -133,38 +133,41 @@ namespace Debugger.Interop [DllImport("kernel32.dll", SetLastError = true)] public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); - - [DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)] - public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect); - + public static List> GetMemoryAddresses(this Process process) { var result = new List>(); SYSTEM_INFO sysinfo = new SYSTEM_INFO(); GetSystemInfo(out sysinfo); - uint handle = process.CorProcess.GetHandle(); long address = 0; MEMORY_BASIC_INFORMATION m = new MEMORY_BASIC_INFORMATION(); - - while (address < sysinfo.lpMaximumApplicationAddress.ToInt64()) - { - if (!VirtualQueryEx(new IntPtr(handle), new IntPtr(address), out m, (uint)Marshal.SizeOf(m))) - break; + IntPtr openedProcess = IntPtr.Zero; + try { + openedProcess = OpenProcess(ProcessAccessFlags.All, false, (int)process.Id); - try { - byte[] temp = new byte[m.RegionSize.ToInt64()]; - int outSize; - if (!ReadProcessMemory(new IntPtr(handle), new IntPtr(address), temp, temp.Length, out outSize)) + while (address < sysinfo.lpMaximumApplicationAddress.ToInt64()) + { + if (!VirtualQueryEx(openedProcess, new IntPtr(address), out m, (uint)Marshal.SizeOf(m))) + break; + + try { + byte[] temp = new byte[m.RegionSize.ToInt64()]; + int outSize; + if (!ReadProcessMemory(openedProcess, new IntPtr(address), temp, temp.Length, out outSize)) + continue; + } catch { continue; - } catch { - continue; - } finally { - // next address - address = m.BaseAddress.ToInt64() + m.RegionSize.ToInt64(); + } finally { + // next address + address = m.BaseAddress.ToInt64() + m.RegionSize.ToInt64(); + } + + result.Add(new Tuple(m.BaseAddress.ToInt64(), m.RegionSize.ToInt64())); } - - result.Add(new Tuple(m.BaseAddress.ToInt64(), m.RegionSize.ToInt64())); + } finally { + if (openedProcess != IntPtr.Zero) + CloseHandle(openedProcess); } return result; @@ -172,15 +175,22 @@ namespace Debugger.Interop public static byte[] ReadProcessMemory(this Process process, long startAddress, long size) { - uint handle = process.CorProcess.GetHandle(); - + IntPtr openedProcess = IntPtr.Zero; byte[] temp = new byte[size]; - int outSize; - bool success = ReadProcessMemory(new IntPtr(handle), new IntPtr(startAddress), temp, temp.Length, out outSize); - if (!success || outSize == 0) { - var proc = System.Diagnostics.Process.GetProcessById((int)process.Id); - return process.ReadProcessMemory(proc.MainModule.BaseAddress.ToInt64(), (long)4096); + try { + openedProcess = OpenProcess(ProcessAccessFlags.All, false, (int)process.Id); + + int outSize; + bool success = ReadProcessMemory(openedProcess, new IntPtr(startAddress), temp, temp.Length, out outSize); + + if (!success || outSize == 0) { + var proc = System.Diagnostics.Process.GetProcessById((int)process.Id); + return process.ReadProcessMemory(proc.MainModule.BaseAddress.ToInt64(), (long)4096); + } + } finally { + if (openedProcess != IntPtr.Zero) + CloseHandle(openedProcess); } return temp;