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 @@
<Compile Include="Src\Threads\ExceptionType.cs" /> <Compile Include="Src\Threads\ExceptionType.cs" />
<Compile Include="Src\Threads\Function.cs" /> <Compile Include="Src\Threads\Function.cs" />
<Compile Include="Src\Threads\NDebugger-Threads.cs" /> <Compile Include="Src\Threads\NDebugger-Threads.cs" />
<Compile Include="Src\Threads\Process.cs" />
<Compile Include="Src\Threads\SourcecodeSegment.cs" /> <Compile Include="Src\Threads\SourcecodeSegment.cs" />
<Compile Include="Src\Threads\Thread.cs" /> <Compile Include="Src\Threads\Thread.cs" />
<Compile Include="Src\Threads\ThreadEventHandler.cs" /> <Compile Include="Src\Threads\ThreadEventHandler.cs" />
@ -87,4 +88,4 @@
<Content Include="README.TXT" /> <Content Include="README.TXT" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" /> <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
static object OnlyOneAtTimeLock = new Object(); static object OnlyOneAtTimeLock = new Object();
static object DataLock = new Object(); static object DataLock = new Object();
object returnValue;
public MTA2STA() public MTA2STA()
{ {
@ -37,7 +38,7 @@ namespace DebuggerInterop.Core
System.Console.WriteLine("MTA2STA: " + msg); 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) { lock (OnlyOneAtTimeLock) {
TraceMsg("call to process: " + functionName + " {"); TraceMsg("call to process: " + functionName + " {");
@ -63,6 +64,7 @@ namespace DebuggerInterop.Core
TraceMsg("} // MTA2STA: call processed: " + functionName); TraceMsg("} // MTA2STA: call processed: " + functionName);
} }
return returnValue;
} }
void PerformCall(object sender, EventArgs e) void PerformCall(object sender, EventArgs e)
@ -105,11 +107,12 @@ namespace DebuggerInterop.Core
} }
} }
TraceMsg ("Invoke " + functionName + "{"); TraceMsg ("Invoke " + functionName + "{");
returnValue = null;
try { try {
if (targetObject is Type) { if (targetObject is Type) {
method.Invoke(null, outputParams); returnValue = method.Invoke(null, outputParams);
} else { } else {
method.Invoke(targetObject, outputParams); returnValue = method.Invoke(targetObject, outputParams);
} }
} catch (System.Exception exception) { } catch (System.Exception exception) {
System.Diagnostics.Debug.Fail("Invoke of " + functionName + " failed.", exception.ToString()); 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
} }
} }
static ICorDebug corDebug; static ICorDebug corDebug;
static ManagedCallback managedCallback; static ManagedCallback managedCallback;
static ManagedCallbackProxy managedCallbackProxy; static ManagedCallbackProxy managedCallbackProxy;
static bool isProcessRunning; static Process mainProcess;
static ICorDebugProcess mainProcess;
static Thread mainThread;
static Thread currentThread;
public static bool CatchHandledExceptions = false; public static bool CatchHandledExceptions = false;
#region Public propeties static internal ICorDebug CorDebug {
get {
static public SourcecodeSegment NextStatement { return corDebug;
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;
}
} }
#endregion static internal Process CurrentProcess {
static internal ICorDebugProcess MainProcess {
get { get {
return mainProcess; return mainProcess;
} }
@ -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 { internal static ManagedCallback ManagedCallback {
get { get {
@ -184,10 +122,7 @@ namespace DebuggerLibrary
ClearThreads(); ClearThreads();
MainProcess = null; CurrentProcess = null;
mainThread = null;
currentThread = null;
isProcessRunning = false;
GC.Collect(GC.MaxGeneration); GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers(); GC.WaitForPendingFinalizers();
@ -303,6 +238,13 @@ namespace DebuggerLibrary
#region Execution control #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) static public void StartWithoutDebugging(System.Diagnostics.ProcessStartInfo psi)
{ {
System.Diagnostics.Process process; System.Diagnostics.Process process;
@ -310,184 +252,118 @@ namespace DebuggerLibrary
process.StartInfo = psi; process.StartInfo = psi;
process.Start(); process.Start();
} }
static MTA2STA m2s = new MTA2STA();
static public void Start(string filename, string workingDirectory, string arguments) static public void Start(string filename, string workingDirectory, string arguments)
{ {
if (IsDebugging) { CurrentProcess = Process.CreateProcess(filename, workingDirectory, arguments);
System.Diagnostics.Debug.Fail("Invalid operation");
return;
}
m2s.CallInSTA(typeof(NDebugger), "StartInternal", new Object[] {filename, workingDirectory, arguments});
return;
} }
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) #endregion
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;
}
static public void Break() public void ToggleBreakpointAt(string fileName, int line, int column)
{ {
if (!IsDebugging || !IsProcessRunning) { // Check if there is breakpoint on that line
System.Diagnostics.Debug.Fail("Invalid operation"); foreach (Breakpoint breakpoint in Breakpoints) {
return; // TODO check filename too
if (breakpoint.SourcecodeSegment.StartLine == line) {
RemoveBreakpoint(breakpoint);
return;
}
} }
corProcess.Stop(5000); // TODO: Hardcoded value // Add the breakpoint
Breakpoint addedBreakpoint = AddBreakpoint(fileName, line, column);
isProcessRunning = false;
OnDebuggingPaused(PausedReason.Break);
OnIsProcessRunningChanged();
}
static public void StepInto() // Check if it wasn't forced to move to different line with breakpoint
{ foreach (Breakpoint breakpoint in Breakpoints) {
try { if (breakpoint != addedBreakpoint) { // Only the old ones
CurrentThread.StepInto(); if (breakpoint.SourcecodeSegment.StartLine == addedBreakpoint.SourcecodeSegment.StartLine) {
} catch (CurrentThreadNotAviableException) { // Whops! We have two breakpoint on signle line, delete one
System.Diagnostics.Debug.Fail("Unable to prerform step. CurrentThreadNotAviableException"); RemoveBreakpoint(addedBreakpoint);
return;
}
}
} }
} }
static public void StepOver()
{ static public bool IsProcessRunning {
try { get {
CurrentThread.StepOver(); if (!IsDebugging) return false;
} catch (CurrentThreadNotAviableException) { return CurrentProcess.IsProcessRunning;
System.Diagnostics.Debug.Fail("Unable to prerform step. CurrentThreadNotAviableException"); }
set {
if (CurrentProcess == null) return;
CurrentProcess.IsProcessRunning = value;
} }
} }
static public void StepOut() static public bool IsDebugging {
{ get {
try { return (CurrentProcess != null);
CurrentThread.StepOut();
} catch (CurrentThreadNotAviableException) {
System.Diagnostics.Debug.Fail("Unable to prerform step. CurrentThreadNotAviableException");
} }
} }
static internal void Continue(ICorDebugAppDomain pAppDomain) static public Thread CurrentThread {
{ get {
ICorDebugProcess outProcess; return CurrentProcess.CurrentThread;
pAppDomain.GetProcess(out outProcess); }
if (MainProcess != outProcess) throw new DebuggerException("Request to continue AppDomain that does not belog to current process"); set {
Continue(); CurrentProcess.CurrentThread = value;
}
} }
static public void Continue() static public Thread MainThread {
{ get {
if (!IsDebugging || IsProcessRunning) { return CurrentProcess.MainThread;
System.Diagnostics.Debug.Fail("Invalid operation");
return;
} }
set {
bool abort = false; CurrentProcess.MainThread = value;
OnDebuggingIsResuming(ref abort);
if (abort == true) return;
isProcessRunning = true;
if (managedCallback.HandlingCallback == false) {
OnDebuggingResumed();
OnIsProcessRunningChanged();
} }
corProcess.Continue(0);
} }
static public void Terminate() static public SourcecodeSegment NextStatement {
{ get{
if (!IsDebugging) { return CurrentProcess.NextStatement;
System.Diagnostics.Debug.Fail("Invalid operation");
return;
} }
}
int running; static public VariableCollection LocalVariables {
corProcess.IsRunning(out running); get{
// Resume stoped tread return CurrentProcess.LocalVariables;
if (running == 0) {
Continue(); // TODO: Remove this...
} }
// Stop&terminate - both must be called
corProcess.Stop(5000); // TODO: ...and this
corProcess.Terminate(0);
} }
static public bool IsProcessRunning { static public void Break()
get { {
if (!IsDebugging) return false; CurrentProcess.Break();
return isProcessRunning;
}
set {
isProcessRunning = value;
}
} }
static public bool IsDebugging { static public void StepInto()
get { {
return (MainProcess != null); 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 CurrentProcess.StepOut();
foreach (Breakpoint breakpoint in Breakpoints) { }
// TODO check filename too
if (breakpoint.SourcecodeSegment.StartLine == line) {
RemoveBreakpoint(breakpoint);
return;
}
}
// Add the breakpoint static public void Continue()
Breakpoint addedBreakpoint = AddBreakpoint(fileName, line, column); {
CurrentProcess.Continue();
}
// Check if it wasn't forced to move to different line with breakpoint static public void Terminate()
foreach (Breakpoint breakpoint in Breakpoints) { {
if (breakpoint != addedBreakpoint) { // Only the old ones CurrentProcess.Terminate();
if (breakpoint.SourcecodeSegment.StartLine == addedBreakpoint.SourcecodeSegment.StartLine) {
// Whops! We have two breakpoint on signle line, delete one
RemoveBreakpoint(addedBreakpoint);
return;
}
}
}
} }
} }
} }

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

@ -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