Browse Source

Introduced new debugger class Process

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@71 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 21 years ago
parent
commit
917576aadc
  1. 3
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
  2. 9
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/MTA2STA.cs
  3. 296
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NDebugger.cs
  4. 212
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs

3
src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj

@ -66,6 +66,7 @@ @@ -66,6 +66,7 @@
<Compile Include="Src\Threads\ExceptionType.cs" />
<Compile Include="Src\Threads\Function.cs" />
<Compile Include="Src\Threads\NDebugger-Threads.cs" />
<Compile Include="Src\Threads\Process.cs" />
<Compile Include="Src\Threads\SourcecodeSegment.cs" />
<Compile Include="Src\Threads\Thread.cs" />
<Compile Include="Src\Threads\ThreadEventHandler.cs" />
@ -87,4 +88,4 @@ @@ -87,4 +88,4 @@
<Content Include="README.TXT" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
</Project>
</Project>

9
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/MTA2STA.cs

@ -25,6 +25,7 @@ namespace DebuggerInterop.Core @@ -25,6 +25,7 @@ namespace DebuggerInterop.Core
static object OnlyOneAtTimeLock = new Object();
static object DataLock = new Object();
object returnValue;
public MTA2STA()
{
@ -37,7 +38,7 @@ namespace DebuggerInterop.Core @@ -37,7 +38,7 @@ namespace DebuggerInterop.Core
System.Console.WriteLine("MTA2STA: " + msg);
}
public void CallInSTA (object targetObject, string functionName, object[] functionParameters)
public object CallInSTA (object targetObject, string functionName, object[] functionParameters)
{
lock (OnlyOneAtTimeLock) {
TraceMsg("call to process: " + functionName + " {");
@ -63,6 +64,7 @@ namespace DebuggerInterop.Core @@ -63,6 +64,7 @@ namespace DebuggerInterop.Core
TraceMsg("} // MTA2STA: call processed: " + functionName);
}
return returnValue;
}
void PerformCall(object sender, EventArgs e)
@ -105,11 +107,12 @@ namespace DebuggerInterop.Core @@ -105,11 +107,12 @@ namespace DebuggerInterop.Core
}
}
TraceMsg ("Invoke " + functionName + "{");
returnValue = null;
try {
if (targetObject is Type) {
method.Invoke(null, outputParams);
returnValue = method.Invoke(null, outputParams);
} else {
method.Invoke(targetObject, outputParams);
returnValue = method.Invoke(targetObject, outputParams);
}
} catch (System.Exception exception) {
System.Diagnostics.Debug.Fail("Invoke of " + functionName + " failed.", exception.ToString());

296
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NDebugger.cs

@ -40,48 +40,21 @@ namespace DebuggerLibrary @@ -40,48 +40,21 @@ namespace DebuggerLibrary
}
}
static ICorDebug corDebug;
static ManagedCallback managedCallback;
static ManagedCallbackProxy managedCallbackProxy;
static bool isProcessRunning;
static ICorDebugProcess mainProcess;
static Thread mainThread;
static Thread currentThread;
static Process mainProcess;
public static bool CatchHandledExceptions = false;
#region Public propeties
static public SourcecodeSegment NextStatement {
get{
try {
return CurrentThread.NextStatement;
} catch (CurrentThreadNotAviableException) {
System.Diagnostics.Debug.Fail("Unable to get NextStatement. CurrentThreadNotAviableException");
throw new NextStatementNotAviableException();
}
}
}
static public VariableCollection LocalVariables {
get{
Thread thread;
try {
thread = CurrentThread;
}
catch (CurrentThreadNotAviableException) {
//System.Diagnostics.Debug.Fail("Unable to get LocalVariables. CurrentThreadNotAviableException");
return new VariableCollection ();
}
return thread.LocalVariables;
}
static internal ICorDebug CorDebug {
get {
return corDebug;
}
}
#endregion
static internal ICorDebugProcess MainProcess {
static internal Process CurrentProcess {
get {
return mainProcess;
}
@ -101,41 +74,6 @@ namespace DebuggerLibrary @@ -101,41 +74,6 @@ namespace DebuggerLibrary
}
}
}
public static Thread MainThread {
get {
return mainThread;
}
set {
mainThread = value;
}
}
static public Thread CurrentThread {
get {
if (!IsDebugging) throw new CurrentThreadNotAviableException();
if (IsProcessRunning) throw new CurrentThreadNotAviableException();
if (currentThread != null) return currentThread;
if (mainThread != null) return mainThread;
throw new CurrentThreadNotAviableException();
}
set {
currentThread = value;
if (mainThread == null) {
mainThread = value;
}
if (managedCallback.HandlingCallback == false) {
OnDebuggingPaused(PausedReason.CurrentThreadChanged);
}
}
}
static internal ICorDebugProcess corProcess {
get {
if (MainProcess != null) return MainProcess;
throw new UnableToGetPropertyException(null, "corProcess", "Make sure debuger is attached to process");
}
}
internal static ManagedCallback ManagedCallback {
get {
@ -184,10 +122,7 @@ namespace DebuggerLibrary @@ -184,10 +122,7 @@ namespace DebuggerLibrary
ClearThreads();
MainProcess = null;
mainThread = null;
currentThread = null;
isProcessRunning = false;
CurrentProcess = null;
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
@ -303,6 +238,13 @@ namespace DebuggerLibrary @@ -303,6 +238,13 @@ namespace DebuggerLibrary
#region Execution control
static internal void Continue(ICorDebugAppDomain pAppDomain)
{
ICorDebugProcess outProcess;
pAppDomain.GetProcess(out outProcess);
outProcess.Continue(0);
}
static public void StartWithoutDebugging(System.Diagnostics.ProcessStartInfo psi)
{
System.Diagnostics.Process process;
@ -310,184 +252,118 @@ namespace DebuggerLibrary @@ -310,184 +252,118 @@ namespace DebuggerLibrary
process.StartInfo = psi;
process.Start();
}
static MTA2STA m2s = new MTA2STA();
static public void Start(string filename, string workingDirectory, string arguments)
{
if (IsDebugging) {
System.Diagnostics.Debug.Fail("Invalid operation");
return;
}
m2s.CallInSTA(typeof(NDebugger), "StartInternal", new Object[] {filename, workingDirectory, arguments});
return;
CurrentProcess = Process.CreateProcess(filename, workingDirectory, arguments);
}
static public unsafe void StartInternal(string filename, string workingDirectory, string arguments)
{
TraceMessage("Executing " + filename);
_SECURITY_ATTRIBUTES secAttr = new _SECURITY_ATTRIBUTES();
secAttr.bInheritHandle = 0;
secAttr.lpSecurityDescriptor = IntPtr.Zero;
secAttr.nLength = (uint)sizeof(_SECURITY_ATTRIBUTES); //=12?
uint[] processStartupInfo = new uint[17];
processStartupInfo[0] = sizeof(uint) * 17;
uint[] processInfo = new uint[4];
ICorDebugProcess outProcess;
fixed (uint* pprocessStartupInfo = processStartupInfo)
fixed (uint* pprocessInfo = processInfo)
corDebug.CreateProcess(
filename, // lpApplicationName
null, // lpCommandLine
ref secAttr, // lpProcessAttributes
ref secAttr, // lpThreadAttributes
1,//TRUE // bInheritHandles
0, // dwCreationFlags
IntPtr.Zero, // lpEnvironment
null, // lpCurrentDirectory
(uint)pprocessStartupInfo, // lpStartupInfo
(uint)pprocessInfo, // lpProcessInformation,
CorDebugCreateProcessFlags.DEBUG_NO_SPECIAL_OPTIONS, // debuggingFlags
out outProcess // ppProcess
);
isProcessRunning = true;
MainProcess = outProcess;
}
#endregion
static public void Break()
public void ToggleBreakpointAt(string fileName, int line, int column)
{
if (!IsDebugging || !IsProcessRunning) {
System.Diagnostics.Debug.Fail("Invalid operation");
return;
// Check if there is breakpoint on that line
foreach (Breakpoint breakpoint in Breakpoints) {
// TODO check filename too
if (breakpoint.SourcecodeSegment.StartLine == line) {
RemoveBreakpoint(breakpoint);
return;
}
}
corProcess.Stop(5000); // TODO: Hardcoded value
isProcessRunning = false;
OnDebuggingPaused(PausedReason.Break);
OnIsProcessRunningChanged();
}
// Add the breakpoint
Breakpoint addedBreakpoint = AddBreakpoint(fileName, line, column);
static public void StepInto()
{
try {
CurrentThread.StepInto();
} catch (CurrentThreadNotAviableException) {
System.Diagnostics.Debug.Fail("Unable to prerform step. CurrentThreadNotAviableException");
// Check if it wasn't forced to move to different line with breakpoint
foreach (Breakpoint breakpoint in Breakpoints) {
if (breakpoint != addedBreakpoint) { // Only the old ones
if (breakpoint.SourcecodeSegment.StartLine == addedBreakpoint.SourcecodeSegment.StartLine) {
// Whops! We have two breakpoint on signle line, delete one
RemoveBreakpoint(addedBreakpoint);
return;
}
}
}
}
static public void StepOver()
{
try {
CurrentThread.StepOver();
} catch (CurrentThreadNotAviableException) {
System.Diagnostics.Debug.Fail("Unable to prerform step. CurrentThreadNotAviableException");
static public bool IsProcessRunning {
get {
if (!IsDebugging) return false;
return CurrentProcess.IsProcessRunning;
}
set {
if (CurrentProcess == null) return;
CurrentProcess.IsProcessRunning = value;
}
}
static public void StepOut()
{
try {
CurrentThread.StepOut();
} catch (CurrentThreadNotAviableException) {
System.Diagnostics.Debug.Fail("Unable to prerform step. CurrentThreadNotAviableException");
static public bool IsDebugging {
get {
return (CurrentProcess != null);
}
}
static internal void Continue(ICorDebugAppDomain pAppDomain)
{
ICorDebugProcess outProcess;
pAppDomain.GetProcess(out outProcess);
if (MainProcess != outProcess) throw new DebuggerException("Request to continue AppDomain that does not belog to current process");
Continue();
static public Thread CurrentThread {
get {
return CurrentProcess.CurrentThread;
}
set {
CurrentProcess.CurrentThread = value;
}
}
static public void Continue()
{
if (!IsDebugging || IsProcessRunning) {
System.Diagnostics.Debug.Fail("Invalid operation");
return;
static public Thread MainThread {
get {
return CurrentProcess.MainThread;
}
bool abort = false;
OnDebuggingIsResuming(ref abort);
if (abort == true) return;
isProcessRunning = true;
if (managedCallback.HandlingCallback == false) {
OnDebuggingResumed();
OnIsProcessRunningChanged();
set {
CurrentProcess.MainThread = value;
}
corProcess.Continue(0);
}
static public void Terminate()
{
if (!IsDebugging) {
System.Diagnostics.Debug.Fail("Invalid operation");
return;
static public SourcecodeSegment NextStatement {
get{
return CurrentProcess.NextStatement;
}
}
int running;
corProcess.IsRunning(out running);
// Resume stoped tread
if (running == 0) {
Continue(); // TODO: Remove this...
static public VariableCollection LocalVariables {
get{
return CurrentProcess.LocalVariables;
}
// Stop&terminate - both must be called
corProcess.Stop(5000); // TODO: ...and this
corProcess.Terminate(0);
}
static public bool IsProcessRunning {
get {
if (!IsDebugging) return false;
return isProcessRunning;
}
set {
isProcessRunning = value;
}
static public void Break()
{
CurrentProcess.Break();
}
static public bool IsDebugging {
get {
return (MainProcess != null);
}
static public void StepInto()
{
CurrentProcess.StepInto();
}
#endregion
static public void StepOver()
{
CurrentProcess.StepOver();
}
public void ToggleBreakpointAt(string fileName, int line, int column)
static public void StepOut()
{
// Check if there is breakpoint on that line
foreach (Breakpoint breakpoint in Breakpoints) {
// TODO check filename too
if (breakpoint.SourcecodeSegment.StartLine == line) {
RemoveBreakpoint(breakpoint);
return;
}
}
CurrentProcess.StepOut();
}
// Add the breakpoint
Breakpoint addedBreakpoint = AddBreakpoint(fileName, line, column);
static public void Continue()
{
CurrentProcess.Continue();
}
// Check if it wasn't forced to move to different line with breakpoint
foreach (Breakpoint breakpoint in Breakpoints) {
if (breakpoint != addedBreakpoint) { // Only the old ones
if (breakpoint.SourcecodeSegment.StartLine == addedBreakpoint.SourcecodeSegment.StartLine) {
// Whops! We have two breakpoint on signle line, delete one
RemoveBreakpoint(addedBreakpoint);
return;
}
}
}
static public void Terminate()
{
CurrentProcess.Terminate();
}
}
}

212
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs

@ -0,0 +1,212 @@ @@ -0,0 +1,212 @@
// <file>
// <owner name="David Srbecký" email="dsrbecky@post.cz"/>
// </file>
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using DebuggerInterop.Core;
using DebuggerInterop.MetaData;
namespace DebuggerLibrary
{
public class Process
{
ICorDebugProcess corProcess;
Thread mainThread;
Thread currentThread;
bool isProcessRunning;
internal Process(ICorDebugProcess corProcess)
{
this.corProcess = corProcess;
}
internal ICorDebugProcess CorProcess {
get {
return corProcess;
}
}
public Thread CurrentThread {
get {
if (IsProcessRunning) throw new CurrentThreadNotAviableException();
if (currentThread != null) return currentThread;
if (mainThread != null) return mainThread;
throw new CurrentThreadNotAviableException();
}
set {
currentThread = value;
if (mainThread == null) {
mainThread = value;
}
if (NDebugger.ManagedCallback.HandlingCallback == false) {
NDebugger.OnDebuggingPaused(PausedReason.CurrentThreadChanged);
}
}
}
public Thread MainThread {
get {
return mainThread;
}
set {
mainThread = value;
}
}
public SourcecodeSegment NextStatement {
get{
try {
return CurrentThread.NextStatement;
} catch (CurrentThreadNotAviableException) {
System.Diagnostics.Debug.Fail("Unable to get NextStatement. CurrentThreadNotAviableException");
throw new NextStatementNotAviableException();
}
}
}
public VariableCollection LocalVariables {
get{
Thread thread;
try {
thread = CurrentThread;
}
catch (CurrentThreadNotAviableException) {
//System.Diagnostics.Debug.Fail("Unable to get LocalVariables. CurrentThreadNotAviableException");
return new VariableCollection ();
}
return thread.LocalVariables;
}
}
static public Process CreateProcess(string filename, string workingDirectory, string arguments)
{
MTA2STA m2s = new MTA2STA();
Process createdProcess = null;
createdProcess = (Process)m2s.CallInSTA(typeof(Process), "StartInternal", new Object[] {filename, workingDirectory, arguments});
return createdProcess;
}
static public unsafe Process StartInternal(string filename, string workingDirectory, string arguments)
{
NDebugger.TraceMessage("Executing " + filename);
_SECURITY_ATTRIBUTES secAttr = new _SECURITY_ATTRIBUTES();
secAttr.bInheritHandle = 0;
secAttr.lpSecurityDescriptor = IntPtr.Zero;
secAttr.nLength = (uint)sizeof(_SECURITY_ATTRIBUTES); //=12?
uint[] processStartupInfo = new uint[17];
processStartupInfo[0] = sizeof(uint) * 17;
uint[] processInfo = new uint[4];
ICorDebugProcess outProcess;
fixed (uint* pprocessStartupInfo = processStartupInfo)
fixed (uint* pprocessInfo = processInfo)
NDebugger.CorDebug.CreateProcess(
filename, // lpApplicationName
null, // lpCommandLine
ref secAttr, // lpProcessAttributes
ref secAttr, // lpThreadAttributes
1,//TRUE // bInheritHandles
0, // dwCreationFlags
IntPtr.Zero, // lpEnvironment
null, // lpCurrentDirectory
(uint)pprocessStartupInfo, // lpStartupInfo
(uint)pprocessInfo, // lpProcessInformation,
CorDebugCreateProcessFlags.DEBUG_NO_SPECIAL_OPTIONS, // debuggingFlags
out outProcess // ppProcess
);
return new Process(outProcess);
}
public void Break()
{
if (!IsProcessRunning) {
System.Diagnostics.Debug.Fail("Invalid operation");
return;
}
corProcess.Stop(5000); // TODO: Hardcoded value
isProcessRunning = false;
NDebugger.OnDebuggingPaused(PausedReason.Break);
NDebugger.OnIsProcessRunningChanged();
}
public void StepInto()
{
try {
CurrentThread.StepInto();
} catch (CurrentThreadNotAviableException) {
System.Diagnostics.Debug.Fail("Unable to prerform step. CurrentThreadNotAviableException");
}
}
public void StepOver()
{
try {
CurrentThread.StepOver();
} catch (CurrentThreadNotAviableException) {
System.Diagnostics.Debug.Fail("Unable to prerform step. CurrentThreadNotAviableException");
}
}
public void StepOut()
{
try {
CurrentThread.StepOut();
} catch (CurrentThreadNotAviableException) {
System.Diagnostics.Debug.Fail("Unable to prerform step. CurrentThreadNotAviableException");
}
}
public void Continue()
{
if (IsProcessRunning) {
System.Diagnostics.Debug.Fail("Invalid operation");
return;
}
bool abort = false;
NDebugger.OnDebuggingIsResuming(ref abort);
if (abort == true) return;
isProcessRunning = true;
if (NDebugger.ManagedCallback.HandlingCallback == false) {
NDebugger.OnDebuggingResumed();
NDebugger.OnIsProcessRunningChanged();
}
corProcess.Continue(0);
}
public void Terminate()
{
int running;
corProcess.IsRunning(out running);
// Resume stoped tread
if (running == 0) {
Continue(); // TODO: Remove this...
}
// Stop&terminate - both must be called
corProcess.Stop(5000); // TODO: ...and this
corProcess.Terminate(0);
}
public bool IsProcessRunning {
get {
return isProcessRunning;
}
set {
isProcessRunning = value;
}
}
}
}
Loading…
Cancel
Save