diff --git a/data/resources/StringResources.resx b/data/resources/StringResources.resx
index c4f3dcf887..f370224778 100644
--- a/data/resources/StringResources.resx
+++ b/data/resources/StringResources.resx
@@ -5746,6 +5746,21 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFxCompiler, WixNetFxExtension<
Previous virtual addresses
+
+ Display bytes size:
+
+
+ Reading from {0} to {1} - size {2}.
+
+
+ Unable to read at address {0} of size {1}.
+
+
+ Not debugging or process is running!
+
+
+ No mappings for memory addresses!
+
Parallel Stacks
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
index b300cf7f33..ac1aee7b5b 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
+++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
@@ -225,6 +225,15 @@
icon="Icons.16x16.Refresh"
tooltip="${res:MainWindow.Windows.Debug.MemoryPad.Refresh}"
class="ICSharpCode.SharpDevelop.Gui.Pads.RefreshAddressCommand"/>
+
+
+
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/MemoryPadCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/MemoryPadCommands.cs
index 58bc7e716d..3b99fcb177 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/MemoryPadCommands.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/MemoryPadCommands.cs
@@ -86,4 +86,42 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
this.pad.MoveToPreviousAddress();
}
}
+
+ public sealed class DisplayByteSizeCommand : AbstractComboBoxCommand
+ {
+ MemoryPad pad;
+ ComboBox comboBox;
+
+ protected override void OnOwnerChanged(EventArgs e)
+ {
+ this.pad = this.Owner as MemoryPad;
+ if (this.pad == null)
+ return;
+
+ comboBox = this.ComboBox as ComboBox;
+
+ if (this.comboBox == null)
+ return;
+
+ comboBox.SelectionChanged += (s, ea) => { Run(); };
+
+ comboBox.Items.Add(2);
+ comboBox.Items.Add(4);
+ comboBox.Items.Add(8);
+ comboBox.Text = "2";
+ comboBox.Width = 33;
+ comboBox.IsEditable = false;
+
+ base.OnOwnerChanged(e);
+ }
+
+ public override void Run()
+ {
+ if (this.pad != null && this.comboBox != null) {
+ pad.DisplayByteSize = Convert.ToByte(this.comboBox.SelectedValue);
+ pad.Refresh();
+ }
+ base.Run();
+ }
+ }
}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs
index a19975fa9b..491bf64f62 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs
@@ -6,15 +6,12 @@ using System.ComponentModel;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using System.Windows;
using System.Windows.Controls;
using Debugger;
using Debugger.Interop;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
-using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
@@ -22,11 +19,44 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{
int currentAddressIndex;
ConsoleControl console;
- int addressStep = 16;
+ int columnsNumber = 16;
+ byte displayByteSize = 2;
+
+ ///
+ /// Gets or sets the number of columns in the display
+ ///
+ [DefaultValue(16)]
+ public int ColumnsNumber {
+ get { return columnsNumber; }
+ set {
+ if (value != columnsNumber) {
+ columnsNumber = value;
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the display byte size: 2, 4, 8
+ ///
+ [DefaultValue(2)]
+ public byte DisplayByteSize {
+ get { return displayByteSize; }
+ set {
+ // check is value is a power of 2 between 1 and 8.
+ if ((value & (value - 1)) != 0)
+ return;
+ if (value <= 1 || value > 8)
+ return;
+
+ if (displayByteSize != value) {
+ displayByteSize = value;
+ }
+ }
+ }
Process debuggedProcess;
List> memoryAddresses = new List>();
- Dictionary addressesMapping = new Dictionary();
+ Dictionary addressesMapping = new Dictionary();
public MemoryPad()
{
@@ -48,7 +78,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
return;
debuggedProcess = process;
- memoryAddresses = debuggedProcess.GetMemoryAddresses();
+ memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses();
currentAddressIndex = 0;
}
@@ -66,7 +96,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
long addr = Int64.Parse(address, NumberStyles.AllowHexSpecifier);
- memoryAddresses = debuggedProcess.GetMemoryAddresses();
+ memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses();
// find index for the address or the near addess
currentAddressIndex = memoryAddresses.BinarySearch(addr);
if (currentAddressIndex == -1) {
@@ -83,16 +113,17 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
return;
// find line
- long mod = addr % addressStep;
+ long mod = addr % (columnsNumber * displayByteSize);
int line;
- string key = (addr - mod).ToString("X8");
+ long key = addr - mod;
+ //int index = addressesMapping.BinarySearch(key);
if (addressesMapping.ContainsKey(key))
line = addressesMapping[key];
else
line = 1;
// jump
- console.SelectText(line, 0, 8);
+ console.SelectText(line + 1, 0, 8);
console.JumpToLine(line);
} catch (System.Exception ex) {
@@ -104,29 +135,31 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
public bool Refresh(bool refreshMemoryAddresses = false)
{
- console.Clear();
+ if (console == null)
+ return false;
+ console.Clear();
if (debuggedProcess == null || debugger.IsProcessRunning) {
- console.Append("Not debugging or process is running!");
+ console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NotDebuggingOrProcessRunning"));
return false;
}
if (currentAddressIndex <= -1) {
- console.Append("No mappings for memory addresses!");
+ console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings"));
currentAddressIndex = -1;
return false;
}
if (refreshMemoryAddresses)
- memoryAddresses = debuggedProcess.GetMemoryAddresses();
+ memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses();
if (memoryAddresses.Count == 0) {
- console.Append("No mappings for memory addresses!");
+ console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings"));
return false;
}
if (currentAddressIndex >= memoryAddresses.Count) {
- console.Append("No mappings for memory addresses!");
+ console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings"));
currentAddressIndex = memoryAddresses.Count ;
return false;
}
@@ -146,27 +179,43 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
long size = item.Item2;
byte[] memory = debuggedProcess.ReadProcessMemory(address, size);
- System.Diagnostics.Debug.Assert(memory != null);
+ if (memory == null) {
+ return string.Format(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.UnableToReadFormat"), address.ToString("X8"), size);
+ }
+
+ int bytesNr = displayByteSize / 2;
+ int totalBytesPerRow = columnsNumber * bytesNr;
+ int numberOfLines = memory.Length / totalBytesPerRow;
+ int remainingMemory = memory.Length % totalBytesPerRow;
- int numberOfLines = memory.Length / addressStep;
- int mod = memory.Length % addressStep;
- int currentLine = 0;
StringBuilder sb = new StringBuilder();
+ sb.Append(string.Format(
+ ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.ReadingFromFormat"),
+ address.ToString("X8"), (address + memory.Length).ToString("X8"), memory.Length));
+ sb.Append(Environment.NewLine);
+
+ int currentLine = 2; // line in the console
+ int index = 0; // index in memory arrray of current line
- while (currentLine < numberOfLines) {
- addressesMapping.Add(address.ToString("X8"), currentLine + 1);
+ while (index < numberOfLines) {
+ addressesMapping.Add(address, currentLine);
// write address
- sb.Append(address.ToString("X8")); address += (long)addressStep;
+ sb.Append(address.ToString("X8")); address += (long)totalBytesPerRow;
sb.Append(" ");
+ int start = index * totalBytesPerRow;
// write bytes
- for (int i = 0; i < addressStep; ++i) {
- sb.Append(memory[currentLine * addressStep + i].ToString("X2") + " ");
+ for (int i = 0; i < columnsNumber; ++i) {
+ for (int j = 0; j < bytesNr; ++j) {
+ sb.Append(memory[start++].ToString("X2"));
+ }
+ sb.Append(" ");
}
// write chars
+ start = index * totalBytesPerRow;
StringBuilder sb1 = new StringBuilder();
- for (int i = 0; i < addressStep; ++i) {
- sb1.Append(((char)memory[currentLine * addressStep + i]).ToString());
+ for (int i = 0; i < totalBytesPerRow; ++i) {
+ sb1.Append(((char)memory[start++]).ToString());
}
string s = sb1.ToString();
s = Regex.Replace(s, @"\r\n", string.Empty);
@@ -176,23 +225,31 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
sb.Append(Environment.NewLine);
currentLine++;
+ index++;
}
- if (mod != 0) {
+ if (remainingMemory != 0) {
// write the rest of memory
- addressesMapping.Add(address.ToString("X8"), currentLine + 1);
+ addressesMapping.Add(address, currentLine);
+
// write address
sb.Append(address.ToString("X8"));
sb.Append(" ");
// write bytes
- for (int i = 0; i < mod; ++i) {
- sb.Append(memory[currentLine * addressStep + i].ToString("X2") + " ");
+ int start = index * remainingMemory * bytesNr;
+ for (int i = 0; i < remainingMemory; ++i) {
+ for (int j = 0; j < bytesNr; j++) {
+ sb.Append(memory[start++].ToString("X2"));
+ }
+ sb.Append(" ");
}
+
// write chars
+ start = index * remainingMemory * bytesNr;
StringBuilder sb1 = new StringBuilder();
- for (int i = 0; i < mod; ++i) {
- sb1.Append(((char)memory[currentLine * addressStep + i]).ToString());
+ for (int i = 0; i < remainingMemory * bytesNr; ++i) {
+ sb1.Append(((char)memory[start++]).ToString());
}
string s = sb1.ToString();
s = Regex.Replace(s, @"\r\n", string.Empty);
@@ -224,8 +281,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
///
/// Source of data.
/// Item to search.
- /// The nearast index.
- internal static int BinarySearch(this List> source, long item1)
+ /// The nearest index.
+ internal static int BinarySearch(this List> source, long item1)
{
// base checks
if (source == null)
diff --git a/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs b/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs
index 02acbede0e..1c65879a1f 100644
--- a/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs
+++ b/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs
@@ -134,7 +134,7 @@ namespace Debugger.Interop
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);
- public static List> GetMemoryAddresses(this Process process)
+ public static List> GetVirtualMemoryAddresses(this Process process)
{
var result = new List>();
SYSTEM_INFO sysinfo = new SYSTEM_INFO();
@@ -148,16 +148,9 @@ namespace Debugger.Interop
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))
+ if (!VirtualQueryEx(openedProcess, new IntPtr(address), out m, (uint)Marshal.SizeOf(m)))
continue;
- } catch {
- continue;
} finally {
// next address
address = m.BaseAddress.ToInt64() + m.RegionSize.ToInt64();
@@ -188,6 +181,8 @@ namespace Debugger.Interop
var proc = System.Diagnostics.Process.GetProcessById((int)process.Id);
return process.ReadProcessMemory(proc.MainModule.BaseAddress.ToInt64(), (long)4096);
}
+ } catch {
+ return null;
} finally {
if (openedProcess != IntPtr.Zero)
CloseHandle(openedProcess);