Further support for identifying modules and threads

A slight restructure too
This commit is contained in:
x1nixmzeng 2018-01-04 23:58:18 +00:00
parent 92d6635c4e
commit ff54eb8b9e
15 changed files with 394 additions and 147 deletions

View File

@ -63,18 +63,24 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Debugger.cs" /> <Compile Include="Debugger\Debugger.cs" />
<Compile Include="DebuggerEventListener.cs" /> <Compile Include="Debugger\DebuggerEventListener.cs" />
<Compile Include="DebuggerModule.cs" /> <Compile Include="Debugger\DebuggerInstance.cs" />
<Compile Include="DebuggerProcess.cs" /> <Compile Include="Debugger\DebuggerModule.cs" />
<Compile Include="DebuggerCallstack.cs" /> <Compile Include="Debugger\DebuggerProcess.cs" />
<Compile Include="DebuggerThread.cs" /> <Compile Include="Debugger\DebuggerCallstack.cs" />
<Compile Include="DebuggerSymbols\DebuggerSymbolProvider.cs" />
<Compile Include="Debugger\DebuggerSymbolServer.cs" />
<Compile Include="Debugger\DebuggerThread.cs" />
<Compile Include="Form1.cs"> <Compile Include="Form1.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="Form1.Designer.cs"> <Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon> <DependentUpon>Form1.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="DebuggerSymbols\HLECache\HLECacheFile.cs" />
<Compile Include="DebuggerSymbols\HLECache\HLECacheProvider.cs" />
<Compile Include="DebuggerSymbols\HLECache\Utils\INIReader.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ThreadHelpers.cs" /> <Compile Include="ThreadHelpers.cs" />
@ -91,7 +97,6 @@
<Compile Include="Win32\Debugging\LOAD_DLL_DEBUG_INFO.cs" /> <Compile Include="Win32\Debugging\LOAD_DLL_DEBUG_INFO.cs" />
<Compile Include="Win32\Debugging\NativeMethods.cs" /> <Compile Include="Win32\Debugging\NativeMethods.cs" />
<Compile Include="Win32\Debugging\OUTPUT_DEBUG_STRING_INFO.cs" /> <Compile Include="Win32\Debugging\OUTPUT_DEBUG_STRING_INFO.cs" />
<Compile Include="Win32\Debugging\PTHREAD_START_ROUTINE.cs" />
<Compile Include="Win32\Debugging\RIP_INFO.cs" /> <Compile Include="Win32\Debugging\RIP_INFO.cs" />
<Compile Include="Win32\Debugging\UNLOAD_DLL_DEBUG_INFO.cs" /> <Compile Include="Win32\Debugging\UNLOAD_DLL_DEBUG_INFO.cs" />
<Compile Include="Win32\Handles\NativeMethods.cs" /> <Compile Include="Win32\Handles\NativeMethods.cs" />

View File

