Adding modules/functions to the debugger.
This commit is contained in:
parent
9d7d6df476
commit
573f190a43
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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?");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
namespace Xenia.Debug.UI.Views {
|
||||
using System;
|
||||
|
||||
namespace Xenia.Debug.UI.Views {
|
||||
partial class CodeDocument {
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
|
@ -24,6 +26,12 @@
|
|||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,10 +23,15 @@
|
|||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -117,4 +117,16 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="columnHeader1.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="columnHeader2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="columnHeader3.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
<metadata name="columnHeader4.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>False</value>
|
||||
</metadata>
|
||||
</root>
|
|
@ -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) {
|
||||
|
|
|
@ -6,10 +6,14 @@ using System.Threading.Tasks;
|
|||
using Xenia.Debug.Utilities;
|
||||
|
||||
namespace Xenia.Debug {
|
||||
public class Breakpoint : Changeable {
|
||||
public class Breakpoint : Changeable<Breakpoint> {
|
||||
// type code/data/kernel
|
||||
// address+[end address]
|
||||
// conditions? script?
|
||||
// action (suspend, trace, etc)
|
||||
|
||||
public Breakpoint() {
|
||||
this.self = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,12 @@ using System.Threading.Tasks;
|
|||
using Xenia.Debug.Utilities;
|
||||
|
||||
namespace Xenia.Debug {
|
||||
public class BreakpointList : Changeable, IReadOnlyCollection<Breakpoint> {
|
||||
public class BreakpointList : Changeable<BreakpointList>, IReadOnlyCollection<Breakpoint> {
|
||||
private readonly Debugger debugger;
|
||||
private readonly List<Breakpoint> breakpoints = new List<Breakpoint>();
|
||||
|
||||
public BreakpointList(Debugger debugger) {
|
||||
this.self = this;
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,11 @@ namespace Xenia.Debug {
|
|||
Paused,
|
||||
}
|
||||
|
||||
public class Context : Changeable {
|
||||
public class Context : Changeable<Context> {
|
||||
private readonly Debugger debugger;
|
||||
|
||||
public Context(Debugger debugger) {
|
||||
this.self = this;
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
|
|
|
@ -193,15 +193,20 @@ namespace Xenia.Debug {
|
|||
|
||||
// Read body.
|
||||
var bodyBuffer = new byte[length];
|
||||
int bodyOffset = 0;
|
||||
while (bodyOffset != bodyBuffer.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) {
|
||||
(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.
|
||||
OnMessageReceived(bodyBuffer);
|
||||
|
|
|
@ -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<Function> {
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,12 @@ using System.Threading.Tasks;
|
|||
using Xenia.Debug.Utilities;
|
||||
|
||||
namespace Xenia.Debug {
|
||||
public class KernelObject : Changeable {
|
||||
public class KernelObject : Changeable<KernelObject> {
|
||||
public readonly Debugger Debugger;
|
||||
public readonly uint Handle;
|
||||
|
||||
public KernelObject(Debugger debugger, uint handle) {
|
||||
this.self = this;
|
||||
this.Debugger = debugger;
|
||||
this.Handle = handle;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||
using Xenia.Debug.Utilities;
|
||||
|
||||
namespace Xenia.Debug {
|
||||
public class Memory : Changeable, IDisposable {
|
||||
public class Memory : Changeable<Memory>, 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,11 @@ using System.Threading.Tasks;
|
|||
using Xenia.Debug.Utilities;
|
||||
|
||||
namespace Xenia.Debug {
|
||||
public class MemoryView : Changeable {
|
||||
public class MemoryView : Changeable<MemoryView> {
|
||||
private readonly Memory memory;
|
||||
|
||||
public MemoryView(Memory memory) {
|
||||
this.self = this;
|
||||
this.memory = memory;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,26 +9,95 @@ using Xenia.Debug.Utilities;
|
|||
|
||||
namespace Xenia.Debug {
|
||||
public class Module : KernelObject, IReadOnlyCollection<Function> {
|
||||
private bool hasFetched = false;
|
||||
private uint functionCount = 0;
|
||||
private readonly List<Function> functions = new List<Function>();
|
||||
|
||||
// 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<Task>();
|
||||
|
||||
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 {
|
||||
|
|
|
@ -8,11 +8,12 @@ using xe.debug.proto;
|
|||
using Xenia.Debug.Utilities;
|
||||
|
||||
namespace Xenia.Debug {
|
||||
public class ModuleList : Changeable, IReadOnlyCollection<Module> {
|
||||
public class ModuleList : Changeable<ModuleList>, IReadOnlyCollection<Module> {
|
||||
private readonly Debugger debugger;
|
||||
private readonly List<Module> modules = new List<Module>();
|
||||
|
||||
public ModuleList(Debugger debugger) {
|
||||
this.self = this;
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
|
@ -26,20 +27,23 @@ namespace Xenia.Debug {
|
|||
response.GetResponseData(responseData);
|
||||
|
||||
var pendingTasks = new List<Task>();
|
||||
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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -7,11 +7,12 @@ using System.Threading.Tasks;
|
|||
using Xenia.Debug.Utilities;
|
||||
|
||||
namespace Xenia.Debug {
|
||||
public class ThreadList : Changeable, IReadOnlyCollection<Thread> {
|
||||
public class ThreadList : Changeable<ThreadList>, IReadOnlyCollection<Thread> {
|
||||
private readonly Debugger debugger;
|
||||
private readonly List<Thread> threads = new List<Thread>();
|
||||
|
||||
public ThreadList(Debugger debugger) {
|
||||
this.self = this;
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,13 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xenia.Debug.Utilities {
|
||||
public delegate void ChangedEventHandler();
|
||||
public delegate void ChangedEventHandler<T>(T sender);
|
||||
|
||||
public class Changeable {
|
||||
public class Changeable<T> {
|
||||
protected T self;
|
||||
private int changeDepth;
|
||||
public event ChangedEventHandler Changed;
|
||||
|
||||
public event ChangedEventHandler<T> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,10 +84,17 @@
|
|||
<Compile Include="Proto\xe\debug\proto\ContinueAction.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ContinueRequest.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ContinueResponse.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\Function.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\FunctionEntry.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\GetFunctionRequest.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\GetFunctionResponse.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\GetModuleRequest.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\GetModuleResponse.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ListBreakpointsRequest.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ListBreakpointsResponse.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ListFunctionsRequest.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ListFunctionsResponse.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ListModuleEntry.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ListModulesRequest.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ListModulesResponse.cs" />
|
||||
<Compile Include="Proto\xe\debug\proto\ListThreadsRequest.cs" />
|
||||
|
|
|
@ -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_) {
|
||||
|
|
|
@ -149,7 +149,6 @@ SymbolStatus Module::DefineVariable(VariableInfo* symbol_info) {
|
|||
}
|
||||
|
||||
void Module::ForEachFunction(std::function<void(FunctionInfo*)> callback) {
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
std::lock_guard<xe::mutex> guard(lock_);
|
||||
for (auto& symbol_info : list_) {
|
||||
if (symbol_info->type() == SymbolType::kFunction) {
|
||||
|
@ -159,21 +158,22 @@ void Module::ForEachFunction(std::function<void(FunctionInfo*)> callback) {
|
|||
}
|
||||
}
|
||||
|
||||
void Module::ForEachFunction(size_t since, size_t& version,
|
||||
std::function<void(FunctionInfo*)> callback) {
|
||||
SCOPE_profile_cpu_f("cpu");
|
||||
void Module::ForEachSymbol(size_t start_index, size_t end_index,
|
||||
std::function<void(SymbolInfo*)> callback) {
|
||||
std::lock_guard<xe::mutex> 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<FunctionInfo*>(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<xe::mutex> guard(lock_);
|
||||
return list_.size();
|
||||
}
|
||||
|
||||
bool Module::ReadMap(const char* file_name) {
|
||||
std::ifstream infile(file_name);
|
||||
|
||||
|
|
|
@ -47,8 +47,9 @@ class Module {
|
|||
SymbolStatus DefineVariable(VariableInfo* symbol_info);
|
||||
|
||||
void ForEachFunction(std::function<void(FunctionInfo*)> callback);
|
||||
void ForEachFunction(size_t since, size_t& version,
|
||||
std::function<void(FunctionInfo*)> callback);
|
||||
void ForEachSymbol(size_t start_index, size_t end_index,
|
||||
std::function<void(SymbolInfo*)> callback);
|
||||
size_t QuerySymbolCount();
|
||||
|
||||
bool ReadMap(const char* file_name);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -235,14 +240,149 @@ void Debugger::OnMessage(std::vector<uint8_t> buffer) {
|
|||
|
||||
case proto::RequestData_ListModulesRequest: {
|
||||
response_data_type = proto::ResponseData_ListModulesResponse;
|
||||
auto modules =
|
||||
emulator()->kernel_state()->object_table()->GetObjectsByType<XModule>(
|
||||
XObject::kTypeModule);
|
||||
std::vector<proto::ListModuleEntry> 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<proto::ListModuleEntry>(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<const proto::GetModuleRequest*>(
|
||||
request->request_data());
|
||||
auto module =
|
||||
emulator()->kernel_state()->object_table()->LookupObject<XModule>(
|
||||
request_data->module_id());
|
||||
flatbuffers::Offset<proto::Module> 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<proto::ModuleType>(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<XKernelModule*>(module.get());
|
||||
break;
|
||||
}
|
||||
case XModule::ModuleType::kUserModule: {
|
||||
auto user_module = reinterpret_cast<XUserModule*>(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<const proto::ListFunctionsRequest*>(
|
||||
request->request_data());
|
||||
auto module =
|
||||
emulator()->kernel_state()->object_table()->LookupObject<XModule>(
|
||||
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<flatbuffers::Offset<proto::FunctionEntry>> 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<xe::cpu::FunctionInfo*>(symbol_info);
|
||||
flatbuffers::Offset<flatbuffers::String> 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<uintptr_t>(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<const proto::GetFunctionRequest*>(
|
||||
request->request_data());
|
||||
auto function_info =
|
||||
reinterpret_cast<xe::cpu::FunctionInfo*>(request_data->identifier());
|
||||
auto function = function_info->function();
|
||||
flatbuffers::Offset<flatbuffers::String> name_offset;
|
||||
if (!function_info->name().empty()) {
|
||||
name_offset = fbb.CreateString(function_info->name());
|
||||
}
|
||||
flatbuffers::Offset<flatbuffers::String> disasm_ppc_offset;
|
||||
flatbuffers::Offset<flatbuffers::String> disasm_hir_raw_offset;
|
||||
flatbuffers::Offset<flatbuffers::String> disasm_hir_opt_offset;
|
||||
flatbuffers::Offset<flatbuffers::String> 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;
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ union RequestData {
|
|||
|
||||
ListModulesRequest,
|
||||
GetModuleRequest,
|
||||
ListFunctionsRequest,
|
||||
GetFunctionRequest,
|
||||
|
||||
StopRequest,
|
||||
BreakRequest,
|
||||
|
@ -47,6 +49,8 @@ union ResponseData {
|
|||
|
||||
ListModulesResponse,
|
||||
GetModuleResponse,
|
||||
ListFunctionsResponse,
|
||||
GetFunctionResponse,
|
||||
|
||||
StopResponse,
|
||||
BreakResponse,
|
||||
|
|
|
@ -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<const xe::debug::proto::RemoveBreakpointsRequest *>(union_obj));
|
||||
case RequestData_ListModulesRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ListModulesRequest *>(union_obj));
|
||||
case RequestData_GetModuleRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetModuleRequest *>(union_obj));
|
||||
case RequestData_ListFunctionsRequest:
|
||||
return verifier.VerifyTable(
|
||||
reinterpret_cast<const xe::debug::proto::ListFunctionsRequest *>(
|
||||
union_obj));
|
||||
case RequestData_GetFunctionRequest:
|
||||
return verifier.VerifyTable(
|
||||
reinterpret_cast<const xe::debug::proto::GetFunctionRequest *>(
|
||||
union_obj));
|
||||
case RequestData_StopRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::StopRequest *>(union_obj));
|
||||
case RequestData_BreakRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::BreakRequest *>(union_obj));
|
||||
case RequestData_ContinueRequest: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ContinueRequest *>(union_obj));
|
||||
|
@ -293,6 +329,14 @@ inline bool VerifyResponseData(flatbuffers::Verifier &verifier, const void *unio
|
|||
case ResponseData_RemoveBreakpointsResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::RemoveBreakpointsResponse *>(union_obj));
|
||||
case ResponseData_ListModulesResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ListModulesResponse *>(union_obj));
|
||||
case ResponseData_GetModuleResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::GetModuleResponse *>(union_obj));
|
||||
case ResponseData_ListFunctionsResponse:
|
||||
return verifier.VerifyTable(
|
||||
reinterpret_cast<const xe::debug::proto::ListFunctionsResponse *>(
|
||||
union_obj));
|
||||
case ResponseData_GetFunctionResponse:
|
||||
return verifier.VerifyTable(
|
||||
reinterpret_cast<const xe::debug::proto::GetFunctionResponse *>(
|
||||
union_obj));
|
||||
case ResponseData_StopResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::StopResponse *>(union_obj));
|
||||
case ResponseData_BreakResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::BreakResponse *>(union_obj));
|
||||
case ResponseData_ContinueResponse: return verifier.VerifyTable(reinterpret_cast<const xe::debug::proto::ContinueResponse *>(union_obj));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<const xe::debug::proto::XObject *>(4); }
|
||||
ModuleType type() const { return static_cast<ModuleType>(GetField<int8_t>(6, 0)); }
|
||||
|
@ -104,19 +128,23 @@ inline flatbuffers::Offset<ListModulesRequest> CreateListModulesRequest(flatbuff
|
|||
}
|
||||
|
||||
struct ListModulesResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::Vector<uint32_t> *module_ids() const { return GetPointer<const flatbuffers::Vector<uint32_t> *>(4); }
|
||||
const flatbuffers::Vector<const ListModuleEntry *> *entry() const {
|
||||
return GetPointer<const flatbuffers::Vector<const ListModuleEntry *> *>(4);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* module_ids */) &&
|
||||
verifier.Verify(module_ids()) &&
|
||||
verifier.EndTable();
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* entry */) &&
|
||||
verifier.Verify(entry()) && verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct ListModulesResponseBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_module_ids(flatbuffers::Offset<flatbuffers::Vector<uint32_t>> module_ids) { fbb_.AddOffset(4, module_ids); }
|
||||
void add_entry(
|
||||
flatbuffers::Offset<flatbuffers::Vector<const ListModuleEntry *>> entry) {
|
||||
fbb_.AddOffset(4, entry);
|
||||
}
|
||||
ListModulesResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
ListModulesResponseBuilder &operator=(const ListModulesResponseBuilder &);
|
||||
flatbuffers::Offset<ListModulesResponse> Finish() {
|
||||
|
@ -125,10 +153,12 @@ struct ListModulesResponseBuilder {
|
|||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<ListModulesResponse> CreateListModulesResponse(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> module_ids = 0) {
|
||||
inline flatbuffers::Offset<ListModulesResponse> CreateListModulesResponse(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::Vector<const ListModuleEntry *>> 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<GetModuleResponse> CreateGetModuleResponse(flatbuffer
|
|||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct FunctionEntry FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
uint64_t identifier() const { return GetField<uint64_t>(4, 0); }
|
||||
uint32_t address_start() const { return GetField<uint32_t>(6, 0); }
|
||||
uint32_t address_end() const { return GetField<uint32_t>(8, 0); }
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(10);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint64_t>(verifier, 4 /* identifier */) &&
|
||||
VerifyField<uint32_t>(verifier, 6 /* address_start */) &&
|
||||
VerifyField<uint32_t>(verifier, 8 /* address_end */) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(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<uint64_t>(4, identifier, 0);
|
||||
}
|
||||
void add_address_start(uint32_t address_start) {
|
||||
fbb_.AddElement<uint32_t>(6, address_start, 0);
|
||||
}
|
||||
void add_address_end(uint32_t address_end) {
|
||||
fbb_.AddElement<uint32_t>(8, address_end, 0);
|
||||
}
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(10, name);
|
||||
}
|
||||
FunctionEntryBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
FunctionEntryBuilder &operator=(const FunctionEntryBuilder &);
|
||||
flatbuffers::Offset<FunctionEntry> Finish() {
|
||||
auto o = flatbuffers::Offset<FunctionEntry>(fbb_.EndTable(start_, 4));
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<FunctionEntry> CreateFunctionEntry(
|
||||
flatbuffers::FlatBufferBuilder &_fbb, uint64_t identifier = 0,
|
||||
uint32_t address_start = 0, uint32_t address_end = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> 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<uint64_t>(4, 0); }
|
||||
uint32_t address_start() const { return GetField<uint32_t>(6, 0); }
|
||||
uint32_t address_end() const { return GetField<uint32_t>(8, 0); }
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(10);
|
||||
}
|
||||
const flatbuffers::String *disasm_ppc() const {
|
||||
return GetPointer<const flatbuffers::String *>(12);
|
||||
}
|
||||
const flatbuffers::String *disasm_hir_raw() const {
|
||||
return GetPointer<const flatbuffers::String *>(14);
|
||||
}
|
||||
const flatbuffers::String *disasm_hir_opt() const {
|
||||
return GetPointer<const flatbuffers::String *>(16);
|
||||
}
|
||||
const flatbuffers::String *disasm_machine_code() const {
|
||||
return GetPointer<const flatbuffers::String *>(18);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint64_t>(verifier, 4 /* identifier */) &&
|
||||
VerifyField<uint32_t>(verifier, 6 /* address_start */) &&
|
||||
VerifyField<uint32_t>(verifier, 8 /* address_end */) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, 10 /* name */) &&
|
||||
verifier.Verify(name()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, 12 /* disasm_ppc */) &&
|
||||
verifier.Verify(disasm_ppc()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier,
|
||||
14 /* disasm_hir_raw */) &&
|
||||
verifier.Verify(disasm_hir_raw()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier,
|
||||
16 /* disasm_hir_opt */) &&
|
||||
verifier.Verify(disasm_hir_opt()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(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<uint64_t>(4, identifier, 0);
|
||||
}
|
||||
void add_address_start(uint32_t address_start) {
|
||||
fbb_.AddElement<uint32_t>(6, address_start, 0);
|
||||
}
|
||||
void add_address_end(uint32_t address_end) {
|
||||
fbb_.AddElement<uint32_t>(8, address_end, 0);
|
||||
}
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(10, name);
|
||||
}
|
||||
void add_disasm_ppc(flatbuffers::Offset<flatbuffers::String> disasm_ppc) {
|
||||
fbb_.AddOffset(12, disasm_ppc);
|
||||
}
|
||||
void add_disasm_hir_raw(
|
||||
flatbuffers::Offset<flatbuffers::String> disasm_hir_raw) {
|
||||
fbb_.AddOffset(14, disasm_hir_raw);
|
||||
}
|
||||
void add_disasm_hir_opt(
|
||||
flatbuffers::Offset<flatbuffers::String> disasm_hir_opt) {
|
||||
fbb_.AddOffset(16, disasm_hir_opt);
|
||||
}
|
||||
void add_disasm_machine_code(
|
||||
flatbuffers::Offset<flatbuffers::String> disasm_machine_code) {
|
||||
fbb_.AddOffset(18, disasm_machine_code);
|
||||
}
|
||||
FunctionBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
FunctionBuilder &operator=(const FunctionBuilder &);
|
||||
flatbuffers::Offset<Function> Finish() {
|
||||
auto o = flatbuffers::Offset<Function>(fbb_.EndTable(start_, 8));
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Function> CreateFunction(
|
||||
flatbuffers::FlatBufferBuilder &_fbb, uint64_t identifier = 0,
|
||||
uint32_t address_start = 0, uint32_t address_end = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> disasm_ppc = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> disasm_hir_raw = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> disasm_hir_opt = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> 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<uint32_t>(4, 0); }
|
||||
uint32_t function_index_start() const { return GetField<uint32_t>(6, 0); }
|
||||
uint32_t function_index_end() const { return GetField<uint32_t>(8, 0); }
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint32_t>(verifier, 4 /* module_id */) &&
|
||||
VerifyField<uint32_t>(verifier, 6 /* function_index_start */) &&
|
||||
VerifyField<uint32_t>(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<uint32_t>(4, module_id, 0);
|
||||
}
|
||||
void add_function_index_start(uint32_t function_index_start) {
|
||||
fbb_.AddElement<uint32_t>(6, function_index_start, 0);
|
||||
}
|
||||
void add_function_index_end(uint32_t function_index_end) {
|
||||
fbb_.AddElement<uint32_t>(8, function_index_end, 0);
|
||||
}
|
||||
ListFunctionsRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
ListFunctionsRequestBuilder &operator=(const ListFunctionsRequestBuilder &);
|
||||
flatbuffers::Offset<ListFunctionsRequest> Finish() {
|
||||
auto o =
|
||||
flatbuffers::Offset<ListFunctionsRequest>(fbb_.EndTable(start_, 3));
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<ListFunctionsRequest> 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<flatbuffers::Offset<FunctionEntry>> *entry() const {
|
||||
return GetPointer<
|
||||
const flatbuffers::Vector<flatbuffers::Offset<FunctionEntry>> *>(4);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(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<flatbuffers::Offset<FunctionEntry>>> entry) {
|
||||
fbb_.AddOffset(4, entry);
|
||||
}
|
||||
ListFunctionsResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
ListFunctionsResponseBuilder &operator=(const ListFunctionsResponseBuilder &);
|
||||
flatbuffers::Offset<ListFunctionsResponse> Finish() {
|
||||
auto o =
|
||||
flatbuffers::Offset<ListFunctionsResponse>(fbb_.EndTable(start_, 1));
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<ListFunctionsResponse> CreateListFunctionsResponse(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FunctionEntry>>>
|
||||
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<uint64_t>(4, 0); }
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<uint64_t>(verifier, 4 /* identifier */) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct GetFunctionRequestBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_identifier(uint64_t identifier) {
|
||||
fbb_.AddElement<uint64_t>(4, identifier, 0);
|
||||
}
|
||||
GetFunctionRequestBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
GetFunctionRequestBuilder &operator=(const GetFunctionRequestBuilder &);
|
||||
flatbuffers::Offset<GetFunctionRequest> Finish() {
|
||||
auto o = flatbuffers::Offset<GetFunctionRequest>(fbb_.EndTable(start_, 1));
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<GetFunctionRequest> 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<const Function *>(4); }
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, 4 /* function */) &&
|
||||
verifier.VerifyTable(function()) && verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct GetFunctionResponseBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_function(flatbuffers::Offset<Function> function) {
|
||||
fbb_.AddOffset(4, function);
|
||||
}
|
||||
GetFunctionResponseBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
GetFunctionResponseBuilder &operator=(const GetFunctionResponseBuilder &);
|
||||
flatbuffers::Offset<GetFunctionResponse> Finish() {
|
||||
auto o = flatbuffers::Offset<GetFunctionResponse>(fbb_.EndTable(start_, 1));
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<GetFunctionResponse> CreateGetFunctionResponse(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<Function> function = 0) {
|
||||
GetFunctionResponseBuilder builder_(_fbb);
|
||||
builder_.add_function(function);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
} // namespace proto
|
||||
} // namespace debug
|
||||
} // namespace xe
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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('\\');
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue