From 576d6492dc97a75e73863d6c909dc3093984a2b8 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sat, 23 May 2015 22:27:43 -0700 Subject: [PATCH] Basic debugger networking. --- build/Xenia.Cpp.x64.Common.props | 4 +- libxenia.vcxproj | 13 +- libxenia.vcxproj.filters | 16 +- src/Xenia.Debug.UI/MainWindow.Designer.cs | 14 +- src/Xenia.Debug.UI/MainWindow.cs | 33 +- src/Xenia.Debug/BreakpointList.cs | 19 +- src/Xenia.Debug/DebugClient.cs | 10 - src/Xenia.Debug/Debugger.cs | 227 +++++++++++-- src/Xenia.Debug/FunctionList.cs | 23 +- src/Xenia.Debug/Memory.cs | 6 + src/Xenia.Debug/ModuleList.cs | 23 +- .../xe/debug/proto/AddBreakpointRequest.cs | 22 ++ .../xe/debug/proto/AddBreakpointResponse.cs | 22 ++ .../Proto/xe/debug/proto/AttachRequest.cs | 22 ++ .../Proto/xe/debug/proto/AttachResponse.cs | 22 ++ src/Xenia.Debug/Proto/xe/debug/proto/Foo.cs | 13 + .../xe/debug/proto/ListBreakpointsRequest.cs | 22 ++ .../xe/debug/proto/ListBreakpointsResponse.cs | 22 ++ .../xe/debug/proto/RemoveBreakpointRequest.cs | 22 ++ .../debug/proto/RemoveBreakpointResponse.cs | 22 ++ .../Proto/xe/debug/proto/Request.cs | 39 +++ .../Proto/xe/debug/proto/RequestData.cs | 17 + .../Proto/xe/debug/proto/Response.cs | 39 +++ .../Proto/xe/debug/proto/ResponseData.cs | 17 + .../Proto/xe/debug/proto/StructTest.cs | 25 ++ .../Proto/xe/debug/proto/TableTest.cs | 35 ++ .../xe/debug/proto/UpdateBreakpointRequest.cs | 22 ++ .../debug/proto/UpdateBreakpointResponse.cs | 22 ++ src/Xenia.Debug/ThreadList.cs | 23 +- src/Xenia.Debug/Utilities/Dispatch.cs | 20 ++ src/Xenia.Debug/Utilities/TaskExtensions.cs | 40 +++ src/Xenia.Debug/Xenia.Debug.csproj | 33 +- .../cpu/frontend/test/xe-cpu-ppc-test.cc | 2 +- src/xenia/cpu/processor.cc | 14 +- src/xenia/cpu/processor.h | 15 +- src/xenia/cpu/test/util.h | 3 +- src/xenia/debug/debug_server.cc | 18 -- src/xenia/debug/debug_server.h | 21 -- src/xenia/debug/debugger.cc | 217 ++++++++++++- src/xenia/debug/debugger.h | 21 +- src/xenia/debug/proto/breakpoints.fbs | 23 ++ src/xenia/debug/proto/breakpoints_generated.h | 210 ++++++++++++ src/xenia/debug/proto/common.fbs | 1 + src/xenia/debug/proto/control.fbs | 3 + src/xenia/debug/proto/messages.fbs | 59 ++++ src/xenia/debug/proto/messages_generated.h | 298 ++++++++++++++++++ src/xenia/debug/proto/test.fbs | 27 -- src/xenia/emulator.cc | 13 +- src/xenia/emulator.h | 5 + src/xenia/kernel/xboxkrnl_module.cc | 3 + xb.bat | 45 ++- 51 files changed, 1745 insertions(+), 162 deletions(-) delete mode 100644 src/Xenia.Debug/DebugClient.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/AddBreakpointRequest.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/AddBreakpointResponse.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/AttachRequest.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/AttachResponse.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/Foo.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/ListBreakpointsRequest.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/ListBreakpointsResponse.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/RemoveBreakpointRequest.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/RemoveBreakpointResponse.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/Request.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/Response.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/StructTest.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/TableTest.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/UpdateBreakpointRequest.cs create mode 100644 src/Xenia.Debug/Proto/xe/debug/proto/UpdateBreakpointResponse.cs create mode 100644 src/Xenia.Debug/Utilities/Dispatch.cs create mode 100644 src/Xenia.Debug/Utilities/TaskExtensions.cs delete mode 100644 src/xenia/debug/debug_server.cc delete mode 100644 src/xenia/debug/debug_server.h create mode 100644 src/xenia/debug/proto/breakpoints.fbs create mode 100644 src/xenia/debug/proto/breakpoints_generated.h create mode 100644 src/xenia/debug/proto/common.fbs create mode 100644 src/xenia/debug/proto/control.fbs create mode 100644 src/xenia/debug/proto/messages.fbs create mode 100644 src/xenia/debug/proto/messages_generated.h delete mode 100644 src/xenia/debug/proto/test.fbs diff --git a/build/Xenia.Cpp.x64.Common.props b/build/Xenia.Cpp.x64.Common.props index d9685794d..fc379a2ea 100644 --- a/build/Xenia.Cpp.x64.Common.props +++ b/build/Xenia.Cpp.x64.Common.props @@ -9,8 +9,8 @@ true - $(SolutionDir)\third_party\gflags\src\;$(SolutionDir)\src\;$(SolutionDir)\third_party;$(SolutionDir)\ - GLEW_STATIC=1;GLEW_MX=1;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32;_WIN64=1;_AMD64=1;MICROPROFILE_MAX_THREADS=256;%(PreprocessorDefinitions) + $(SolutionDir)\third_party\flatbuffers\include\;$(SolutionDir)\third_party\gflags\src\;$(SolutionDir)\src\;$(SolutionDir)\third_party;$(SolutionDir)\ + GLEW_STATIC=1;GLEW_MX=1;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;WIN32;_WIN64=1;_AMD64=1;MICROPROFILE_MAX_THREADS=128;%(PreprocessorDefinitions) Level4 true MultiThreadedDLL diff --git a/libxenia.vcxproj b/libxenia.vcxproj index 37c87626c..b89c8237e 100644 --- a/libxenia.vcxproj +++ b/libxenia.vcxproj @@ -92,7 +92,6 @@ - @@ -291,9 +290,10 @@ - + + @@ -419,6 +419,7 @@ + @@ -485,7 +486,7 @@ Level3 Disabled BEA_ENGINE_STATIC=1;_LIB;%(PreprocessorDefinitions) - $(SolutionDir)\third_party\libav-bin\include\;$(SolutionDir)\third_party\beaengine\include\;$(SolutionDir)\third_party\llvm\include\;$(SolutionDir)\third_party\gflags\src\;$(SolutionDir)\src\;$(SolutionDir)\third_party;$(SolutionDir)\ + $(SolutionDir)\third_party\libav-bin\include\;$(SolutionDir)\third_party\beaengine\include\;$(SolutionDir)\third_party\llvm\include\;%(AdditionalIncludeDirectories) Windows @@ -503,7 +504,7 @@ Level3 Disabled BEA_ENGINE_STATIC=1;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - $(SolutionDir)\third_party\libav-bin\include\;$(SolutionDir)\third_party\beaengine\include\;$(SolutionDir)\third_party\llvm\include\;$(SolutionDir)\third_party\gflags\src\;$(SolutionDir)\src\;$(SolutionDir)\third_party;$(SolutionDir)\ + $(SolutionDir)\third_party\libav-bin\include\;$(SolutionDir)\third_party\beaengine\include\;$(SolutionDir)\third_party\llvm\include\;%(AdditionalIncludeDirectories) Windows @@ -523,7 +524,7 @@ true true BEA_ENGINE_STATIC=1;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - $(SolutionDir)\third_party\libav-bin\include\;$(SolutionDir)\third_party\beaengine\include\;$(SolutionDir)\third_party\llvm\include\;$(SolutionDir)\third_party\gflags\src\;$(SolutionDir)\src\;$(SolutionDir)\third_party;$(SolutionDir)\ + $(SolutionDir)\third_party\libav-bin\include\;$(SolutionDir)\third_party\beaengine\include\;$(SolutionDir)\third_party\llvm\include\;%(AdditionalIncludeDirectories) Windows @@ -539,4 +540,4 @@ - \ No newline at end of file + diff --git a/libxenia.vcxproj.filters b/libxenia.vcxproj.filters index 563796688..2fa2d11a0 100644 --- a/libxenia.vcxproj.filters +++ b/libxenia.vcxproj.filters @@ -382,9 +382,6 @@ src\xenia\debug - - src\xenia\debug - src\xenia\cpu\compiler\passes @@ -984,9 +981,6 @@ src\xenia\debug - - src\xenia\debug - src\xenia\debug @@ -1349,6 +1343,11 @@ src\xenia\apu + + src\xenia\debug\proto + + + src\xenia\debug\proto @@ -1379,5 +1378,8 @@ src\xenia\kernel + + src\xenia\debug\proto + - \ No newline at end of file + diff --git a/src/Xenia.Debug.UI/MainWindow.Designer.cs b/src/Xenia.Debug.UI/MainWindow.Designer.cs index bc11d14c0..ef0ef581b 100644 --- a/src/Xenia.Debug.UI/MainWindow.Designer.cs +++ b/src/Xenia.Debug.UI/MainWindow.Designer.cs @@ -29,7 +29,7 @@ this.mainToolStrip = new System.Windows.Forms.ToolStrip(); this.toolStripButton1 = new System.Windows.Forms.ToolStripButton(); this.statusStrip = new System.Windows.Forms.StatusStrip(); - this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); + this.statusMessageLabel = new System.Windows.Forms.ToolStripStatusLabel(); this.mainMenuStrip.SuspendLayout(); this.mainToolStrip.SuspendLayout(); this.statusStrip.SuspendLayout(); @@ -72,18 +72,18 @@ // statusStrip // this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripStatusLabel1}); + this.statusMessageLabel}); this.statusStrip.Location = new System.Drawing.Point(0, 1081); this.statusStrip.Name = "statusStrip"; this.statusStrip.Size = new System.Drawing.Size(1571, 22); this.statusStrip.TabIndex = 4; this.statusStrip.Text = "statusStrip1"; // - // toolStripStatusLabel1 + // statusMessageLabel // - this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; - this.toolStripStatusLabel1.Size = new System.Drawing.Size(118, 17); - this.toolStripStatusLabel1.Text = "toolStripStatusLabel1"; + this.statusMessageLabel.Name = "statusMessageLabel"; + this.statusMessageLabel.Size = new System.Drawing.Size(118, 17); + this.statusMessageLabel.Text = ""; // // MainWindow // @@ -115,7 +115,7 @@ private System.Windows.Forms.ToolStrip mainToolStrip; private System.Windows.Forms.ToolStripButton toolStripButton1; private System.Windows.Forms.StatusStrip statusStrip; - private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; + private System.Windows.Forms.ToolStripStatusLabel statusMessageLabel; private WeifenLuo.WinFormsUI.Docking.DockPanel dockPanel; } } \ No newline at end of file diff --git a/src/Xenia.Debug.UI/MainWindow.cs b/src/Xenia.Debug.UI/MainWindow.cs index bcff2b7d8..4434e1c1a 100644 --- a/src/Xenia.Debug.UI/MainWindow.cs +++ b/src/Xenia.Debug.UI/MainWindow.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using System.Windows.Forms; using WeifenLuo.WinFormsUI.Docking; using Xenia.Debug.UI.Views; +using Xenia.Debug.Utilities; namespace Xenia.Debug.UI { public partial class MainWindow : Form { @@ -16,14 +17,14 @@ namespace Xenia.Debug.UI { private BreakpointsPanel breakpointsPanel; private CallstackPanel callstackPanel; - private List codeDocuments = new List(); + private readonly List codeDocuments = new List(); private FilesystemPanel filesystemPanel; private FunctionsPanel functionsPanel; private HeapDocument heapDocument; - private List memoryDocuments = new List(); + private readonly List memoryDocuments = new List(); private ModulesPanel modulesPanel; private ProfilePanel profilePanel; - private List registersPanels = new List(); + private readonly List registersPanels = new List(); private StatisticsDocument statisticsDocument; private ThreadsPanel threadsPanel; private TracePanel tracePanel; @@ -44,7 +45,9 @@ namespace Xenia.Debug.UI { Controls.Add(dockPanel); Controls.SetChildIndex(dockPanel, 0); - this.Debugger = new Debugger(); + Debugger = new Debugger((AsyncTask task) => { + BeginInvoke(task); + }); breakpointsPanel = new BreakpointsPanel(Debugger); callstackPanel = new CallstackPanel(Debugger); @@ -66,6 +69,28 @@ namespace Xenia.Debug.UI { // new DeserializeDockContent(GetContentFromPersistString); SetupDefaultLayout(); + + Debugger.StateChanged += Debugger_StateChanged; + Debugger_StateChanged(this, Debugger.CurrentState); + + Debugger.Attach(); + } + + private void Debugger_StateChanged(object sender, Debugger.State e) { + switch (e) { + case Debugger.State.Idle: + statusMessageLabel.Text = "Idle"; + break; + case Debugger.State.Attaching: + statusMessageLabel.Text = "Attaching"; + break; + case Debugger.State.Attached: + statusMessageLabel.Text = "Attached"; + break; + case Debugger.State.Detached: + statusMessageLabel.Text = "Detached"; + break; + } } private void SetupDefaultLayout() { diff --git a/src/Xenia.Debug/BreakpointList.cs b/src/Xenia.Debug/BreakpointList.cs index a5564e773..d7adf5c4b 100644 --- a/src/Xenia.Debug/BreakpointList.cs +++ b/src/Xenia.Debug/BreakpointList.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,16 +7,26 @@ using System.Threading.Tasks; using Xenia.Debug.Utilities; namespace Xenia.Debug { - public class BreakpointList : Changeable { + public class BreakpointList : Changeable, IReadOnlyCollection { + private readonly Debugger debugger; private readonly List breakpoints = new List(); - public void Add(Breakpoint breakpoint) { + public BreakpointList(Debugger debugger) { + this.debugger = debugger; } - public void Remove(Breakpoint breakpoint) { + public int Count { + get { + return breakpoints.Count; + } } - public void Clear() { + public IEnumerator GetEnumerator() { + return breakpoints.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return breakpoints.GetEnumerator(); } } } diff --git a/src/Xenia.Debug/DebugClient.cs b/src/Xenia.Debug/DebugClient.cs deleted file mode 100644 index 7ce678035..000000000 --- a/src/Xenia.Debug/DebugClient.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Xenia.Debug { - public class DebugClient { - } -} diff --git a/src/Xenia.Debug/Debugger.cs b/src/Xenia.Debug/Debugger.cs index 0ab55e72a..c11d6a45f 100644 --- a/src/Xenia.Debug/Debugger.cs +++ b/src/Xenia.Debug/Debugger.cs @@ -1,15 +1,47 @@ -using System; +using FlatBuffers; +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Net; +using System.Net.Sockets; using System.Text; +using System.Threading; using System.Threading.Tasks; +using xe.debug.proto; +using Xenia.Debug.Utilities; namespace Xenia.Debug { + public class Debugger { - public DebugClient DebugClient { - get; + private readonly static string kServerHostname = ""; + private readonly static int kServerPort = 19000; + + public enum State { + Idle, + Attaching, + Attached, + Detached, } + private class PendingRequest { + public uint requestId; + public ByteBuffer byteBuffer; + public TaskCompletionSource responseTask; + } + + private Socket socket; + private readonly ConcurrentDictionary + pendingRequests = new ConcurrentDictionary(); + private uint nextRequestId = 1; + + public event EventHandler StateChanged; + + public State CurrentState { + get; private set; + } + = State.Idle; + public BreakpointList BreakpointList { get; } @@ -25,28 +57,187 @@ namespace Xenia.Debug { public ThreadList ThreadList { get; } - - public Debugger() { - this.DebugClient = new DebugClient(); - this.BreakpointList = new BreakpointList(); - this.FunctionList = new FunctionList(); - this.Memory = new Memory(); - this.ModuleList = new ModuleList(); - this.ThreadList = new ThreadList(); + public Debugger(AsyncTaskRunner asyncTaskRunner) { + Dispatch.AsyncTaskRunner = asyncTaskRunner; + + this.BreakpointList = new BreakpointList(this); + this.FunctionList = new FunctionList(this); + this.Memory = new Memory(this); + this.ModuleList = new ModuleList(this); + this.ThreadList = new ThreadList(this); } - public bool Open() { - return true; + public Task Attach() { + return Attach(CancellationToken.None); } - public delegate void ChangedEventHandler(EventArgs e); + public async Task Attach(CancellationToken cancellationToken) { + System.Diagnostics.Debug.Assert(CurrentState == State.Idle); - public event ChangedEventHandler Changed; + SocketPermission permission = new SocketPermission( + NetworkAccess.Connect, + TransportType.Tcp, + kServerHostname, + kServerPort + ); + permission.Demand(); - private void OnChanged(EventArgs e) { - if (Changed != null) { - Changed(e); + IPAddress ipAddress = new IPAddress(new byte[] { 127, 0, 0, 1 }); + IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, kServerPort); + + socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, + ProtocolType.Tcp); + socket.Blocking = false; + socket.NoDelay = true; + socket.ReceiveBufferSize = 1024 * 1024; + socket.SendBufferSize = 1024 * 1024; + socket.ReceiveTimeout = 0; + socket.SendTimeout = 0; + + OnStateChanged(State.Attaching); + + while (true) { + Task task = Task.Factory.FromAsync(socket.BeginConnect, socket.EndConnect, ipEndPoint, null); + try { + await task.WithCancellation(cancellationToken); + } catch (OperationCanceledException) { + socket.Close(); + socket = null; + OnStateChanged(State.Idle); + return; + } catch (SocketException e) { + if (e.SocketErrorCode == SocketError.ConnectionRefused) { + // Not found - emulator may still be starting. + System.Diagnostics.Debug.WriteLine("Connection refused; trying again..."); + continue; + } + OnStateChanged(State.Idle); + return; + } + break; + } + + // Start recv pump. + Dispatch.Issue(() => ReceivePump()); + + var fbb = BeginRequest(); + AttachRequest.StartAttachRequest(fbb); + int requestDataOffset = AttachRequest.EndAttachRequest(fbb); + var response = await CommitRequest(fbb, RequestData.AttachRequest, requestDataOffset); + + OnStateChanged(State.Attached); + } + + public void Detach() { + if (CurrentState == State.Idle || CurrentState == State.Detached) { + return; + } + + socket.Close(); + socket = null; + + OnStateChanged(State.Detached); + } + + private async void ReceivePump() { + // Read length. + var lengthBuffer = new byte[4]; + int receiveLength; + try { + receiveLength = await Task.Factory.FromAsync( + (callback, state) => socket.BeginReceive(lengthBuffer, 0, lengthBuffer.Length, + SocketFlags.None, callback, state), + asyncResult => socket.EndReceive(asyncResult), null); + } catch (SocketException) { + System.Diagnostics.Debug.WriteLine("Socket read error; detaching"); + Detach(); + return; + } + if (receiveLength == 0 || receiveLength != 4) { + // Failed? + ReceivePump(); + return; + } + var length = BitConverter.ToInt32(lengthBuffer, 0); + + // Read body. + var bodyBuffer = new byte[length]; + receiveLength = await Task.Factory.FromAsync( + (callback, state) => socket.BeginReceive(bodyBuffer, 0, bodyBuffer.Length, SocketFlags.None, callback, state), + asyncResult => socket.EndReceive(asyncResult), + null); + if (receiveLength == 0 || receiveLength != bodyBuffer.Length) { + // Failed? + ReceivePump(); + return; + } + + // Emit message. + OnMessageReceived(bodyBuffer); + + // Continue pumping. + Dispatch.Issue(() => ReceivePump()); + } + + private void OnMessageReceived(byte[] buffer) { + ByteBuffer byteBuffer = new ByteBuffer(buffer); + var response = Response.GetRootAsResponse(byteBuffer); + if (response.Id != 0) { + // Response. + PendingRequest pendingRequest; + if (!pendingRequests.TryRemove(response.Id, out pendingRequest)) { + System.Diagnostics.Debug.WriteLine("Unexpected message from debug server?"); + return; + } + pendingRequest.byteBuffer = byteBuffer; + pendingRequest.responseTask.SetResult(response); + } else { + // Event. + // TODO(benvanik): events. + } + } + + public FlatBufferBuilder BeginRequest() { + var fbb = new FlatBufferBuilder(32 * 1024); + return fbb; + } + + public async Task CommitRequest(FlatBufferBuilder fbb, + RequestData requestDataType, + int requestDataOffset) { + PendingRequest request = new PendingRequest(); + request.requestId = nextRequestId++; + request.responseTask = new TaskCompletionSource(); + pendingRequests.TryAdd(request.requestId, request); + + int requestOffset = + Request.CreateRequest(fbb, request.requestId, + requestDataType, requestDataOffset); + fbb.Finish(requestOffset); + + // Update the placeholder size. + int bufferOffset = fbb.DataBuffer.Position; + int bufferLength = fbb.DataBuffer.Length - fbb.DataBuffer.Position; + fbb.DataBuffer.PutInt(bufferOffset - 4, bufferLength); + + // Send request. + await socket.SendTaskAsync(fbb.DataBuffer.Data, bufferOffset - 4, + bufferLength + 4, SocketFlags.None); + + // Await response. + var response = await request.responseTask.Task; + + return response; + } + + private void OnStateChanged(State newState) { + if (newState == CurrentState) { + return; + } + CurrentState = newState; + if (StateChanged != null) { + StateChanged(this, newState); } } } diff --git a/src/Xenia.Debug/FunctionList.cs b/src/Xenia.Debug/FunctionList.cs index 840fd252b..28d3a055f 100644 --- a/src/Xenia.Debug/FunctionList.cs +++ b/src/Xenia.Debug/FunctionList.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,6 +7,26 @@ using System.Threading.Tasks; using Xenia.Debug.Utilities; namespace Xenia.Debug { - public class FunctionList : Changeable { + public class FunctionList : Changeable, IReadOnlyCollection { + private readonly Debugger debugger; + private readonly List functions = new List(); + + public FunctionList(Debugger debugger) { + this.debugger = debugger; + } + + public int Count { + get { + return functions.Count; + } + } + + public IEnumerator GetEnumerator() { + return functions.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return functions.GetEnumerator(); + } } } diff --git a/src/Xenia.Debug/Memory.cs b/src/Xenia.Debug/Memory.cs index 99fb89fa7..ddf216afa 100644 --- a/src/Xenia.Debug/Memory.cs +++ b/src/Xenia.Debug/Memory.cs @@ -7,6 +7,12 @@ using Xenia.Debug.Utilities; namespace Xenia.Debug { public class Memory : Changeable { + private readonly Debugger debugger; + + public Memory(Debugger debugger) { + this.debugger = debugger; + } + public MemoryView CreateView() { return new MemoryView(this); } diff --git a/src/Xenia.Debug/ModuleList.cs b/src/Xenia.Debug/ModuleList.cs index d292f99fc..6303db5e2 100644 --- a/src/Xenia.Debug/ModuleList.cs +++ b/src/Xenia.Debug/ModuleList.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,6 +7,26 @@ using System.Threading.Tasks; using Xenia.Debug.Utilities; namespace Xenia.Debug { - public class ModuleList : Changeable { + public class ModuleList : Changeable, IReadOnlyCollection { + private readonly Debugger debugger; + private readonly List modules = new List(); + + public ModuleList(Debugger debugger) { + this.debugger = debugger; + } + + public int Count { + get { + return modules.Count; + } + } + + public IEnumerator GetEnumerator() { + return modules.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return modules.GetEnumerator(); + } } } diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/AddBreakpointRequest.cs b/src/Xenia.Debug/Proto/xe/debug/proto/AddBreakpointRequest.cs new file mode 100644 index 000000000..c813f81b8 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/AddBreakpointRequest.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class AddBreakpointRequest : Table { + public static AddBreakpointRequest GetRootAsAddBreakpointRequest(ByteBuffer _bb) { return GetRootAsAddBreakpointRequest(_bb, new AddBreakpointRequest()); } + public static AddBreakpointRequest GetRootAsAddBreakpointRequest(ByteBuffer _bb, AddBreakpointRequest obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public AddBreakpointRequest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartAddBreakpointRequest(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndAddBreakpointRequest(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/AddBreakpointResponse.cs b/src/Xenia.Debug/Proto/xe/debug/proto/AddBreakpointResponse.cs new file mode 100644 index 000000000..dd4545606 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/AddBreakpointResponse.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class AddBreakpointResponse : Table { + public static AddBreakpointResponse GetRootAsAddBreakpointResponse(ByteBuffer _bb) { return GetRootAsAddBreakpointResponse(_bb, new AddBreakpointResponse()); } + public static AddBreakpointResponse GetRootAsAddBreakpointResponse(ByteBuffer _bb, AddBreakpointResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public AddBreakpointResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartAddBreakpointResponse(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndAddBreakpointResponse(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/AttachRequest.cs b/src/Xenia.Debug/Proto/xe/debug/proto/AttachRequest.cs new file mode 100644 index 000000000..71d91ac13 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/AttachRequest.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class AttachRequest : Table { + public static AttachRequest GetRootAsAttachRequest(ByteBuffer _bb) { return GetRootAsAttachRequest(_bb, new AttachRequest()); } + public static AttachRequest GetRootAsAttachRequest(ByteBuffer _bb, AttachRequest obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public AttachRequest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartAttachRequest(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndAttachRequest(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/AttachResponse.cs b/src/Xenia.Debug/Proto/xe/debug/proto/AttachResponse.cs new file mode 100644 index 000000000..137aa0cee --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/AttachResponse.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class AttachResponse : Table { + public static AttachResponse GetRootAsAttachResponse(ByteBuffer _bb) { return GetRootAsAttachResponse(_bb, new AttachResponse()); } + public static AttachResponse GetRootAsAttachResponse(ByteBuffer _bb, AttachResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public AttachResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartAttachResponse(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndAttachResponse(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/Foo.cs b/src/Xenia.Debug/Proto/xe/debug/proto/Foo.cs new file mode 100644 index 000000000..7e2cf22f0 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/Foo.cs @@ -0,0 +1,13 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +public enum Foo : sbyte +{ + A = 1, + B = 2, +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ListBreakpointsRequest.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ListBreakpointsRequest.cs new file mode 100644 index 000000000..4c9d418b5 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/ListBreakpointsRequest.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class ListBreakpointsRequest : Table { + public static ListBreakpointsRequest GetRootAsListBreakpointsRequest(ByteBuffer _bb) { return GetRootAsListBreakpointsRequest(_bb, new ListBreakpointsRequest()); } + public static ListBreakpointsRequest GetRootAsListBreakpointsRequest(ByteBuffer _bb, ListBreakpointsRequest obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public ListBreakpointsRequest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartListBreakpointsRequest(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndListBreakpointsRequest(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ListBreakpointsResponse.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ListBreakpointsResponse.cs new file mode 100644 index 000000000..60855c76e --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/ListBreakpointsResponse.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class ListBreakpointsResponse : Table { + public static ListBreakpointsResponse GetRootAsListBreakpointsResponse(ByteBuffer _bb) { return GetRootAsListBreakpointsResponse(_bb, new ListBreakpointsResponse()); } + public static ListBreakpointsResponse GetRootAsListBreakpointsResponse(ByteBuffer _bb, ListBreakpointsResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public ListBreakpointsResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartListBreakpointsResponse(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndListBreakpointsResponse(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/RemoveBreakpointRequest.cs b/src/Xenia.Debug/Proto/xe/debug/proto/RemoveBreakpointRequest.cs new file mode 100644 index 000000000..6048fd602 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/RemoveBreakpointRequest.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class RemoveBreakpointRequest : Table { + public static RemoveBreakpointRequest GetRootAsRemoveBreakpointRequest(ByteBuffer _bb) { return GetRootAsRemoveBreakpointRequest(_bb, new RemoveBreakpointRequest()); } + public static RemoveBreakpointRequest GetRootAsRemoveBreakpointRequest(ByteBuffer _bb, RemoveBreakpointRequest obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public RemoveBreakpointRequest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartRemoveBreakpointRequest(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndRemoveBreakpointRequest(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/RemoveBreakpointResponse.cs b/src/Xenia.Debug/Proto/xe/debug/proto/RemoveBreakpointResponse.cs new file mode 100644 index 000000000..67a7e1491 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/RemoveBreakpointResponse.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class RemoveBreakpointResponse : Table { + public static RemoveBreakpointResponse GetRootAsRemoveBreakpointResponse(ByteBuffer _bb) { return GetRootAsRemoveBreakpointResponse(_bb, new RemoveBreakpointResponse()); } + public static RemoveBreakpointResponse GetRootAsRemoveBreakpointResponse(ByteBuffer _bb, RemoveBreakpointResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public RemoveBreakpointResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartRemoveBreakpointResponse(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndRemoveBreakpointResponse(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/Request.cs b/src/Xenia.Debug/Proto/xe/debug/proto/Request.cs new file mode 100644 index 000000000..4072dd1d6 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/Request.cs @@ -0,0 +1,39 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class Request : Table { + public static Request GetRootAsRequest(ByteBuffer _bb) { return GetRootAsRequest(_bb, new Request()); } + public static Request GetRootAsRequest(ByteBuffer _bb, Request obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public Request __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public uint Id { get { int o = __offset(4); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public RequestData RequestDataType { get { int o = __offset(6); return o != 0 ? (RequestData)bb.Get(o + bb_pos) : (RequestData)0; } } + public Table GetRequestData(Table obj) { int o = __offset(8); return o != 0 ? __union(obj, o) : null; } + + public static int CreateRequest(FlatBufferBuilder builder, + uint id = 0, + RequestData request_data_type = 0, + int request_data = 0) { + builder.StartObject(3); + Request.AddRequestData(builder, request_data); + Request.AddId(builder, id); + Request.AddRequestDataType(builder, request_data_type); + return Request.EndRequest(builder); + } + + public static void StartRequest(FlatBufferBuilder builder) { builder.StartObject(3); } + public static void AddId(FlatBufferBuilder builder, uint id) { builder.AddUint(0, id, 0); } + public static void AddRequestDataType(FlatBufferBuilder builder, RequestData requestDataType) { builder.AddByte(1, (byte)(requestDataType), 0); } + public static void AddRequestData(FlatBufferBuilder builder, int requestDataOffset) { builder.AddOffset(2, requestDataOffset, 0); } + public static int EndRequest(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs b/src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs new file mode 100644 index 000000000..8e9a3857e --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs @@ -0,0 +1,17 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +public enum RequestData : byte +{ + NONE = 0, + AttachRequest = 1, + ListBreakpointsRequest = 2, + AddBreakpointRequest = 3, + UpdateBreakpointRequest = 4, + RemoveBreakpointRequest = 5, +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/Response.cs b/src/Xenia.Debug/Proto/xe/debug/proto/Response.cs new file mode 100644 index 000000000..7066a1810 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/Response.cs @@ -0,0 +1,39 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class Response : Table { + public static Response GetRootAsResponse(ByteBuffer _bb) { return GetRootAsResponse(_bb, new Response()); } + public static Response GetRootAsResponse(ByteBuffer _bb, Response obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public Response __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public uint Id { get { int o = __offset(4); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + public ResponseData ResponseDataType { get { int o = __offset(6); return o != 0 ? (ResponseData)bb.Get(o + bb_pos) : (ResponseData)0; } } + public Table GetResponseData(Table obj) { int o = __offset(8); return o != 0 ? __union(obj, o) : null; } + + public static int CreateResponse(FlatBufferBuilder builder, + uint id = 0, + ResponseData response_data_type = 0, + int response_data = 0) { + builder.StartObject(3); + Response.AddResponseData(builder, response_data); + Response.AddId(builder, id); + Response.AddResponseDataType(builder, response_data_type); + return Response.EndResponse(builder); + } + + public static void StartResponse(FlatBufferBuilder builder) { builder.StartObject(3); } + public static void AddId(FlatBufferBuilder builder, uint id) { builder.AddUint(0, id, 0); } + public static void AddResponseDataType(FlatBufferBuilder builder, ResponseData responseDataType) { builder.AddByte(1, (byte)(responseDataType), 0); } + public static void AddResponseData(FlatBufferBuilder builder, int responseDataOffset) { builder.AddOffset(2, responseDataOffset, 0); } + public static int EndResponse(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs new file mode 100644 index 000000000..1b7f0264d --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs @@ -0,0 +1,17 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +public enum ResponseData : byte +{ + NONE = 0, + AttachResponse = 1, + ListBreakpointsResponse = 2, + AddBreakpointResponse = 3, + UpdateBreakpointResponse = 4, + RemoveBreakpointResponse = 5, +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/StructTest.cs b/src/Xenia.Debug/Proto/xe/debug/proto/StructTest.cs new file mode 100644 index 000000000..fd5945560 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/StructTest.cs @@ -0,0 +1,25 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class StructTest : Struct { + public StructTest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public short A { get { return bb.GetShort(bb_pos + 0); } } + public sbyte B { get { return bb.GetSbyte(bb_pos + 2); } } + public Foo C { get { return (Foo)bb.GetSbyte(bb_pos + 3); } } + + public static int CreateStructTest(FlatBufferBuilder builder, short A, sbyte B, Foo C) { + builder.Prep(2, 4); + builder.PutSbyte((sbyte)(C)); + builder.PutSbyte(B); + builder.PutShort(A); + return builder.Offset; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/TableTest.cs b/src/Xenia.Debug/Proto/xe/debug/proto/TableTest.cs new file mode 100644 index 000000000..25d353e73 --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/TableTest.cs @@ -0,0 +1,35 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class TableTest : Table { + public static TableTest GetRootAsTableTest(ByteBuffer _bb) { return GetRootAsTableTest(_bb, new TableTest()); } + public static TableTest GetRootAsTableTest(ByteBuffer _bb, TableTest obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public TableTest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public StructTest St { get { return GetSt(new StructTest()); } } + public StructTest GetSt(StructTest obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; } + public byte GetIv(int j) { int o = __offset(6); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; } + public int IvLength { get { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } } + public string Name { get { int o = __offset(8); return o != 0 ? __string(o + bb_pos) : null; } } + public uint Id { get { int o = __offset(10); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } + + public static void StartTableTest(FlatBufferBuilder builder) { builder.StartObject(4); } + public static void AddSt(FlatBufferBuilder builder, int stOffset) { builder.AddStruct(0, stOffset, 0); } + public static void AddIv(FlatBufferBuilder builder, int ivOffset) { builder.AddOffset(1, ivOffset, 0); } + public static int CreateIvVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); } + public static void StartIvVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } + public static void AddName(FlatBufferBuilder builder, int nameOffset) { builder.AddOffset(2, nameOffset, 0); } + public static void AddId(FlatBufferBuilder builder, uint id) { builder.AddUint(3, id, 0); } + public static int EndTableTest(FlatBufferBuilder builder) { + int o = builder.EndObject(); + builder.Required(o, 8); // name + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/UpdateBreakpointRequest.cs b/src/Xenia.Debug/Proto/xe/debug/proto/UpdateBreakpointRequest.cs new file mode 100644 index 000000000..322625e1e --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/UpdateBreakpointRequest.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class UpdateBreakpointRequest : Table { + public static UpdateBreakpointRequest GetRootAsUpdateBreakpointRequest(ByteBuffer _bb) { return GetRootAsUpdateBreakpointRequest(_bb, new UpdateBreakpointRequest()); } + public static UpdateBreakpointRequest GetRootAsUpdateBreakpointRequest(ByteBuffer _bb, UpdateBreakpointRequest obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public UpdateBreakpointRequest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartUpdateBreakpointRequest(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndUpdateBreakpointRequest(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/UpdateBreakpointResponse.cs b/src/Xenia.Debug/Proto/xe/debug/proto/UpdateBreakpointResponse.cs new file mode 100644 index 000000000..273e654cb --- /dev/null +++ b/src/Xenia.Debug/Proto/xe/debug/proto/UpdateBreakpointResponse.cs @@ -0,0 +1,22 @@ +// automatically generated, do not modify + +namespace xe.debug.proto +{ + +using FlatBuffers; + +public sealed class UpdateBreakpointResponse : Table { + public static UpdateBreakpointResponse GetRootAsUpdateBreakpointResponse(ByteBuffer _bb) { return GetRootAsUpdateBreakpointResponse(_bb, new UpdateBreakpointResponse()); } + public static UpdateBreakpointResponse GetRootAsUpdateBreakpointResponse(ByteBuffer _bb, UpdateBreakpointResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public UpdateBreakpointResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartUpdateBreakpointResponse(FlatBufferBuilder builder) { builder.StartObject(0); } + public static int EndUpdateBreakpointResponse(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return o; + } +}; + + +} diff --git a/src/Xenia.Debug/ThreadList.cs b/src/Xenia.Debug/ThreadList.cs index 3f7cabdff..099e65311 100644 --- a/src/Xenia.Debug/ThreadList.cs +++ b/src/Xenia.Debug/ThreadList.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,6 +7,26 @@ using System.Threading.Tasks; using Xenia.Debug.Utilities; namespace Xenia.Debug { - public class ThreadList : Changeable { + public class ThreadList : Changeable, IReadOnlyCollection { + private readonly Debugger debugger; + private readonly List threads = new List(); + + public ThreadList(Debugger debugger) { + this.debugger = debugger; + } + + public int Count { + get { + return threads.Count; + } + } + + public IEnumerator GetEnumerator() { + return threads.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { + return threads.GetEnumerator(); + } } } diff --git a/src/Xenia.Debug/Utilities/Dispatch.cs b/src/Xenia.Debug/Utilities/Dispatch.cs new file mode 100644 index 000000000..e24f3b3db --- /dev/null +++ b/src/Xenia.Debug/Utilities/Dispatch.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Xenia.Debug.Utilities { + public delegate void AsyncTask(); + public delegate void AsyncTaskRunner(AsyncTask task); + + public static class Dispatch { + public static AsyncTaskRunner AsyncTaskRunner { + get; set; + } + + public static void Issue(AsyncTask task) { + AsyncTaskRunner(task); + } + } +} diff --git a/src/Xenia.Debug/Utilities/TaskExtensions.cs b/src/Xenia.Debug/Utilities/TaskExtensions.cs new file mode 100644 index 000000000..46ba4afae --- /dev/null +++ b/src/Xenia.Debug/Utilities/TaskExtensions.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Xenia.Debug.Utilities { + public static class TaskExtensions { + public static async Task + WithCancellation(this Task task, CancellationToken cancellationToken) { + var tcs = new TaskCompletionSource(); + using (cancellationToken.Register( + s => ((TaskCompletionSource)s).TrySetResult(true), tcs)) { + if (task != await Task.WhenAny(task, tcs.Task)) + throw new OperationCanceledException(cancellationToken); + } + await task; + } + + public static async Task WithCancellation( + this Task task, CancellationToken cancellationToken) { + var tcs = new TaskCompletionSource(); + using (cancellationToken.Register( + s => ((TaskCompletionSource)s).TrySetResult(true), tcs)) { + if (task != await Task.WhenAny(task, tcs.Task)) + throw new OperationCanceledException(cancellationToken); + } + return await task; + } + + public static Task SendTaskAsync(this Socket socket, byte[] buffer, + int offset, int size, SocketFlags flags) { + IAsyncResult result = + socket.BeginSend(buffer, offset, size, flags, null, null); + return Task.Factory.FromAsync(result, socket.EndSend); + } + } +} diff --git a/src/Xenia.Debug/Xenia.Debug.csproj b/src/Xenia.Debug/Xenia.Debug.csproj index b556d6a31..794b5a7dd 100644 --- a/src/Xenia.Debug/Xenia.Debug.csproj +++ b/src/Xenia.Debug/Xenia.Debug.csproj @@ -43,10 +43,24 @@ + + Flatbuffers\ByteBuffer.cs + + + Flatbuffers\FlatBufferBuilder.cs + + + Flatbuffers\FlatBufferConstants.cs + + + Flatbuffers\Struct.cs + + + Flatbuffers\Table.cs + - @@ -55,9 +69,26 @@ + + + + + + + + + + + + + + + + +