/*
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 dnSpy.Contracts.Debugger.Breakpoints.Code;
using dnSpy.Contracts.Debugger.Exceptions;
namespace dnSpy.Contracts.Debugger {
///
/// Debugger message kind
///
public enum DbgMessageKind {
///
/// A process was created ()
///
ProcessCreated,
///
/// A process has exited ()
///
ProcessExited,
///
/// A runtime was created ()
///
RuntimeCreated,
///
/// A runtime has exited ()
///
RuntimeExited,
///
/// An app domain was loaded ()
///
AppDomainLoaded,
///
/// An app domain was unloaded (). This message isn't sent if the program has exited.
///
AppDomainUnloaded,
///
/// A module was loaded ()
///
ModuleLoaded,
///
/// A module was unloaded (). This message isn't sent if the program has exited or if its app domain has unloaded.
///
ModuleUnloaded,
///
/// A thread was created ()
///
ThreadCreated,
///
/// A thread has exited (). This message isn't sent if the program has exited.
///
ThreadExited,
///
/// An exception was thrown ()
///
ExceptionThrown,
///
/// The entry point has been reached ().
/// This message is only sent if the user chose to break at the entry point.
///
EntryPointBreak,
///
/// Message from the debugged program ()
///
ProgramMessage,
///
/// A bound breakpoint was hit ()
///
BoundBreakpoint,
///
/// The program paused itself by executing a break instruction or method ()
///
ProgramBreak,
///
/// Step into/over/out is complete ()
///
StepComplete,
///
/// SetIP() is complete ()
///
SetIPComplete,
///
/// Some message that should be shown to the user, eg. we failed to connect to the debugged process ()
///
UserMessage,
///
/// The program was paused by the user, or because some other program was paused for some other reason ()
///
Break,
///
/// Message from the debugged program ()
///
AsyncProgramMessage,
}
///
/// Base class of all debugger messages
///
public abstract class DbgMessageEventArgs : EventArgs {
///
/// Gets the message kind
///
public abstract DbgMessageKind Kind { get; }
///
/// true if the program should be paused. It's only possible to write true to this property.
///
public bool Pause {
get => pause;
set => pause |= value;
}
bool pause;
}
///
/// Process message base class
///
public abstract class DbgMessageProcessEventArgs : DbgMessageEventArgs {
///
/// Gets the process
///
public DbgProcess Process { get; }
///
/// Constructor
///
/// Process
protected DbgMessageProcessEventArgs(DbgProcess process) =>
Process = process ?? throw new ArgumentNullException(nameof(process));
}
///
/// Process created message ()
///
public sealed class DbgMessageProcessCreatedEventArgs : DbgMessageProcessEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.ProcessCreated;
///
/// Constructor
///
/// Process
public DbgMessageProcessCreatedEventArgs(DbgProcess process)
: base(process) {
}
}
///
/// Process exited message ()
///
public sealed class DbgMessageProcessExitedEventArgs : DbgMessageProcessEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.ProcessExited;
///
/// Gets the exit code
///
public int ExitCode { get; }
///
/// Constructor
///
/// Process
/// Process exit code
public DbgMessageProcessExitedEventArgs(DbgProcess process, int exitCode)
: base(process) {
}
}
///
/// Runtime message base class
///
public abstract class DbgMessageRuntimeEventArgs : DbgMessageEventArgs {
///
/// Gets the runtime
///
public DbgRuntime Runtime { get; }
///
/// Constructor
///
/// Runtime
protected DbgMessageRuntimeEventArgs(DbgRuntime runtime) =>
Runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
}
///
/// Runtime created message ()
///
public sealed class DbgMessageRuntimeCreatedEventArgs : DbgMessageRuntimeEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.RuntimeCreated;
///
/// Constructor
///
/// Runtime
public DbgMessageRuntimeCreatedEventArgs(DbgRuntime runtime)
: base(runtime) {
}
}
///
/// Runtime exited message ()
///
public sealed class DbgMessageRuntimeExitedEventArgs : DbgMessageRuntimeEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.RuntimeExited;
///
/// Constructor
///
/// Runtime
public DbgMessageRuntimeExitedEventArgs(DbgRuntime runtime)
: base(runtime) {
}
}
///
/// App domain message base class
///
public abstract class DbgMessageAppDomainEventArgs : DbgMessageEventArgs {
///
/// Gets the app domain
///
public DbgAppDomain AppDomain { get; }
///
/// Constructor
///
/// App domain
protected DbgMessageAppDomainEventArgs(DbgAppDomain appDomain) =>
AppDomain = appDomain ?? throw new ArgumentNullException(nameof(appDomain));
}
///
/// App domain loaded message ()
///
public sealed class DbgMessageAppDomainLoadedEventArgs : DbgMessageAppDomainEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.AppDomainLoaded;
///
/// Constructor
///
/// App domain
public DbgMessageAppDomainLoadedEventArgs(DbgAppDomain appDomain)
: base(appDomain) {
}
}
///
/// App domain unloaded message ()
///
public sealed class DbgMessageAppDomainUnloadedEventArgs : DbgMessageAppDomainEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.AppDomainUnloaded;
///
/// Constructor
///
/// App domain
public DbgMessageAppDomainUnloadedEventArgs(DbgAppDomain appDomain)
: base(appDomain) {
}
}
///
/// Module message base class
///
public abstract class DbgMessageModuleEventArgs : DbgMessageEventArgs {
///
/// Gets the module
///
public DbgModule Module { get; }
///
/// Constructor
///
/// Module
protected DbgMessageModuleEventArgs(DbgModule module) =>
Module = module ?? throw new ArgumentNullException(nameof(module));
}
///
/// Module loaded message ()
///
public sealed class DbgMessageModuleLoadedEventArgs : DbgMessageModuleEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.ModuleLoaded;
///
/// Constructor
///
/// Module
public DbgMessageModuleLoadedEventArgs(DbgModule module)
: base(module) {
}
}
///
/// Module unloaded message ()
///
public sealed class DbgMessageModuleUnloadedEventArgs : DbgMessageModuleEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.ModuleUnloaded;
///
/// Constructor
///
/// Module
public DbgMessageModuleUnloadedEventArgs(DbgModule module)
: base(module) {
}
}
///
/// Thread message base class
///
public abstract class DbgMessageThreadEventArgs : DbgMessageEventArgs {
///
/// Gets the thread
///
public DbgThread Thread { get; }
///
/// Constructor
///
/// Thread
protected DbgMessageThreadEventArgs(DbgThread thread) =>
Thread = thread ?? throw new ArgumentNullException(nameof(thread));
}
///
/// Thread created message ()
///
public sealed class DbgMessageThreadCreatedEventArgs : DbgMessageThreadEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.ThreadCreated;
///
/// Constructor
///
/// Thread
public DbgMessageThreadCreatedEventArgs(DbgThread thread)
: base(thread) {
}
}
///
/// Thread exited message ()
///
public sealed class DbgMessageThreadExitedEventArgs : DbgMessageThreadEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.ThreadExited;
///
/// Gets the exit code
///
public int ExitCode { get; }
///
/// Constructor
///
/// Thread
/// Thread exit code
public DbgMessageThreadExitedEventArgs(DbgThread thread, int exitCode)
: base(thread) {
}
}
///
/// Exception thrown message ()
///
public sealed class DbgMessageExceptionThrownEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.ExceptionThrown;
///
/// Gets the exception
///
public DbgException Exception { get; }
///
/// Constructor
///
/// Exception
public DbgMessageExceptionThrownEventArgs(DbgException exception) =>
Exception = exception ?? throw new ArgumentNullException(nameof(exception));
}
///
/// The entry point has been reached ().
/// This message is only sent if the user chose to break at the entry point.
///
public sealed class DbgMessageEntryPointBreakEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.EntryPointBreak;
///
/// Gets the runtime
///
public DbgRuntime Runtime { get; }
///
/// Gets the thread or null if it's unknown
///
public DbgThread? Thread { get; }
///
/// Constructor
///
/// Runtime
/// Thread or null if it's unknown
public DbgMessageEntryPointBreakEventArgs(DbgRuntime runtime, DbgThread? thread) {
Runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
Thread = thread;
}
}
///
/// Message from the debugged program ()
///
public sealed class DbgMessageProgramMessageEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.ProgramMessage;
///
/// Gets the text
///
public string Message { get; }
///
/// Gets the runtime
///
public DbgRuntime Runtime { get; }
///
/// Gets the thread or null if it's unknown
///
public DbgThread? Thread { get; }
///
/// Constructor
///
/// Message
/// Runtime
/// Thread or null if it's unknown
public DbgMessageProgramMessageEventArgs(string message, DbgRuntime runtime, DbgThread? thread) {
Message = message ?? throw new ArgumentNullException(nameof(message));
Runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
Thread = thread;
}
}
///
/// A bound breakpoint was hit ()
///
public sealed class DbgMessageBoundBreakpointEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.BoundBreakpoint;
///
/// Gets the bound breakpoint
///
public DbgBoundCodeBreakpoint BoundBreakpoint { get; }
///
/// Gets the thread or null if it's unknown
///
public DbgThread? Thread { get; }
///
/// Constructor
///
/// Bound breakpoint
/// Thread or null if it's unknown
public DbgMessageBoundBreakpointEventArgs(DbgBoundCodeBreakpoint boundBreakpoint, DbgThread? thread) {
BoundBreakpoint = boundBreakpoint ?? throw new ArgumentNullException(nameof(boundBreakpoint));
Thread = thread;
}
}
///
/// The program paused itself by executing a break instruction or method ()
///
public sealed class DbgMessageProgramBreakEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.ProgramBreak;
///
/// Gets the runtime
///
public DbgRuntime Runtime { get; }
///
/// Gets the thread or null if it's unknown
///
public DbgThread? Thread { get; }
///
/// Constructor
///
/// Runtime
/// Thread or null if it's unknown
public DbgMessageProgramBreakEventArgs(DbgRuntime runtime, DbgThread? thread) {
Runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
Thread = thread;
}
}
///
/// Step into/over/out is complete ()
///
public sealed class DbgMessageStepCompleteEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.StepComplete;
///
/// Gets the runtime
///
public DbgRuntime Runtime => Thread.Runtime;
///
/// Gets the thread
///
public DbgThread Thread { get; }
///
/// Gets the error message or null if none
///
public string? Error { get; }
///
/// true if there was an error. Error message is in
///
public bool HasError => Error is not null;
///
/// Constructor
///
/// Thread
/// Error message or null if none
public DbgMessageStepCompleteEventArgs(DbgThread thread, string? error) {
Thread = thread ?? throw new ArgumentNullException(nameof(thread));
Error = error;
}
}
///
/// SetIP() is complete ()
///
public sealed class DbgMessageSetIPCompleteEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.SetIPComplete;
///
/// Gets the runtime
///
public DbgRuntime Runtime => Thread.Runtime;
///
/// Gets the thread
///
public DbgThread Thread { get; }
///
/// true if all frames in the thread have been invalidated
///
public bool FramesInvalidated { get; }
///
/// Gets the error message or null if none
///
public string? Error { get; }
///
/// true if there was an error. Error message is in
///
public bool HasError => Error is not null;
///
/// Constructor
///
/// Thread
/// true if all frames in the thread have been invalidated
/// Error message or null if none
public DbgMessageSetIPCompleteEventArgs(DbgThread thread, bool framesInvalidated, string? error) {
Thread = thread ?? throw new ArgumentNullException(nameof(thread));
FramesInvalidated = framesInvalidated;
Error = error;
}
}
///
/// A message that should be shown to the user
///
public sealed class DbgMessageUserMessageEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.UserMessage;
///
/// Gets the message kind
///
public UserMessageKind MessageKind { get; }
///
/// Gets the message
///
public string Message { get; }
///
/// Constructor
///
/// Message kind
/// Message
public DbgMessageUserMessageEventArgs(UserMessageKind messageKind, string message) {
MessageKind = messageKind;
Message = message ?? throw new ArgumentNullException(nameof(message));
}
}
///
/// message kinds
///
public enum UserMessageKind {
///
/// We failed to connect to the debugged process
///
CouldNotConnect,
///
/// Could not break the debugged process
///
CouldNotBreak,
}
///
/// The program was paused by the user, or because some other program was paused for some other reason ()
///
public sealed class DbgMessageBreakEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.Break;
///
/// Gets the runtime
///
public DbgRuntime Runtime { get; }
///
/// Gets the thread or null if it's unknown
///
public DbgThread? Thread { get; }
///
/// Constructor
///
/// Runtime
/// Thread or null if it's unknown
public DbgMessageBreakEventArgs(DbgRuntime runtime, DbgThread? thread) {
Runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
Thread = thread;
}
}
///
/// Message source kind
///
public enum AsyncProgramMessageSource {
///
/// Some other source
///
Other,
///
/// Standard output text
///
StandardOutput,
///
/// Standard error text
///
StandardError,
}
///
/// Message from the debugged program ()
///
public sealed class DbgMessageAsyncProgramMessageEventArgs : DbgMessageEventArgs {
///
/// Returns
///
public override DbgMessageKind Kind => DbgMessageKind.AsyncProgramMessage;
///
/// Gets the message source kind
///
public AsyncProgramMessageSource Source { get; }
///
/// Gets the text
///
public string Message { get; }
///
/// Gets the runtime
///
public DbgRuntime Runtime { get; }
///
/// Constructor
///
/// Source
/// Message
/// Runtime
public DbgMessageAsyncProgramMessageEventArgs(AsyncProgramMessageSource source, string message, DbgRuntime runtime) {
Source = source;
Message = message ?? throw new ArgumentNullException(nameof(message));
Runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
}
}
}