diff --git a/source/Cosmos.VS.Windows/Cosmos.VS.Windows.csproj b/source/Cosmos.VS.Windows/Cosmos.VS.Windows.csproj index 03eb31110..121022ad4 100644 --- a/source/Cosmos.VS.Windows/Cosmos.VS.Windows.csproj +++ b/source/Cosmos.VS.Windows/Cosmos.VS.Windows.csproj @@ -53,6 +53,7 @@ + diff --git a/source/Cosmos.VS.Windows/CosmosMenuCmdSet.cs b/source/Cosmos.VS.Windows/CosmosMenuCmdSet.cs index c685be59d..30e2f45bc 100644 --- a/source/Cosmos.VS.Windows/CosmosMenuCmdSet.cs +++ b/source/Cosmos.VS.Windows/CosmosMenuCmdSet.cs @@ -75,7 +75,7 @@ namespace Cosmos.VS.Windows private void ShowWindowRegisters(object aCommand, EventArgs e) { - ShowWindow(typeof(RegistersTW)); + ShowWindow(typeof(RegistersToolWindow)); } private void ShowWindowStack(object aCommand, EventArgs e) diff --git a/source/Cosmos.VS.Windows/CosmosWindowsPackage.cs b/source/Cosmos.VS.Windows/CosmosWindowsPackage.cs index bed44200f..329b506d5 100644 --- a/source/Cosmos.VS.Windows/CosmosWindowsPackage.cs +++ b/source/Cosmos.VS.Windows/CosmosWindowsPackage.cs @@ -19,7 +19,7 @@ namespace Cosmos.VS.Windows [PackageRegistration(UseManagedResourcesOnly = true)] [ProvideMenuResource("Menus.ctmenu", 1)] [ProvideToolWindow(typeof(AssemblyToolWindow))] - [ProvideToolWindow(typeof(RegistersTW))] + [ProvideToolWindow(typeof(RegistersToolWindow))] [ProvideToolWindow(typeof(StackTW))] [ProvideToolWindow(typeof(InternalTW))] [ProvideToolWindow(typeof(ConsoleTW))] @@ -113,7 +113,7 @@ namespace Cosmos.VS.Windows break; case Debugger2Windows.Registers: - UpdateWindow(typeof(RegistersTW), null, xMsg); + UpdateWindow(typeof(RegistersToolWindow), null, xMsg); break; case Debugger2Windows.Quit: @@ -218,7 +218,7 @@ namespace Cosmos.VS.Windows byte[] aData = cWindow.UserControl.GetCurrentState(); StateStorer.StoreState("StackTW", aData == null ? null : (byte[])aData.Clone()); - cWindow = FindWindow(typeof(RegistersTW)); + cWindow = FindWindow(typeof(RegistersToolWindow)); aData = cWindow.UserControl.GetCurrentState(); StateStorer.StoreState("RegistersTW", aData == null ? null : (byte[])aData.Clone()); } @@ -229,7 +229,7 @@ namespace Cosmos.VS.Windows byte[] aData = StateStorer.RetrieveState(StateStorer.CurrLineId, "StackTW"); cWindow.UserControl.SetCurrentState(aData == null ? null : (byte[])aData.Clone()); - cWindow = FindWindow(typeof(RegistersTW)); + cWindow = FindWindow(typeof(RegistersToolWindow)); aData = StateStorer.RetrieveState(StateStorer.CurrLineId, "RegistersTW"); cWindow.UserControl.SetCurrentState(aData == null ? null : (byte[])aData.Clone()); } diff --git a/source/Cosmos.VS.Windows/ToolWindows/AssemblyToolWindow.cs b/source/Cosmos.VS.Windows/ToolWindows/AssemblyToolWindow.cs index 3eb2565d7..2a4f5dba6 100644 --- a/source/Cosmos.VS.Windows/ToolWindows/AssemblyToolWindow.cs +++ b/source/Cosmos.VS.Windows/ToolWindows/AssemblyToolWindow.cs @@ -1,28 +1,19 @@ using System; using System.Runtime.InteropServices; +using Microsoft.VisualStudio.Imaging; using Microsoft.VisualStudio.Shell; namespace Cosmos.VS.Windows.ToolWindows { - [Guid("f019fb29-c2c2-4d27-9abf-739533c939be")] + [Guid(ToolWindowGuid)] internal class AssemblyToolWindow : ToolWindowPane2 { + public const string ToolWindowGuid = "f019fb29-c2c2-4d27-9abf-739533c939be"; + public AssemblyToolWindow() { - //ToolBar = new CommandID(GuidList.guidAsmToolbarCmdSet, (int)PkgCmdIDList.AsmToolbar); + BitmapImageMoniker = KnownMonikers.DisassemblyWindow; Caption = "Cosmos Assembly"; - - // Set the image that will appear on the tab of the window frame - // when docked with an other window. - // The resource ID correspond to the one defined in the resx file - // while the Index is the offset in the bitmap strip. Each image in - // the strip being 16x16. - BitmapResourceID = 301; - BitmapIndex = 1; - - // This is the user control hosted by the tool window; Note that, even if this class implements IDisposable, - // we are not calling Dispose on this object. This is because ToolWindowPane calls Dispose on - // the object returned by the Content property. Content = new AssemblyUC(); } } diff --git a/source/Cosmos.VS.Windows/ToolWindows/AssemblyUC.xaml b/source/Cosmos.VS.Windows/ToolWindows/AssemblyUC.xaml index 6a18ce80b..16c645125 100644 --- a/source/Cosmos.VS.Windows/ToolWindows/AssemblyUC.xaml +++ b/source/Cosmos.VS.Windows/ToolWindows/AssemblyUC.xaml @@ -5,7 +5,6 @@ xmlns:imaging="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.Imaging" xmlns:imagecatalog="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.ImageCatalog" xmlns:platformui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.15.0" - x:Name="CosmosAssemblyUserControl" Background="{DynamicResource {x:Static platformui:EnvironmentColors.ToolWindowBackgroundBrushKey}}" Foreground="{DynamicResource {x:Static platformui:EnvironmentColors.ToolWindowTextBrushKey}}"> diff --git a/source/Cosmos.VS.Windows/ToolWindows/RegistersControl.xaml b/source/Cosmos.VS.Windows/ToolWindows/RegistersControl.xaml new file mode 100644 index 000000000..275e188e3 --- /dev/null +++ b/source/Cosmos.VS.Windows/ToolWindows/RegistersControl.xaml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/Cosmos.VS.Windows/ToolWindows/RegistersControl.xaml.cs b/source/Cosmos.VS.Windows/ToolWindows/RegistersControl.xaml.cs new file mode 100644 index 000000000..daab4d40c --- /dev/null +++ b/source/Cosmos.VS.Windows/ToolWindows/RegistersControl.xaml.cs @@ -0,0 +1,126 @@ +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Threading; + +namespace Cosmos.VS.Windows +{ + public partial class RegistersControl : DebuggerUC + { + private RegistersViewModel mViewModel; + + public RegistersControl() + { + InitializeComponent(); + DataContext = mViewModel = new RegistersViewModel(); + } + + protected override void DoUpdate(string aTag) + { + Application.Current.Dispatcher.Invoke( + () => + { + if (mData != null) + { + mViewModel.UpdateData(mData); + } + }, DispatcherPriority.Normal); + } + } + + internal class RegistersViewModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + //Push All + // Temp = (ESP); + // Push(EAX); 28 + // Push(ECX); 24 + // Push(EDX); 20 + // Push(EBX); 16 + // Push(Temp); 12 // Have to get from another source, ESP is already in DS when we pushall + // Push(EBP); 8 + // Push(ESI); 4 + // Push(EDI); 0 + // We get them from bottom up, so we receive them in reverse order as shown above. That is 0-3 is EDI. + // + // Additional ones sent manually (at end, not from stack) + // ESP 32 + // EIP 36 + // + //TODO: Flags + private byte[] mData; + private object mSyncObject = new object(); + + public void UpdateData(byte[] data) + { + lock (mSyncObject) + { + mData = data; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(String.Empty)); + } + } + + public string EAX => GetRegisterValue(28).ToHexString(); + public string AX => EAX.Substring(4, 4); + public string AH => EAX.Substring(4, 2); + public string AL => EAX.Substring(6, 2); + + public string EBX => GetRegisterValue(16).ToHexString(); + public string BX => EBX.Substring(4, 4); + public string BH => EBX.Substring(4, 2); + public string BL => EBX.Substring(6, 2); + + public string ECX => GetRegisterValue(24).ToHexString(); + public string CX => ECX.Substring(4, 4); + public string CH => ECX.Substring(4, 2); + public string CL => ECX.Substring(6, 2); + + public string EDX => GetRegisterValue(20).ToHexString(); + public string DX => EDX.Substring(4, 4); + public string DH => EDX.Substring(4, 2); + public string DL => EDX.Substring(6, 2); + + public string ESI => GetRegisterValue(8).ToHexString(); + public string EDI => GetRegisterValue(4).ToHexString(); + + public string EBP => GetRegisterValue(0).ToHexString(); + public string ESP => GetRegisterValue(32).ToHexString(); + + public string EIP => GetRegisterValue(36).ToHexString(); + public string Flags => ((uint?)null).ToHexString(); + + private uint? GetRegisterValue(int offset) + { + lock (mSyncObject) + { + if (mData == null) + { + return null; + } + +#if DEBUG + if (offset >= mData.Length) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } +#endif + + return BitConverter.ToUInt32(mData, offset); + } + } + } + + internal static class ExtensionMethods + { + public static string ToHexString(this uint? value) + { + if (value.HasValue) + { + return value.Value.ToString("X8"); + } + + return "--------"; + } + } +} diff --git a/source/Cosmos.VS.Windows/ToolWindows/RegistersToolWindow.cs b/source/Cosmos.VS.Windows/ToolWindows/RegistersToolWindow.cs new file mode 100644 index 000000000..b41a72430 --- /dev/null +++ b/source/Cosmos.VS.Windows/ToolWindows/RegistersToolWindow.cs @@ -0,0 +1,20 @@ +using System; +using System.Runtime.InteropServices; +using Microsoft.VisualStudio.Imaging; +using Microsoft.VisualStudio.Shell; + +namespace Cosmos.VS.Windows.ToolWindows +{ + [Guid(ToolWindowGuid)] + internal class RegistersToolWindow : ToolWindowPane2 + { + public const string ToolWindowGuid = "ce2a2d0f-0f1b-4a1f-a9ac-5a5f2a5e2c25"; + + public RegistersToolWindow() + { + BitmapImageMoniker = KnownMonikers.RegistersWindow; + Caption = "Cosmos Registers"; + Content = new RegistersControl(); + } + } +} diff --git a/source/Cosmos.VS.Windows/ToolWindows/RegistersUC.xaml b/source/Cosmos.VS.Windows/ToolWindows/RegistersUC.xaml deleted file mode 100644 index 321eda8fa..000000000 --- a/source/Cosmos.VS.Windows/ToolWindows/RegistersUC.xaml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/source/Cosmos.VS.Windows/ToolWindows/RegistersUC.xaml.cs b/source/Cosmos.VS.Windows/ToolWindows/RegistersUC.xaml.cs deleted file mode 100644 index e36524493..000000000 --- a/source/Cosmos.VS.Windows/ToolWindows/RegistersUC.xaml.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Windows.Threading; - -namespace Cosmos.VS.Windows -{ - [Guid("CE2A2D0F-0F1B-4A1F-A9AC-5A5F2A5E2C25")] - public class RegistersTW : ToolWindowPane2 - { - public RegistersTW() - { - Caption = "Cosmos x86 Registers"; - BitmapResourceID = 301; - BitmapIndex = 1; - Content = new RegistersUC(); - } - } - - public partial class RegistersUC : DebuggerUC - { - public RegistersUC() - { - InitializeComponent(); - } - - protected UInt32 mCurrEBP = 0x0; - public UInt32 CurrentEBP - { - get - { - return mCurrEBP; - } - } - - protected void UpdateRegisters(byte[] aData, int aOffset, DataBytesUC a32, DataBytesUC a16, DataBytesUC a8Hi, DataBytesUC a8Lo) - { - a8Lo.Value = aData[aOffset]; - a8Hi.Value = aData[aOffset + 1]; - a16.Value = a8Hi.Value << 8 | a8Lo.Value; - UpdateRegister32(aData, aOffset, a32); - } - - protected void UpdateRegister32(byte[] aData, int aOffset, DataBytesUC a32) - { - UInt32 x32 = (UInt32) - (aData[aOffset + 3] << 24 | - aData[aOffset + 2] << 16 | - aData[aOffset + 1] << 8 | - aData[aOffset]); - a32.Value = x32; - - if (a32 == dataEBP) - { - mCurrEBP = x32; - } - } - - protected override void DoUpdate(string aTag) - { - //Push All - // Temp = (ESP); - // Push(EAX); 28 - // Push(ECX); 24 - // Push(EDX); 20 - // Push(EBX); 16 - // Push(Temp); 12 // Have to get from another source, ESP is already in DS when we pushall - // Push(EBP); 8 - // Push(ESI); 4 - // Push(EDI); 0 - // We get them from bottom up, so we receive them in reverse order as shown above. That is 0-3 is EDI. - // - // Additional ones sent manually (at end, not from stack) - // ESP 32 - // EIP 36 - // - System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, - (Action)delegate() - { - if (mData == null) - { - dataEAX.Value = null; - dataAX.Value = null; - dataAH.Value = null; - dataAL.Value = null; - - dataEBX.Value = null; - dataBX.Value = null; - dataBH.Value = null; - dataBL.Value = null; - - dataECX.Value = null; - dataCX.Value = null; - dataCH.Value = null; - dataCL.Value = null; - - dataEDX.Value = null; - dataDX.Value = null; - dataDH.Value = null; - dataDL.Value = null; - - dataEBP.Value = null; - mCurrEBP = 0x0; - - dataESI.Value = null; - dataEDI.Value = null; - dataESP.Value = null; - dataEIP.Value = null; - } - else - { - try - { - UpdateRegisters(mData, 28, dataEAX, dataAX, dataAH, dataAL); - UpdateRegisters(mData, 16, dataEBX, dataBX, dataBH, dataBL); - UpdateRegisters(mData, 24, dataECX, dataCX, dataCH, dataCL); - UpdateRegisters(mData, 20, dataEDX, dataDX, dataDH, dataDL); - UpdateRegister32(mData, 8, dataEBP); - UpdateRegister32(mData, 4, dataESI); - UpdateRegister32(mData, 0, dataEDI); - UpdateRegister32(mData, 32, dataESP); - UpdateRegister32(mData, 36, dataEIP); - } - catch - { - } - } - } - ); - //TODO: Flags - } - } -}