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. 9
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs
  3. 63
      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. 143
      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 @@
<Compile Include="Src\Variables\Variable.cs" /> <Compile Include="Src\Variables\Variable.cs" />
<Compile Include="Src\Variables\VariableEventArgs.cs" /> <Compile Include="Src\Variables\VariableEventArgs.cs" />
<Compile Include="Src\Variables\VariableCollectionEventArgs.cs" /> <Compile Include="Src\Variables\VariableCollectionEventArgs.cs" />
<Compile Include="Src\Threads\Stepper.cs" />
<Compile Include="Src\Threads\StepperEventArgs.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="README.TXT" /> <Content Include="README.TXT" />

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

@ -113,6 +113,15 @@ namespace Debugger
{ {
EnterCallback("StepComplete (" + reason.ToString() + ")", pThread); 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) { if (!callingThread.LastFunction.HasSymbols) {
// This should not happen with JMC enabled // This should not happen with JMC enabled
debugger.TraceMessage(" - leaving code without symbols"); debugger.TraceMessage(" - leaving code without symbols");

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

@ -22,8 +22,13 @@ namespace Debugger
NDebugger debugger; NDebugger debugger;
Module module; Module module;
ICorDebugILFrame corILFrame;
ICorDebugFunction corFunction; ICorDebugFunction corFunction;
ICorDebugILFrame corILFrame;
object corILFrameDebuggerSessionID;
Thread thread;
uint chainIndex;
uint frameIndex;
MethodProps methodProps; MethodProps methodProps;
@ -65,36 +70,66 @@ namespace Debugger
} }
} }
/// <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 { public ObjectValue ThisValue {
get { get {
if (IsStatic) { if (IsStatic) {
throw new DebuggerException("Static method does not have 'this'."); throw new DebuggerException("Static method does not have 'this'.");
} else { } else {
ICorDebugValue argThis = null; ICorDebugValue argThis = null;
corILFrame.GetArgument(0, out argThis); CorILFrame.GetArgument(0, out argThis);
return new ObjectValue(debugger, argThis, ContaingClass); 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.corILFrame = corILFrame;
this.corILFrameDebuggerSessionID = debugger.SessionID;
corILFrame.GetFunction(out corFunction); corILFrame.GetFunction(out corFunction);
uint functionToken; uint functionToken;
corFunction.GetToken(out functionToken); corFunction.GetToken(out functionToken);
ICorDebugModule corModule; ICorDebugModule corModule;
corFunction.GetModule(out corModule); corFunction.GetModule(out corModule);
module = debugger.GetModule(corModule); module = debugger.GetModule(corModule);
methodProps = module.MetaData.GetMethodProps(functionToken); 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 #region Helpping proprerties
internal ICorDebugILFrame CorILFrame { internal ICorDebugILFrame CorILFrame {
get { get {
if (HasExpired) throw new DebuggerException("Function has expired");
if (corILFrameDebuggerSessionID != debugger.SessionID) {
corILFrame = thread.GetFunctionAt(chainIndex, frameIndex).CorILFrame;
corILFrameDebuggerSessionID = debugger.SessionID;
}
return corILFrame; return corILFrame;
} }
} }
@ -103,7 +138,7 @@ namespace Debugger
get { get {
uint corInstructionPtr; uint corInstructionPtr;
CorDebugMappingResult MappingResult; CorDebugMappingResult MappingResult;
corILFrame.GetIP(out corInstructionPtr,out MappingResult); CorILFrame.GetIP(out corInstructionPtr,out MappingResult);
return corInstructionPtr; return corInstructionPtr;
} }
} }
@ -147,7 +182,7 @@ namespace Debugger
public void StepOut() public void StepOut()
{ {
ICorDebugStepper stepper; ICorDebugStepper stepper;
corILFrame.CreateStepper(out stepper); CorILFrame.CreateStepper(out stepper);
stepper.StepOut(); stepper.StepOut();
debugger.CurrentThread.AddActiveStepper(stepper); debugger.CurrentThread.AddActiveStepper(stepper);
@ -171,7 +206,7 @@ namespace Debugger
ICorDebugStepper stepper; ICorDebugStepper stepper;
if (stepIn) { if (stepIn) {
corILFrame.CreateStepper(out stepper); CorILFrame.CreateStepper(out stepper);
if (stepper is ICorDebugStepper2) { // Is the debuggee .NET 2.0? if (stepper is ICorDebugStepper2) { // Is the debuggee .NET 2.0?
stepper.SetUnmappedStopMask(CorDebugUnmappedStop.STOP_NONE); stepper.SetUnmappedStopMask(CorDebugUnmappedStop.STOP_NONE);
@ -188,7 +223,7 @@ namespace Debugger
// Mind that step in which ends in code without symblols is cotinued // Mind that step in which ends in code without symblols is cotinued
// so the next step over ensures that we atleast do step over // 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? if (stepper is ICorDebugStepper2) { // Is the debuggee .NET 2.0?
stepper.SetUnmappedStopMask(CorDebugUnmappedStop.STOP_NONE); stepper.SetUnmappedStopMask(CorDebugUnmappedStop.STOP_NONE);
@ -348,9 +383,9 @@ namespace Debugger
} else { } else {
try { try {
if (simulate) { if (simulate) {
corILFrame.CanSetIP((uint)ilOffset); CorILFrame.CanSetIP((uint)ilOffset);
} else { } else {
corILFrame.SetIP((uint)ilOffset); CorILFrame.SetIP((uint)ilOffset);
debugger.FakePause(PausedReason.SetIP, false); debugger.FakePause(PausedReason.SetIP, false);
} }
} catch { } catch {
@ -395,7 +430,7 @@ namespace Debugger
public int ArgumentCount { public int ArgumentCount {
get { get {
ICorDebugValueEnum argumentEnum; ICorDebugValueEnum argumentEnum;
corILFrame.EnumerateArguments(out argumentEnum); CorILFrame.EnumerateArguments(out argumentEnum);
uint argCount; uint argCount;
argumentEnum.GetCount(out argCount); argumentEnum.GetCount(out argCount);
if (!IsStatic) { if (!IsStatic) {
@ -409,7 +444,7 @@ namespace Debugger
{ {
ICorDebugValue arg; ICorDebugValue arg;
// Non-static functions include 'this' as first argument // 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; return arg;
} }
@ -480,7 +515,7 @@ namespace Debugger
void AddVariableToVariableCollection(ISymbolVariable symVar, ref VariableCollection collection) void AddVariableToVariableCollection(ISymbolVariable symVar, ref VariableCollection collection)
{ {
ICorDebugValue runtimeVar; ICorDebugValue runtimeVar;
corILFrame.GetLocalVariable((uint)symVar.AddressField1, out runtimeVar); CorILFrame.GetLocalVariable((uint)symVar.AddressField1, out runtimeVar);
collection.Add(Variable.CreateVariable(debugger, runtimeVar, symVar.Name)); collection.Add(Variable.CreateVariable(debugger, runtimeVar, symVar.Name));
} }
} }

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

@ -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 @@
// <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;
}
}
}

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

@ -25,6 +25,7 @@ namespace Debugger
Process process; Process process;
List<ICorDebugStepper> activeSteppers = new List<ICorDebugStepper>(); List<ICorDebugStepper> activeSteppers = new List<ICorDebugStepper>();
List<Stepper> steppers = new List<Stepper>();
uint id; uint id;
bool lastSuspendedState = false; bool lastSuspendedState = false;
@ -146,6 +147,37 @@ namespace Debugger
process.Continue(); 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 { internal IList<ICorDebugStepper> ActiveSteppers {
get { get {
return activeSteppers.AsReadOnly(); return activeSteppers.AsReadOnly();
@ -193,46 +225,89 @@ namespace Debugger
public IEnumerable<Function> Callstack { public IEnumerable<Function> Callstack {
get { 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
chainIndex--;
ICorDebugChainEnum corChainEnum; int isManaged;
corThread.EnumerateChains(out corChainEnum); 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) { while (true) {
uint chainsFetched; uint framesFetched;
ICorDebugChain[] corChains = new ICorDebugChain[1]; // One at time ICorDebugFrame[] corFrames = new ICorDebugFrame[1]; // Only one at time
corChainEnum.Next(1, corChains, out chainsFetched); corFrameEnum.Next(1, corFrames, out framesFetched);
if (chainsFetched == 0) break; // We are done if (framesFetched == 0) break; // We are done
int isManaged; frameIndex--;
corChains[0].IsManaged(out isManaged);
if (isManaged == 0) continue; // Only managed ones Function function = null;
try {
ICorDebugFrameEnum corFrameEnum; if (corFrames[0] is ICorDebugILFrame) {
corChains[0].EnumerateFrames(out corFrameEnum); function = new Function(this, chainIndex, frameIndex, (ICorDebugILFrame)corFrames[0]);
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;
} }
} catch (COMException) {
// TODO
};
if (function != null) {
yield return function;
} }
} }
} // get }
} // End of public FunctionCollection Callstack }
public Function CurrentFunction { public Function CurrentFunction {
get { get {

Loading…
Cancel
Save