Update debugger types and thread report handling
This commit is contained in:
parent
3a740d7933
commit
96155736e5
|
@ -9,6 +9,7 @@ using WinDebug = VsChromium.Core.Win32.Debugging;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using WinLowLevel = LowLevelDesign.Win32.Windows.NativeMethods;
|
using WinLowLevel = LowLevelDesign.Win32.Windows.NativeMethods;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CxbxDebugger
|
namespace CxbxDebugger
|
||||||
{
|
{
|
||||||
|
@ -32,13 +33,18 @@ namespace CxbxDebugger
|
||||||
string[] args = new string[] { };
|
string[] args = new string[] { };
|
||||||
string Target = "";
|
string Target = "";
|
||||||
|
|
||||||
|
public string ProcessName
|
||||||
|
{
|
||||||
|
get { return Target; }
|
||||||
|
}
|
||||||
|
|
||||||
RunState State = RunState.NotLaunched;
|
RunState State = RunState.NotLaunched;
|
||||||
|
|
||||||
DebuggerMessages.DebuggerInit InitParams = new DebuggerMessages.DebuggerInit();
|
DebuggerMessages.DebuggerInit InitParams = new DebuggerMessages.DebuggerInit();
|
||||||
|
|
||||||
DebuggerInstance DebugInstance;
|
DebuggerInstance DebugInstance;
|
||||||
|
|
||||||
List<IDebuggerGeneralEvents> GeneralEvents = new List<IDebuggerGeneralEvents>();
|
List<IDebuggerSessionEvents> SessionEvents = new List<IDebuggerSessionEvents>();
|
||||||
List<IDebuggerProcessEvents> ProcessEvents = new List<IDebuggerProcessEvents>();
|
List<IDebuggerProcessEvents> ProcessEvents = new List<IDebuggerProcessEvents>();
|
||||||
List<IDebuggerThreadEvents> ThreadEvents = new List<IDebuggerThreadEvents>();
|
List<IDebuggerThreadEvents> ThreadEvents = new List<IDebuggerThreadEvents>();
|
||||||
List<IDebuggerModuleEvents> ModuleEvents = new List<IDebuggerModuleEvents>();
|
List<IDebuggerModuleEvents> ModuleEvents = new List<IDebuggerModuleEvents>();
|
||||||
|
@ -103,7 +109,7 @@ namespace CxbxDebugger
|
||||||
bpStall.Set();
|
bpStall.Set();
|
||||||
|
|
||||||
// Remove all events
|
// Remove all events
|
||||||
GeneralEvents.Clear();
|
SessionEvents.Clear();
|
||||||
ProcessEvents.Clear();
|
ProcessEvents.Clear();
|
||||||
ThreadEvents.Clear();
|
ThreadEvents.Clear();
|
||||||
ModuleEvents.Clear();
|
ModuleEvents.Clear();
|
||||||
|
@ -172,6 +178,9 @@ namespace CxbxDebugger
|
||||||
if (CanLaunch() == false)
|
if (CanLaunch() == false)
|
||||||
throw new Exception("Unable to launch in this state");
|
throw new Exception("Unable to launch in this state");
|
||||||
|
|
||||||
|
if (args.Length == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
var DebugCreationFlags =
|
var DebugCreationFlags =
|
||||||
WinProcesses.ProcessCreationFlags.DEBUG_ONLY_THIS_PROCESS |
|
WinProcesses.ProcessCreationFlags.DEBUG_ONLY_THIS_PROCESS |
|
||||||
WinProcesses.ProcessCreationFlags.CREATE_NEW_CONSOLE;
|
WinProcesses.ProcessCreationFlags.CREATE_NEW_CONSOLE;
|
||||||
|
@ -197,7 +206,7 @@ namespace CxbxDebugger
|
||||||
// Store so they can be marshalled and closed correctly
|
// Store so they can be marshalled and closed correctly
|
||||||
hProcess = new WinProcesses.SafeProcessHandle(stProcessInfo.hProcess);
|
hProcess = new WinProcesses.SafeProcessHandle(stProcessInfo.hProcess);
|
||||||
hThread = new WinProcesses.SafeThreadHandle(stProcessInfo.hThread);
|
hThread = new WinProcesses.SafeThreadHandle(stProcessInfo.hThread);
|
||||||
|
|
||||||
bContinue = true;
|
bContinue = true;
|
||||||
|
|
||||||
State = RunState.Running;
|
State = RunState.Running;
|
||||||
|
@ -313,10 +322,7 @@ namespace CxbxDebugger
|
||||||
Thread.StartAddress = DebugInfo.lpStartAddress;
|
Thread.StartAddress = DebugInfo.lpStartAddress;
|
||||||
Thread.ThreadBase = DebugInfo.lpThreadLocalBase;
|
Thread.ThreadBase = DebugInfo.lpThreadLocalBase;
|
||||||
|
|
||||||
foreach (IDebuggerThreadEvents Event in ThreadEvents )
|
Parallel.ForEach(ThreadEvents, Event => Event.OnThreadCreate(Thread));
|
||||||
{
|
|
||||||
Event.OnThreadCreate(Thread);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleExitThread(WinDebug.DEBUG_EVENT DebugEvent)
|
private void HandleExitThread(WinDebug.DEBUG_EVENT DebugEvent)
|
||||||
|
@ -333,10 +339,7 @@ namespace CxbxDebugger
|
||||||
{
|
{
|
||||||
uint ExitCode = DebugInfo.dwExitCode;
|
uint ExitCode = DebugInfo.dwExitCode;
|
||||||
|
|
||||||
foreach (IDebuggerThreadEvents Event in ThreadEvents)
|
Parallel.ForEach(ThreadEvents, Event => Event.OnThreadExit(TargetThread, ExitCode));
|
||||||
{
|
|
||||||
Event.OnThreadExit(TargetThread, ExitCode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,26 +372,17 @@ namespace CxbxDebugger
|
||||||
DebugInstance = new DebuggerInstance(Process);
|
DebugInstance = new DebuggerInstance(Process);
|
||||||
RegisterEventInterfaces(DebugInstance);
|
RegisterEventInterfaces(DebugInstance);
|
||||||
|
|
||||||
foreach (IDebuggerProcessEvents Event in ProcessEvents)
|
Parallel.ForEach(ProcessEvents, Event => Event.OnProcessCreate(Process));
|
||||||
{
|
|
||||||
Event.OnProcessCreate(Process);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (IDebuggerThreadEvents Event in ThreadEvents)
|
Parallel.ForEach(ThreadEvents, Event => Event.OnThreadCreate(MainThread));
|
||||||
{
|
|
||||||
Event.OnThreadCreate(MainThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
var XboxModule = new DebuggerModule();
|
var XboxModule = new DebuggerModule();
|
||||||
|
|
||||||
XboxModule.Path = Target;
|
XboxModule.Path = Target;
|
||||||
XboxModule.ImageBase = DebugInfo.lpBaseOfImage;
|
XboxModule.ImageBase = DebugInfo.lpBaseOfImage;
|
||||||
XboxModule.Core = true;
|
XboxModule.Core = true;
|
||||||
|
|
||||||
foreach (IDebuggerModuleEvents Event in ModuleEvents)
|
Parallel.ForEach(ModuleEvents, Event => Event.OnModuleLoaded(XboxModule));
|
||||||
{
|
|
||||||
Event.OnModuleLoaded(XboxModule);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleExitProcess(WinDebug.DEBUG_EVENT DebugEvent)
|
private void HandleExitProcess(WinDebug.DEBUG_EVENT DebugEvent)
|
||||||
|
@ -405,10 +399,7 @@ namespace CxbxDebugger
|
||||||
|
|
||||||
if (TargetProcess != null)
|
if (TargetProcess != null)
|
||||||
{
|
{
|
||||||
foreach (IDebuggerProcessEvents Event in ProcessEvents)
|
Parallel.ForEach(ProcessEvents, Event => Event.OnProcessExit(TargetProcess, ExitCode));
|
||||||
{
|
|
||||||
Event.OnProcessExit(TargetProcess, ExitCode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,10 +417,7 @@ namespace CxbxDebugger
|
||||||
Module.Path = ResolveProcessPath(DebugInfo.hFile);
|
Module.Path = ResolveProcessPath(DebugInfo.hFile);
|
||||||
Module.ImageBase = DebugInfo.lpBaseOfDll;
|
Module.ImageBase = DebugInfo.lpBaseOfDll;
|
||||||
|
|
||||||
foreach (IDebuggerModuleEvents Event in ModuleEvents)
|
Parallel.ForEach(ModuleEvents, Event => Event.OnModuleLoaded(Module));
|
||||||
{
|
|
||||||
Event.OnModuleLoaded(Module);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleUnloadDll(WinDebug.DEBUG_EVENT DebugEvent)
|
private void HandleUnloadDll(WinDebug.DEBUG_EVENT DebugEvent)
|
||||||
|
@ -445,10 +433,7 @@ namespace CxbxDebugger
|
||||||
|
|
||||||
if (TargetModule != null)
|
if (TargetModule != null)
|
||||||
{
|
{
|
||||||
foreach (IDebuggerModuleEvents Event in ModuleEvents)
|
Parallel.ForEach(ModuleEvents, Event => Event.OnModuleUnloaded(TargetModule));
|
||||||
{
|
|
||||||
Event.OnModuleUnloaded(TargetModule);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,10 +443,7 @@ namespace CxbxDebugger
|
||||||
|
|
||||||
string debugString = ReadProcessString(DebugInfo.lpDebugStringData, DebugInfo.nDebugStringLength, DebugInfo.fUnicode == 1);
|
string debugString = ReadProcessString(DebugInfo.lpDebugStringData, DebugInfo.nDebugStringLength, DebugInfo.fUnicode == 1);
|
||||||
|
|
||||||
foreach(IDebuggerOutputEvents Event in OutputEvents)
|
Parallel.ForEach(OutputEvents, Event => Event.OnDebugOutput(debugString));
|
||||||
{
|
|
||||||
Event.OnDebugOutput(debugString);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleException(WinDebug.DEBUG_EVENT DebugEvent)
|
private void HandleException(WinDebug.DEBUG_EVENT DebugEvent)
|
||||||
|
@ -482,12 +464,28 @@ namespace CxbxDebugger
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ExceptionCode.PrivilegedInstruction:
|
||||||
|
{
|
||||||
|
// Seeing this frequently called in Win10
|
||||||
|
|
||||||
|
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ExceptionCode.StatusHandleNotClosable:
|
||||||
|
{
|
||||||
|
// Seeing this frequently called in Win10
|
||||||
|
|
||||||
|
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case (ExceptionCode)DebuggerMessages.ReportType.OVERRIDE_EXCEPTION:
|
case (ExceptionCode)DebuggerMessages.ReportType.OVERRIDE_EXCEPTION:
|
||||||
{
|
{
|
||||||
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
var Query = DebuggerMessages.GetExceptionHandledQuery(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
|
var Query = DebuggerMessages.GetExceptionHandledQuery(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
|
|
||||||
bool Handled = false;
|
bool Handled = false;
|
||||||
foreach (IDebuggerExceptionEvents Event in ExceptionEvents)
|
foreach (IDebuggerExceptionEvents Event in ExceptionEvents)
|
||||||
|
@ -506,7 +504,7 @@ namespace CxbxDebugger
|
||||||
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
var Report = DebuggerMessages.GetHLECacheReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
|
var Report = DebuggerMessages.GetHLECacheReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
SetupHLECacheProvider(Report.FileName);
|
SetupHLECacheProvider(Report.FileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,7 +515,7 @@ namespace CxbxDebugger
|
||||||
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
var Report = DebuggerMessages.GetKernelPatchReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
|
var Report = DebuggerMessages.GetKernelPatchReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
|
|
||||||
KernelSymbolProvider.AddKernelSymbolFromMessage(Report);
|
KernelSymbolProvider.AddKernelSymbolFromMessage(Report);
|
||||||
}
|
}
|
||||||
|
@ -529,12 +527,9 @@ namespace CxbxDebugger
|
||||||
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
var Report = DebuggerMessages.GetFileOpenedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
|
var Report = DebuggerMessages.GetFileOpenedReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
|
|
||||||
foreach (IDebuggerFileEvents Event in FileEvents)
|
Parallel.ForEach(FileEvents, Event => Event.OnFileOpened(Report));
|
||||||
{
|
|
||||||
Event.OnFileOpened(Report);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -544,12 +539,9 @@ namespace CxbxDebugger
|
||||||
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
var Report = DebuggerMessages.GetFileReadReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
|
var Report = DebuggerMessages.GetFileReadReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
|
|
||||||
foreach (IDebuggerFileEvents Event in FileEvents)
|
Parallel.ForEach(FileEvents, Event => Event.OnFileRead(Report));
|
||||||
{
|
|
||||||
Event.OnFileRead(Report);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -559,12 +551,9 @@ namespace CxbxDebugger
|
||||||
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
var Report = DebuggerMessages.GetFileWriteReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
|
var Report = DebuggerMessages.GetFileWriteReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
|
|
||||||
foreach (IDebuggerFileEvents Event in FileEvents)
|
Parallel.ForEach(FileEvents, Event => Event.OnFileWrite(Report));
|
||||||
{
|
|
||||||
Event.OnFileWrite(Report);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -574,13 +563,10 @@ namespace CxbxDebugger
|
||||||
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
var Report = DebuggerMessages.GetFileClosedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
|
var Report = DebuggerMessages.GetFileClosedReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
if (Report != null)
|
if (Report != null)
|
||||||
{
|
{
|
||||||
foreach (IDebuggerFileEvents Event in FileEvents)
|
Parallel.ForEach(FileEvents, Event => Event.OnFileClosed(Report));
|
||||||
{
|
|
||||||
Event.OnFileClosed(Report);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -591,14 +577,23 @@ namespace CxbxDebugger
|
||||||
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
var Report = DebuggerMessages.GetDebuggerInitReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
|
var Report = DebuggerMessages.GetDebuggerInitReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
|
|
||||||
InitParams = Report;
|
InitParams = Report;
|
||||||
|
|
||||||
foreach (IDebuggerGeneralEvents Event in GeneralEvents)
|
Parallel.ForEach(SessionEvents, Event => Event.OnDebugTitleLoaded(InitParams.Title));
|
||||||
{
|
}
|
||||||
Event.OnDebugTitleLoaded(InitParams.Title);
|
}
|
||||||
}
|
break;
|
||||||
|
|
||||||
|
case (ExceptionCode)DebuggerMessages.ReportType.DEBUGGER_NEW_TARGET:
|
||||||
|
{
|
||||||
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
|
if (Thread != null)
|
||||||
|
{
|
||||||
|
var Report = DebuggerMessages.GetDebuggerNewTargetReport(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
|
|
||||||
|
Parallel.ForEach(SessionEvents, Event => Event.OnDebugTargetChanged(Report.CommandLine));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -608,7 +603,7 @@ namespace CxbxDebugger
|
||||||
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId);
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
var Report = DebuggerMessages.GetMSVCThreadName(Thread, DebugInfo.ExceptionRecord.ExceptionInformation);
|
var Report = DebuggerMessages.GetMSVCThreadName(Thread, new DebuggerMessages.DataProcessor(DebugInfo.ExceptionRecord.ExceptionInformation));
|
||||||
if(Report != null)
|
if(Report != null)
|
||||||
{
|
{
|
||||||
// Resolve the ThreadId of an invalid ID to the current thread name
|
// Resolve the ThreadId of an invalid ID to the current thread name
|
||||||
|
@ -623,10 +618,7 @@ namespace CxbxDebugger
|
||||||
// Update the resolved thread name
|
// Update the resolved thread name
|
||||||
ResolvedThread.DebugName = Report.Name;
|
ResolvedThread.DebugName = Report.Name;
|
||||||
|
|
||||||
foreach (IDebuggerThreadEvents Event in ThreadEvents)
|
Parallel.ForEach(ThreadEvents, Event => Event.OnThreadNamed(Thread));
|
||||||
{
|
|
||||||
Event.OnThreadNamed(Thread);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -644,10 +636,7 @@ namespace CxbxDebugger
|
||||||
|
|
||||||
bpStall.Reset();
|
bpStall.Reset();
|
||||||
|
|
||||||
foreach (IDebuggerExceptionEvents Event in ExceptionEvents)
|
Parallel.ForEach(ExceptionEvents, Event => Event.OnBreakpoint(Thread, BpAddr, BpCode, FirstChance));
|
||||||
{
|
|
||||||
Event.OnBreakpoint(Thread, BpAddr, BpCode, FirstChance);
|
|
||||||
}
|
|
||||||
|
|
||||||
bpStall.WaitOne();
|
bpStall.WaitOne();
|
||||||
}
|
}
|
||||||
|
@ -674,10 +663,7 @@ namespace CxbxDebugger
|
||||||
WinDebug.DEBUG_EVENT DbgEvt = new WinDebug.DEBUG_EVENT();
|
WinDebug.DEBUG_EVENT DbgEvt = new WinDebug.DEBUG_EVENT();
|
||||||
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE;
|
ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE;
|
||||||
|
|
||||||
foreach (IDebuggerGeneralEvents Event in GeneralEvents)
|
Parallel.ForEach(SessionEvents, Event => Event.OnDebugStart());
|
||||||
{
|
|
||||||
Event.OnDebugStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop until told to stop
|
// Loop until told to stop
|
||||||
while (bContinue == true)
|
while (bContinue == true)
|
||||||
|
@ -734,10 +720,7 @@ namespace CxbxDebugger
|
||||||
|
|
||||||
State = RunState.Ended;
|
State = RunState.Ended;
|
||||||
|
|
||||||
foreach (IDebuggerGeneralEvents Event in GeneralEvents)
|
Parallel.ForEach(SessionEvents, Event => Event.OnDebugEnd());
|
||||||
{
|
|
||||||
Event.OnDebugEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DebuggerSymbol ResolveSymbol(uint Address)
|
public DebuggerSymbol ResolveSymbol(uint Address)
|
||||||
|
@ -757,8 +740,8 @@ namespace CxbxDebugger
|
||||||
|
|
||||||
public void RegisterEventInterfaces(object EventClass)
|
public void RegisterEventInterfaces(object EventClass)
|
||||||
{
|
{
|
||||||
IDebuggerGeneralEvents GeneralListener = EventClass as IDebuggerGeneralEvents;
|
IDebuggerSessionEvents SessionListener = EventClass as IDebuggerSessionEvents;
|
||||||
if(GeneralListener != null ) GeneralEvents.Add(GeneralListener);
|
if(SessionListener != null ) SessionEvents.Add(SessionListener);
|
||||||
|
|
||||||
IDebuggerProcessEvents ProcessListener = EventClass as IDebuggerProcessEvents;
|
IDebuggerProcessEvents ProcessListener = EventClass as IDebuggerProcessEvents;
|
||||||
if (ProcessListener != null) ProcessEvents.Add(ProcessListener);
|
if (ProcessListener != null) ProcessEvents.Add(ProcessListener);
|
||||||
|
|
|
@ -5,11 +5,12 @@ using System;
|
||||||
|
|
||||||
namespace CxbxDebugger
|
namespace CxbxDebugger
|
||||||
{
|
{
|
||||||
public interface IDebuggerGeneralEvents
|
public interface IDebuggerSessionEvents
|
||||||
{
|
{
|
||||||
void OnDebugStart();
|
void OnDebugStart();
|
||||||
void OnDebugEnd();
|
void OnDebugEnd();
|
||||||
void OnDebugTitleLoaded(string Title);
|
void OnDebugTitleLoaded(string Title);
|
||||||
|
void OnDebugTargetChanged(string CommandLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IDebuggerProcessEvents
|
public interface IDebuggerProcessEvents
|
||||||
|
|
|
@ -9,15 +9,20 @@ namespace CxbxDebugger
|
||||||
{
|
{
|
||||||
public enum ReportType : uint
|
public enum ReportType : uint
|
||||||
{
|
{
|
||||||
HLECACHE_FILE = 0x00deed00,
|
HLECACHE_FILE = 0x1000,
|
||||||
KERNEL_PATCH = 0x00deed01,
|
|
||||||
FILE_OPENED = 0x00deed02,
|
|
||||||
FILE_READ = 0x00deed03,
|
|
||||||
FILE_CLOSED = 0x00deed04,
|
|
||||||
DEBUGGER_INIT = 0x00deed05,
|
|
||||||
FILE_WRITE = 0x00deed06,
|
|
||||||
|
|
||||||
OVERRIDE_EXCEPTION = 0x00ceed01,
|
KERNEL_PATCH = 0x2000,
|
||||||
|
|
||||||
|
FILE_OPENED = 0x3000,
|
||||||
|
|
||||||
|
FILE_READ = 0x3001,
|
||||||
|
FILE_WRITE = 0x3002,
|
||||||
|
FILE_CLOSED = 0x3003,
|
||||||
|
|
||||||
|
DEBUGGER_INIT = 0x400,
|
||||||
|
DEBUGGER_NEW_TARGET = 0x401,
|
||||||
|
|
||||||
|
OVERRIDE_EXCEPTION = 0x500,
|
||||||
|
|
||||||
// Exception code from https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
// Exception code from https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||||
MS_VC_EXCEPTION = 0x406D1388,
|
MS_VC_EXCEPTION = 0x406D1388,
|
||||||
|
@ -29,22 +34,38 @@ namespace CxbxDebugger
|
||||||
WCHAR,
|
WCHAR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public class DataProcessor
|
||||||
|
{
|
||||||
|
uint[] SourceData;
|
||||||
|
uint SourceIndex;
|
||||||
|
|
||||||
|
public DataProcessor(uint[] Data)
|
||||||
|
{
|
||||||
|
SourceData = Data;
|
||||||
|
SourceIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Pop()
|
||||||
|
{
|
||||||
|
return SourceData[SourceIndex++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class HLECache
|
public class HLECache
|
||||||
{
|
{
|
||||||
public string FileName { get; set; }
|
public string FileName { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HLECache GetHLECacheReport(DebuggerThread Context, uint[] Data)
|
public static HLECache GetHLECacheReport(DebuggerThread Context, DataProcessor Data)
|
||||||
{
|
{
|
||||||
HLECache Report = new HLECache();
|
HLECache Report = new HLECache();
|
||||||
|
|
||||||
StringType Type = (StringType)Data[0];
|
var Type = (StringType)Data.Pop();
|
||||||
|
|
||||||
if (Type != StringType.CHAR)
|
if (Type != StringType.CHAR)
|
||||||
throw new Exception("GetHLECacheReport expects a string message");
|
throw new Exception("GetHLECacheReport expects a string message");
|
||||||
|
|
||||||
uint Length = Data[1];
|
var Length = Data.Pop(); ;
|
||||||
IntPtr MessagePtr = new IntPtr(Data[2]);
|
var MessagePtr = new IntPtr(Data.Pop());
|
||||||
|
|
||||||
Report.FileName = Context.OwningProcess.ReadString(MessagePtr, Length);
|
Report.FileName = Context.OwningProcess.ReadString(MessagePtr, Length);
|
||||||
|
|
||||||
|
@ -57,20 +78,19 @@ namespace CxbxDebugger
|
||||||
public IntPtr Address { get; set; }
|
public IntPtr Address { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KernelPatch GetKernelPatchReport(DebuggerThread Context, uint[] Data)
|
public static KernelPatch GetKernelPatchReport(DebuggerThread Context, DataProcessor Data)
|
||||||
{
|
{
|
||||||
KernelPatch Report = new KernelPatch();
|
KernelPatch Report = new KernelPatch();
|
||||||
|
|
||||||
StringType Type = (StringType)Data[0];
|
var Type = (StringType)Data.Pop();
|
||||||
|
|
||||||
if (Type != StringType.CHAR)
|
if (Type != StringType.CHAR)
|
||||||
throw new Exception("GetKernelPatchReport expects a string message");
|
throw new Exception("GetKernelPatchReport expects a string message");
|
||||||
|
|
||||||
uint Length = Data[1];
|
var Length = Data.Pop();
|
||||||
IntPtr MessagePtr = new IntPtr(Data[2]);
|
var MessagePtr = new IntPtr(Data.Pop());
|
||||||
|
|
||||||
Report.Name = Context.OwningProcess.ReadString(MessagePtr, Length);
|
Report.Name = Context.OwningProcess.ReadString(MessagePtr, Length);
|
||||||
Report.Address = new IntPtr(Data[3]);
|
Report.Address = new IntPtr(Data.Pop());
|
||||||
|
|
||||||
return Report;
|
return Report;
|
||||||
}
|
}
|
||||||
|
@ -82,23 +102,21 @@ namespace CxbxDebugger
|
||||||
public bool Succeeded { get; set; }
|
public bool Succeeded { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileOpened GetFileOpenedReport(DebuggerThread Context, uint[] Data)
|
public static FileOpened GetFileOpenedReport(DebuggerThread Context, DataProcessor Data)
|
||||||
{
|
{
|
||||||
FileOpened Report = new FileOpened();
|
FileOpened Report = new FileOpened();
|
||||||
|
|
||||||
Report.Handle = new IntPtr(Data[0]);
|
Report.Handle = new IntPtr(Data.Pop());
|
||||||
|
|
||||||
StringType Type = (StringType)Data[1];
|
|
||||||
|
|
||||||
|
var Type = (StringType)Data.Pop();
|
||||||
if (Type != StringType.WCHAR)
|
if (Type != StringType.WCHAR)
|
||||||
throw new Exception("GetFileOpenedReport expects a widestring message");
|
throw new Exception("GetFileOpenedReport expects a widestring message");
|
||||||
|
|
||||||
uint Length = Data[2];
|
var Length = Data.Pop();
|
||||||
IntPtr MessagePtr = new IntPtr(Data[3]);
|
var MessagePtr = new IntPtr(Data.Pop());
|
||||||
|
|
||||||
Report.FileName = Context.OwningProcess.ReadWString(MessagePtr, Length);
|
Report.FileName = Context.OwningProcess.ReadWString(MessagePtr, Length);
|
||||||
|
Report.Succeeded = Data.Pop() != 0;
|
||||||
Report.Succeeded = Data[4] != 0;
|
|
||||||
|
|
||||||
return Report;
|
return Report;
|
||||||
}
|
}
|
||||||
|
@ -110,13 +128,13 @@ namespace CxbxDebugger
|
||||||
public uint Offset { get; set; }
|
public uint Offset { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileRead GetFileReadReport(DebuggerThread Context, uint[] Data)
|
public static FileRead GetFileReadReport(DebuggerThread Context, DataProcessor Data)
|
||||||
{
|
{
|
||||||
FileRead Report = new FileRead();
|
FileRead Report = new FileRead();
|
||||||
|
|
||||||
Report.Handle = new IntPtr(Data[0]);
|
Report.Handle = new IntPtr(Data.Pop());
|
||||||
Report.Length = Data[1];
|
Report.Length = Data.Pop();
|
||||||
Report.Offset = Data[2];
|
Report.Offset = Data.Pop();
|
||||||
|
|
||||||
return Report;
|
return Report;
|
||||||
}
|
}
|
||||||
|
@ -128,13 +146,13 @@ namespace CxbxDebugger
|
||||||
public uint Offset { get; set; }
|
public uint Offset { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileWrite GetFileWriteReport(DebuggerThread Context, uint[] Data)
|
public static FileWrite GetFileWriteReport(DebuggerThread Context, DataProcessor Data)
|
||||||
{
|
{
|
||||||
FileWrite Report = new FileWrite();
|
FileWrite Report = new FileWrite();
|
||||||
|
|
||||||
Report.Handle = new IntPtr(Data[0]);
|
Report.Handle = new IntPtr(Data.Pop());
|
||||||
Report.Length = Data[1];
|
Report.Length = Data.Pop();
|
||||||
Report.Offset = Data[2];
|
Report.Offset = Data.Pop();
|
||||||
|
|
||||||
return Report;
|
return Report;
|
||||||
}
|
}
|
||||||
|
@ -144,18 +162,20 @@ namespace CxbxDebugger
|
||||||
public IntPtr Handle { get; set; }
|
public IntPtr Handle { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileClosed GetFileClosedReport(DebuggerThread Context, uint[] Data)
|
public static FileClosed GetFileClosedReport(DebuggerThread Context, DataProcessor Data)
|
||||||
{
|
{
|
||||||
// TODO: Restructure this library
|
// TODO: Restructure this library
|
||||||
uint InvalidHandle = (uint)VsChromium.Core.Win32.Handles.NativeMethods.INVALID_HANDLE_VALUE;
|
uint InvalidHandle = (uint)VsChromium.Core.Win32.Handles.NativeMethods.INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
var Handle = Data.Pop();
|
||||||
|
|
||||||
// Skip invalid file handles
|
// Skip invalid file handles
|
||||||
if (Data[0] == InvalidHandle)
|
if (Handle == InvalidHandle)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
FileClosed Report = new FileClosed();
|
FileClosed Report = new FileClosed();
|
||||||
|
|
||||||
Report.Handle = new IntPtr(Data[0]);
|
Report.Handle = new IntPtr(Handle);
|
||||||
|
|
||||||
return Report;
|
return Report;
|
||||||
}
|
}
|
||||||
|
@ -169,59 +189,78 @@ namespace CxbxDebugger
|
||||||
public IntPtr ParameterBase { get; set; }
|
public IntPtr ParameterBase { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExceptionHandledQuery GetExceptionHandledQuery(DebuggerThread Context, uint[] Data)
|
public static ExceptionHandledQuery GetExceptionHandledQuery(DebuggerThread Context, DataProcessor Data)
|
||||||
{
|
{
|
||||||
ExceptionHandledQuery Query = new ExceptionHandledQuery();
|
ExceptionHandledQuery Query = new ExceptionHandledQuery();
|
||||||
|
|
||||||
Query.ReponseAddr = new IntPtr(Data[0]);
|
Query.ReponseAddr = new IntPtr(Data.Pop());
|
||||||
Query.ExceptionAddress = Data[1];
|
Query.ExceptionAddress = Data.Pop();
|
||||||
Query.ExceptionCode = Data[2];
|
Query.ExceptionCode = Data.Pop();
|
||||||
Query.ParameterCount = Data[3];
|
Query.ParameterCount = Data.Pop();
|
||||||
Query.ParameterBase = new IntPtr(Data[4]);
|
Query.ParameterBase = new IntPtr(Data.Pop());
|
||||||
|
|
||||||
return Query;
|
return Query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DebuggerInit
|
public class DebuggerInit
|
||||||
{
|
{
|
||||||
public uint TitleID { get; set; }
|
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DebuggerInit GetDebuggerInitReport(DebuggerThread Context, uint[] Data)
|
public static DebuggerInit GetDebuggerInitReport(DebuggerThread Context, DataProcessor Data)
|
||||||
{
|
{
|
||||||
DebuggerInit Report = new DebuggerInit();
|
DebuggerInit Report = new DebuggerInit();
|
||||||
|
|
||||||
Report.TitleID = Data[0];
|
StringType Type = (StringType)Data.Pop();
|
||||||
|
|
||||||
StringType Type = (StringType)Data[1];
|
|
||||||
|
|
||||||
if (Type != StringType.CHAR)
|
if (Type != StringType.CHAR)
|
||||||
throw new Exception("GetDebuggerInitReport expects a string message");
|
throw new Exception("GetDebuggerInitReport expects a string message");
|
||||||
|
|
||||||
uint Length = Data[2];
|
uint Length = Data.Pop();
|
||||||
IntPtr MessagePtr = new IntPtr(Data[3]);
|
IntPtr MessagePtr = new IntPtr(Data.Pop());
|
||||||
|
|
||||||
Report.Title = Context.OwningProcess.ReadString(MessagePtr, Length);
|
Report.Title = Context.OwningProcess.ReadString(MessagePtr, Length);
|
||||||
|
|
||||||
return Report;
|
return Report;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class DebuggerNewTarget
|
||||||
|
{
|
||||||
|
public string CommandLine { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DebuggerNewTarget GetDebuggerNewTargetReport(DebuggerThread Context, DataProcessor Data)
|
||||||
|
{
|
||||||
|
var Report = new DebuggerNewTarget();
|
||||||
|
|
||||||
|
StringType Type = (StringType)Data.Pop();
|
||||||
|
|
||||||
|
if (Type != StringType.CHAR)
|
||||||
|
throw new Exception("GetDebuggerInitReport expects a string message");
|
||||||
|
|
||||||
|
uint Length = Data.Pop();
|
||||||
|
IntPtr MessagePtr = new IntPtr(Data.Pop());
|
||||||
|
|
||||||
|
Report.CommandLine = Context.OwningProcess.ReadString(MessagePtr, Length);
|
||||||
|
|
||||||
|
return Report;
|
||||||
|
}
|
||||||
|
|
||||||
public class MSVCThreadName
|
public class MSVCThreadName
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public uint ThreadId { get; set; }
|
public uint ThreadId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MSVCThreadName GetMSVCThreadName(DebuggerThread Context, uint[] Data)
|
public static MSVCThreadName GetMSVCThreadName(DebuggerThread Context, DataProcessor Data)
|
||||||
{
|
{
|
||||||
uint Type = Data[0];
|
var Type = Data.Pop();
|
||||||
if (Type != 0x1000)
|
if (Type != 0x1000)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
string ReportName = "";
|
string ReportName = "";
|
||||||
|
|
||||||
IntPtr MessagePtr = new IntPtr(Data[1]);
|
IntPtr MessagePtr = new IntPtr(Data.Pop());
|
||||||
if (MessagePtr != IntPtr.Zero)
|
if (MessagePtr != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
ReportName = Context.OwningProcess.ReadString(MessagePtr);
|
ReportName = Context.OwningProcess.ReadString(MessagePtr);
|
||||||
|
@ -230,7 +269,7 @@ namespace CxbxDebugger
|
||||||
MSVCThreadName Report = new MSVCThreadName();
|
MSVCThreadName Report = new MSVCThreadName();
|
||||||
|
|
||||||
Report.Name = ReportName;
|
Report.Name = ReportName;
|
||||||
Report.ThreadId = Data[2];
|
Report.ThreadId = Data.Pop();
|
||||||
|
|
||||||
return Report;
|
return Report;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue