From 5aa615a22764c8cbd48f9380e2b944e5a5545394 Mon Sep 17 00:00:00 2001 From: Sour Date: Sat, 22 Feb 2020 19:33:40 -0500 Subject: [PATCH] Debugger: Added .sym file support (wla-dx) Unsure if this is correct as different projects appear to generate the .sym file using different logic for the addressing. --- UI/Debugger/Code/SymbolCodeDataProvider.cs | 20 +- UI/Debugger/Controls/ctrlDisassemblyView.cs | 4 +- UI/Debugger/Integration/DbgImporter.cs | 12 +- UI/Debugger/Integration/ISymbolProvider.cs | 4 +- UI/Debugger/Integration/WlaDxImporter.cs | 177 ++++++++++++++++++ .../Workspace/DebugWorkspaceManager.cs | 9 + UI/Debugger/frmDebugger.Designer.cs | 1 + UI/Debugger/frmDebugger.cs | 55 +++++- UI/UI.csproj | 1 + 9 files changed, 256 insertions(+), 27 deletions(-) create mode 100644 UI/Debugger/Integration/WlaDxImporter.cs diff --git a/UI/Debugger/Code/SymbolCodeDataProvider.cs b/UI/Debugger/Code/SymbolCodeDataProvider.cs index 0268515..5918c57 100644 --- a/UI/Debugger/Code/SymbolCodeDataProvider.cs +++ b/UI/Debugger/Code/SymbolCodeDataProvider.cs @@ -31,11 +31,11 @@ namespace Mesen.GUI.Debugger.Code public CodeLineData GetCodeLineData(int lineIndex) { - int prgAddress = _symbolProvider.GetPrgAddress(_file, lineIndex); + AddressInfo? address = _symbolProvider.GetLineAddress(_file, lineIndex); CodeLineData data = new CodeLineData(_type) { Address = GetLineAddress(lineIndex), - AbsoluteAddress = prgAddress, + AbsoluteAddress = address.HasValue ? address.Value.Address : -1, EffectiveAddress = -1, Flags = LineFlags.VerifiedCode }; @@ -74,11 +74,12 @@ namespace Mesen.GUI.Debugger.Code public int GetLineAddress(int lineIndex) { - AddressInfo absAddress = new AddressInfo() { - Address = _symbolProvider.GetPrgAddress(_file, lineIndex), - Type = SnesMemoryType.PrgRom - }; - return DebugApi.GetRelativeAddress(absAddress).Address; + AddressInfo? absAddress = _symbolProvider.GetLineAddress(_file, lineIndex); + if(absAddress != null) { + return DebugApi.GetRelativeAddress(absAddress.Value).Address; + } else { + return -1; + } } public int GetLineCount() @@ -88,9 +89,10 @@ namespace Mesen.GUI.Debugger.Code public int GetLineIndex(uint cpuAddress) { - int absAddress = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = (int)cpuAddress, Type = SnesMemoryType.CpuMemory }).Address; + AddressInfo absAddress = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = (int)cpuAddress, Type = SnesMemoryType.CpuMemory }); for(int i = 0; i < _lineCount; i++) { - if(_symbolProvider.GetPrgAddress(_file, i) == absAddress) { + AddressInfo? lineAddr = _symbolProvider.GetLineAddress(_file, i); + if(lineAddr != null && lineAddr.Value.Address == absAddress.Address && lineAddr.Value.Type == absAddress.Type) { return i; } } diff --git a/UI/Debugger/Controls/ctrlDisassemblyView.cs b/UI/Debugger/Controls/ctrlDisassemblyView.cs index 5edf020..e3e613f 100644 --- a/UI/Debugger/Controls/ctrlDisassemblyView.cs +++ b/UI/Debugger/Controls/ctrlDisassemblyView.cs @@ -312,8 +312,8 @@ namespace Mesen.GUI.Debugger.Controls { if(_inSourceView) { AddressInfo absAddress = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = (int)address, Type = SnesMemoryType.CpuMemory }); - if(absAddress.Address >= 0 && absAddress.Type == SnesMemoryType.PrgRom) { - SourceCodeLocation line = _symbolProvider?.GetSourceCodeLineInfo(absAddress.Address); + if(absAddress.Address >= 0) { + SourceCodeLocation line = _symbolProvider?.GetSourceCodeLineInfo(absAddress); if(line != null) { foreach(SourceFileInfo fileInfo in cboSourceFile.Items) { if(line.File == fileInfo) { diff --git a/UI/Debugger/Integration/DbgImporter.cs b/UI/Debugger/Integration/DbgImporter.cs index d7ac5f2..bd5f084 100644 --- a/UI/Debugger/Integration/DbgImporter.cs +++ b/UI/Debugger/Integration/DbgImporter.cs @@ -66,18 +66,18 @@ namespace Mesen.GUI.Debugger.Integration public List SourceFiles { get { return _sourceFiles; } } - public int GetPrgAddress(SourceFileInfo file, int lineIndex) + public AddressInfo? GetLineAddress(SourceFileInfo file, int lineIndex) { return GetPrgAddress((file.InternalFile as FileInfo).ID, lineIndex); } - private int GetPrgAddress(int fileID, int lineIndex) + private AddressInfo? GetPrgAddress(int fileID, int lineIndex) { int prgAddress; if(_prgAddressByLine.TryGetValue(fileID.ToString() + "_" + lineIndex.ToString(), out prgAddress)) { - return prgAddress; + return new AddressInfo() { Address = prgAddress, Type = SnesMemoryType.CpuMemory }; } - return -1; + return null; } private int GetPrgAddress(SpanInfo span) @@ -91,10 +91,10 @@ namespace Mesen.GUI.Debugger.Integration return -1; } - public SourceCodeLocation GetSourceCodeLineInfo(int prgRomAddress) + public SourceCodeLocation GetSourceCodeLineInfo(AddressInfo address) { SourceCodeLocation line; - if(_linesByPrgAddress.TryGetValue(prgRomAddress, out line)) { + if(address.Type == SnesMemoryType.CpuMemory && _linesByPrgAddress.TryGetValue(address.Address, out line)) { return line; } return null; diff --git a/UI/Debugger/Integration/ISymbolProvider.cs b/UI/Debugger/Integration/ISymbolProvider.cs index 7c01806..677db44 100644 --- a/UI/Debugger/Integration/ISymbolProvider.cs +++ b/UI/Debugger/Integration/ISymbolProvider.cs @@ -11,9 +11,9 @@ namespace Mesen.GUI.Debugger.Integration List SourceFiles { get; } - int GetPrgAddress(SourceFileInfo file, int lineIndex); + AddressInfo? GetLineAddress(SourceFileInfo file, int lineIndex); string GetSourceCodeLine(int prgRomAddress); - SourceCodeLocation GetSourceCodeLineInfo(int prgRomAddress); + SourceCodeLocation GetSourceCodeLineInfo(AddressInfo address); AddressInfo? GetSymbolAddressInfo(SourceSymbol symbol); SourceCodeLocation GetSymbolDefinition(SourceSymbol symbol); SourceSymbol GetSymbol(string word, int prgStartAddress, int prgEndAddress); diff --git a/UI/Debugger/Integration/WlaDxImporter.cs b/UI/Debugger/Integration/WlaDxImporter.cs new file mode 100644 index 0000000..56729a7 --- /dev/null +++ b/UI/Debugger/Integration/WlaDxImporter.cs @@ -0,0 +1,177 @@ +using Mesen.GUI.Config; +using Mesen.GUI.Debugger.Labels; +using Mesen.GUI.Debugger.Workspace; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Mesen.GUI.Debugger.Integration +{ + public class WlaDxImporter : ISymbolProvider + { + private Dictionary _sourceFiles = new Dictionary(); + private Dictionary _addressByLine = new Dictionary(); + private Dictionary _linesByAddress = new Dictionary(); + + public DateTime SymbolFileStamp { get; private set; } + public string SymbolPath { get; private set; } + + public List SourceFiles { get { return _sourceFiles.Values.ToList(); } } + + public AddressInfo? GetLineAddress(SourceFileInfo file, int lineIndex) + { + AddressInfo address; + if(_addressByLine.TryGetValue(file.Name.ToString() + "_" + lineIndex.ToString(), out address)) { + return address; + } + return null; + } + + public string GetSourceCodeLine(int prgRomAddress) + { + throw new NotImplementedException(); + } + + public SourceCodeLocation GetSourceCodeLineInfo(AddressInfo address) + { + string key = address.Type.ToString() + address.Address.ToString(); + SourceCodeLocation location; + if(_linesByAddress.TryGetValue(key, out location)) { + return location; + } + return null; + } + + public SourceSymbol GetSymbol(string word, int prgStartAddress, int prgEndAddress) + { + return null; + } + + public AddressInfo? GetSymbolAddressInfo(SourceSymbol symbol) + { + return null; + } + + public SourceCodeLocation GetSymbolDefinition(SourceSymbol symbol) + { + return null; + } + + public List GetSymbols() + { + return new List(); + } + + public int GetSymbolSize(SourceSymbol srcSymbol) + { + return 1; + } + + public void Import(string path, bool silent) + { + string basePath = Path.GetDirectoryName(path); + string[] lines = File.ReadAllLines(path); + + Regex labelRegex = new Regex(@"^([0-9a-fA-F]{2}):([0-9a-fA-F]{4}) ([^\s]*)", RegexOptions.Compiled); + Regex fileRegex = new Regex(@"^([0-9a-fA-F]{4}) ([0-9a-fA-F]{8}) (.*)", RegexOptions.Compiled); + Regex addrRegex = new Regex(@"^([0-9a-fA-F]{2}):([0-9a-fA-F]{4}) ([0-9a-fA-F]{4}):([0-9a-fA-F]{8})", RegexOptions.Compiled); + + Dictionary labels = new Dictionary(); + + for(int i = 0; i < lines.Length; i++) { + string str = lines[i].Trim(); + if(str == "[labels]") { + for(; i < lines.Length; i++) { + if(lines[i].Length > 0) { + Match m = labelRegex.Match(lines[i]); + if(m.Success) { + int bank = Int32.Parse(m.Groups[1].Value, System.Globalization.NumberStyles.HexNumber); + int addr = (bank << 16) | Int32.Parse(m.Groups[2].Value, System.Globalization.NumberStyles.HexNumber); + string label = m.Groups[3].Value; + + if(!LabelManager.LabelRegex.IsMatch(label)) { + //ignore labels that don't respect the label naming restrictions + continue; + } + + AddressInfo relAddr = new AddressInfo() { Address = addr, Type = SnesMemoryType.CpuMemory }; + AddressInfo absAddr = DebugApi.GetAbsoluteAddress(relAddr); + + if(absAddr.Address < 0) { + continue; + } + + string orgLabel = label; + int j = 1; + while(labels.ContainsKey(label)) { + label = orgLabel + j.ToString(); + j++; + } + + labels[label] = new CodeLabel() { + Label = label, + Address = (UInt32)absAddr.Address, + MemoryType = absAddr.Type, + Comment = "", + Flags = CodeLabelFlags.None, + Length = 1 + }; + } + } else { + break; + } + } + } else if(str == "[source files]") { + for(; i < lines.Length; i++) { + if(lines[i].Length > 0) { + Match m = fileRegex.Match(lines[i]); + if(m.Success) { + int fileId = Int32.Parse(m.Groups[1].Value, System.Globalization.NumberStyles.HexNumber); + //int fileCrc = Int32.Parse(m.Groups[2].Value, System.Globalization.NumberStyles.HexNumber); + string filePath = m.Groups[3].Value; + + string fullPath = Path.Combine(basePath, filePath); + _sourceFiles[fileId] = new SourceFileInfo() { + Name = filePath, + Data = File.Exists(fullPath) ? File.ReadAllLines(fullPath) : new string[0] + }; + } + } else { + break; + } + } + } else if(str == "[addr-to-line mapping]") { + for(; i < lines.Length; i++) { + if(lines[i].Length > 0) { + Match m = addrRegex.Match(lines[i]); + if(m.Success) { + int bank = Int32.Parse(m.Groups[1].Value, System.Globalization.NumberStyles.HexNumber); + int addr = (bank << 16) | Int32.Parse(m.Groups[2].Value, System.Globalization.NumberStyles.HexNumber); + + int fileId = Int32.Parse(m.Groups[3].Value, System.Globalization.NumberStyles.HexNumber); + int lineNumber = Int32.Parse(m.Groups[4].Value, System.Globalization.NumberStyles.HexNumber); + + if(lineNumber <= 1) { + //Ignore line number 0 and 1, seems like bad data? + continue; + } + + AddressInfo absAddr = new AddressInfo() { Address = addr, Type = SnesMemoryType.PrgRom }; + _addressByLine[_sourceFiles[fileId].Name + "_" + lineNumber.ToString()] = absAddr; + _linesByAddress[absAddr.Type.ToString() + absAddr.Address.ToString()] = new SourceCodeLocation() { File = _sourceFiles[fileId], LineNumber = lineNumber }; + } + } else { + break; + } + } + } + } + + LabelManager.SetLabels(labels.Values, true); + } + } +} diff --git a/UI/Debugger/Workspace/DebugWorkspaceManager.cs b/UI/Debugger/Workspace/DebugWorkspaceManager.cs index 6ad41f3..c117711 100644 --- a/UI/Debugger/Workspace/DebugWorkspaceManager.cs +++ b/UI/Debugger/Workspace/DebugWorkspaceManager.cs @@ -113,6 +113,15 @@ namespace Mesen.GUI.Debugger.Workspace LabelManager.RefreshLabels(); } + public static void ImportSymFile(string symPath, bool silent = false) + { + if(ConfigManager.Config.Debug.DbgIntegration.ResetLabelsOnImport) { + ResetLabels(); + } + new WlaDxImporter().Import(symPath, silent); + LabelManager.RefreshLabels(); + } + public static void ImportDbgFile(string dbgPath = null) { _symbolProvider = null; diff --git a/UI/Debugger/frmDebugger.Designer.cs b/UI/Debugger/frmDebugger.Designer.cs index f87ee26..f9385f6 100644 --- a/UI/Debugger/frmDebugger.Designer.cs +++ b/UI/Debugger/frmDebugger.Designer.cs @@ -1059,6 +1059,7 @@ // // frmDebugger // + this.AllowDrop = true; this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(832, 644); diff --git a/UI/Debugger/frmDebugger.cs b/UI/Debugger/frmDebugger.cs index 85412b0..f3530e8 100644 --- a/UI/Debugger/frmDebugger.cs +++ b/UI/Debugger/frmDebugger.cs @@ -609,22 +609,61 @@ namespace Mesen.GUI.Debugger } } + protected override void OnDragEnter(DragEventArgs e) + { + base.OnDragEnter(e); + + try { + if(e.Data != null && e.Data.GetDataPresent(DataFormats.FileDrop)) { + string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); + if(files != null && files.Length > 0) { + string ext = Path.GetExtension(files[0]).ToLower(); + if(ext == ".dbg" || ext == ".msl" || ext == ".sym") { + e.Effect = DragDropEffects.Copy; + } + } + } + } catch(Exception ex) { + MesenMsgBox.Show("UnexpectedError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString()); + } + } + + protected override void OnDragDrop(DragEventArgs e) + { + base.OnDragDrop(e); + + try { + string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); + if(files != null && File.Exists(files[0])) { + ImportLabelFile(files[0]); + } + } catch(Exception ex) { + MesenMsgBox.Show("UnexpectedError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString()); + } + } + private void mnuImportLabels_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); - ofd.SetFilter("All supported files (*.dbg, *.msl)|*.dbg;*.msl"); + ofd.SetFilter("All supported files (*.dbg, *.msl, *.sym)|*.dbg;*.msl;*.sym"); if(ofd.ShowDialog() == DialogResult.OK) { - string path = ofd.FileName; - string ext = Path.GetExtension(path).ToLower(); - if(ext == ".msl") { - DebugWorkspaceManager.ImportMslFile(path); - } else { - DebugWorkspaceManager.ImportDbgFile(path); - } + ImportLabelFile(ofd.FileName); RefreshDisassembly(); } } + private static void ImportLabelFile(string path) + { + string ext = Path.GetExtension(path).ToLower(); + if(ext == ".msl") { + DebugWorkspaceManager.ImportMslFile(path); + } else if(ext == ".sym") { + DebugWorkspaceManager.ImportSymFile(path); + } else { + DebugWorkspaceManager.ImportDbgFile(path); + } + } + private void mnuExportLabels_Click(object sender, EventArgs e) { SaveFileDialog sfd = new SaveFileDialog(); diff --git a/UI/UI.csproj b/UI/UI.csproj index 5f89713..63179ca 100644 --- a/UI/UI.csproj +++ b/UI/UI.csproj @@ -365,6 +365,7 @@ frmIntegrationSettings.cs + UserControl