Browse Source

Debugger.Function valid as long as possible

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@826 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 20 years ago
parent
commit
c06565d3de
  1. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
  2. 15
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs
  3. 71
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs
  4. 55
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Stepper.cs
  5. 28
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/StepperEventArgs.cs
  6. 141
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs

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

@ -205,6 +205,8 @@ @@ -205,6 +205,8 @@
<Compile Include="Src\Variables\Variable.cs" />
<Compile Include="Src\Variables\VariableEventArgs.cs" />
<Compile Include="Src\Variables\VariableCollectionEventArgs.cs" />
<Compile Include="Src\Threads\Stepper.cs" />
<Compile Include="Src\Threads\StepperEventArgs.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="README.TXT" />

15
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs

@ -108,15 +108,24 @@ namespace Debugger @@ -108,15 +108,24 @@ namespace Debugger
#region Program folow control
public void StepComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugStepper pStepper, CorDebugStepReason reason)
{
EnterCallback("StepComplete (" + reason.ToString() + ")", pThread);
Stepper stepper = debugger.GetThread(pThread).GetStepper(pStepper);
if (stepper != null) {
stepper.OnStepComplete();
if (!stepper.PauseWhenComplete) {
ExitCallback_Continue();
return;
}
}
if (!callingThread.LastFunction.HasSymbols) {
// This should not happen with JMC enabled
debugger.TraceMessage(" - leaving code without symbols");
ExitCallback_Continue();
} else {

71
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs

@ -20,11 +20,16 @@ namespace Debugger @@ -20,11 +20,16 @@ namespace Debugger
public class Function: RemotingObjectBase
{
NDebugger debugger;
Module module;
ICorDebugILFrame corILFrame;
ICorDebugFunction corFunction;
ICorDebugILFrame corILFrame;
object corILFrameDebuggerSessionID;
Thread thread;
uint chainIndex;
uint frameIndex;
MethodProps methodProps;
public NDebugger Debugger {
@ -64,6 +69,19 @@ namespace Debugger @@ -64,6 +69,19 @@ namespace Debugger
return corClass;
}
}
/// <summary>
/// True if function stepped out and is not longer valid.
/// </summary>
public bool HasExpired {
get {
if (corILFrameDebuggerSessionID == debugger.SessionID) {
return false; // valid
} else {
return thread == null;
}
}
}
public ObjectValue ThisValue {
get {
@ -71,30 +89,47 @@ namespace Debugger @@ -71,30 +89,47 @@ namespace Debugger
throw new DebuggerException("Static method does not have 'this'.");
} else {
ICorDebugValue argThis = null;
corILFrame.GetArgument(0, out argThis);
CorILFrame.GetArgument(0, out argThis);
return new ObjectValue(debugger, argThis, ContaingClass);
}
}
}
internal unsafe Function(NDebugger debugger, ICorDebugILFrame corILFrame)
internal Function(Thread thread, uint chainIndex, uint frameIndex, ICorDebugILFrame corILFrame)
{
this.debugger = debugger;
this.debugger = thread.Debugger;
this.thread = thread;
this.chainIndex = chainIndex;
this.frameIndex = frameIndex;
this.corILFrame = corILFrame;
this.corILFrameDebuggerSessionID = debugger.SessionID;
corILFrame.GetFunction(out corFunction);
uint functionToken;
uint functionToken;
corFunction.GetToken(out functionToken);
ICorDebugModule corModule;
corFunction.GetModule(out corModule);
module = debugger.GetModule(corModule);
methodProps = module.MetaData.GetMethodProps(functionToken);
// Expiry the function when it is finished
Stepper tracingStepper = thread.CreateStepper();
tracingStepper.CorStepper.StepOut();
tracingStepper.PauseWhenComplete = false;
tracingStepper.StepComplete += delegate {
thread = null;
};
}
#region Helpping proprerties
internal ICorDebugILFrame CorILFrame {
get {
if (HasExpired) throw new DebuggerException("Function has expired");
if (corILFrameDebuggerSessionID != debugger.SessionID) {
corILFrame = thread.GetFunctionAt(chainIndex, frameIndex).CorILFrame;
corILFrameDebuggerSessionID = debugger.SessionID;
}
return corILFrame;
}
}
@ -103,7 +138,7 @@ namespace Debugger @@ -103,7 +138,7 @@ namespace Debugger
get {
uint corInstructionPtr;
CorDebugMappingResult MappingResult;
corILFrame.GetIP(out corInstructionPtr,out MappingResult);
CorILFrame.GetIP(out corInstructionPtr,out MappingResult);
return corInstructionPtr;
}
}
@ -147,7 +182,7 @@ namespace Debugger @@ -147,7 +182,7 @@ namespace Debugger
public void StepOut()
{
ICorDebugStepper stepper;
corILFrame.CreateStepper(out stepper);
CorILFrame.CreateStepper(out stepper);
stepper.StepOut();
debugger.CurrentThread.AddActiveStepper(stepper);
@ -171,7 +206,7 @@ namespace Debugger @@ -171,7 +206,7 @@ namespace Debugger
ICorDebugStepper stepper;
if (stepIn) {
corILFrame.CreateStepper(out stepper);
CorILFrame.CreateStepper(out stepper);
if (stepper is ICorDebugStepper2) { // Is the debuggee .NET 2.0?
stepper.SetUnmappedStopMask(CorDebugUnmappedStop.STOP_NONE);
@ -188,7 +223,7 @@ namespace Debugger @@ -188,7 +223,7 @@ namespace Debugger
// Mind that step in which ends in code without symblols is cotinued
// so the next step over ensures that we atleast do step over
corILFrame.CreateStepper(out stepper);
CorILFrame.CreateStepper(out stepper);
if (stepper is ICorDebugStepper2) { // Is the debuggee .NET 2.0?
stepper.SetUnmappedStopMask(CorDebugUnmappedStop.STOP_NONE);
@ -348,9 +383,9 @@ namespace Debugger @@ -348,9 +383,9 @@ namespace Debugger
} else {
try {
if (simulate) {
corILFrame.CanSetIP((uint)ilOffset);
CorILFrame.CanSetIP((uint)ilOffset);
} else {
corILFrame.SetIP((uint)ilOffset);
CorILFrame.SetIP((uint)ilOffset);
debugger.FakePause(PausedReason.SetIP, false);
}
} catch {
@ -395,7 +430,7 @@ namespace Debugger @@ -395,7 +430,7 @@ namespace Debugger
public int ArgumentCount {
get {
ICorDebugValueEnum argumentEnum;
corILFrame.EnumerateArguments(out argumentEnum);
CorILFrame.EnumerateArguments(out argumentEnum);
uint argCount;
argumentEnum.GetCount(out argCount);
if (!IsStatic) {
@ -409,7 +444,7 @@ namespace Debugger @@ -409,7 +444,7 @@ namespace Debugger
{
ICorDebugValue arg;
// Non-static functions include 'this' as first argument
corILFrame.GetArgument((uint)(IsStatic? index : (index + 1)), out arg);
CorILFrame.GetArgument((uint)(IsStatic? index : (index + 1)), out arg);
return arg;
}
@ -480,7 +515,7 @@ namespace Debugger @@ -480,7 +515,7 @@ namespace Debugger
void AddVariableToVariableCollection(ISymbolVariable symVar, ref VariableCollection collection)
{
ICorDebugValue runtimeVar;
corILFrame.GetLocalVariable((uint)symVar.AddressField1, out runtimeVar);
CorILFrame.GetLocalVariable((uint)symVar.AddressField1, out runtimeVar);
collection.Add(Variable.CreateVariable(debugger, runtimeVar, symVar.Name));
}
}

55
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Stepper.cs

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
// <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using Debugger.Interop.CorDebug;
namespace Debugger
{
class Stepper
{
NDebugger debugger;
ICorDebugStepper corStepper;
bool pauseWhenComplete = true;
public event EventHandler<StepperEventArgs> StepComplete;
public NDebugger Debugger {
get {
return debugger;
}
}
public ICorDebugStepper CorStepper {
get {
return corStepper;
}
}
public bool PauseWhenComplete {
get {
return pauseWhenComplete;
}
set {
pauseWhenComplete = value;
}
}
public Stepper(NDebugger debugger, ICorDebugStepper corStepper)
{
this.debugger = debugger;
this.corStepper = corStepper;
}
protected internal virtual void OnStepComplete() {
if (StepComplete != null) {
StepComplete(this, new StepperEventArgs(this));
}
}
}
}

28
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/StepperEventArgs.cs

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
// <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger
{
[Serializable]
class StepperEventArgs: DebuggerEventArgs
{
Stepper stepper;
public Stepper Stepper {
get {
return stepper;
}
}
public StepperEventArgs(Stepper stepper): base(stepper.Debugger)
{
this.stepper = stepper;
}
}
}

141
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs

@ -25,6 +25,7 @@ namespace Debugger @@ -25,6 +25,7 @@ namespace Debugger
Process process;
List<ICorDebugStepper> activeSteppers = new List<ICorDebugStepper>();
List<Stepper> steppers = new List<Stepper>();
uint id;
bool lastSuspendedState = false;
@ -145,7 +146,38 @@ namespace Debugger @@ -145,7 +146,38 @@ namespace Debugger
}
process.Continue();
}
internal Stepper CreateStepper()
{
ICorDebugStepper corStepper;
corThread.CreateStepper(out corStepper);
Stepper stepper = new Stepper(debugger, corStepper);
stepper.StepComplete += delegate {
steppers.Remove(stepper);
};
steppers.Add(stepper);
return stepper;
}
internal Stepper GetStepper(ICorDebugStepper corStepper)
{
foreach(Stepper stepper in steppers) {
if (stepper.CorStepper == corStepper) {
return stepper;
}
}
return null;
}
internal IList<Stepper> Steppers {
get {
return steppers.AsReadOnly();
}
}
internal IList<ICorDebugStepper> ActiveSteppers {
get {
return activeSteppers.AsReadOnly();
@ -193,46 +225,89 @@ namespace Debugger @@ -193,46 +225,89 @@ namespace Debugger
public IEnumerable<Function> Callstack {
get {
if (process.IsRunning) yield break;
return GetCallstackAt(uint.MaxValue, uint.MaxValue);
}
}
internal Function GetFunctionAt(uint firstChainIndex, uint firstFrameIndex)
{
foreach(Function f in GetCallstackAt(firstChainIndex, firstFrameIndex)) {
return f;
}
throw new DebuggerException("Function not found");
}
internal IEnumerable<Function> GetCallstackAt(uint firstChainIndex, uint firstFrameIndex)
{
if (process.IsRunning) yield break; // TODO: thow exception
ICorDebugChainEnum corChainEnum;
corThread.EnumerateChains(out corChainEnum);
uint chainCount;
corChainEnum.GetCount(out chainCount);
uint chainIndex = chainCount;
if (firstChainIndex != uint.MaxValue) {
int skipCount = (int)chainCount - (int)firstChainIndex - 1;
if (skipCount < 0) throw new ArgumentException("Chain index too big", "firstChainIndex");
corChainEnum.Skip((uint)skipCount);
chainIndex -= (uint)skipCount;
firstChainIndex = chainIndex;
}
while (true) {
uint chainsFetched;
ICorDebugChain[] corChains = new ICorDebugChain[1]; // One at time
corChainEnum.Next(1, corChains, out chainsFetched);
if (chainsFetched == 0) break; // We are done
ICorDebugChainEnum corChainEnum;
corThread.EnumerateChains(out corChainEnum);
chainIndex--;
int isManaged;
corChains[0].IsManaged(out isManaged);
if (isManaged == 0) continue; // Only managed ones
ICorDebugFrameEnum corFrameEnum;
corChains[0].EnumerateFrames(out corFrameEnum);
uint frameCount;
corFrameEnum.GetCount(out frameCount);
uint frameIndex = frameCount;
if (firstFrameIndex != uint.MaxValue && chainIndex == firstChainIndex) {
int skipCount = (int)frameCount - (int)firstFrameIndex - 1;
if (skipCount < 0) throw new ArgumentException("Frame index too big", "firstFrameIndex");
corFrameEnum.Skip((uint)skipCount);
frameIndex -= (uint)skipCount;
firstFrameIndex = frameIndex;
}
while (true) {
uint chainsFetched;
ICorDebugChain[] corChains = new ICorDebugChain[1]; // One at time
corChainEnum.Next(1, corChains, out chainsFetched);
if (chainsFetched == 0) break; // We are done
int isManaged;
corChains[0].IsManaged(out isManaged);
if (isManaged == 0) continue; // Only managed ones
uint framesFetched;
ICorDebugFrame[] corFrames = new ICorDebugFrame[1]; // Only one at time
corFrameEnum.Next(1, corFrames, out framesFetched);
if (framesFetched == 0) break; // We are done
ICorDebugFrameEnum corFrameEnum;
corChains[0].EnumerateFrames(out corFrameEnum);
frameIndex--;
while (true) {
uint framesFetched;
ICorDebugFrame[] corFrames = new ICorDebugFrame[1]; // Only one at time
corFrameEnum.Next(1, corFrames, out framesFetched);
if (framesFetched == 0) break; // We are done
Function function = null;
try {
if (corFrames[0] is ICorDebugILFrame) {
function = new Function(debugger, (ICorDebugILFrame)corFrames[0]);
}
} catch (COMException) {
// TODO
};
if (function != null) {
yield return function;
Function function = null;
try {
if (corFrames[0] is ICorDebugILFrame) {
function = new Function(this, chainIndex, frameIndex, (ICorDebugILFrame)corFrames[0]);
}
} catch (COMException) {
// TODO
};
if (function != null) {
yield return function;
}
}
} // get
} // End of public FunctionCollection Callstack
}
}
public Function CurrentFunction {
get {

Loading…
Cancel
Save