/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see .
*/
using System;
using System.Collections.Generic;
using dndbg.COM.CorDebug;
namespace dndbg.Engine {
sealed class DebuggerState {
///
/// Current process or null
///
public DnProcess? Process { get; }
///
/// Current AppDomain or null
///
public DnAppDomain? AppDomain { get; }
///
/// Current thread or null
///
public DnThread? Thread { get; }
///
/// Event args or null if it was an event that wasn't generated by the CLR debugger, eg.
/// .
///
public DebugCallbackEventArgs? EventArgs { get; }
///
/// Gets the first IL frame in or null if none
///
public CorFrame? ILFrame {
get {
if (Thread is null)
return null;
// Never cache the result since set-ip could be called which will invalidate all frames
foreach (var chain in Thread.Chains) {
foreach (var frame in chain.Frames) {
if (frame.IsILFrame)
return frame;
}
}
return null;
}
}
internal ICorDebugController? Controller {
get {
ICorDebugController? controller = null;
if (controller is null && EventArgs is not null)
controller = EventArgs.CorDebugController;
if (controller is null && AppDomain is not null)
controller = AppDomain.CorAppDomain.RawObject;
if (controller is null && Process is not null)
controller = Process.CorProcess.RawObject;
return controller;
}
}
public DebuggerPauseState[] PauseStates {
get => pauseStates!;
internal set => pauseStates = value ?? Array.Empty();
}
DebuggerPauseState[]? pauseStates;
public DebuggerState(DebugCallbackEventArgs? e)
: this(e, null, null, null) {
}
public DebuggerState(DebugCallbackEventArgs? e, DnProcess? process, DnAppDomain? appDomain, DnThread? thread) {
EventArgs = e;
PauseStates = null!;
Process = process;
AppDomain = appDomain;
Thread = thread;
}
public DebuggerPauseState? GetPauseState(DebuggerPauseReason reason) {
foreach (var state in pauseStates!) {
if (state.Reason == reason)
return state;
}
return null;
}
public IEnumerable GetPauseStates(DebuggerPauseReason reason) {
foreach (var state in pauseStates!) {
if (state.Reason == reason)
yield return state;
}
}
}
}