@ -7,11 +7,10 @@ using System.Text;
using WinProcesses = VsChromium.Core.Win32.Processes; using WinProcesses = VsChromium.Core.Win32.Processes;
using WinDebug = VsChromium.Core.Win32.Debugging; using WinDebug = VsChromium.Core.Win32.Debugging;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using CxbxDebugger.TheadHelpers;
namespace CxbxDebugger namespace CxbxDebugger
{ {
public class Debugger : IDisposable public class Debugger : DebuggerEventListener, IDisposable
{ {
enum RunState enum RunState
{ {
@ -32,28 +31,30 @@ namespace CxbxDebugger
RunState State = RunState.NotLaunched; RunState State = RunState.NotLaunched;
List<DebuggerModule> ModuleList = new List<DebuggerModule>(); DebuggerInstance DebugInstance;
List<DebuggerThread> ThreadList = new List<DebuggerThread>();
List<DebuggerProcess> ProcessList = new List<DebuggerProcess>();
List<DebuggerEventListener> EventListeners = new List<DebuggerEventListener>(); List<DebuggerEventListener> EventListeners = new List<DebuggerEventListener>();
CONTEXT_x86 lastReadCtxt = new CONTEXT_x86 DebuggerSymbolServer SymbolSrv;
private void Init()
{ {
ContextFlags = DebugInstance = null;
ContextFlags.CONTEXT_i386 |
ContextFlags.CONTEXT_CONTROL | SymbolSrv = new DebuggerSymbolServer();
ContextFlags.CONTEXT_INTEGER |
ContextFlags.CONTEXT_SEGMENTS RegisterEventListener(this);
}; }
public Debugger() public Debugger()
{ {
// Init();
} }
public Debugger(string[] x_args) public Debugger(string[] x_args)
{ {
Init();
if (x_args == null) if (x_args == null)
return; return;
@ -82,20 +83,17 @@ namespace CxbxDebugger
public void Break() public void Break()
{ {
// This will ONLY suspend the main process if (DebugInstance != null)
// Not ideal if there are multiple processes in play
if (!hThread.IsInvalid)
{ {
WinProcesses.NativeMethods.SuspendThread(hThread.DangerousGetHandle()); DebugInstance.MainProcess.Suspend();
} }
} }
public void Resume() public void Resume()
{ {
if (!hThread.IsInvalid) if (DebugInstance != null)
{ {
WinProcesses.NativeMethods.ResumeThread(hThread.DangerousGetHandle()); DebugInstance.MainProcess.Resume();
} }
} }
@ -111,6 +109,26 @@ namespace CxbxDebugger
return false; return false;
} }
static string CxbxDebuggerPrefix = "CxbxDebugger! ";
public override void OnDebugOutput(string Message)
{
if (Message.StartsWith(CxbxDebuggerPrefix))
{
SetupHLECacheProvider(Message.Substring(CxbxDebuggerPrefix.Length));
}
}
private void SetupHLECacheProvider(string Filename)
{
var Provider = new HLECacheProvider();
if( Provider.Load(Filename) )
{
SymbolSrv.RegisterProvider(Provider);
}
}
public bool Launch() public bool Launch()
{ {
if (CanLaunch() == false) if (CanLaunch() == false)
@ -137,9 +155,28 @@ namespace CxbxDebugger
if (bRet == true) if (bRet == true)
{ {
// Store these so they can be marshalled, and closed correctly // Store these so they can be marshalled, and closed correctly
// TODO Move to Debugger* classes
hProcess = new WinProcesses.SafeProcessHandle(stProcessInfo.hProcess); hProcess = new WinProcesses.SafeProcessHandle(stProcessInfo.hProcess);
hThread = new WinProcesses.SafeThreadHandle(stProcessInfo.hThread); hThread = new WinProcesses.SafeThreadHandle(stProcessInfo.hThread);
var Process = new DebuggerProcess();
Process.Handle = stProcessInfo.hProcess;
Process.ProcessID = (uint)stProcessInfo.dwProcessId;
var Thread = new DebuggerThread(Process);
Thread.Handle = stProcessInfo.hThread;
Thread.ThreadID = NativeMethods.GetThreadId(Thread.Handle);
Process.Threads.Add(Thread);
Process.MainThread = Thread;
DebugInstance = new DebuggerInstance(Process);
// Register the instance to track thread creation
RegisterEventListener(DebugInstance);
State = RunState.Running; State = RunState.Running;
} }
@ -173,8 +210,10 @@ namespace CxbxDebugger
private string ReadProcessString(IntPtr NamePtr, uint Length, bool Unicode) private string ReadProcessString(IntPtr NamePtr, uint Length, bool Unicode)
{ {
string resultStr = "";
if (Length == 0 || Length > 512) if (Length == 0 || Length > 512)
return ""; return resultStr;
byte[] buffer = new byte[Length]; byte[] buffer = new byte[Length];
@ -193,15 +232,18 @@ namespace CxbxDebugger
// FIXME Questionable Unicode support here // FIXME Questionable Unicode support here
if (Unicode) if (Unicode)
{ {
return Encoding.Unicode.GetString(buffer, 0, (int)numRead); resultStr = Encoding.Unicode.GetString(buffer, 0, (int)numRead);
} }
else else
{ {
return Encoding.ASCII.GetString(buffer, 0, (int)numRead); // TODO Investigate why the read length includes the nul-terminator
if (numRead > 1) --numRead;
resultStr = Encoding.ASCII.GetString(buffer, 0, (int)numRead);
} }
} }
return ""; return resultStr;
} }
private uint GetMemory(IntPtr addr) private uint GetMemory(IntPtr addr)
@ -223,61 +265,46 @@ namespace CxbxDebugger
return BitConverter.ToUInt32(buffer, 0); return BitConverter.ToUInt32(buffer, 0);
} }
private void BuildCallstack() private void HandleCreateThread(WinDebug.DEBUG_EVENT DebugEvent)
{ {
// Skip if we have nothing to report to var DebugInfo = DebugEvent.CreateThread;
if (EventListeners.Count == 0)
return;
bool Result = NativeMethods.GetThreadContext(hThread.DangerousGetHandle(), ref lastReadCtxt); var Thread = new DebuggerThread(DebugInstance.MainProcess);
if (!Result)
{
// TODO: Handle this
return;
}
var ebp = lastReadCtxt.ebp; Thread.Handle = DebugInfo.hThread;
Thread.ThreadID = Thread.ThreadID = NativeMethods.GetThreadId(Thread.Handle);
var Callstack = new DebuggerCallstack();
Callstack.AddFrame(new DebuggerStackFrame(new IntPtr(ebp), new IntPtr(lastReadCtxt.eip)));
do
{
var ReturnAddr = GetMemory(new IntPtr(ebp + 4));
ebp = GetMemory(new IntPtr(ebp));
if (ebp == 0 || ReturnAddr == ebp)
break;
Callstack.AddFrame(new DebuggerStackFrame(new IntPtr(ebp), new IntPtr(ReturnAddr)));
}
while (!Callstack.HasEnoughFrames);
foreach (DebuggerEventListener EvtListener in EventListeners) foreach (DebuggerEventListener EvtListener in EventListeners)
{ {
EvtListener.OnCallstack(Callstack); EvtListener.OnThreadCreate(Thread);
}
}
private void HandleExitThread(WinDebug.DEBUG_EVENT DebugEvent)
{
var DebugInfo = DebugEvent.ExitThread;
var TargetThread = DebugInstance.MainProcess.Threads.Find(Thread => Thread.ThreadID == DebugEvent.dwThreadId);
//uint ExitCode = DebugInfo.dwExitCode;
if (TargetThread != null)
{
foreach (DebuggerEventListener EvtListener in EventListeners)
{
EvtListener.OnThreadExit(TargetThread);
}
} }
} }
private void HandleCreateProcess(WinDebug.DEBUG_EVENT DebugEvent) private void HandleCreateProcess(WinDebug.DEBUG_EVENT DebugEvent)
{ {
// TODO Investigate why this is throwing an exception converting to this type var DebugInfo = DebugEvent.CreateProcessInfo;
//var DebugInfo = DebugEvent.CreateProcessInfo;
var Process = new DebuggerProcess(); // Stub
//DebugInfo.hFile
//DebugInfo.hProcess
//DebugInfo.hThread
//DebugInfo.lpBaseOfImage
//DebugInfo.lpStartAddress
ProcessList.Add(Process);
foreach (DebuggerEventListener EvtListener in EventListeners) foreach (DebuggerEventListener EvtListener in EventListeners)
{ {
EvtListener.OnProcessCreate(Process); EvtListener.OnProcessCreate(null);
} }
} }
@ -285,7 +312,7 @@ namespace CxbxDebugger
{ {
var DebugInfo = DebugEvent.ExitProcess; var DebugInfo = DebugEvent.ExitProcess;
//DebugInfo.dwExitCode // Stub
foreach (DebuggerEventListener EvtListener in EventListeners) foreach (DebuggerEventListener EvtListener in EventListeners)
{ {
@ -300,8 +327,7 @@ namespace CxbxDebugger
var Module = new DebuggerModule(); var Module = new DebuggerModule();
Module.Path = ResolveProcessPath(DebugInfo.hFile); Module.Path = ResolveProcessPath(DebugInfo.hFile);
Module.ImageBase = DebugInfo.lpBaseOfDll;
ModuleList.Add(Module);
foreach (DebuggerEventListener EvtListener in EventListeners) foreach (DebuggerEventListener EvtListener in EventListeners)
{ {
@ -313,11 +339,14 @@ namespace CxbxDebugger
{ {
var DebugInfo = DebugEvent.UnloadDll; var DebugInfo = DebugEvent.UnloadDll;
//DebugInfo.lpBaseOfDll var TargetModule = DebugInstance.MainProcess.Modules.Find(Module => Module.ImageBase == DebugInfo.lpBaseOfDll);
if (TargetModule != null)
{
foreach (DebuggerEventListener EvtListener in EventListeners) foreach (DebuggerEventListener EvtListener in EventListeners)
{ {
EvtListener.OnModuleUnloaded(null); EvtListener.OnModuleUnloaded(TargetModule);
}
} }
} }
@ -335,7 +364,7 @@ namespace CxbxDebugger
public void Run() public void Run()
{ {
WinDebug.DEBUG_EVENT DbgEvt; WinDebug.DEBUG_EVENT DbgEvt = new WinDebug.DEBUG_EVENT();
WinDebug.CONTINUE_STATUS ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE; WinDebug.CONTINUE_STATUS ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE;
bool bContinue = true; bool bContinue = true;
@ -353,17 +382,37 @@ namespace CxbxDebugger
switch (DbgEvt.dwDebugEventCode) switch (DbgEvt.dwDebugEventCode)
{ {
case WinDebug.DEBUG_EVENT_CODE.EXCEPTION_DEBUG_EVENT:
{
// TODO: Handle
}
break;
case WinDebug.DEBUG_EVENT_CODE.CREATE_THREAD_DEBUG_EVENT:
{
HandleCreateThread(DbgEvt);
}
break;
case WinDebug.DEBUG_EVENT_CODE.CREATE_PROCESS_DEBUG_EVENT: case WinDebug.DEBUG_EVENT_CODE.CREATE_PROCESS_DEBUG_EVENT:
{ {
// TODO: Limit support for multiple processes
HandleCreateProcess(DbgEvt); HandleCreateProcess(DbgEvt);
} }
break; break;
case WinDebug.DEBUG_EVENT_CODE.EXIT_THREAD_DEBUG_EVENT:
{
HandleExitThread(DbgEvt);
}
break;
case WinDebug.DEBUG_EVENT_CODE.EXIT_PROCESS_DEBUG_EVENT: case WinDebug.DEBUG_EVENT_CODE.EXIT_PROCESS_DEBUG_EVENT:
{ {
HandleExitProcess(DbgEvt); HandleExitProcess(DbgEvt);
// XX temp // XX Temporary
bContinue = false; bContinue = false;
} }
break; break;
@ -371,29 +420,24 @@ namespace CxbxDebugger
case WinDebug.DEBUG_EVENT_CODE.LOAD_DLL_DEBUG_EVENT: case WinDebug.DEBUG_EVENT_CODE.LOAD_DLL_DEBUG_EVENT:
{ {
HandleLoadDll(DbgEvt); HandleLoadDll(DbgEvt);
} }
break; break;
case WinDebug.DEBUG_EVENT_CODE.UNLOAD_DLL_DEBUG_EVENT: case WinDebug.DEBUG_EVENT_CODE.UNLOAD_DLL_DEBUG_EVENT:
{ {
HandleUnloadDll(DbgEvt); HandleUnloadDll(DbgEvt);
} }
break; break;
case WinDebug.DEBUG_EVENT_CODE.OUTPUT_DEBUG_STRING_EVENT: case WinDebug.DEBUG_EVENT_CODE.OUTPUT_DEBUG_STRING_EVENT:
{ {
HandleOutputDebugString(DbgEvt); HandleOutputDebugString(DbgEvt);
} }
break; break;
case WinDebug.DEBUG_EVENT_CODE.EXCEPTION_DEBUG_EVENT: case WinDebug.DEBUG_EVENT_CODE.RIP_EVENT:
{ {
// TODO: Handle properly // TODO: Handle
BuildCallstack();
} }
break; break;
} }

View File

@ -1,20 +1,31 @@
using System; // Written by x1nixmzeng for the Cxbx-Reloaded project
//
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CxbxDebugger namespace CxbxDebugger
{ {
public class DebuggerStackFrame public class DebuggerStackFrame
{ {
public IntPtr BasePointer { get; } public IntPtr PC { get; }
public IntPtr CodeAddress { get; } public IntPtr Base { get; }
public IntPtr Stack { get; }
public DebuggerStackFrame(IntPtr Base, IntPtr CodeAddr) // TOOD Resolve symbol for this frame
public DebuggerStackFrame(IntPtr EIP, IntPtr EBP, IntPtr ESP)
{ {
BasePointer = Base; PC = EIP;
CodeAddress = CodeAddr; Base = EBP;
Stack = ESP;
}
public DebuggerStackFrame(IntPtr EIP, IntPtr EBP)
{
PC = EIP;
Base = EBP;
Stack = IntPtr.Zero;
} }
} }
@ -42,6 +53,7 @@ namespace CxbxDebugger
} }
} }
// TODO Rename this property
public bool HasEnoughFrames public bool HasEnoughFrames
{ {
get get

View File

@ -5,10 +5,6 @@ namespace CxbxDebugger
{ {
public abstract class DebuggerEventListener public abstract class DebuggerEventListener
{ {
public DebuggerEventListener()
{
}
public virtual void OnDebugStart() { } public virtual void OnDebugStart() { }
public virtual void OnDebugEnd() { } public virtual void OnDebugEnd() { }

View File

@ -0,0 +1,44 @@
// Written by x1nixmzeng for the Cxbx-Reloaded project
//
using System.Collections.Generic;
namespace CxbxDebugger
{
public class DebuggerInstance : DebuggerEventListener
{
public List<DebuggerProcess> Processes { get; set; }
public DebuggerProcess MainProcess { get; set; }
public DebuggerThread CurrentThread { get; set; }
public DebuggerInstance(DebuggerProcess InitialProcess)
{
Processes = new List<DebuggerProcess>();
Processes.Add(InitialProcess);
MainProcess = InitialProcess;
CurrentThread = InitialProcess.MainThread;
}
public override void OnThreadCreate(DebuggerThread Thread)
{
MainProcess.Threads.Add(Thread);
}
public override void OnThreadExit(DebuggerThread Thread)
{
MainProcess.Threads.Remove(Thread);
}
public override void OnModuleLoaded(DebuggerModule Module)
{
MainProcess.Modules.Add(Module);
}
public override void OnModuleUnloaded(DebuggerModule Module)
{
MainProcess.Modules.Remove(Module);
}
}
}

View File

@ -0,0 +1,20 @@
// Written by x1nixmzeng for the Cxbx-Reloaded project
//
using System;
namespace CxbxDebugger
{
public class DebuggerModule
{
public IntPtr ImageBase { get; set; }
public string Path { get; set; }
// Based on DebugProcessModule
public DebuggerModule()
{
ImageBase = IntPtr.Zero;
Path = "";
}
}
}

View File

@ -0,0 +1,72 @@
// Written by x1nixmzeng for the Cxbx-Reloaded project
//
using System;
using System.Collections.Generic;
using WinProcesses = VsChromium.Core.Win32.Processes;
namespace CxbxDebugger
{
public class DebuggerProcess
{
public IntPtr Handle { get; set; }
public uint ProcessID { get; set; }
public List<DebuggerModule> Modules { get; set; }
public List<DebuggerThread> Threads { get; set; }
public DebuggerModule MainModule { get; set; }
public DebuggerThread MainThread { get; set; }
// Based on DebugProcess
public DebuggerProcess()
{
Handle = IntPtr.Zero;
ProcessID = 0;
Modules = new List<DebuggerModule>();
Threads = new List<DebuggerThread>();
MainModule = null;
MainThread = null;
}
public void Suspend()
{
// TODO Thread may already be in a non-suspended state
foreach (DebuggerThread Thread in Threads)
{
WinProcesses.NativeMethods.SuspendThread(Thread.Handle);
}
}
public void Resume()
{
// TODO Thread may already be in a non-suspended state
foreach (DebuggerThread Thread in Threads)
{
WinProcesses.NativeMethods.ResumeThread(Thread.Handle);
}
}
public uint ReadMemory(IntPtr addr)
{
byte[] buffer = new byte[4];
uint numRead = 0;
WinProcesses.NativeMethods.ReadProcessMemory
(
Handle,
addr,
buffer,
4,
out numRead
);
return BitConverter.ToUInt32(buffer, 0);
}
}
}

View File

@ -0,0 +1,64 @@
// Written by x1nixmzeng for the Cxbx-Reloaded project
//
using System;
namespace CxbxDebugger
{
public class DebuggerThread
{
public DebuggerProcess OwningProcess { get; set; }
public IntPtr Handle { get; set; }
public uint ThreadID { get; set; }
public IntPtr StartAddress { get; set; }
public IntPtr ThreadBase { get; set; }
CONTEXT_x86 ContextCache = new CONTEXT_x86
{
ContextFlags =
ContextFlags.CONTEXT_i386 |
ContextFlags.CONTEXT_CONTROL |
ContextFlags.CONTEXT_INTEGER |
ContextFlags.CONTEXT_SEGMENTS
};
DebuggerCallstack CallstackCache = new DebuggerCallstack();
// Based on DebugThread
public DebuggerThread(DebuggerProcess Owner)
{
OwningProcess = Owner;
Handle = IntPtr.Zero;
ThreadID = 0;
StartAddress = IntPtr.Zero;
ThreadBase = IntPtr.Zero;
}
public void UpdateContext()
{
bool Result = NativeMethods.GetThreadContext(Handle, ref ContextCache);
if (!Result)
return;
var ebp = ContextCache.ebp;
CallstackCache = new DebuggerCallstack();
CallstackCache.AddFrame(new DebuggerStackFrame(new IntPtr(ContextCache.eip), new IntPtr(ebp), new IntPtr(ContextCache.esp)));
do
{
var ReturnAddr = OwningProcess.ReadMemory(new IntPtr(ebp + 4));
ebp = OwningProcess.ReadMemory(new IntPtr(ebp));
if (ebp == 0 || ReturnAddr == ebp)
break;
CallstackCache.AddFrame(new DebuggerStackFrame(new IntPtr(ReturnAddr), new IntPtr(ebp)));
}
while (!CallstackCache.HasEnoughFrames);
}
}
}

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CxbxDebugger
{
public class DebuggerModule
{
public string Path { get; set; }
}
}

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CxbxDebugger
{
public class DebuggerProcess
{
}
}

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CxbxDebugger
{
public class DebuggerThread
{
}
}

View File

@ -37,7 +37,7 @@ namespace CxbxDebugger
SetDebugProcessActive(false); SetDebugProcessActive(false);
// TODO: Wait for user to start this? // TODO: Wait for user to start this?
StartDebugging(); //StartDebugging();
} }
private void StartDebugging() private void StartDebugging()
@ -182,21 +182,37 @@ namespace CxbxDebugger
frm.DebugEvent("Ended debugging session"); frm.DebugEvent("Ended debugging session");
} }
public override void OnThreadCreate(DebuggerThread Thread)
{
frm.DebugEvent(string.Format("Thread created {0}", Thread.ThreadID));
}
public override void OnThreadExit(DebuggerThread Thread)
{
frm.DebugEvent(string.Format("Thread exited {0}", Thread.ThreadID));
}
public override void OnModuleLoaded(DebuggerModule Module) public override void OnModuleLoaded(DebuggerModule Module)
{ {
frm.DebugEvent("Loading module: " + Module.Path); frm.DebugEvent(string.Format("Loaded module \"{0}\"", Module.Path));
}
public override void OnModuleUnloaded(DebuggerModule Module)
{
frm.DebugEvent(string.Format("Unloaded module \"{0}\"", Module.Path));
} }
public override void OnDebugOutput(string Message) public override void OnDebugOutput(string Message)
{ {
frm.DebugEvent("Debug string: " + Message); frm.DebugEvent(string.Format("OutputDebugString \"{0}\"", Message));
} }
// TODO Update DebuggerStackFrame to query symbols
public override void OnCallstack(DebuggerCallstack Callstack) public override void OnCallstack(DebuggerCallstack Callstack)
{ {
foreach( DebuggerStackFrame StackFrame in Callstack.StackFrames) foreach( DebuggerStackFrame StackFrame in Callstack.StackFrames)
{ {
var stackFrameStr = string.Format("{0:X8} and {1:X8}", (uint)StackFrame.BasePointer, (uint)StackFrame.CodeAddress); var stackFrameStr = string.Format("{0:X8} --> {1:X8}", (uint)StackFrame.Base, (uint)StackFrame.PC);
frm.DebugEvent("Callstack: " + stackFrameStr); frm.DebugEvent("Callstack: " + stackFrameStr);
} }
} }

View File

@ -4,7 +4,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace CxbxDebugger.TheadHelpers namespace CxbxDebugger
{ {
[Flags] [Flags]
public enum ContextFlags : uint public enum ContextFlags : uint
@ -263,5 +263,8 @@ namespace CxbxDebugger.TheadHelpers
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT_x86 lpContext); public static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT_x86 lpContext);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetThreadId(IntPtr hThread);
} }
} }

View File

@ -65,7 +65,13 @@ namespace VsChromium.Core.Win32.Processes
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ReadProcessMemory(SafeProcessHandle hProcess, IntPtr lpBaseAddress, public static extern bool ReadProcessMemory(SafeProcessHandle hProcess, IntPtr lpBaseAddress,
[Out] byte[] buffer, uint size, out UInt32 lpNumberOfBytesRead); [Out] byte[] buffer, uint size, out uint lpNumberOfBytesRead);
// x1nix: added
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[Out] byte[] buffer, uint size, out uint lpNumberOfBytesRead);
[DllImport("ntdll.dll", SetLastError = true)] [DllImport("ntdll.dll", SetLastError = true)]
public static extern int NtQueryInformationProcess(SafeProcessHandle hProcess, ProcessInfoClass pic, ref ProcessBasicInformation pbi, int cb, out int pSize); public static extern int NtQueryInformationProcess(SafeProcessHandle hProcess, ProcessInfoClass pic, ref ProcessBasicInformation pbi, int cb, out int pSize);

View File

@ -14,6 +14,10 @@ namespace LowLevelDesign.Win32.Windows
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// x1nix: added
[DllImport("kernel32.dll")]
public static extern uint GetProcessId(IntPtr hProcess);
// x1nix: added // x1nix: added
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetFinalPathNameByHandleW(IntPtr hFile, IntPtr lpszFilePath, uint cchFilePath = 0u, uint dwFlags = 0u); public static extern uint GetFinalPathNameByHandleW(IntPtr hFile, IntPtr lpszFilePath, uint cchFilePath = 0u, uint dwFlags = 0u);