Skip to content

Commit

Permalink
Impl debugger intrinsics methods, fixes #528
Browse files Browse the repository at this point in the history
  • Loading branch information
wtfsck committed Oct 20, 2017
1 parent 961ae27 commit b02cb56
Show file tree
Hide file tree
Showing 21 changed files with 678 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,42 @@ DbgDotNetAliasInfo[] GetAliases2(DbgEvaluationContext context2, DbgStackFrame fr

DbgDotNetAliasInfo[] GetAliasesCore(DbgEvaluationContext context, DbgStackFrame frame, CancellationToken cancellationToken) {
Dispatcher.VerifyAccess();
return Array.Empty<DbgDotNetAliasInfo>();//TODO:

DbgDotNetValue exception = null;
DbgDotNetValue stowedException = null;
var returnValues = Array.Empty<DbgDotNetReturnValueInfo>();
try {
exception = GetExceptionCore(context, frame, DbgDotNetRuntimeConstants.ExceptionId, cancellationToken);
stowedException = GetStowedExceptionCore(context, frame, DbgDotNetRuntimeConstants.StowedExceptionId, cancellationToken);
returnValues = GetReturnValuesCore(context, frame, cancellationToken);

int count = (exception != null ? 1 : 0) + (stowedException != null ? 1 : 0) + returnValues.Length + (returnValues.Length != 0 ? 1 : 0);
if (count == 0)
return Array.Empty<DbgDotNetAliasInfo>();

var res = new DbgDotNetAliasInfo[count];
int w = 0;
if (exception != null)
res[w++] = new DbgDotNetAliasInfo(DbgDotNetAliasInfoKind.Exception, exception.Type, 0, Guid.Empty, null);
if (stowedException != null)
res[w++] = new DbgDotNetAliasInfo(DbgDotNetAliasInfoKind.StowedException, stowedException.Type, 0, Guid.Empty, null);
if (returnValues.Length != 0) {
res[w++] = new DbgDotNetAliasInfo(DbgDotNetAliasInfoKind.ReturnValue, returnValues[returnValues.Length - 1].Value.Type, DbgDotNetRuntimeConstants.LastReturnValueId, Guid.Empty, null);
foreach (var returnValue in returnValues) {
Debug.Assert(returnValue.Id != DbgDotNetRuntimeConstants.LastReturnValueId);
res[w++] = new DbgDotNetAliasInfo(DbgDotNetAliasInfoKind.ReturnValue, returnValue.Value.Type, returnValue.Id, Guid.Empty, null);
}
}
if (w != res.Length)
throw new InvalidOperationException();
return res;
}
finally {
exception?.Dispose();
stowedException?.Dispose();
foreach (var rv in returnValues)
rv.Value?.Dispose();
}
}

public DbgDotNetExceptionInfo[] GetExceptions(DbgEvaluationContext context, DbgStackFrame frame, CancellationToken cancellationToken) {
Expand All @@ -621,14 +656,29 @@ DbgDotNetExceptionInfo[] GetExceptions2(DbgEvaluationContext context2, DbgStackF
DbgDotNetExceptionInfo[] GetExceptionsCore(DbgEvaluationContext context, DbgStackFrame frame, CancellationToken cancellationToken) {
Dispatcher.VerifyAccess();
cancellationToken.ThrowIfCancellationRequested();
var dnThread = engine.GetThread(frame.Thread);
var corValue = dnThread.CorThread.CurrentException;
if (corValue == null)
return Array.Empty<DbgDotNetExceptionInfo>();
var reflectionAppDomain = frame.Thread.AppDomain.GetReflectionAppDomain() ?? throw new InvalidOperationException();
var value = engine.CreateDotNetValue_CorDebug(corValue, reflectionAppDomain, tryCreateStrongHandle: true);
const uint exceptionId = 1;
return new[] { new DbgDotNetExceptionInfo(value, exceptionId, DbgDotNetExceptionInfoFlags.None) };
DbgDotNetValue exception = null;
DbgDotNetValue stowedException = null;
try {
exception = GetExceptionCore(context, frame, DbgDotNetRuntimeConstants.ExceptionId, cancellationToken);
stowedException = GetStowedExceptionCore(context, frame, DbgDotNetRuntimeConstants.StowedExceptionId, cancellationToken);
int count = (exception != null ? 1 : 0) + (stowedException != null ? 1 : 0);
if (count == 0)
return Array.Empty<DbgDotNetExceptionInfo>();
var res = new DbgDotNetExceptionInfo[count];
int w = 0;
if (exception != null)
res[w++] = new DbgDotNetExceptionInfo(exception, DbgDotNetRuntimeConstants.ExceptionId, DbgDotNetExceptionInfoFlags.None);
if (stowedException != null)
res[w++] = new DbgDotNetExceptionInfo(stowedException, DbgDotNetRuntimeConstants.StowedExceptionId, DbgDotNetExceptionInfoFlags.StowedException);
if (w != res.Length)
throw new InvalidOperationException();
return res;
}
catch {
exception?.Dispose();
stowedException?.Dispose();
throw;
}
}

public DbgDotNetReturnValueInfo[] GetReturnValues(DbgEvaluationContext context, DbgStackFrame frame, CancellationToken cancellationToken) {
Expand All @@ -646,6 +696,74 @@ DbgDotNetReturnValueInfo[] GetReturnValuesCore(DbgEvaluationContext context, Dbg
return Array.Empty<DbgDotNetReturnValueInfo>();//TODO:
}

public DbgDotNetValue GetException(DbgEvaluationContext context, DbgStackFrame frame, uint id, CancellationToken cancellationToken) {
if (Dispatcher.CheckAccess())
return GetExceptionCore(context, frame, id, cancellationToken);
return GetException2(context, frame, id, cancellationToken);

DbgDotNetValue GetException2(DbgEvaluationContext context2, DbgStackFrame frame2, uint id2, CancellationToken cancellationToken2) =>
Dispatcher.InvokeRethrow(() => GetExceptionCore(context2, frame2, id2, cancellationToken2));
}

DbgDotNetValue GetExceptionCore(DbgEvaluationContext context, DbgStackFrame frame, uint id, CancellationToken cancellationToken) {
Dispatcher.VerifyAccess();
cancellationToken.ThrowIfCancellationRequested();
if (id != DbgDotNetRuntimeConstants.ExceptionId)
return null;
var corException = TryGetException(frame);
if (corException == null)
return null;
var reflectionAppDomain = frame.Thread.AppDomain.GetReflectionAppDomain() ?? throw new InvalidOperationException();
return engine.CreateDotNetValue_CorDebug(corException, reflectionAppDomain, tryCreateStrongHandle: true);
}

public DbgDotNetValue GetStowedException(DbgEvaluationContext context, DbgStackFrame frame, uint id, CancellationToken cancellationToken) {
if (Dispatcher.CheckAccess())
return GetStowedExceptionCore(context, frame, id, cancellationToken);
return GetStowedException2(context, frame, id, cancellationToken);

DbgDotNetValue GetStowedException2(DbgEvaluationContext context2, DbgStackFrame frame2, uint id2, CancellationToken cancellationToken2) =>
Dispatcher.InvokeRethrow(() => GetStowedExceptionCore(context2, frame2, id2, cancellationToken2));
}

DbgDotNetValue GetStowedExceptionCore(DbgEvaluationContext context, DbgStackFrame frame, uint id, CancellationToken cancellationToken) {
Dispatcher.VerifyAccess();
cancellationToken.ThrowIfCancellationRequested();
if (id != DbgDotNetRuntimeConstants.StowedExceptionId)
return null;
var corStowedException = TryGetStowedException(frame);
if (corStowedException == null)
return null;
var reflectionAppDomain = frame.Thread.AppDomain.GetReflectionAppDomain() ?? throw new InvalidOperationException();
return engine.CreateDotNetValue_CorDebug(corStowedException, reflectionAppDomain, tryCreateStrongHandle: true);
}

CorValue TryGetException(DbgStackFrame frame) {
Dispatcher.VerifyAccess();
var dnThread = engine.GetThread(frame.Thread);
return dnThread.CorThread.CurrentException;
}

CorValue TryGetStowedException(DbgStackFrame frame) {
Dispatcher.VerifyAccess();
return null;//TODO:
}

public DbgDotNetValue GetReturnValue(DbgEvaluationContext context, DbgStackFrame frame, uint id, CancellationToken cancellationToken) {
if (Dispatcher.CheckAccess())
return GetReturnValueCore(context, frame, id, cancellationToken);
return GetReturnValue2(context, frame, id, cancellationToken);

DbgDotNetValue GetReturnValue2(DbgEvaluationContext context2, DbgStackFrame frame2, uint id2, CancellationToken cancellationToken2) =>
Dispatcher.InvokeRethrow(() => GetReturnValueCore(context2, frame2, id2, cancellationToken2));
}

DbgDotNetValue GetReturnValueCore(DbgEvaluationContext context, DbgStackFrame frame, uint id, CancellationToken cancellationToken) {
Dispatcher.VerifyAccess();
cancellationToken.ThrowIfCancellationRequested();
return null;//TODO: If id==DbgDotNetRuntimeConstants.LastReturnValueId, return the last return value
}

DbgDotNetValueResult CreateValue(CorValue value, ILDbgEngineStackFrame ilFrame) {
var reflectionAppDomain = ilFrame.GetReflectionModule().AppDomain;
var dnValue = engine.CreateDotNetValue_CorDebug(value, reflectionAppDomain, tryCreateStrongHandle: true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ You should have received a copy of the GNU General Public License
using dnSpy.Contracts.Debugger.DotNet.Metadata;
using dnSpy.Contracts.Debugger.Engine.Evaluation;
using dnSpy.Contracts.Debugger.Engine.Evaluation.Internal;
using dnSpy.Contracts.Debugger.Evaluation;
using dnSpy.Contracts.Decompiler;
using dnSpy.Contracts.Resources;

Expand All @@ -43,6 +44,7 @@ sealed class DbgDotNetLanguageServiceImpl : DbgDotNetLanguageService2 {
readonly Lazy<DbgModuleReferenceProvider> dbgModuleReferenceProvider;
readonly Lazy<DbgDotNetEngineValueNodeFactoryService> dbgDotNetEngineValueNodeFactoryService;
readonly Lazy<DbgDotNetILInterpreter> dnILInterpreter;
readonly Lazy<DbgObjectIdService> objectIdService;
readonly Lazy<DbgDotNetExpressionCompiler, IDbgDotNetExpressionCompilerMetadata>[] dbgDotNetExpressionCompilers;
readonly IDecompilerService decompilerService;
readonly IPredefinedEvaluationErrorMessagesHelper predefinedEvaluationErrorMessagesHelper;
Expand All @@ -52,11 +54,12 @@ sealed class DbgDotNetLanguageServiceImpl : DbgDotNetLanguageService2 {
static readonly Guid visualBasicDecompilerGuid = new Guid(PredefinedDecompilerGuids.VisualBasic);

[ImportingConstructor]
DbgDotNetLanguageServiceImpl(Lazy<DbgMetadataService> dbgMetadataService, Lazy<DbgModuleReferenceProvider> dbgModuleReferenceProvider, Lazy<DbgDotNetEngineValueNodeFactoryService> dbgDotNetEngineValueNodeFactoryService, Lazy<DbgDotNetILInterpreter> dnILInterpreter, [ImportMany] IEnumerable<Lazy<DbgDotNetExpressionCompiler, IDbgDotNetExpressionCompilerMetadata>> dbgDotNetExpressionCompilers, IDecompilerService decompilerService, IPredefinedEvaluationErrorMessagesHelper predefinedEvaluationErrorMessagesHelper, [ImportMany] IEnumerable<Lazy<DbgDotNetFormatter, IDbgDotNetFormatterMetadata>> dbgDotNetFormatters) {
DbgDotNetLanguageServiceImpl(Lazy<DbgMetadataService> dbgMetadataService, Lazy<DbgModuleReferenceProvider> dbgModuleReferenceProvider, Lazy<DbgDotNetEngineValueNodeFactoryService> dbgDotNetEngineValueNodeFactoryService, Lazy<DbgDotNetILInterpreter> dnILInterpreter, Lazy<DbgObjectIdService> objectIdService, [ImportMany] IEnumerable<Lazy<DbgDotNetExpressionCompiler, IDbgDotNetExpressionCompilerMetadata>> dbgDotNetExpressionCompilers, IDecompilerService decompilerService, IPredefinedEvaluationErrorMessagesHelper predefinedEvaluationErrorMessagesHelper, [ImportMany] IEnumerable<Lazy<DbgDotNetFormatter, IDbgDotNetFormatterMetadata>> dbgDotNetFormatters) {
this.dbgMetadataService = dbgMetadataService;
this.dbgModuleReferenceProvider = dbgModuleReferenceProvider;
this.dbgDotNetEngineValueNodeFactoryService = dbgDotNetEngineValueNodeFactoryService;
this.dnILInterpreter = dnILInterpreter;
this.objectIdService = objectIdService;
this.decompilerService = decompilerService;
this.predefinedEvaluationErrorMessagesHelper = predefinedEvaluationErrorMessagesHelper;
var eeList = new List<Lazy<DbgDotNetExpressionCompiler, IDbgDotNetExpressionCompilerMetadata>>();
Expand Down Expand Up @@ -110,7 +113,7 @@ public override IEnumerable<DbgEngineLanguage> CreateLanguages() {
continue;

var languageDisplayName = ResourceHelper.GetString(lz.Value, lz.Metadata.LanguageDisplayName);
yield return new DbgEngineLanguageImpl(dbgModuleReferenceProvider.Value, lz.Metadata.LanguageName, languageDisplayName, lz.Value, dbgMetadataService.Value, decompiler, formatter.Value, valueNodeFactory, dnILInterpreter.Value, predefinedEvaluationErrorMessagesHelper);
yield return new DbgEngineLanguageImpl(dbgModuleReferenceProvider.Value, lz.Metadata.LanguageName, languageDisplayName, lz.Value, dbgMetadataService.Value, decompiler, formatter.Value, valueNodeFactory, dnILInterpreter.Value, objectIdService.Value, predefinedEvaluationErrorMessagesHelper);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ sealed class DbgEngineExpressionEvaluatorImpl : DbgEngineExpressionEvaluator, ID
readonly DbgModuleReferenceProvider dbgModuleReferenceProvider;
readonly DbgDotNetExpressionCompiler expressionCompiler;
readonly DbgDotNetILInterpreter dnILInterpreter;
readonly DbgObjectIdService objectIdService;
readonly IPredefinedEvaluationErrorMessagesHelper predefinedEvaluationErrorMessagesHelper;

public DbgEngineExpressionEvaluatorImpl(DbgModuleReferenceProvider dbgModuleReferenceProvider, DbgDotNetExpressionCompiler expressionCompiler, DbgDotNetILInterpreter dnILInterpreter, IPredefinedEvaluationErrorMessagesHelper predefinedEvaluationErrorMessagesHelper) {
public DbgEngineExpressionEvaluatorImpl(DbgModuleReferenceProvider dbgModuleReferenceProvider, DbgDotNetExpressionCompiler expressionCompiler, DbgDotNetILInterpreter dnILInterpreter, DbgObjectIdService objectIdService, IPredefinedEvaluationErrorMessagesHelper predefinedEvaluationErrorMessagesHelper) {
this.dbgModuleReferenceProvider = dbgModuleReferenceProvider ?? throw new ArgumentNullException(nameof(dbgModuleReferenceProvider));
this.expressionCompiler = expressionCompiler ?? throw new ArgumentNullException(nameof(expressionCompiler));
this.dnILInterpreter = dnILInterpreter ?? throw new ArgumentNullException(nameof(dnILInterpreter));
this.objectIdService = objectIdService ?? throw new ArgumentNullException(nameof(objectIdService));
this.predefinedEvaluationErrorMessagesHelper = predefinedEvaluationErrorMessagesHelper ?? throw new ArgumentNullException(nameof(predefinedEvaluationErrorMessagesHelper));
}

Expand Down Expand Up @@ -361,7 +363,55 @@ public override void Clear() { }
}

DbgDotNetAlias[] GetAliases(DbgEvaluationContext context, DbgStackFrame frame, CancellationToken cancellationToken) {
return Array.Empty<DbgDotNetAlias>();//TODO:
var runtime = context.Runtime.GetDotNetRuntime();
var objectIds = objectIdService.GetObjectIds(context.Runtime);
var aliases = runtime.GetAliases(context, frame, cancellationToken);

if (objectIds.Length == 0 && aliases.Length == 0)
return Array.Empty<DbgDotNetAlias>();

var res = new DbgDotNetAlias[objectIds.Length + aliases.Length];

var sb = ObjectCache.AllocStringBuilder();
var output = new StringBuilderTextColorOutput(sb);
int w = 0;
foreach (var alias in aliases) {
output.Reset();
DbgDotNetAliasKind dnAliasKind;
string aliasName;
switch (alias.Kind) {
case DbgDotNetAliasInfoKind.Exception:
dnAliasKind = DbgDotNetAliasKind.Exception;
context.Language.Formatter.FormatExceptionName(context, output, alias.Id);
aliasName = sb.ToString();
break;
case DbgDotNetAliasInfoKind.StowedException:
dnAliasKind = DbgDotNetAliasKind.StowedException;
context.Language.Formatter.FormatStowedExceptionName(context, output, alias.Id);
aliasName = sb.ToString();
break;
case DbgDotNetAliasInfoKind.ReturnValue:
dnAliasKind = DbgDotNetAliasKind.ReturnValue;
context.Language.Formatter.FormatReturnValueName(context, output, alias.Id);
aliasName = sb.ToString();
break;
default:
throw new InvalidOperationException();
}
res[w++] = new DbgDotNetAlias(dnAliasKind, alias.Type.AssemblyQualifiedName, aliasName, alias.CustomTypeInfoId, alias.CustomTypeInfo);
}
foreach (var objectId in objectIds) {
output.Reset();
var value = objectId.GetValue(context, frame, cancellationToken);
var dnValue = (DbgDotNetValue)value.InternalValue;
context.Language.Formatter.FormatObjectIdName(context, output, objectId.Id);
res[w++] = new DbgDotNetAlias(DbgDotNetAliasKind.ObjectId, dnValue.Type.AssemblyQualifiedName, sb.ToString(), Guid.Empty, null);
value.Close();
}
if (w != res.Length)
throw new InvalidOperationException();
ObjectCache.Free(ref sb);
return res;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,29 @@ sealed class DbgEngineLanguageImpl : DbgEngineLanguage {
public override DbgEngineValueNodeFactory ValueNodeFactory { get; }

readonly DbgMetadataService dbgMetadataService;
readonly DbgDotNetExpressionCompiler expressionCompiler;
readonly IDecompiler decompiler;
readonly IDebuggerDisplayAttributeEvaluator debuggerDisplayAttributeEvaluator;

public DbgEngineLanguageImpl(DbgModuleReferenceProvider dbgModuleReferenceProvider, string name, string displayName, DbgDotNetExpressionCompiler expressionCompiler, DbgMetadataService dbgMetadataService, IDecompiler decompiler, DbgDotNetFormatter formatter, DbgDotNetEngineValueNodeFactory valueNodeFactory, DbgDotNetILInterpreter dnILInterpreter, IPredefinedEvaluationErrorMessagesHelper predefinedEvaluationErrorMessagesHelper) {
public DbgEngineLanguageImpl(DbgModuleReferenceProvider dbgModuleReferenceProvider, string name, string displayName, DbgDotNetExpressionCompiler expressionCompiler, DbgMetadataService dbgMetadataService, IDecompiler decompiler, DbgDotNetFormatter formatter, DbgDotNetEngineValueNodeFactory valueNodeFactory, DbgDotNetILInterpreter dnILInterpreter, DbgObjectIdService objectIdService, IPredefinedEvaluationErrorMessagesHelper predefinedEvaluationErrorMessagesHelper) {
if (dbgModuleReferenceProvider == null)
throw new ArgumentNullException(nameof(dbgModuleReferenceProvider));
if (expressionCompiler == null)
throw new ArgumentNullException(nameof(expressionCompiler));
if (formatter == null)
throw new ArgumentNullException(nameof(formatter));
if (valueNodeFactory == null)
throw new ArgumentNullException(nameof(valueNodeFactory));
if (dnILInterpreter == null)
throw new ArgumentNullException(nameof(dnILInterpreter));
if (objectIdService == null)
throw new ArgumentNullException(nameof(objectIdService));
if (predefinedEvaluationErrorMessagesHelper == null)
throw new ArgumentNullException(nameof(predefinedEvaluationErrorMessagesHelper));
Name = name ?? throw new ArgumentNullException(nameof(name));
DisplayName = displayName ?? throw new ArgumentNullException(nameof(displayName));
this.dbgMetadataService = dbgMetadataService ?? throw new ArgumentNullException(nameof(dbgMetadataService));
this.expressionCompiler = expressionCompiler ?? throw new ArgumentNullException(nameof(expressionCompiler));
this.decompiler = decompiler ?? throw new ArgumentNullException(nameof(decompiler));
var expressionEvaluator = new DbgEngineExpressionEvaluatorImpl(dbgModuleReferenceProvider, expressionCompiler, dnILInterpreter, predefinedEvaluationErrorMessagesHelper);
var expressionEvaluator = new DbgEngineExpressionEvaluatorImpl(dbgModuleReferenceProvider, expressionCompiler, dnILInterpreter, objectIdService, predefinedEvaluationErrorMessagesHelper);
ExpressionEvaluator = expressionEvaluator;
ValueFormatter = new DbgEngineValueFormatterImpl(formatter);
Formatter = new DbgEngineFormatterImpl(formatter);
Expand Down Expand Up @@ -127,6 +129,8 @@ public override void InitializeContext(DbgEvaluationContext context, DbgCodeLoca
Debug.Assert(context.Runtime.GetDotNetRuntime() != null);

IDebuggerDisplayAttributeEvaluatorUtils.Initialize(context, debuggerDisplayAttributeEvaluator);
// Needed by DebuggerRuntimeImpl (calls expressionCompiler.TryGetAliasInfo())
context.GetOrCreateData(() => expressionCompiler);

var loc = location as IDbgDotNetCodeLocation;
if (loc == null) {
Expand Down
Loading

0 comments on commit b02cb56

Please sign in to comment.