diff --git a/src/Xenia.Debug.UI/Controls/BaseDocument.cs b/src/Xenia.Debug.UI/Controls/BaseDocument.cs
index 79b96f8ac..90930261b 100644
--- a/src/Xenia.Debug.UI/Controls/BaseDocument.cs
+++ b/src/Xenia.Debug.UI/Controls/BaseDocument.cs
@@ -11,6 +11,8 @@ using WeifenLuo.WinFormsUI.Docking;
namespace Xenia.Debug.UI.Controls {
public partial class BaseDocument : DockContent {
+ public static MainWindow MainWindow;
+
public BaseDocument() {
InitializeComponent();
}
diff --git a/src/Xenia.Debug.UI/Controls/BasePanel.cs b/src/Xenia.Debug.UI/Controls/BasePanel.cs
index 90c30589b..d3ec117ef 100644
--- a/src/Xenia.Debug.UI/Controls/BasePanel.cs
+++ b/src/Xenia.Debug.UI/Controls/BasePanel.cs
@@ -11,6 +11,8 @@ using WeifenLuo.WinFormsUI.Docking;
namespace Xenia.Debug.UI.Controls {
public partial class BasePanel : DockContent {
+ public static MainWindow MainWindow;
+
public BasePanel() {
InitializeComponent();
}
diff --git a/src/Xenia.Debug.UI/MainWindow.cs b/src/Xenia.Debug.UI/MainWindow.cs
index 17b7ebcb4..a262fe933 100644
--- a/src/Xenia.Debug.UI/MainWindow.cs
+++ b/src/Xenia.Debug.UI/MainWindow.cs
@@ -8,6 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
+using Xenia.Debug.UI.Controls;
using Xenia.Debug.UI.Views;
using Xenia.Debug.Utilities;
@@ -36,6 +37,9 @@ namespace Xenia.Debug.UI {
public MainWindow() {
InitializeComponent();
+ BasePanel.MainWindow = this;
+ BaseDocument.MainWindow = this;
+
dockPanel = new DockPanel();
dockPanel.Dock = System.Windows.Forms.DockStyle.Fill;
dockPanel.DockBackColor = System.Drawing.SystemColors.AppWorkspace;
@@ -76,7 +80,7 @@ namespace Xenia.Debug.UI {
Debugger.StateChanged += Debugger_StateChanged;
Debugger_StateChanged(this, Debugger.CurrentState);
Debugger.CurrentContext.Changed += CurrentContext_Changed;
- CurrentContext_Changed();
+ CurrentContext_Changed(Debugger.CurrentContext);
Debugger.Attach();
}
@@ -102,7 +106,7 @@ namespace Xenia.Debug.UI {
controlToolStrip.Enabled = enabled;
}
- private void CurrentContext_Changed() {
+ private void CurrentContext_Changed(Context sender) {
bool enabled = false;
switch (Debugger.CurrentContext.RunState) {
case RunState.Updating:
@@ -157,6 +161,11 @@ namespace Xenia.Debug.UI {
dockPanel.ResumeLayout(true, true);
}
+ public void OpenFunction(Function function) {
+ var document = codeDocuments[0];
+ document.Show(function);
+ }
+
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
//if (keyData == (Keys.Control | Keys.F)) {
// MessageBox.Show("What the Ctrl+F?");
diff --git a/src/Xenia.Debug.UI/Views/BreakpointsPanel.cs b/src/Xenia.Debug.UI/Views/BreakpointsPanel.cs
index ae7e02875..d4e9022a2 100644
--- a/src/Xenia.Debug.UI/Views/BreakpointsPanel.cs
+++ b/src/Xenia.Debug.UI/Views/BreakpointsPanel.cs
@@ -19,10 +19,10 @@ namespace Xenia.Debug.UI.Views {
this.debugger = debugger;
debugger.BreakpointList.Changed += UpdateBreakpointsList;
- UpdateBreakpointsList();
+ UpdateBreakpointsList(debugger.BreakpointList);
}
- private void UpdateBreakpointsList() {
+ private void UpdateBreakpointsList(BreakpointList sender) {
breakpointsListView.BeginUpdate();
breakpointsListView.Items.Clear();
foreach (Breakpoint breakpoint in debugger.BreakpointList) {
diff --git a/src/Xenia.Debug.UI/Views/CodeDocument.Designer.cs b/src/Xenia.Debug.UI/Views/CodeDocument.Designer.cs
index 2a9570716..b4ba47e88 100644
--- a/src/Xenia.Debug.UI/Views/CodeDocument.Designer.cs
+++ b/src/Xenia.Debug.UI/Views/CodeDocument.Designer.cs
@@ -1,4 +1,6 @@
-namespace Xenia.Debug.UI.Views {
+using System;
+
+namespace Xenia.Debug.UI.Views {
partial class CodeDocument {
///
/// Required designer variable.
@@ -24,6 +26,12 @@
///
private void InitializeComponent() {
this.sourceTextBox = new System.Windows.Forms.TextBox();
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.disasmMachineCodeCheckBox = new System.Windows.Forms.CheckBox();
+ this.disasmOptimizedHirCheckBox = new System.Windows.Forms.CheckBox();
+ this.disasmUnoptimizedHirCheckBox = new System.Windows.Forms.CheckBox();
+ this.disasmPpcCheckBox = new System.Windows.Forms.CheckBox();
+ this.panel1.SuspendLayout();
this.SuspendLayout();
//
// sourceTextBox
@@ -31,20 +39,93 @@
this.sourceTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
+ this.sourceTextBox.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.sourceTextBox.HideSelection = false;
this.sourceTextBox.Location = new System.Drawing.Point(12, 75);
+ this.sourceTextBox.MaxLength = 99999;
this.sourceTextBox.Multiline = true;
this.sourceTextBox.Name = "sourceTextBox";
- this.sourceTextBox.Size = new System.Drawing.Size(740, 586);
+ this.sourceTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.sourceTextBox.Size = new System.Drawing.Size(740, 563);
this.sourceTextBox.TabIndex = 0;
//
+ // panel1
+ //
+ this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.panel1.Controls.Add(this.disasmMachineCodeCheckBox);
+ this.panel1.Controls.Add(this.disasmOptimizedHirCheckBox);
+ this.panel1.Controls.Add(this.disasmUnoptimizedHirCheckBox);
+ this.panel1.Controls.Add(this.disasmPpcCheckBox);
+ this.panel1.Location = new System.Drawing.Point(12, 644);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(740, 17);
+ this.panel1.TabIndex = 1;
+ //
+ // disasmMachineCodeCheckBox
+ //
+ this.disasmMachineCodeCheckBox.AutoSize = true;
+ this.disasmMachineCodeCheckBox.Checked = true;
+ this.disasmMachineCodeCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.disasmMachineCodeCheckBox.Location = new System.Drawing.Point(302, 0);
+ this.disasmMachineCodeCheckBox.Name = "disasmMachineCodeCheckBox";
+ this.disasmMachineCodeCheckBox.Size = new System.Drawing.Size(95, 17);
+ this.disasmMachineCodeCheckBox.TabIndex = 3;
+ this.disasmMachineCodeCheckBox.Text = "Machine Code";
+ this.disasmMachineCodeCheckBox.UseVisualStyleBackColor = true;
+ this.disasmMachineCodeCheckBox.CheckedChanged += new System.EventHandler(this.DisasmCheckBoxChanged);
+ //
+ // disasmOptimizedHirCheckBox
+ //
+ this.disasmOptimizedHirCheckBox.AutoSize = true;
+ this.disasmOptimizedHirCheckBox.Checked = true;
+ this.disasmOptimizedHirCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.disasmOptimizedHirCheckBox.Location = new System.Drawing.Point(202, 0);
+ this.disasmOptimizedHirCheckBox.Name = "disasmOptimizedHirCheckBox";
+ this.disasmOptimizedHirCheckBox.Size = new System.Drawing.Size(94, 17);
+ this.disasmOptimizedHirCheckBox.TabIndex = 2;
+ this.disasmOptimizedHirCheckBox.Text = "Optimized HIR";
+ this.disasmOptimizedHirCheckBox.UseVisualStyleBackColor = true;
+ this.disasmOptimizedHirCheckBox.CheckedChanged += new System.EventHandler(this.DisasmCheckBoxChanged);
+ //
+ // disasmUnoptimizedHirCheckBox
+ //
+ this.disasmUnoptimizedHirCheckBox.AutoSize = true;
+ this.disasmUnoptimizedHirCheckBox.Checked = true;
+ this.disasmUnoptimizedHirCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.disasmUnoptimizedHirCheckBox.Location = new System.Drawing.Point(90, 0);
+ this.disasmUnoptimizedHirCheckBox.Name = "disasmUnoptimizedHirCheckBox";
+ this.disasmUnoptimizedHirCheckBox.Size = new System.Drawing.Size(106, 17);
+ this.disasmUnoptimizedHirCheckBox.TabIndex = 1;
+ this.disasmUnoptimizedHirCheckBox.Text = "Unoptimized HIR";
+ this.disasmUnoptimizedHirCheckBox.UseVisualStyleBackColor = true;
+ this.disasmUnoptimizedHirCheckBox.CheckedChanged += new System.EventHandler(this.DisasmCheckBoxChanged);
+ //
+ // disasmPpcCheckBox
+ //
+ this.disasmPpcCheckBox.AutoSize = true;
+ this.disasmPpcCheckBox.Checked = true;
+ this.disasmPpcCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.disasmPpcCheckBox.Location = new System.Drawing.Point(0, 0);
+ this.disasmPpcCheckBox.Name = "disasmPpcCheckBox";
+ this.disasmPpcCheckBox.Size = new System.Drawing.Size(84, 17);
+ this.disasmPpcCheckBox.TabIndex = 0;
+ this.disasmPpcCheckBox.Text = "Source PPC";
+ this.disasmPpcCheckBox.UseVisualStyleBackColor = true;
+ this.disasmPpcCheckBox.CheckedChanged += new System.EventHandler(this.DisasmCheckBoxChanged);
+ //
// CodeDocument
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(764, 673);
+ this.Controls.Add(this.panel1);
this.Controls.Add(this.sourceTextBox);
+ this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Name = "CodeDocument";
this.Text = "Code";
+ this.panel1.ResumeLayout(false);
+ this.panel1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@@ -53,5 +134,10 @@
#endregion
private System.Windows.Forms.TextBox sourceTextBox;
+ private System.Windows.Forms.Panel panel1;
+ private System.Windows.Forms.CheckBox disasmMachineCodeCheckBox;
+ private System.Windows.Forms.CheckBox disasmOptimizedHirCheckBox;
+ private System.Windows.Forms.CheckBox disasmUnoptimizedHirCheckBox;
+ private System.Windows.Forms.CheckBox disasmPpcCheckBox;
}
}
\ No newline at end of file
diff --git a/src/Xenia.Debug.UI/Views/CodeDocument.cs b/src/Xenia.Debug.UI/Views/CodeDocument.cs
index 138b70301..508e336b5 100644
--- a/src/Xenia.Debug.UI/Views/CodeDocument.cs
+++ b/src/Xenia.Debug.UI/Views/CodeDocument.cs
@@ -14,9 +14,67 @@ namespace Xenia.Debug.UI.Views {
public partial class CodeDocument : BaseDocument {
private readonly Debugger debugger;
+ private Function function;
+
public CodeDocument(Debugger debugger) {
InitializeComponent();
this.debugger = debugger;
}
+
+ public async void Show(Function function) {
+ this.function = function;
+
+ this.sourceTextBox.Text = "Loading...";
+ await function.Invalidate();
+
+ UpdateSourceTextBox();
+ }
+
+ private void UpdateSourceTextBox() {
+ string combinedString = "";
+
+ if (disasmPpcCheckBox.Checked) {
+ combinedString += "Source PPC" + Environment.NewLine;
+ if (function.DisasmPpc != null) {
+ combinedString += function.DisasmPpc;
+ } else {
+ combinedString += "(unavailable)";
+ }
+ combinedString += Environment.NewLine + Environment.NewLine;
+ }
+ if (disasmUnoptimizedHirCheckBox.Checked) {
+ combinedString += "Unoptimized HIR" + Environment.NewLine;
+ if (function.DisasmHirUnoptimized != null) {
+ combinedString += function.DisasmHirUnoptimized;
+ } else {
+ combinedString += "(unavailable)";
+ }
+ combinedString += Environment.NewLine + Environment.NewLine;
+ }
+ if (disasmOptimizedHirCheckBox.Checked) {
+ combinedString += "Optimized HIR" + Environment.NewLine;
+ if (function.DisasmHirOptimized != null) {
+ combinedString += function.DisasmHirOptimized;
+ } else {
+ combinedString += "(unavailable)";
+ }
+ combinedString += Environment.NewLine + Environment.NewLine;
+ }
+ if (disasmMachineCodeCheckBox.Checked) {
+ combinedString += "Machine Code" + Environment.NewLine;
+ if (function.DisasmMachineCode != null) {
+ combinedString += function.DisasmMachineCode;
+ } else {
+ combinedString += "(unavailable)";
+ }
+ combinedString += Environment.NewLine + Environment.NewLine;
+ }
+
+ this.sourceTextBox.Text = combinedString;
+ }
+
+ private void DisasmCheckBoxChanged(object sender, EventArgs e) {
+ UpdateSourceTextBox();
+ }
}
}
diff --git a/src/Xenia.Debug.UI/Views/FunctionsPanel.Designer.cs b/src/Xenia.Debug.UI/Views/FunctionsPanel.Designer.cs
index 6ebbc7b88..726be557c 100644
--- a/src/Xenia.Debug.UI/Views/FunctionsPanel.Designer.cs
+++ b/src/Xenia.Debug.UI/Views/FunctionsPanel.Designer.cs
@@ -28,15 +28,17 @@
this.functionsListBox = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
- // moduleComboBox
+ // modulesComboBox
//
this.modulesComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
+ this.modulesComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.modulesComboBox.FormattingEnabled = true;
this.modulesComboBox.Location = new System.Drawing.Point(12, 12);
- this.modulesComboBox.Name = "moduleComboBox";
+ this.modulesComboBox.Name = "modulesComboBox";
this.modulesComboBox.Size = new System.Drawing.Size(234, 21);
this.modulesComboBox.TabIndex = 0;
+ this.modulesComboBox.SelectedIndexChanged += new System.EventHandler(this.modulesComboBox_SelectedIndexChanged);
//
// filterTextBox
//
@@ -48,6 +50,7 @@
this.filterTextBox.Name = "filterTextBox";
this.filterTextBox.Size = new System.Drawing.Size(234, 20);
this.filterTextBox.TabIndex = 1;
+ this.filterTextBox.TextChanged += new System.EventHandler(this.filterTextBox_TextChanged);
//
// functionsListBox
//
@@ -59,6 +62,7 @@
this.functionsListBox.Name = "functionsListBox";
this.functionsListBox.Size = new System.Drawing.Size(234, 524);
this.functionsListBox.TabIndex = 2;
+ this.functionsListBox.SelectedIndexChanged += new System.EventHandler(this.functionsListBox_SelectedIndexChanged);
//
// FunctionsPanel
//
@@ -68,6 +72,7 @@
this.Controls.Add(this.functionsListBox);
this.Controls.Add(this.filterTextBox);
this.Controls.Add(this.modulesComboBox);
+ this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Name = "FunctionsPanel";
this.Text = "Functions";
this.ResumeLayout(false);
diff --git a/src/Xenia.Debug.UI/Views/FunctionsPanel.cs b/src/Xenia.Debug.UI/Views/FunctionsPanel.cs
index c2dc25ceb..80555caa6 100644
--- a/src/Xenia.Debug.UI/Views/FunctionsPanel.cs
+++ b/src/Xenia.Debug.UI/Views/FunctionsPanel.cs
@@ -18,17 +18,84 @@ namespace Xenia.Debug.UI.Views {
InitializeComponent();
this.debugger = debugger;
+ RefreshFunctionList();
+
debugger.ModuleList.Changed += UpdateModulesList;
- UpdateModulesList();
+ UpdateModulesList(debugger.ModuleList);
}
- private void UpdateModulesList() {
+ private void UpdateModulesList(ModuleList sender) {
modulesComboBox.BeginUpdate();
modulesComboBox.Items.Clear();
foreach (Module module in debugger.ModuleList) {
- modulesComboBox.Items.Add("Module A");
+ modulesComboBox.Items.Add(module);
+ module.Changed += Module_Changed;
}
modulesComboBox.EndUpdate();
}
+
+ private void Module_Changed(KernelObject sender) {
+ if (modulesComboBox.SelectedItem != sender) {
+ return;
+ }
+
+ RefreshFunctionList();
+ }
+
+ private void modulesComboBox_SelectedIndexChanged(object sender, EventArgs e) {
+ if (modulesComboBox.SelectedItem == null) {
+ return;
+ }
+ var module = (Module)modulesComboBox.SelectedItem;
+
+ RefreshFunctionList();
+ }
+
+ private void RefreshFunctionList() {
+ if (modulesComboBox.SelectedItem == null) {
+ functionsListBox.Items.Clear();
+ functionsListBox.Enabled = false;
+ filterTextBox.Enabled = false;
+ return;
+ }
+ functionsListBox.Enabled = true;
+ filterTextBox.Enabled = true;
+ var module = (Module)modulesComboBox.SelectedItem;
+
+ functionsListBox.BeginUpdate();
+ functionsListBox.Items.Clear();
+
+ foreach (Function function in module) {
+ functionsListBox.Items.Add(function);
+ }
+
+ functionsListBox.EndUpdate();
+ }
+
+ private void filterTextBox_TextChanged(object sender, EventArgs e) {
+ var module = (Module)modulesComboBox.SelectedItem;
+
+ var filter = filterTextBox.Text.ToLowerInvariant();
+
+ functionsListBox.BeginUpdate();
+ functionsListBox.Items.Clear();
+
+ foreach (Function function in module) {
+ if (filter.Length == 0 || function.LowerName.Contains(filter)) {
+ functionsListBox.Items.Add(function);
+ }
+ }
+
+ functionsListBox.EndUpdate();
+ }
+
+ private void functionsListBox_SelectedIndexChanged(object sender, EventArgs e) {
+ var function = (Function)functionsListBox.SelectedItem;
+ if (function == null) {
+ return;
+ }
+
+ MainWindow.OpenFunction(function);
+ }
}
}
diff --git a/src/Xenia.Debug.UI/Views/ModulesPanel.Designer.cs b/src/Xenia.Debug.UI/Views/ModulesPanel.Designer.cs
index ba7e8e824..7e68fe63c 100644
--- a/src/Xenia.Debug.UI/Views/ModulesPanel.Designer.cs
+++ b/src/Xenia.Debug.UI/Views/ModulesPanel.Designer.cs
@@ -23,10 +23,15 @@
/// the contents of this method with the code editor.
///
private void InitializeComponent() {
+ System.Windows.Forms.ColumnHeader columnHeader1;
+ System.Windows.Forms.ColumnHeader columnHeader2;
+ System.Windows.Forms.ColumnHeader columnHeader3;
+ System.Windows.Forms.ColumnHeader columnHeader4;
this.modulesListView = new System.Windows.Forms.ListView();
- this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.SuspendLayout();
//
// modulesListView
@@ -35,9 +40,10 @@
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.modulesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
- this.columnHeader1,
- this.columnHeader2,
- this.columnHeader3});
+ columnHeader1,
+ columnHeader2,
+ columnHeader3,
+ columnHeader4});
this.modulesListView.Location = new System.Drawing.Point(12, 12);
this.modulesListView.Name = "modulesListView";
this.modulesListView.Size = new System.Drawing.Size(748, 206);
@@ -45,12 +51,32 @@
this.modulesListView.UseCompatibleStateImageBehavior = false;
this.modulesListView.View = System.Windows.Forms.View.Details;
//
+ // columnHeader1
+ //
+ columnHeader1.Text = "Handle";
+ //
+ // columnHeader2
+ //
+ columnHeader2.Text = "Type";
+ columnHeader2.Width = 80;
+ //
+ // columnHeader3
+ //
+ columnHeader3.Text = "Name";
+ columnHeader3.Width = 120;
+ //
+ // columnHeader4
+ //
+ columnHeader4.Text = "Path";
+ columnHeader4.Width = 300;
+ //
// ModulesPanel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(772, 230);
this.Controls.Add(this.modulesListView);
+ this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Name = "ModulesPanel";
this.Text = "Modules";
this.ResumeLayout(false);
@@ -60,8 +86,5 @@
#endregion
private System.Windows.Forms.ListView modulesListView;
- private System.Windows.Forms.ColumnHeader columnHeader1;
- private System.Windows.Forms.ColumnHeader columnHeader2;
- private System.Windows.Forms.ColumnHeader columnHeader3;
}
}
\ No newline at end of file
diff --git a/src/Xenia.Debug.UI/Views/ModulesPanel.cs b/src/Xenia.Debug.UI/Views/ModulesPanel.cs
index ff9fe72f0..18ddc0c29 100644
--- a/src/Xenia.Debug.UI/Views/ModulesPanel.cs
+++ b/src/Xenia.Debug.UI/Views/ModulesPanel.cs
@@ -19,14 +19,21 @@ namespace Xenia.Debug.UI.Views {
this.debugger = debugger;
debugger.ModuleList.Changed += UpdateModulesList;
- UpdateModulesList();
+ UpdateModulesList(debugger.ModuleList);
}
- private void UpdateModulesList() {
+ private void UpdateModulesList(ModuleList sender) {
modulesListView.BeginUpdate();
modulesListView.Items.Clear();
foreach (Module module in debugger.ModuleList) {
- modulesListView.Items.Add("Module A");
+ var item = new ListViewItem(new string[]{
+ module.Handle.ToString("X4"),
+ module.ModuleType == xe.debug.proto.ModuleType.Kernel ? "Kernel"
+ : "User",
+ module.Name,
+ module.Path,
+ });
+ modulesListView.Items.Add(item);
}
modulesListView.EndUpdate();
}
diff --git a/src/Xenia.Debug.UI/Views/ModulesPanel.resx b/src/Xenia.Debug.UI/Views/ModulesPanel.resx
index 1af7de150..9ebd52322 100644
--- a/src/Xenia.Debug.UI/Views/ModulesPanel.resx
+++ b/src/Xenia.Debug.UI/Views/ModulesPanel.resx
@@ -117,4 +117,16 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
\ No newline at end of file
diff --git a/src/Xenia.Debug.UI/Views/ThreadsPanel.cs b/src/Xenia.Debug.UI/Views/ThreadsPanel.cs
index 0357b2aa8..bd6784d8a 100644
--- a/src/Xenia.Debug.UI/Views/ThreadsPanel.cs
+++ b/src/Xenia.Debug.UI/Views/ThreadsPanel.cs
@@ -19,10 +19,10 @@ namespace Xenia.Debug.UI.Views {
this.debugger = debugger;
debugger.ThreadList.Changed += UpdateThreadList;
- UpdateThreadList();
+ UpdateThreadList(debugger.ThreadList);
}
- private void UpdateThreadList() {
+ private void UpdateThreadList(ThreadList sender) {
threadsListView.BeginUpdate();
threadsListView.Items.Clear();
foreach (Thread thread in debugger.ThreadList) {
diff --git a/src/Xenia.Debug/Breakpoint.cs b/src/Xenia.Debug/Breakpoint.cs
index 4412f5bff..43cb39e57 100644
--- a/src/Xenia.Debug/Breakpoint.cs
+++ b/src/Xenia.Debug/Breakpoint.cs
@@ -6,10 +6,14 @@ using System.Threading.Tasks;
using Xenia.Debug.Utilities;
namespace Xenia.Debug {
- public class Breakpoint : Changeable {
+ public class Breakpoint : Changeable {
// type code/data/kernel
// address+[end address]
// conditions? script?
// action (suspend, trace, etc)
+
+ public Breakpoint() {
+ this.self = this;
+ }
}
}
diff --git a/src/Xenia.Debug/BreakpointList.cs b/src/Xenia.Debug/BreakpointList.cs
index d7adf5c4b..e0bc303d2 100644
--- a/src/Xenia.Debug/BreakpointList.cs
+++ b/src/Xenia.Debug/BreakpointList.cs
@@ -7,11 +7,12 @@ using System.Threading.Tasks;
using Xenia.Debug.Utilities;
namespace Xenia.Debug {
- public class BreakpointList : Changeable, IReadOnlyCollection {
+ public class BreakpointList : Changeable, IReadOnlyCollection {
private readonly Debugger debugger;
private readonly List breakpoints = new List();
public BreakpointList(Debugger debugger) {
+ this.self = this;
this.debugger = debugger;
}
diff --git a/src/Xenia.Debug/Context.cs b/src/Xenia.Debug/Context.cs
index 762f3e6d9..853147e46 100644
--- a/src/Xenia.Debug/Context.cs
+++ b/src/Xenia.Debug/Context.cs
@@ -12,10 +12,11 @@ namespace Xenia.Debug {
Paused,
}
- public class Context : Changeable {
+ public class Context : Changeable {
private readonly Debugger debugger;
public Context(Debugger debugger) {
+ this.self = this;
this.debugger = debugger;
}
diff --git a/src/Xenia.Debug/Debugger.cs b/src/Xenia.Debug/Debugger.cs
index 212a762df..0d1818d5d 100644
--- a/src/Xenia.Debug/Debugger.cs
+++ b/src/Xenia.Debug/Debugger.cs
@@ -193,14 +193,19 @@ namespace Xenia.Debug {
// 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;
+ int bodyOffset = 0;
+ while (bodyOffset != bodyBuffer.Length) {
+ receiveLength = await Task.Factory.FromAsync(
+ (callback, state) => socket.BeginReceive(
+ bodyBuffer, bodyOffset, bodyBuffer.Length - bodyOffset,
+ SocketFlags.None, callback, state),
+ asyncResult => socket.EndReceive(asyncResult), null);
+ if (receiveLength == 0) {
+ // Failed?
+ ReceivePump();
+ return;
+ }
+ bodyOffset += receiveLength;
}
// Emit message.
diff --git a/src/Xenia.Debug/Function.cs b/src/Xenia.Debug/Function.cs
index 63170f899..913f6413a 100644
--- a/src/Xenia.Debug/Function.cs
+++ b/src/Xenia.Debug/Function.cs
@@ -3,18 +3,21 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using xe.debug.proto;
using Xenia.Debug.Utilities;
namespace Xenia.Debug {
- public class Function : Changeable {
+ public class Function : Changeable {
// status: declared, defined, failed
- // module
- // name
- // startAddress
- // endAddress
// behavior: default, prolog, epilog, epilog_return, extern
// extern info?
+ public readonly Debugger Debugger;
+ public readonly Module Module;
+ public readonly ulong Identifier;
+ public readonly uint AddressStart;
+ public readonly uint AddressEnd;
+
// source map
// disasm:
@@ -29,5 +32,79 @@ namespace Xenia.Debug {
// call count
// caller history
// instruction execution counts
+
+ public string DisasmPpc {
+ get; private set;
+ }
+ public string DisasmHirUnoptimized {
+ get; private set;
+ }
+ public string DisasmHirOptimized {
+ get; private set;
+ }
+ public string DisasmMachineCode {
+ get; private set;
+ }
+
+ public Function(Debugger debugger, Module module, xe.debug.proto.FunctionEntry functionEntry) {
+ this.self = this;
+ this.Debugger = debugger;
+ this.Module = module;
+ Identifier = functionEntry.Identifier;
+ AddressStart = functionEntry.AddressStart;
+ AddressEnd = functionEntry.AddressEnd;
+ Name = functionEntry.Name;
+ }
+
+ private string name;
+ public string Name {
+ get {
+ return name;
+ }
+ set {
+ name = value;
+ if (value == null) {
+ name = "sub_" + AddressStart.ToString("X8");
+ }
+ LowerName = name.ToLowerInvariant();
+ }
+ }
+ public string LowerName {
+ get; set;
+ }
+
+ public override string ToString() {
+ return Name;
+ }
+
+ public async Task Invalidate() {
+ var fbb = Debugger.BeginRequest();
+ int requestDataOffset = GetFunctionRequest.CreateGetFunctionRequest(fbb, Identifier);
+ var response = await Debugger.CommitRequest(
+ fbb, RequestData.GetFunctionRequest, requestDataOffset);
+
+ var responseData = new GetFunctionResponse();
+ response.GetResponseData(responseData);
+ var functionData = responseData.Function;
+
+ this.DisasmPpc = functionData.DisasmPpc;
+ this.DisasmHirUnoptimized = functionData.DisasmHirRaw;
+ this.DisasmHirOptimized = functionData.DisasmHirOpt;
+ this.DisasmMachineCode = functionData.DisasmMachineCode;
+ if (DisasmPpc != null) {
+ DisasmPpc = DisasmPpc.Replace("\n", "\r\n");
+ }
+ if (DisasmHirUnoptimized != null) {
+ DisasmHirUnoptimized = DisasmHirUnoptimized.Replace("\n", "\r\n");
+ }
+ if (DisasmHirOptimized != null) {
+ DisasmHirOptimized = DisasmHirOptimized.Replace("\n", "\r\n");
+ }
+ if (DisasmMachineCode != null) {
+ DisasmMachineCode = DisasmMachineCode.Replace("\n", "\r\n");
+ }
+
+ OnChanged();
+ }
}
}
diff --git a/src/Xenia.Debug/KernelObject.cs b/src/Xenia.Debug/KernelObject.cs
index 0a70e3988..55035e98a 100644
--- a/src/Xenia.Debug/KernelObject.cs
+++ b/src/Xenia.Debug/KernelObject.cs
@@ -6,11 +6,12 @@ using System.Threading.Tasks;
using Xenia.Debug.Utilities;
namespace Xenia.Debug {
- public class KernelObject : Changeable {
+ public class KernelObject : Changeable {
public readonly Debugger Debugger;
public readonly uint Handle;
public KernelObject(Debugger debugger, uint handle) {
+ this.self = this;
this.Debugger = debugger;
this.Handle = handle;
}
diff --git a/src/Xenia.Debug/Memory.cs b/src/Xenia.Debug/Memory.cs
index 979e864bb..44dd9328c 100644
--- a/src/Xenia.Debug/Memory.cs
+++ b/src/Xenia.Debug/Memory.cs
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
using Xenia.Debug.Utilities;
namespace Xenia.Debug {
- public class Memory : Changeable, IDisposable {
+ public class Memory : Changeable, IDisposable {
private readonly Debugger debugger;
private class MapInfo {
@@ -41,6 +41,7 @@ namespace Xenia.Debug {
public UIntPtr PhysicalMembase;
public Memory(Debugger debugger) {
+ this.self = this;
this.debugger = debugger;
}
diff --git a/src/Xenia.Debug/MemoryView.cs b/src/Xenia.Debug/MemoryView.cs
index e15969a9e..7c2dc9e57 100644
--- a/src/Xenia.Debug/MemoryView.cs
+++ b/src/Xenia.Debug/MemoryView.cs
@@ -6,10 +6,11 @@ using System.Threading.Tasks;
using Xenia.Debug.Utilities;
namespace Xenia.Debug {
- public class MemoryView : Changeable {
+ public class MemoryView : Changeable {
private readonly Memory memory;
public MemoryView(Memory memory) {
+ this.self = this;
this.memory = memory;
}
diff --git a/src/Xenia.Debug/Module.cs b/src/Xenia.Debug/Module.cs
index faa779154..9e0928bd3 100644
--- a/src/Xenia.Debug/Module.cs
+++ b/src/Xenia.Debug/Module.cs
@@ -9,26 +9,95 @@ using Xenia.Debug.Utilities;
namespace Xenia.Debug {
public class Module : KernelObject, IReadOnlyCollection {
+ private bool hasFetched = false;
+ private uint functionCount = 0;
private readonly List functions = new List();
- // xobject: handle
- // path
- // type: user, kernel
- // if user:
- // xex header?
-
public Module(Debugger debugger, uint moduleHandle) : base(debugger, moduleHandle) {
}
- public async Task Invalidate() {
+ public async Task Invalidate(uint newFunctionCount) {
+ if (hasFetched && newFunctionCount == functionCount) {
+ // No-op.
+ return;
+ }
+
+ var pendingTasks = new List();
+
+ if (!hasFetched) {
+ pendingTasks.Add(InvalidateModule());
+ hasFetched = true;
+ }
+
+ if (newFunctionCount != functionCount) {
+ uint functionIndexStart = functionCount;
+ uint functionIndexEnd = newFunctionCount - 1;
+ functionCount = newFunctionCount;
+ pendingTasks.Add(InvalidateFunctions(functionIndexStart, functionIndexEnd));
+ }
+
+ await Task.WhenAll(pendingTasks);
+
+ OnChanged();
+ }
+
+ private async Task InvalidateModule() {
var fbb = Debugger.BeginRequest();
int requestDataOffset = GetModuleRequest.CreateGetModuleRequest(fbb, Handle);
var response = await Debugger.CommitRequest(
fbb, RequestData.GetModuleRequest, requestDataOffset);
- GetModuleResponse responseData = new GetModuleResponse();
+
+ var responseData = new GetModuleResponse();
response.GetResponseData(responseData);
- //
+ ModuleType = responseData.Module.Type;
+ Name = responseData.Module.Name;
+ Path = responseData.Module.Path;
+ }
+
+ private async Task InvalidateFunctions(uint functionIndexStart, uint functionIndexEnd) {
+ var fbb = Debugger.BeginRequest();
+ int requestDataOffset = ListFunctionsRequest.CreateListFunctionsRequest(
+ fbb, Handle, functionIndexStart, functionIndexEnd);
+ var response = await Debugger.CommitRequest(
+ fbb, RequestData.ListFunctionsRequest, requestDataOffset);
+
+ var responseData = new ListFunctionsResponse();
+ response.GetResponseData(responseData);
+
+ var functionEntry = new xe.debug.proto.FunctionEntry();
+ for (int i = 0; i < responseData.EntryLength; ++i) {
+ responseData.GetEntry(functionEntry, i);
+ var function = new Function(Debugger, this, functionEntry);
+ functions.Add(function);
+ }
+
+ functions.Sort((Function a, Function b) => {
+ return (int)((long)a.AddressStart - (long)b.AddressStart);
+ });
+ }
+
+ public ModuleType ModuleType {
+ get;
+ private set;
+ }
+
+ public string Name {
+ get;
+ private set;
+ }
+
+ public string Path {
+ get;
+ private set;
+ }
+
+ public override string ToString() {
+ return ToShortString();
+ }
+
+ public string ToShortString() {
+ return string.Format("[{0:X4}] {1}", Handle, Name);
}
public int Count {
diff --git a/src/Xenia.Debug/ModuleList.cs b/src/Xenia.Debug/ModuleList.cs
index f68d14589..3919891ca 100644
--- a/src/Xenia.Debug/ModuleList.cs
+++ b/src/Xenia.Debug/ModuleList.cs
@@ -8,11 +8,12 @@ using xe.debug.proto;
using Xenia.Debug.Utilities;
namespace Xenia.Debug {
- public class ModuleList : Changeable, IReadOnlyCollection {
+ public class ModuleList : Changeable, IReadOnlyCollection {
private readonly Debugger debugger;
private readonly List modules = new List();
public ModuleList(Debugger debugger) {
+ this.self = this;
this.debugger = debugger;
}
@@ -26,20 +27,23 @@ namespace Xenia.Debug {
response.GetResponseData(responseData);
var pendingTasks = new List();
- for (int i = 0; i < responseData.ModuleIdsLength; ++i) {
- uint moduleHandle = responseData.GetModuleIds(i);
- var module = modules.Find((m) => m.Handle == moduleHandle);
+ for (int i = 0; i < responseData.EntryLength; ++i) {
+ var moduleEntry = responseData.GetEntry(i);
+ var module = modules.Find((m) => m.Handle == moduleEntry.Handle);
if (module == null) {
// Module not found.
- module = new Module(debugger, moduleHandle);
- pendingTasks.Add(module.Invalidate());
+ module = new Module(debugger, moduleEntry.Handle);
+ pendingTasks.Add(module.Invalidate(moduleEntry.FunctionCount));
+ modules.Add(module);
} else {
// Module already present.
- // Modules are immutable, so ignore?
+ pendingTasks.Add(module.Invalidate(moduleEntry.FunctionCount));
}
}
await Task.WhenAll(pendingTasks);
+
+ OnChanged();
}
public int Count {
diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/Function.cs b/src/Xenia.Debug/Proto/xe/debug/proto/Function.cs
new file mode 100644
index 000000000..939737021
--- /dev/null
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/Function.cs
@@ -0,0 +1,59 @@
+// automatically generated, do not modify
+
+namespace xe.debug.proto
+{
+
+using FlatBuffers;
+
+public sealed class Function : Table {
+ public static Function GetRootAsFunction(ByteBuffer _bb) { return GetRootAsFunction(_bb, new Function()); }
+ public static Function GetRootAsFunction(ByteBuffer _bb, Function obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public Function __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+
+ public ulong Identifier { get { int o = __offset(4); return o != 0 ? bb.GetUlong(o + bb_pos) : (ulong)0; } }
+ public uint AddressStart { get { int o = __offset(6); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
+ public uint AddressEnd { get { int o = __offset(8); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
+ public string Name { get { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } }
+ public string DisasmPpc { get { int o = __offset(12); return o != 0 ? __string(o + bb_pos) : null; } }
+ public string DisasmHirRaw { get { int o = __offset(14); return o != 0 ? __string(o + bb_pos) : null; } }
+ public string DisasmHirOpt { get { int o = __offset(16); return o != 0 ? __string(o + bb_pos) : null; } }
+ public string DisasmMachineCode { get { int o = __offset(18); return o != 0 ? __string(o + bb_pos) : null; } }
+
+ public static int CreateFunction(FlatBufferBuilder builder,
+ ulong identifier = 0,
+ uint address_start = 0,
+ uint address_end = 0,
+ int name = 0,
+ int disasm_ppc = 0,
+ int disasm_hir_raw = 0,
+ int disasm_hir_opt = 0,
+ int disasm_machine_code = 0) {
+ builder.StartObject(8);
+ Function.AddIdentifier(builder, identifier);
+ Function.AddDisasmMachineCode(builder, disasm_machine_code);
+ Function.AddDisasmHirOpt(builder, disasm_hir_opt);
+ Function.AddDisasmHirRaw(builder, disasm_hir_raw);
+ Function.AddDisasmPpc(builder, disasm_ppc);
+ Function.AddName(builder, name);
+ Function.AddAddressEnd(builder, address_end);
+ Function.AddAddressStart(builder, address_start);
+ return Function.EndFunction(builder);
+ }
+
+ public static void StartFunction(FlatBufferBuilder builder) { builder.StartObject(8); }
+ public static void AddIdentifier(FlatBufferBuilder builder, ulong identifier) { builder.AddUlong(0, identifier, 0); }
+ public static void AddAddressStart(FlatBufferBuilder builder, uint addressStart) { builder.AddUint(1, addressStart, 0); }
+ public static void AddAddressEnd(FlatBufferBuilder builder, uint addressEnd) { builder.AddUint(2, addressEnd, 0); }
+ public static void AddName(FlatBufferBuilder builder, int nameOffset) { builder.AddOffset(3, nameOffset, 0); }
+ public static void AddDisasmPpc(FlatBufferBuilder builder, int disasmPpcOffset) { builder.AddOffset(4, disasmPpcOffset, 0); }
+ public static void AddDisasmHirRaw(FlatBufferBuilder builder, int disasmHirRawOffset) { builder.AddOffset(5, disasmHirRawOffset, 0); }
+ public static void AddDisasmHirOpt(FlatBufferBuilder builder, int disasmHirOptOffset) { builder.AddOffset(6, disasmHirOptOffset, 0); }
+ public static void AddDisasmMachineCode(FlatBufferBuilder builder, int disasmMachineCodeOffset) { builder.AddOffset(7, disasmMachineCodeOffset, 0); }
+ public static int EndFunction(FlatBufferBuilder builder) {
+ int o = builder.EndObject();
+ return o;
+ }
+};
+
+
+}
diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/FunctionEntry.cs b/src/Xenia.Debug/Proto/xe/debug/proto/FunctionEntry.cs
new file mode 100644
index 000000000..2c8678db6
--- /dev/null
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/FunctionEntry.cs
@@ -0,0 +1,43 @@
+// automatically generated, do not modify
+
+namespace xe.debug.proto
+{
+
+using FlatBuffers;
+
+public sealed class FunctionEntry : Table {
+ public static FunctionEntry GetRootAsFunctionEntry(ByteBuffer _bb) { return GetRootAsFunctionEntry(_bb, new FunctionEntry()); }
+ public static FunctionEntry GetRootAsFunctionEntry(ByteBuffer _bb, FunctionEntry obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public FunctionEntry __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+
+ public ulong Identifier { get { int o = __offset(4); return o != 0 ? bb.GetUlong(o + bb_pos) : (ulong)0; } }
+ public uint AddressStart { get { int o = __offset(6); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
+ public uint AddressEnd { get { int o = __offset(8); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
+ public string Name { get { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } }
+
+ public static int CreateFunctionEntry(FlatBufferBuilder builder,
+ ulong identifier = 0,
+ uint address_start = 0,
+ uint address_end = 0,
+ int name = 0) {
+ builder.StartObject(4);
+ FunctionEntry.AddIdentifier(builder, identifier);
+ FunctionEntry.AddName(builder, name);
+ FunctionEntry.AddAddressEnd(builder, address_end);
+ FunctionEntry.AddAddressStart(builder, address_start);
+ return FunctionEntry.EndFunctionEntry(builder);
+ }
+
+ public static void StartFunctionEntry(FlatBufferBuilder builder) { builder.StartObject(4); }
+ public static void AddIdentifier(FlatBufferBuilder builder, ulong identifier) { builder.AddUlong(0, identifier, 0); }
+ public static void AddAddressStart(FlatBufferBuilder builder, uint addressStart) { builder.AddUint(1, addressStart, 0); }
+ public static void AddAddressEnd(FlatBufferBuilder builder, uint addressEnd) { builder.AddUint(2, addressEnd, 0); }
+ public static void AddName(FlatBufferBuilder builder, int nameOffset) { builder.AddOffset(3, nameOffset, 0); }
+ public static int EndFunctionEntry(FlatBufferBuilder builder) {
+ int o = builder.EndObject();
+ return o;
+ }
+};
+
+
+}
diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/GetFunctionRequest.cs b/src/Xenia.Debug/Proto/xe/debug/proto/GetFunctionRequest.cs
new file mode 100644
index 000000000..811b62195
--- /dev/null
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/GetFunctionRequest.cs
@@ -0,0 +1,31 @@
+// automatically generated, do not modify
+
+namespace xe.debug.proto
+{
+
+using FlatBuffers;
+
+public sealed class GetFunctionRequest : Table {
+ public static GetFunctionRequest GetRootAsGetFunctionRequest(ByteBuffer _bb) { return GetRootAsGetFunctionRequest(_bb, new GetFunctionRequest()); }
+ public static GetFunctionRequest GetRootAsGetFunctionRequest(ByteBuffer _bb, GetFunctionRequest obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public GetFunctionRequest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+
+ public ulong Identifier { get { int o = __offset(4); return o != 0 ? bb.GetUlong(o + bb_pos) : (ulong)0; } }
+
+ public static int CreateGetFunctionRequest(FlatBufferBuilder builder,
+ ulong identifier = 0) {
+ builder.StartObject(1);
+ GetFunctionRequest.AddIdentifier(builder, identifier);
+ return GetFunctionRequest.EndGetFunctionRequest(builder);
+ }
+
+ public static void StartGetFunctionRequest(FlatBufferBuilder builder) { builder.StartObject(1); }
+ public static void AddIdentifier(FlatBufferBuilder builder, ulong identifier) { builder.AddUlong(0, identifier, 0); }
+ public static int EndGetFunctionRequest(FlatBufferBuilder builder) {
+ int o = builder.EndObject();
+ return o;
+ }
+};
+
+
+}
diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/GetFunctionResponse.cs b/src/Xenia.Debug/Proto/xe/debug/proto/GetFunctionResponse.cs
new file mode 100644
index 000000000..d380ba848
--- /dev/null
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/GetFunctionResponse.cs
@@ -0,0 +1,32 @@
+// automatically generated, do not modify
+
+namespace xe.debug.proto
+{
+
+using FlatBuffers;
+
+public sealed class GetFunctionResponse : Table {
+ public static GetFunctionResponse GetRootAsGetFunctionResponse(ByteBuffer _bb) { return GetRootAsGetFunctionResponse(_bb, new GetFunctionResponse()); }
+ public static GetFunctionResponse GetRootAsGetFunctionResponse(ByteBuffer _bb, GetFunctionResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public GetFunctionResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+
+ public Function Function { get { return GetFunction(new Function()); } }
+ public Function GetFunction(Function obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
+
+ public static int CreateGetFunctionResponse(FlatBufferBuilder builder,
+ int function = 0) {
+ builder.StartObject(1);
+ GetFunctionResponse.AddFunction(builder, function);
+ return GetFunctionResponse.EndGetFunctionResponse(builder);
+ }
+
+ public static void StartGetFunctionResponse(FlatBufferBuilder builder) { builder.StartObject(1); }
+ public static void AddFunction(FlatBufferBuilder builder, int functionOffset) { builder.AddOffset(0, functionOffset, 0); }
+ public static int EndGetFunctionResponse(FlatBufferBuilder builder) {
+ int o = builder.EndObject();
+ return o;
+ }
+};
+
+
+}
diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ListFunctionsRequest.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ListFunctionsRequest.cs
new file mode 100644
index 000000000..a5db92929
--- /dev/null
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/ListFunctionsRequest.cs
@@ -0,0 +1,39 @@
+// automatically generated, do not modify
+
+namespace xe.debug.proto
+{
+
+using FlatBuffers;
+
+public sealed class ListFunctionsRequest : Table {
+ public static ListFunctionsRequest GetRootAsListFunctionsRequest(ByteBuffer _bb) { return GetRootAsListFunctionsRequest(_bb, new ListFunctionsRequest()); }
+ public static ListFunctionsRequest GetRootAsListFunctionsRequest(ByteBuffer _bb, ListFunctionsRequest obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public ListFunctionsRequest __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+
+ public uint ModuleId { get { int o = __offset(4); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
+ public uint FunctionIndexStart { get { int o = __offset(6); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
+ public uint FunctionIndexEnd { get { int o = __offset(8); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
+
+ public static int CreateListFunctionsRequest(FlatBufferBuilder builder,
+ uint module_id = 0,
+ uint function_index_start = 0,
+ uint function_index_end = 0) {
+ builder.StartObject(3);
+ ListFunctionsRequest.AddFunctionIndexEnd(builder, function_index_end);
+ ListFunctionsRequest.AddFunctionIndexStart(builder, function_index_start);
+ ListFunctionsRequest.AddModuleId(builder, module_id);
+ return ListFunctionsRequest.EndListFunctionsRequest(builder);
+ }
+
+ public static void StartListFunctionsRequest(FlatBufferBuilder builder) { builder.StartObject(3); }
+ public static void AddModuleId(FlatBufferBuilder builder, uint moduleId) { builder.AddUint(0, moduleId, 0); }
+ public static void AddFunctionIndexStart(FlatBufferBuilder builder, uint functionIndexStart) { builder.AddUint(1, functionIndexStart, 0); }
+ public static void AddFunctionIndexEnd(FlatBufferBuilder builder, uint functionIndexEnd) { builder.AddUint(2, functionIndexEnd, 0); }
+ public static int EndListFunctionsRequest(FlatBufferBuilder builder) {
+ int o = builder.EndObject();
+ return o;
+ }
+};
+
+
+}
diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ListFunctionsResponse.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ListFunctionsResponse.cs
new file mode 100644
index 000000000..22edf0de0
--- /dev/null
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/ListFunctionsResponse.cs
@@ -0,0 +1,35 @@
+// automatically generated, do not modify
+
+namespace xe.debug.proto
+{
+
+using FlatBuffers;
+
+public sealed class ListFunctionsResponse : Table {
+ public static ListFunctionsResponse GetRootAsListFunctionsResponse(ByteBuffer _bb) { return GetRootAsListFunctionsResponse(_bb, new ListFunctionsResponse()); }
+ public static ListFunctionsResponse GetRootAsListFunctionsResponse(ByteBuffer _bb, ListFunctionsResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+ public ListFunctionsResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+
+ public FunctionEntry GetEntry(int j) { return GetEntry(new FunctionEntry(), j); }
+ public FunctionEntry GetEntry(FunctionEntry obj, int j) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; }
+ public int EntryLength { get { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } }
+
+ public static int CreateListFunctionsResponse(FlatBufferBuilder builder,
+ int entry = 0) {
+ builder.StartObject(1);
+ ListFunctionsResponse.AddEntry(builder, entry);
+ return ListFunctionsResponse.EndListFunctionsResponse(builder);
+ }
+
+ public static void StartListFunctionsResponse(FlatBufferBuilder builder) { builder.StartObject(1); }
+ public static void AddEntry(FlatBufferBuilder builder, int entryOffset) { builder.AddOffset(0, entryOffset, 0); }
+ public static int CreateEntryVector(FlatBufferBuilder builder, int[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i]); return builder.EndVector(); }
+ public static void StartEntryVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
+ public static int EndListFunctionsResponse(FlatBufferBuilder builder) {
+ int o = builder.EndObject();
+ return o;
+ }
+};
+
+
+}
diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ListModuleEntry.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ListModuleEntry.cs
new file mode 100644
index 000000000..225ab1995
--- /dev/null
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/ListModuleEntry.cs
@@ -0,0 +1,23 @@
+// automatically generated, do not modify
+
+namespace xe.debug.proto
+{
+
+using FlatBuffers;
+
+public sealed class ListModuleEntry : Struct {
+ public ListModuleEntry __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+
+ public uint Handle { get { return bb.GetUint(bb_pos + 0); } }
+ public uint FunctionCount { get { return bb.GetUint(bb_pos + 4); } }
+
+ public static int CreateListModuleEntry(FlatBufferBuilder builder, uint Handle, uint FunctionCount) {
+ builder.Prep(4, 8);
+ builder.PutUint(FunctionCount);
+ builder.PutUint(Handle);
+ return builder.Offset;
+ }
+};
+
+
+}
diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ListModulesResponse.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ListModulesResponse.cs
index adc2c0e7d..65d3fff2a 100644
--- a/src/Xenia.Debug/Proto/xe/debug/proto/ListModulesResponse.cs
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/ListModulesResponse.cs
@@ -10,20 +10,20 @@ public sealed class ListModulesResponse : Table {
public static ListModulesResponse GetRootAsListModulesResponse(ByteBuffer _bb, ListModulesResponse obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public ListModulesResponse __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
- public uint GetModuleIds(int j) { int o = __offset(4); return o != 0 ? bb.GetUint(__vector(o) + j * 4) : (uint)0; }
- public int ModuleIdsLength { get { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } }
+ public ListModuleEntry GetEntry(int j) { return GetEntry(new ListModuleEntry(), j); }
+ public ListModuleEntry GetEntry(ListModuleEntry obj, int j) { int o = __offset(4); return o != 0 ? obj.__init(__vector(o) + j * 8, bb) : null; }
+ public int EntryLength { get { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } }
public static int CreateListModulesResponse(FlatBufferBuilder builder,
- int module_ids = 0) {
+ int entry = 0) {
builder.StartObject(1);
- ListModulesResponse.AddModuleIds(builder, module_ids);
+ ListModulesResponse.AddEntry(builder, entry);
return ListModulesResponse.EndListModulesResponse(builder);
}
public static void StartListModulesResponse(FlatBufferBuilder builder) { builder.StartObject(1); }
- public static void AddModuleIds(FlatBufferBuilder builder, int moduleIdsOffset) { builder.AddOffset(0, moduleIdsOffset, 0); }
- public static int CreateModuleIdsVector(FlatBufferBuilder builder, uint[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddUint(data[i]); return builder.EndVector(); }
- public static void StartModuleIdsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
+ public static void AddEntry(FlatBufferBuilder builder, int entryOffset) { builder.AddOffset(0, entryOffset, 0); }
+ public static void StartEntryVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 4); }
public static int EndListModulesResponse(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
index 6bd9343c4..d76d6b417 100644
--- a/src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/RequestData.cs
@@ -13,10 +13,12 @@ public enum RequestData : byte
RemoveBreakpointsRequest = 5,
ListModulesRequest = 6,
GetModuleRequest = 7,
- StopRequest = 8,
- BreakRequest = 9,
- ContinueRequest = 10,
- StepRequest = 11,
+ ListFunctionsRequest = 8,
+ GetFunctionRequest = 9,
+ StopRequest = 10,
+ BreakRequest = 11,
+ ContinueRequest = 12,
+ StepRequest = 13,
};
diff --git a/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs b/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs
index 9c9380bef..e7bec17f4 100644
--- a/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs
+++ b/src/Xenia.Debug/Proto/xe/debug/proto/ResponseData.cs
@@ -13,12 +13,14 @@ public enum ResponseData : byte
RemoveBreakpointsResponse = 5,
ListModulesResponse = 6,
GetModuleResponse = 7,
- StopResponse = 8,
- BreakResponse = 9,
- ContinueResponse = 10,
- StepResponse = 11,
- BreakpointEvent = 12,
- AccessViolationEvent = 13,
+ ListFunctionsResponse = 8,
+ GetFunctionResponse = 9,
+ StopResponse = 10,
+ BreakResponse = 11,
+ ContinueResponse = 12,
+ StepResponse = 13,
+ BreakpointEvent = 14,
+ AccessViolationEvent = 15,
};
diff --git a/src/Xenia.Debug/ThreadList.cs b/src/Xenia.Debug/ThreadList.cs
index 099e65311..09e1a514c 100644
--- a/src/Xenia.Debug/ThreadList.cs
+++ b/src/Xenia.Debug/ThreadList.cs
@@ -7,11 +7,12 @@ using System.Threading.Tasks;
using Xenia.Debug.Utilities;
namespace Xenia.Debug {
- public class ThreadList : Changeable, IReadOnlyCollection {
+ public class ThreadList : Changeable, IReadOnlyCollection {
private readonly Debugger debugger;
private readonly List threads = new List();
public ThreadList(Debugger debugger) {
+ this.self = this;
this.debugger = debugger;
}
diff --git a/src/Xenia.Debug/Utilities/Changeable.cs b/src/Xenia.Debug/Utilities/Changeable.cs
index fe527782c..b32057775 100644
--- a/src/Xenia.Debug/Utilities/Changeable.cs
+++ b/src/Xenia.Debug/Utilities/Changeable.cs
@@ -5,11 +5,13 @@ using System.Text;
using System.Threading.Tasks;
namespace Xenia.Debug.Utilities {
- public delegate void ChangedEventHandler();
+ public delegate void ChangedEventHandler(T sender);
- public class Changeable {
+ public class Changeable {
+ protected T self;
private int changeDepth;
- public event ChangedEventHandler Changed;
+
+ public event ChangedEventHandler Changed;
protected void BeginChanging() {
++changeDepth;
@@ -24,7 +26,7 @@ namespace Xenia.Debug.Utilities {
protected void OnChanged() {
System.Diagnostics.Debug.Assert(changeDepth == 0);
if (Changed != null) {
- Changed();
+ Changed(self);
}
}
}
diff --git a/src/Xenia.Debug/Xenia.Debug.csproj b/src/Xenia.Debug/Xenia.Debug.csproj
index 45fb6e891..8bd96dc71 100644
--- a/src/Xenia.Debug/Xenia.Debug.csproj
+++ b/src/Xenia.Debug/Xenia.Debug.csproj
@@ -84,10 +84,17 @@
+
+
+
+
+
+
+
diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc
index ee1f3c875..23fc8f48d 100644
--- a/src/xenia/apu/audio_system.cc
+++ b/src/xenia/apu/audio_system.cc
@@ -201,7 +201,7 @@ void AudioSystem::WorkerThreadMain() {
void AudioSystem::DecoderThreadMain() {
while (decoder_running_) {
// Wait for a kick from WriteRegister.
- decoder_fence_.Wait();
+ //decoder_fence_.Wait();
// Check to see if we're supposed to exit
if (!decoder_running_) {
diff --git a/src/xenia/cpu/module.cc b/src/xenia/cpu/module.cc
index d7fb2abde..8bf30e68d 100644
--- a/src/xenia/cpu/module.cc
+++ b/src/xenia/cpu/module.cc
@@ -149,7 +149,6 @@ SymbolStatus Module::DefineVariable(VariableInfo* symbol_info) {
}
void Module::ForEachFunction(std::function callback) {
- SCOPE_profile_cpu_f("cpu");
std::lock_guard guard(lock_);
for (auto& symbol_info : list_) {
if (symbol_info->type() == SymbolType::kFunction) {
@@ -159,21 +158,22 @@ void Module::ForEachFunction(std::function callback) {
}
}
-void Module::ForEachFunction(size_t since, size_t& version,
- std::function callback) {
- SCOPE_profile_cpu_f("cpu");
+void Module::ForEachSymbol(size_t start_index, size_t end_index,
+ std::function callback) {
std::lock_guard guard(lock_);
- size_t count = list_.size();
- version = count;
- for (size_t n = since; n < count; n++) {
- auto& symbol_info = list_[n];
- if (symbol_info->type() == SymbolType::kFunction) {
- FunctionInfo* info = static_cast(symbol_info.get());
- callback(info);
- }
+ start_index = std::min(start_index, list_.size());
+ end_index = std::min(end_index, list_.size());
+ for (size_t i = start_index; i <= end_index; ++i) {
+ auto& symbol_info = list_[i];
+ callback(symbol_info.get());
}
}
+size_t Module::QuerySymbolCount() {
+ std::lock_guard guard(lock_);
+ return list_.size();
+}
+
bool Module::ReadMap(const char* file_name) {
std::ifstream infile(file_name);
diff --git a/src/xenia/cpu/module.h b/src/xenia/cpu/module.h
index 555585fcf..517c59557 100644
--- a/src/xenia/cpu/module.h
+++ b/src/xenia/cpu/module.h
@@ -47,8 +47,9 @@ class Module {
SymbolStatus DefineVariable(VariableInfo* symbol_info);
void ForEachFunction(std::function callback);
- void ForEachFunction(size_t since, size_t& version,
- std::function callback);
+ void ForEachSymbol(size_t start_index, size_t end_index,
+ std::function callback);
+ size_t QuerySymbolCount();
bool ReadMap(const char* file_name);
diff --git a/src/xenia/debug/debugger.cc b/src/xenia/debug/debugger.cc
index 90fc69724..b5ca19770 100644
--- a/src/xenia/debug/debugger.cc
+++ b/src/xenia/debug/debugger.cc
@@ -22,6 +22,9 @@
#include "xenia/cpu/function.h"
#include "xenia/cpu/processor.h"
#include "xenia/emulator.h"
+#include "xenia/kernel/objects/xkernel_module.h"
+#include "xenia/kernel/objects/xmodule.h"
+#include "xenia/kernel/objects/xuser_module.h"
// Autogenerated Flatbuffers files:
#include "xenia/debug/proto/breakpoints_generated.h"
@@ -39,6 +42,8 @@ DEFINE_bool(exit_with_debugger, true, "Exit whe the debugger disconnects.");
namespace xe {
namespace debug {
+using namespace xe::kernel;
+
using xe::cpu::ThreadState;
Breakpoint::Breakpoint(Type type, uint32_t address)
@@ -69,7 +74,7 @@ bool Debugger::StartSession() {
functions_trace_path_ = xe::join_paths(session_path, L"functions.trace");
functions_trace_file_ = ChunkedMappedMemoryWriter::Open(
- functions_trace_path_, 32 * 1024 * 1024, true);
+ functions_trace_path_, 32 * 1024 * 1024, true);
listen_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_socket_ < 1) {
@@ -235,14 +240,149 @@ void Debugger::OnMessage(std::vector buffer) {
case proto::RequestData_ListModulesRequest: {
response_data_type = proto::ResponseData_ListModulesResponse;
+ auto modules =
+ emulator()->kernel_state()->object_table()->GetObjectsByType(
+ XObject::kTypeModule);
+ std::vector module_entries;
+ for (size_t i = 0; i < modules.size(); ++i) {
+ auto& module = modules[i];
+ auto processor_module = module->processor_module();
+ module_entries.emplace_back(
+ module->handle(),
+ processor_module ? uint32_t(processor_module->QuerySymbolCount())
+ : 0);
+ }
+ auto module_entries_offset =
+ fbb.CreateVectorOfStructs(module_entries);
auto response_data = proto::ListModulesResponseBuilder(fbb);
- //
+ response_data.add_entry(module_entries_offset);
response_data_offset = response_data.Finish().Union();
} break;
case proto::RequestData_GetModuleRequest: {
+ auto request_data = reinterpret_cast(
+ request->request_data());
+ auto module =
+ emulator()->kernel_state()->object_table()->LookupObject(
+ request_data->module_id());
+ flatbuffers::Offset module_offset;
+ if (module) {
+ proto::XObject xobject_data(module->handle());
+ auto module_name_offset = fbb.CreateString(module->name());
+ auto module_path_offset = fbb.CreateString(module->path());
+ proto::ModuleBuilder module_builder(fbb);
+ module_builder.add_object(&xobject_data);
+ module_builder.add_type(
+ static_cast(module->module_type()));
+ module_builder.add_name(module_name_offset);
+ module_builder.add_path(module_path_offset);
+ switch (module->module_type()) {
+ case XModule::ModuleType::kKernelModule: {
+ auto kernel_module = reinterpret_cast(module.get());
+ break;
+ }
+ case XModule::ModuleType::kUserModule: {
+ auto user_module = reinterpret_cast(module.get());
+ // user_module->xex?
+ break;
+ }
+ default:
+ assert_unhandled_case(module->module_type());
+ break;
+ }
+ module_offset = module_builder.Finish();
+ }
response_data_type = proto::ResponseData_GetModuleResponse;
auto response_data = proto::GetModuleResponseBuilder(fbb);
- //
+ response_data.add_module(module_offset);
+ response_data_offset = response_data.Finish().Union();
+ } break;
+ case proto::RequestData_ListFunctionsRequest: {
+ auto request_data = reinterpret_cast(
+ request->request_data());
+ auto module =
+ emulator()->kernel_state()->object_table()->LookupObject(
+ request_data->module_id());
+ if (!module || !module->processor_module()) {
+ response_data_type = proto::ResponseData_ListFunctionsResponse;
+ auto response_data = proto::ListFunctionsResponseBuilder(fbb);
+ response_data_offset = response_data.Finish().Union();
+ break;
+ }
+ auto processor_module = module->processor_module();
+ size_t max_function_count = request_data->function_index_end() -
+ request_data->function_index_start() + 1;
+ std::vector> function_list;
+ function_list.reserve(max_function_count);
+ processor_module->ForEachSymbol(request_data->function_index_start(),
+ request_data->function_index_end(),
+ [&](xe::cpu::SymbolInfo* symbol_info) {
+ if (symbol_info->type() != xe::cpu::SymbolType::kFunction) {
+ return;
+ }
+ auto function_info =
+ reinterpret_cast(symbol_info);
+ flatbuffers::Offset name_offset;
+ if (!function_info->name().empty()) {
+ name_offset = fbb.CreateString(function_info->name());
+ }
+ auto function_entry = proto::FunctionEntryBuilder(fbb);
+ function_entry.add_identifier(
+ reinterpret_cast(function_info));
+ function_entry.add_address_start(function_info->address());
+ function_entry.add_address_end(function_info->end_address());
+ function_entry.add_name(name_offset);
+ function_list.push_back(function_entry.Finish());
+ });
+ auto function_list_data = fbb.CreateVector(function_list);
+ response_data_type = proto::ResponseData_ListFunctionsResponse;
+ auto response_data = proto::ListFunctionsResponseBuilder(fbb);
+ response_data.add_entry(function_list_data);
+ response_data_offset = response_data.Finish().Union();
+ } break;
+ case proto::RequestData_GetFunctionRequest: {
+ auto request_data = reinterpret_cast(
+ request->request_data());
+ auto function_info =
+ reinterpret_cast(request_data->identifier());
+ auto function = function_info->function();
+ flatbuffers::Offset name_offset;
+ if (!function_info->name().empty()) {
+ name_offset = fbb.CreateString(function_info->name());
+ }
+ flatbuffers::Offset disasm_ppc_offset;
+ flatbuffers::Offset disasm_hir_raw_offset;
+ flatbuffers::Offset disasm_hir_opt_offset;
+ flatbuffers::Offset disasm_machine_code_offset;
+ if (function && function->debug_info()) {
+ auto debug_info = function->debug_info();
+ if (debug_info->source_disasm()) {
+ disasm_ppc_offset = fbb.CreateString(debug_info->source_disasm());
+ }
+ if (debug_info->raw_hir_disasm()) {
+ disasm_hir_raw_offset =
+ fbb.CreateString(debug_info->raw_hir_disasm());
+ }
+ if (debug_info->hir_disasm()) {
+ disasm_hir_opt_offset = fbb.CreateString(debug_info->hir_disasm());
+ }
+ if (debug_info->machine_code_disasm()) {
+ disasm_machine_code_offset =
+ fbb.CreateString(debug_info->machine_code_disasm());
+ }
+ }
+ auto function_data = proto::FunctionBuilder(fbb);
+ function_data.add_identifier(request_data->identifier());
+ function_data.add_address_start(function_info->address());
+ function_data.add_address_end(function_info->end_address());
+ function_data.add_name(name_offset);
+ function_data.add_disasm_ppc(disasm_ppc_offset);
+ function_data.add_disasm_hir_raw(disasm_hir_raw_offset);
+ function_data.add_disasm_hir_opt(disasm_hir_opt_offset);
+ function_data.add_disasm_machine_code(disasm_machine_code_offset);
+ auto function_offset = function_data.Finish();
+ response_data_type = proto::ResponseData_GetFunctionResponse;
+ auto response_data = proto::GetFunctionResponseBuilder(fbb);
+ response_data.add_function(function_offset);
response_data_offset = response_data.Finish().Union();
} break;
diff --git a/src/xenia/debug/proto/messages.fbs b/src/xenia/debug/proto/messages.fbs
index 48a2cdaf2..9c3017915 100644
--- a/src/xenia/debug/proto/messages.fbs
+++ b/src/xenia/debug/proto/messages.fbs
@@ -25,6 +25,8 @@ union RequestData {
ListModulesRequest,
GetModuleRequest,
+ ListFunctionsRequest,
+ GetFunctionRequest,
StopRequest,
BreakRequest,
@@ -47,6 +49,8 @@ union ResponseData {
ListModulesResponse,
GetModuleResponse,
+ ListFunctionsResponse,
+ GetFunctionResponse,
StopResponse,
BreakResponse,
diff --git a/src/xenia/debug/proto/messages_generated.h b/src/xenia/debug/proto/messages_generated.h
index 2efb31298..fad763993 100644
--- a/src/xenia/debug/proto/messages_generated.h
+++ b/src/xenia/debug/proto/messages_generated.h
@@ -48,9 +48,16 @@ namespace debug {
namespace proto {
struct Module;
struct ListModulesRequest;
+struct ListModuleEntry;
struct ListModulesResponse;
struct GetModuleRequest;
struct GetModuleResponse;
+struct FunctionEntry;
+struct Function;
+struct ListFunctionsRequest;
+struct ListFunctionsResponse;
+struct GetFunctionRequest;
+struct GetFunctionResponse;
} // namespace proto
} // namespace debug
} // namespace xe
@@ -82,14 +89,24 @@ enum RequestData {
RequestData_RemoveBreakpointsRequest = 5,
RequestData_ListModulesRequest = 6,
RequestData_GetModuleRequest = 7,
- RequestData_StopRequest = 8,
- RequestData_BreakRequest = 9,
- RequestData_ContinueRequest = 10,
- RequestData_StepRequest = 11
+ RequestData_ListFunctionsRequest = 8,
+ RequestData_GetFunctionRequest = 9,
+ RequestData_StopRequest = 10,
+ RequestData_BreakRequest = 11,
+ RequestData_ContinueRequest = 12,
+ RequestData_StepRequest = 13
};
inline const char **EnumNamesRequestData() {
- static const char *names[] = { "NONE", "AttachRequest", "ListBreakpointsRequest", "AddBreakpointsRequest", "UpdateBreakpointsRequest", "RemoveBreakpointsRequest", "ListModulesRequest", "GetModuleRequest", "StopRequest", "BreakRequest", "ContinueRequest", "StepRequest", nullptr };
+ static const char *names[] = {
+ "NONE", "AttachRequest",
+ "ListBreakpointsRequest", "AddBreakpointsRequest",
+ "UpdateBreakpointsRequest", "RemoveBreakpointsRequest",
+ "ListModulesRequest", "GetModuleRequest",
+ "ListFunctionsRequest", "GetFunctionRequest",
+ "StopRequest", "BreakRequest",
+ "ContinueRequest", "StepRequest",
+ nullptr};
return names;
}
@@ -106,16 +123,27 @@ enum ResponseData {
ResponseData_RemoveBreakpointsResponse = 5,
ResponseData_ListModulesResponse = 6,
ResponseData_GetModuleResponse = 7,
- ResponseData_StopResponse = 8,
- ResponseData_BreakResponse = 9,
- ResponseData_ContinueResponse = 10,
- ResponseData_StepResponse = 11,
- ResponseData_BreakpointEvent = 12,
- ResponseData_AccessViolationEvent = 13
+ ResponseData_ListFunctionsResponse = 8,
+ ResponseData_GetFunctionResponse = 9,
+ ResponseData_StopResponse = 10,
+ ResponseData_BreakResponse = 11,
+ ResponseData_ContinueResponse = 12,
+ ResponseData_StepResponse = 13,
+ ResponseData_BreakpointEvent = 14,
+ ResponseData_AccessViolationEvent = 15
};
inline const char **EnumNamesResponseData() {
- static const char *names[] = { "NONE", "AttachResponse", "ListBreakpointsResponse", "AddBreakpointsResponse", "UpdateBreakpointsResponse", "RemoveBreakpointsResponse", "ListModulesResponse", "GetModuleResponse", "StopResponse", "BreakResponse", "ContinueResponse", "StepResponse", "BreakpointEvent", "AccessViolationEvent", nullptr };
+ static const char *names[] = {
+ "NONE", "AttachResponse",
+ "ListBreakpointsResponse", "AddBreakpointsResponse",
+ "UpdateBreakpointsResponse", "RemoveBreakpointsResponse",
+ "ListModulesResponse", "GetModuleResponse",
+ "ListFunctionsResponse", "GetFunctionResponse",
+ "StopResponse", "BreakResponse",
+ "ContinueResponse", "StepResponse",
+ "BreakpointEvent", "AccessViolationEvent",
+ nullptr};
return names;
}
@@ -275,6 +303,14 @@ inline bool VerifyRequestData(flatbuffers::Verifier &verifier, const void *union
case RequestData_RemoveBreakpointsRequest: return verifier.VerifyTable(reinterpret_cast(union_obj));
case RequestData_ListModulesRequest: return verifier.VerifyTable(reinterpret_cast(union_obj));
case RequestData_GetModuleRequest: return verifier.VerifyTable(reinterpret_cast(union_obj));
+ case RequestData_ListFunctionsRequest:
+ return verifier.VerifyTable(
+ reinterpret_cast(
+ union_obj));
+ case RequestData_GetFunctionRequest:
+ return verifier.VerifyTable(
+ reinterpret_cast(
+ union_obj));
case RequestData_StopRequest: return verifier.VerifyTable(reinterpret_cast(union_obj));
case RequestData_BreakRequest: return verifier.VerifyTable(reinterpret_cast(union_obj));
case RequestData_ContinueRequest: return verifier.VerifyTable(reinterpret_cast(union_obj));
@@ -293,6 +329,14 @@ inline bool VerifyResponseData(flatbuffers::Verifier &verifier, const void *unio
case ResponseData_RemoveBreakpointsResponse: return verifier.VerifyTable(reinterpret_cast(union_obj));
case ResponseData_ListModulesResponse: return verifier.VerifyTable(reinterpret_cast(union_obj));
case ResponseData_GetModuleResponse: return verifier.VerifyTable(reinterpret_cast(union_obj));
+ case ResponseData_ListFunctionsResponse:
+ return verifier.VerifyTable(
+ reinterpret_cast(
+ union_obj));
+ case ResponseData_GetFunctionResponse:
+ return verifier.VerifyTable(
+ reinterpret_cast(
+ union_obj));
case ResponseData_StopResponse: return verifier.VerifyTable(reinterpret_cast(union_obj));
case ResponseData_BreakResponse: return verifier.VerifyTable(reinterpret_cast(union_obj));
case ResponseData_ContinueResponse: return verifier.VerifyTable(reinterpret_cast(union_obj));
diff --git a/src/xenia/debug/proto/modules.fbs b/src/xenia/debug/proto/modules.fbs
index 8f30ce1ad..b41271f54 100644
--- a/src/xenia/debug/proto/modules.fbs
+++ b/src/xenia/debug/proto/modules.fbs
@@ -3,8 +3,8 @@ include "common.fbs";
namespace xe.debug.proto;
enum ModuleType:byte {
- Kernel,
- User,
+ Kernel = 0,
+ User = 1,
}
table Module {
@@ -18,8 +18,12 @@ table Module {
table ListModulesRequest {
}
+struct ListModuleEntry {
+ handle:uint;
+ function_count:uint;
+}
table ListModulesResponse {
- module_ids:[uint];
+ entry:[ListModuleEntry];
}
table GetModuleRequest {
@@ -29,3 +33,36 @@ table GetModuleResponse {
module:Module;
}
+table FunctionEntry {
+ identifier:ulong;
+ address_start:uint;
+ address_end:uint;
+ name:string;
+}
+table Function {
+ identifier:ulong;
+ address_start:uint;
+ address_end:uint;
+ name:string;
+
+ disasm_ppc:string;
+ disasm_hir_raw:string;
+ disasm_hir_opt:string;
+ disasm_machine_code:string;
+}
+
+table ListFunctionsRequest {
+ module_id:uint;
+ function_index_start:uint;
+ function_index_end:uint;
+}
+table ListFunctionsResponse {
+ entry:[FunctionEntry];
+}
+
+table GetFunctionRequest {
+ identifier:ulong;
+}
+table GetFunctionResponse {
+ function:Function;
+}
diff --git a/src/xenia/debug/proto/modules_generated.h b/src/xenia/debug/proto/modules_generated.h
index 23d221130..6ca094f3f 100644
--- a/src/xenia/debug/proto/modules_generated.h
+++ b/src/xenia/debug/proto/modules_generated.h
@@ -19,9 +19,16 @@ namespace proto {
struct Module;
struct ListModulesRequest;
+struct ListModuleEntry;
struct ListModulesResponse;
struct GetModuleRequest;
struct GetModuleResponse;
+struct FunctionEntry;
+struct Function;
+struct ListFunctionsRequest;
+struct ListFunctionsResponse;
+struct GetFunctionRequest;
+struct GetFunctionResponse;
enum ModuleType {
ModuleType_Kernel = 0,
@@ -35,6 +42,23 @@ inline const char **EnumNamesModuleType() {
inline const char *EnumNameModuleType(ModuleType e) { return EnumNamesModuleType()[e]; }
+MANUALLY_ALIGNED_STRUCT(4) ListModuleEntry FLATBUFFERS_FINAL_CLASS {
+ private:
+ uint32_t handle_;
+ uint32_t function_count_;
+
+ public:
+ ListModuleEntry(uint32_t handle, uint32_t function_count)
+ : handle_(flatbuffers::EndianScalar(handle)),
+ function_count_(flatbuffers::EndianScalar(function_count)) {}
+
+ uint32_t handle() const { return flatbuffers::EndianScalar(handle_); }
+ uint32_t function_count() const {
+ return flatbuffers::EndianScalar(function_count_);
+ }
+};
+STRUCT_END(ListModuleEntry, 8);
+
struct Module FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const xe::debug::proto::XObject *object() const { return GetStruct(4); }
ModuleType type() const { return static_cast(GetField(6, 0)); }
@@ -104,19 +128,23 @@ inline flatbuffers::Offset CreateListModulesRequest(flatbuff
}
struct ListModulesResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
- const flatbuffers::Vector *module_ids() const { return GetPointer *>(4); }
+ const flatbuffers::Vector *entry() const {
+ return GetPointer *>(4);
+ }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
- VerifyField(verifier, 4 /* module_ids */) &&
- verifier.Verify(module_ids()) &&
- verifier.EndTable();
+ VerifyField(verifier, 4 /* entry */) &&
+ verifier.Verify(entry()) && verifier.EndTable();
}
};
struct ListModulesResponseBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
- void add_module_ids(flatbuffers::Offset> module_ids) { fbb_.AddOffset(4, module_ids); }
+ void add_entry(
+ flatbuffers::Offset> entry) {
+ fbb_.AddOffset(4, entry);
+ }
ListModulesResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
ListModulesResponseBuilder &operator=(const ListModulesResponseBuilder &);
flatbuffers::Offset Finish() {
@@ -125,10 +153,12 @@ struct ListModulesResponseBuilder {
}
};
-inline flatbuffers::Offset CreateListModulesResponse(flatbuffers::FlatBufferBuilder &_fbb,
- flatbuffers::Offset> module_ids = 0) {
+inline flatbuffers::Offset CreateListModulesResponse(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset> entry =
+ 0) {
ListModulesResponseBuilder builder_(_fbb);
- builder_.add_module_ids(module_ids);
+ builder_.add_entry(entry);
return builder_.Finish();
}
@@ -189,6 +219,317 @@ inline flatbuffers::Offset CreateGetModuleResponse(flatbuffer
return builder_.Finish();
}
+struct FunctionEntry FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ uint64_t identifier() const { return GetField(4, 0); }
+ uint32_t address_start() const { return GetField(6, 0); }
+ uint32_t address_end() const { return GetField(8, 0); }
+ const flatbuffers::String *name() const {
+ return GetPointer(10);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField(verifier, 4 /* identifier */) &&
+ VerifyField(verifier, 6 /* address_start */) &&
+ VerifyField(verifier, 8 /* address_end */) &&
+ VerifyField(verifier, 10 /* name */) &&
+ verifier.Verify(name()) && verifier.EndTable();
+ }
+};
+
+struct FunctionEntryBuilder {
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_identifier(uint64_t identifier) {
+ fbb_.AddElement(4, identifier, 0);
+ }
+ void add_address_start(uint32_t address_start) {
+ fbb_.AddElement(6, address_start, 0);
+ }
+ void add_address_end(uint32_t address_end) {
+ fbb_.AddElement(8, address_end, 0);
+ }
+ void add_name(flatbuffers::Offset name) {
+ fbb_.AddOffset(10, name);
+ }
+ FunctionEntryBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ FunctionEntryBuilder &operator=(const FunctionEntryBuilder &);
+ flatbuffers::Offset Finish() {
+ auto o = flatbuffers::Offset(fbb_.EndTable(start_, 4));
+ return o;
+ }
+};
+
+inline flatbuffers::Offset CreateFunctionEntry(
+ flatbuffers::FlatBufferBuilder &_fbb, uint64_t identifier = 0,
+ uint32_t address_start = 0, uint32_t address_end = 0,
+ flatbuffers::Offset name = 0) {
+ FunctionEntryBuilder builder_(_fbb);
+ builder_.add_identifier(identifier);
+ builder_.add_name(name);
+ builder_.add_address_end(address_end);
+ builder_.add_address_start(address_start);
+ return builder_.Finish();
+}
+
+struct Function FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ uint64_t identifier() const { return GetField(4, 0); }
+ uint32_t address_start() const { return GetField(6, 0); }
+ uint32_t address_end() const { return GetField(8, 0); }
+ const flatbuffers::String *name() const {
+ return GetPointer(10);
+ }
+ const flatbuffers::String *disasm_ppc() const {
+ return GetPointer(12);
+ }
+ const flatbuffers::String *disasm_hir_raw() const {
+ return GetPointer(14);
+ }
+ const flatbuffers::String *disasm_hir_opt() const {
+ return GetPointer(16);
+ }
+ const flatbuffers::String *disasm_machine_code() const {
+ return GetPointer(18);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField(verifier, 4 /* identifier */) &&
+ VerifyField(verifier, 6 /* address_start */) &&
+ VerifyField(verifier, 8 /* address_end */) &&
+ VerifyField(verifier, 10 /* name */) &&
+ verifier.Verify(name()) &&
+ VerifyField(verifier, 12 /* disasm_ppc */) &&
+ verifier.Verify(disasm_ppc()) &&
+ VerifyField(verifier,
+ 14 /* disasm_hir_raw */) &&
+ verifier.Verify(disasm_hir_raw()) &&
+ VerifyField(verifier,
+ 16 /* disasm_hir_opt */) &&
+ verifier.Verify(disasm_hir_opt()) &&
+ VerifyField(verifier,
+ 18 /* disasm_machine_code */) &&
+ verifier.Verify(disasm_machine_code()) && verifier.EndTable();
+ }
+};
+
+struct FunctionBuilder {
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_identifier(uint64_t identifier) {
+ fbb_.AddElement(4, identifier, 0);
+ }
+ void add_address_start(uint32_t address_start) {
+ fbb_.AddElement(6, address_start, 0);
+ }
+ void add_address_end(uint32_t address_end) {
+ fbb_.AddElement(8, address_end, 0);
+ }
+ void add_name(flatbuffers::Offset name) {
+ fbb_.AddOffset(10, name);
+ }
+ void add_disasm_ppc(flatbuffers::Offset disasm_ppc) {
+ fbb_.AddOffset(12, disasm_ppc);
+ }
+ void add_disasm_hir_raw(
+ flatbuffers::Offset disasm_hir_raw) {
+ fbb_.AddOffset(14, disasm_hir_raw);
+ }
+ void add_disasm_hir_opt(
+ flatbuffers::Offset disasm_hir_opt) {
+ fbb_.AddOffset(16, disasm_hir_opt);
+ }
+ void add_disasm_machine_code(
+ flatbuffers::Offset disasm_machine_code) {
+ fbb_.AddOffset(18, disasm_machine_code);
+ }
+ FunctionBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ FunctionBuilder &operator=(const FunctionBuilder &);
+ flatbuffers::Offset Finish() {
+ auto o = flatbuffers::Offset(fbb_.EndTable(start_, 8));
+ return o;
+ }
+};
+
+inline flatbuffers::Offset CreateFunction(
+ flatbuffers::FlatBufferBuilder &_fbb, uint64_t identifier = 0,
+ uint32_t address_start = 0, uint32_t address_end = 0,
+ flatbuffers::Offset name = 0,
+ flatbuffers::Offset disasm_ppc = 0,
+ flatbuffers::Offset disasm_hir_raw = 0,
+ flatbuffers::Offset disasm_hir_opt = 0,
+ flatbuffers::Offset disasm_machine_code = 0) {
+ FunctionBuilder builder_(_fbb);
+ builder_.add_identifier(identifier);
+ builder_.add_disasm_machine_code(disasm_machine_code);
+ builder_.add_disasm_hir_opt(disasm_hir_opt);
+ builder_.add_disasm_hir_raw(disasm_hir_raw);
+ builder_.add_disasm_ppc(disasm_ppc);
+ builder_.add_name(name);
+ builder_.add_address_end(address_end);
+ builder_.add_address_start(address_start);
+ return builder_.Finish();
+}
+
+struct ListFunctionsRequest FLATBUFFERS_FINAL_CLASS
+ : private flatbuffers::Table {
+ uint32_t module_id() const { return GetField(4, 0); }
+ uint32_t function_index_start() const { return GetField(6, 0); }
+ uint32_t function_index_end() const { return GetField(8, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField(verifier, 4 /* module_id */) &&
+ VerifyField(verifier, 6 /* function_index_start */) &&
+ VerifyField(verifier, 8 /* function_index_end */) &&
+ verifier.EndTable();
+ }
+};
+
+struct ListFunctionsRequestBuilder {
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_module_id(uint32_t module_id) {
+ fbb_.AddElement(4, module_id, 0);
+ }
+ void add_function_index_start(uint32_t function_index_start) {
+ fbb_.AddElement(6, function_index_start, 0);
+ }
+ void add_function_index_end(uint32_t function_index_end) {
+ fbb_.AddElement(8, function_index_end, 0);
+ }
+ ListFunctionsRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ ListFunctionsRequestBuilder &operator=(const ListFunctionsRequestBuilder &);
+ flatbuffers::Offset Finish() {
+ auto o =
+ flatbuffers::Offset(fbb_.EndTable(start_, 3));
+ return o;
+ }
+};
+
+inline flatbuffers::Offset CreateListFunctionsRequest(
+ flatbuffers::FlatBufferBuilder &_fbb, uint32_t module_id = 0,
+ uint32_t function_index_start = 0, uint32_t function_index_end = 0) {
+ ListFunctionsRequestBuilder builder_(_fbb);
+ builder_.add_function_index_end(function_index_end);
+ builder_.add_function_index_start(function_index_start);
+ builder_.add_module_id(module_id);
+ return builder_.Finish();
+}
+
+struct ListFunctionsResponse FLATBUFFERS_FINAL_CLASS
+ : private flatbuffers::Table {
+ const flatbuffers::Vector> *entry() const {
+ return GetPointer<
+ const flatbuffers::Vector> *>(4);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField(verifier, 4 /* entry */) &&
+ verifier.Verify(entry()) && verifier.VerifyVectorOfTables(entry()) &&
+ verifier.EndTable();
+ }
+};
+
+struct ListFunctionsResponseBuilder {
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_entry(flatbuffers::Offset<
+ flatbuffers::Vector>> entry) {
+ fbb_.AddOffset(4, entry);
+ }
+ ListFunctionsResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ ListFunctionsResponseBuilder &operator=(const ListFunctionsResponseBuilder &);
+ flatbuffers::Offset Finish() {
+ auto o =
+ flatbuffers::Offset(fbb_.EndTable(start_, 1));
+ return o;
+ }
+};
+
+inline flatbuffers::Offset CreateListFunctionsResponse(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset>>
+ entry = 0) {
+ ListFunctionsResponseBuilder builder_(_fbb);
+ builder_.add_entry(entry);
+ return builder_.Finish();
+}
+
+struct GetFunctionRequest FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ uint64_t identifier() const { return GetField(4, 0); }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField(verifier, 4 /* identifier */) &&
+ verifier.EndTable();
+ }
+};
+
+struct GetFunctionRequestBuilder {
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_identifier(uint64_t identifier) {
+ fbb_.AddElement(4, identifier, 0);
+ }
+ GetFunctionRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ GetFunctionRequestBuilder &operator=(const GetFunctionRequestBuilder &);
+ flatbuffers::Offset Finish() {
+ auto o = flatbuffers::Offset(fbb_.EndTable(start_, 1));
+ return o;
+ }
+};
+
+inline flatbuffers::Offset CreateGetFunctionRequest(
+ flatbuffers::FlatBufferBuilder &_fbb, uint64_t identifier = 0) {
+ GetFunctionRequestBuilder builder_(_fbb);
+ builder_.add_identifier(identifier);
+ return builder_.Finish();
+}
+
+struct GetFunctionResponse FLATBUFFERS_FINAL_CLASS
+ : private flatbuffers::Table {
+ const Function *function() const { return GetPointer(4); }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField(verifier, 4 /* function */) &&
+ verifier.VerifyTable(function()) && verifier.EndTable();
+ }
+};
+
+struct GetFunctionResponseBuilder {
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_function(flatbuffers::Offset function) {
+ fbb_.AddOffset(4, function);
+ }
+ GetFunctionResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ GetFunctionResponseBuilder &operator=(const GetFunctionResponseBuilder &);
+ flatbuffers::Offset Finish() {
+ auto o = flatbuffers::Offset(fbb_.EndTable(start_, 1));
+ return o;
+ }
+};
+
+inline flatbuffers::Offset CreateGetFunctionResponse(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset function = 0) {
+ GetFunctionResponseBuilder builder_(_fbb);
+ builder_.add_function(function);
+ return builder_.Finish();
+}
+
} // namespace proto
} // namespace debug
} // namespace xe
diff --git a/src/xenia/kernel/objects/xkernel_module.cc b/src/xenia/kernel/objects/xkernel_module.cc
index 8093e0346..9f714ebf9 100644
--- a/src/xenia/kernel/objects/xkernel_module.cc
+++ b/src/xenia/kernel/objects/xkernel_module.cc
@@ -18,7 +18,7 @@ namespace xe {
namespace kernel {
XKernelModule::XKernelModule(KernelState* kernel_state, const char* path)
- : XModule(kernel_state, path) {
+ : XModule(kernel_state, ModuleType::kKernelModule, path) {
emulator_ = kernel_state->emulator();
memory_ = emulator_->memory();
export_resolver_ = kernel_state->emulator()->export_resolver();
diff --git a/src/xenia/kernel/objects/xmodule.cc b/src/xenia/kernel/objects/xmodule.cc
index a4505ab82..db2dd1e87 100644
--- a/src/xenia/kernel/objects/xmodule.cc
+++ b/src/xenia/kernel/objects/xmodule.cc
@@ -15,8 +15,12 @@
namespace xe {
namespace kernel {
-XModule::XModule(KernelState* kernel_state, const std::string& path)
- : XObject(kernel_state, kTypeModule), path_(path) {
+XModule::XModule(KernelState* kernel_state, ModuleType module_type,
+ const std::string& path)
+ : XObject(kernel_state, kTypeModule),
+ module_type_(module_type),
+ path_(path),
+ processor_module_(nullptr) {
auto last_slash = path.find_last_of('/');
if (last_slash == path.npos) {
last_slash = path.find_last_of('\\');
diff --git a/src/xenia/kernel/objects/xmodule.h b/src/xenia/kernel/objects/xmodule.h
index 123ace447..5c62c2d50 100644
--- a/src/xenia/kernel/objects/xmodule.h
+++ b/src/xenia/kernel/objects/xmodule.h
@@ -12,6 +12,7 @@
#include
+#include "xenia/cpu/module.h"
#include "xenia/kernel/xobject.h"
#include "xenia/xbox.h"
@@ -20,13 +21,23 @@ namespace kernel {
class XModule : public XObject {
public:
- XModule(KernelState* kernel_state, const std::string& path);
+ enum class ModuleType {
+ // Matches debugger Module type.
+ kKernelModule = 0,
+ kUserModule = 1,
+ };
+
+ XModule(KernelState* kernel_state, ModuleType module_type,
+ const std::string& path);
virtual ~XModule();
+ ModuleType module_type() const { return module_type_; }
const std::string& path() const { return path_; }
const std::string& name() const { return name_; }
bool Matches(const std::string& name) const;
+ xe::cpu::Module* processor_module() const { return processor_module_; }
+
virtual uint32_t GetProcAddressByOrdinal(uint16_t ordinal) = 0;
virtual uint32_t GetProcAddressByName(const char* name) = 0;
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
@@ -35,8 +46,11 @@ class XModule : public XObject {
protected:
void OnLoad();
+ ModuleType module_type_;
std::string name_;
std::string path_;
+
+ xe::cpu::Module* processor_module_;
};
} // namespace kernel
diff --git a/src/xenia/kernel/objects/xuser_module.cc b/src/xenia/kernel/objects/xuser_module.cc
index 907069b81..830729aaa 100644
--- a/src/xenia/kernel/objects/xuser_module.cc
+++ b/src/xenia/kernel/objects/xuser_module.cc
@@ -21,7 +21,9 @@ namespace kernel {
using namespace xe::cpu;
XUserModule::XUserModule(KernelState* kernel_state, const char* path)
- : XModule(kernel_state, path), xex_(nullptr), execution_info_ptr_(0) {}
+ : XModule(kernel_state, ModuleType::kUserModule, path),
+ xex_(nullptr),
+ execution_info_ptr_(0) {}
XUserModule::~XUserModule() {
kernel_state()->memory()->SystemHeapFree(execution_info_ptr_);
@@ -119,6 +121,7 @@ X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) {
if (!xex_module->Load(name_, path_, xex_)) {
return X_STATUS_UNSUCCESSFUL;
}
+ processor_module_ = xex_module.get();
if (!processor->AddModule(std::move(xex_module))) {
return X_STATUS_UNSUCCESSFUL;
}