From d3e5c0644d3168874b6c87ac352504876607f5c1 Mon Sep 17 00:00:00 2001 From: x1nixmzeng Date: Sat, 6 Jan 2018 18:27:39 +0000 Subject: [PATCH] Skeleton support for resolving symbols --- src/CxbxDebugger/CxbxDebugger.csproj | 1 + src/CxbxDebugger/Debugger/Debugger.cs | 21 +++++++-- .../Debugger/DebuggerSymbolServer.cs | 45 +++++++++++++------ .../DebuggerSymbols/DebuggerSymbolProvider.cs | 44 ++++++++++++++++-- .../HLECache/HLECacheProvider.cs | 30 ++++++++----- .../Kernel/KernelSymbolProvider.cs | 25 +++++++++++ src/CxbxDebugger/Form1.cs | 13 +++++- 7 files changed, 146 insertions(+), 33 deletions(-) create mode 100644 src/CxbxDebugger/DebuggerSymbols/Kernel/KernelSymbolProvider.cs diff --git a/src/CxbxDebugger/CxbxDebugger.csproj b/src/CxbxDebugger/CxbxDebugger.csproj index 53f72bf2c..cc74e3d40 100644 --- a/src/CxbxDebugger/CxbxDebugger.csproj +++ b/src/CxbxDebugger/CxbxDebugger.csproj @@ -63,6 +63,7 @@ + diff --git a/src/CxbxDebugger/Debugger/Debugger.cs b/src/CxbxDebugger/Debugger/Debugger.cs index 46275ae13..be6adbe27 100644 --- a/src/CxbxDebugger/Debugger/Debugger.cs +++ b/src/CxbxDebugger/Debugger/Debugger.cs @@ -41,6 +41,7 @@ namespace CxbxDebugger List ExceptionEvents = new List(); DebuggerSymbolServer SymbolSrv; + KernelProvider KernelSymbolProvider; private void Init() { @@ -48,6 +49,9 @@ namespace CxbxDebugger SymbolSrv = new DebuggerSymbolServer(); + KernelSymbolProvider = new KernelProvider(); + SymbolSrv.RegisterProvider(KernelSymbolProvider); + RegisterEventInterfaces(this); } @@ -115,19 +119,20 @@ namespace CxbxDebugger } static string CxbxDebuggerPrefix = "CxbxDebugger! "; + static string KernelImportPrefix = "KernelImport_"; public void OnDebugOutput(string Message) { if (Message.StartsWith(CxbxDebuggerPrefix)) { string Payload = Message.Substring(CxbxDebuggerPrefix.Length); - if (Payload.StartsWith("IoCreateFile@")) + if (Payload.StartsWith(KernelImportPrefix)) { - Payload = Payload.Substring("IoCreateFile@".Length); - // TODO: Something with payload + KernelSymbolProvider.AddKernelSymbolFromMessage(Payload); } else { + // TODO Ensure this SetupHLECacheProvider(Payload); } } @@ -482,6 +487,16 @@ namespace CxbxDebugger } } + public DebuggerSymbol ResolveSymbol(uint Address) + { + return SymbolSrv.FindSymbol(Address); + } + + public DebuggerSymbol ResolveSymbol(IntPtr Address) + { + return SymbolSrv.FindSymbol((uint)Address); + } + public void RegisterEventInterfaces(object EventClass) { IDebuggerGeneralEvents GeneralListener = EventClass as IDebuggerGeneralEvents; diff --git a/src/CxbxDebugger/Debugger/DebuggerSymbolServer.cs b/src/CxbxDebugger/Debugger/DebuggerSymbolServer.cs index b90c09782..6e7fac671 100644 --- a/src/CxbxDebugger/Debugger/DebuggerSymbolServer.cs +++ b/src/CxbxDebugger/Debugger/DebuggerSymbolServer.cs @@ -7,31 +7,50 @@ namespace CxbxDebugger { public class DebuggerSymbolServer { - List Providers = new List(); - - public DebuggerSymbolServer() { } - - public DebuggerSymbolResult ResolveAddress(uint Address) + List Providers = new List(); + + public DebuggerSymbol FindSymbol(uint Address) { - DebuggerSymbolResult Result = new DebuggerSymbolResult(); + if (Providers.Count == 0) + return null; - foreach (DebuggerSymbolProvider SymbolProvider in Providers) + DebuggerSymbol BestResult = null; + + // Find the first provider who can give a symbol for this address + + int ProviderIndex = 0; + do { - Result = SymbolProvider.ResolveAddress(Address); - - if (Result.Success) + BestResult = Providers[ProviderIndex].FindSymbolFromAddress(Address); + if (BestResult != null) break; } + while (ProviderIndex < Providers.Count); - return Result; + // Try to find another symbol which is closer to the given address + // TODO Investigate adding symbol size metadata this can just check if Address is within a given range + + for (int i = ProviderIndex + 1; i < Providers.Count; ++i) + { + DebuggerSymbol OtherResult = Providers[i].FindSymbolFromAddress(Address); + if (OtherResult == null) + continue; + + if(OtherResult.AddrBegin < BestResult.AddrBegin ) + { + BestResult = OtherResult; + } + } + + return BestResult; } - public void RegisterProvider(DebuggerSymbolProvider Provider) + public void RegisterProvider(DebuggerSymbolProviderBase Provider) { Providers.Add(Provider); } - public void UnregisterProvider(DebuggerSymbolProvider Provider) + public void UnregisterProvider(DebuggerSymbolProviderBase Provider) { Providers.Remove(Provider); } diff --git a/src/CxbxDebugger/DebuggerSymbols/DebuggerSymbolProvider.cs b/src/CxbxDebugger/DebuggerSymbols/DebuggerSymbolProvider.cs index bfbb4391a..372bce8ee 100644 --- a/src/CxbxDebugger/DebuggerSymbols/DebuggerSymbolProvider.cs +++ b/src/CxbxDebugger/DebuggerSymbols/DebuggerSymbolProvider.cs @@ -1,15 +1,51 @@ // Written by x1nixmzeng for the Cxbx-Reloaded project // +using System.Collections; +using System.Collections.Generic; + namespace CxbxDebugger { - public class DebuggerSymbolResult + public class DebuggerSymbol { - public bool Success { get; set; } = false; + public string Name { get; set; } = ""; + + public uint AddrBegin { get; set; } = 0; + public uint AddrEnd { get; set; } = 0; } - public abstract class DebuggerSymbolProvider + public class DebuggerSymbolProviderBase { - public virtual DebuggerSymbolResult ResolveAddress(uint Address) { return new DebuggerSymbolResult(); } + // Stored in a map so the addresses are sorted + Dictionary Symbols = new Dictionary(); + + protected void AddSymbol(DebuggerSymbol Symbol) + { + Symbols.Add(Symbol.AddrBegin, Symbol); + } + + protected void RemoveSymbol(DebuggerSymbol Symbol) + { + Symbols.Remove(Symbol.AddrBegin); + } + + // TODO Find an inbuilt lower bound method + public DebuggerSymbol FindSymbolFromAddress(uint Address) + { + uint BestAddr = 0; + + foreach (uint SymbolAddr in Symbols.Keys) + { + if (SymbolAddr > Address) + break; + + BestAddr = SymbolAddr; + } + + if (!Symbols.ContainsKey(BestAddr)) + return null; + + return Symbols[BestAddr]; + } } } diff --git a/src/CxbxDebugger/DebuggerSymbols/HLECache/HLECacheProvider.cs b/src/CxbxDebugger/DebuggerSymbols/HLECache/HLECacheProvider.cs index 34f460b91..9a5b44654 100644 --- a/src/CxbxDebugger/DebuggerSymbols/HLECache/HLECacheProvider.cs +++ b/src/CxbxDebugger/DebuggerSymbols/HLECache/HLECacheProvider.cs @@ -1,26 +1,32 @@ // Written by x1nixmzeng for the Cxbx-Reloaded project // +using System.Collections.Generic; +using System.IO; + namespace CxbxDebugger { - public class HLECacheProvider : DebuggerSymbolProvider + public class HLECacheProvider : DebuggerSymbolProviderBase { - HLECacheFile CacheFile; - public bool Load(string FileName) { - CacheFile = new HLECacheFile(); - return CacheFile.Load(FileName); - } + if (!File.Exists(FileName)) + return false; - public override DebuggerSymbolResult ResolveAddress(uint Address) - { - var SymbolResult = new DebuggerSymbolResult(); + HLECacheFile CacheFile = new HLECacheFile(); + if (!CacheFile.Load(FileName)) + return false; - // TODO: Resolve me - SymbolResult.Success = false; + foreach(KeyValuePair Item in CacheFile.AddressMap) + { + DebuggerSymbol NewSymbol = new DebuggerSymbol(); + NewSymbol.Name = Item.Value; + NewSymbol.AddrBegin = Item.Key; - return SymbolResult; + AddSymbol(NewSymbol); + } + + return true; } } } diff --git a/src/CxbxDebugger/DebuggerSymbols/Kernel/KernelSymbolProvider.cs b/src/CxbxDebugger/DebuggerSymbols/Kernel/KernelSymbolProvider.cs new file mode 100644 index 000000000..3291f56a9 --- /dev/null +++ b/src/CxbxDebugger/DebuggerSymbols/Kernel/KernelSymbolProvider.cs @@ -0,0 +1,25 @@ +// Written by x1nixmzeng for the Cxbx-Reloaded project +// + +namespace CxbxDebugger +{ + public class KernelProvider : DebuggerSymbolProviderBase + { + public void AddKernelSymbolFromMessage(string Message) + { + var Parts = Message.Split('@'); + if( Parts.Length == 2 ) + { + uint Address = 0; + if( uint.TryParse(Parts[1], out Address) ) + { + DebuggerSymbol NewSymbol = new DebuggerSymbol(); + NewSymbol.Name = Parts[0]; + NewSymbol.AddrBegin = Address; + + AddSymbol(NewSymbol); + } + } + } + } +} diff --git a/src/CxbxDebugger/Form1.cs b/src/CxbxDebugger/Form1.cs index 191b94aa3..03e121137 100644 --- a/src/CxbxDebugger/Form1.cs +++ b/src/CxbxDebugger/Form1.cs @@ -260,6 +260,9 @@ namespace CxbxDebugger public void OnAccessViolation() { frm.DebugEvent("Access violation exception occured"); + + // Already suspended at this point, so we can rebuild the callstack list + frm.PopulateThreadList(frm.cbThreads.Items); } } @@ -297,9 +300,17 @@ namespace CxbxDebugger var Callstack = DebugThreads[Index].CallstackCache; foreach(DebuggerStackFrame StackFrame in Callstack.StackFrames) { - // TODO Resolve symbol names string FrameString = string.Format("{0:X8} {1:X8}", (uint)StackFrame.Base, (uint)StackFrame.PC); + // Try to resolve the symbol name + var Symbol = DebuggerInst.ResolveSymbol(StackFrame.Base); + if( Symbol != null) + { + uint Offset = Symbol.AddrBegin - (uint)StackFrame.Base; + + FrameString = string.Format("{0} + 0x{1:X}", Symbol.Name, Offset); + } + lbRegisters.Items.Add(FrameString); } }