internal DbgDotNetValue CreateDotNetValue_CorDebug(CorValue value, DmdAppDomain reflectionAppDomain, bool tryCreateStrongHandle, bool closeOnContinue = true) { debuggerThread.VerifyAccess(); if (value is null) { return(new SyntheticValue(reflectionAppDomain.System_Void, new DbgDotNetRawValue(DbgSimpleValueType.Void))); } try { var type = new ReflectionTypeCreator(this, reflectionAppDomain).Create(value.ExactType); if (tryCreateStrongHandle && !value.IsNull && !value.IsHandle && value.IsReference && !type.IsPointer && !type.IsFunctionPointer && !type.IsByRef) { var derefValue = value.GetDereferencedValue(out int hr); var strongHandle = derefValue?.CreateHandle(CorDebugHandleType.HANDLE_STRONG); Debug2.Assert(derefValue is null || !(strongHandle is null) || type == type.AppDomain.System_TypedReference); if (!(strongHandle is null)) { value = strongHandle; } } var dnValue = new DbgDotNetValueImpl(this, new DbgCorValueHolder(this, value, type)); if (closeOnContinue) { lock (lockObj) dotNetValuesToCloseOnContinue.Add(dnValue); } return(dnValue); } catch { dnDebugger.DisposeHandle(value); throw; } }
DbgDotNetRawValue?ReadField_CorDebug(CorValue obj, DbgAppDomain appDomain, string fieldName) { if (obj == null) { return(null); } var reflectionAppDomain = appDomain.GetReflectionAppDomain(); if (reflectionAppDomain == null) { return(null); } DbgDotNetValueImpl objImp = null; try { objImp = CreateDotNetValue_CorDebug(obj, reflectionAppDomain, tryCreateStrongHandle: false) as DbgDotNetValueImpl; if (objImp == null) { return(null); } return(ReadField_CorDebug(objImp, fieldName)); } finally { objImp?.Dispose(); } }
string TryGetExceptionMessage(DbgDotNetValueImpl exObj) { if (exObj == null) return null; var res = ReadField_CorDebug(exObj, "_message"); if (res == null || !res.Value.HasRawValue) return null; return res.Value.RawValue as string ?? dnSpy_Debugger_DotNet_CorDebug_Resources.ExceptionMessageIsNull; }
internal DbgDotNetValue CreateDotNetValue_CorDebug(DbgCorValueHolder value) { debuggerThread.VerifyAccess(); var dnValue = new DbgDotNetValueImpl(this, value); lock (lockObj) dotNetValuesToCloseOnContinue.Add(dnValue); return(dnValue); }
internal DbgDotNetValue CreateDotNetValue_MonoDebug(ValueLocation valueLocation) { debuggerThread.VerifyAccess(); var value = valueLocation.Load(); if (value == null) { return(new SyntheticNullValue(valueLocation.Type)); } var dnValue = new DbgDotNetValueImpl(this, valueLocation, value); lock (lockObj) dotNetValuesToCloseOnContinue.Add(dnValue); return(dnValue); }
DbgDotNetRawValue?ReadField_CorDebug(DbgDotNetValueImpl obj, string fieldName1, string?fieldName2) { const DmdBindingFlags fieldFlags = DmdBindingFlags.Public | DmdBindingFlags.NonPublic | DmdBindingFlags.Instance; var field = obj.Type.GetField(fieldName1, fieldFlags); if (field is null && !(fieldName2 is null)) { field = obj.Type.GetField(fieldName2, fieldFlags); } Debug2.Assert(!(field is null)); if (field is null) { return(null); } var dnAppDomain = ((DbgCorDebugInternalAppDomainImpl)obj.Type.AppDomain.GetDebuggerAppDomain().InternalAppDomain).DnAppDomain; var corFieldDeclType = GetType(dnAppDomain.CorAppDomain, field.DeclaringType !); var objValue = DbgCorDebugInternalRuntimeImpl.TryGetObjectOrPrimitiveValue(obj.TryGetCorValue(), out int hr); if (objValue is null) { return(null); } if (objValue.IsObject) { // This isn't a generic read-field method, so we won't try to load any classes by calling cctors. var fieldValue = objValue.GetFieldValue(corFieldDeclType.Class, (uint)field.MetadataToken, out hr); if (fieldValue is null) { return(null); } DbgDotNetValue?dnValue = null; try { dnValue = CreateDotNetValue_CorDebug(fieldValue, field.AppDomain, tryCreateStrongHandle: false); return(dnValue.GetRawValue()); } finally { dnValue?.Dispose(); } } return(null); }
void DnDebugger_DebugCallbackEvent(DnDebugger dbg, DebugCallbackEventArgs e) { string msg; DbgModule module; switch (e.Kind) { case DebugCallbackKind.CreateProcess: var cp = (CreateProcessDebugCallbackEventArgs)e; hProcess_debuggee = Native.NativeMethods.OpenProcess(Native.NativeMethods.PROCESS_QUERY_LIMITED_INFORMATION, false, (uint)(cp.CorProcess?.ProcessId ?? -1)); SendMessage(new DbgMessageConnected((uint)cp.CorProcess.ProcessId, GetMessageFlags())); e.AddPauseReason(DebuggerPauseReason.Other); break; case DebugCallbackKind.CreateAppDomain: // CreateProcess is too early, we must do this when the AppDomain gets created if (!clrDacInitd) { clrDacInitd = true; var p = dnDebugger.Processes.FirstOrDefault(); if (p != null) clrDac = clrDacProvider.Create(p.ProcessId, dnDebugger.CLRPath, this); } break; case DebugCallbackKind.Exception2: var e2 = (Exception2DebugCallbackEventArgs)e; DbgExceptionEventFlags exFlags; if (e2.EventType == CorDebugExceptionCallbackType.DEBUG_EXCEPTION_FIRST_CHANCE) exFlags = DbgExceptionEventFlags.FirstChance; else if (e2.EventType == CorDebugExceptionCallbackType.DEBUG_EXCEPTION_UNHANDLED) { exFlags = DbgExceptionEventFlags.SecondChance | DbgExceptionEventFlags.Unhandled; isUnhandledException = true; } else break; // Ignore exceptions when evaluating except if it's an unhandled exception, those must always be reported if (dbg.IsEvaluating && e2.EventType != CorDebugExceptionCallbackType.DEBUG_EXCEPTION_UNHANDLED) break; module = TryGetModule(e2.CorFrame, e2.CorThread); var exObj = e2.CorThread?.CurrentException; var reflectionAppDomain = module?.GetReflectionModule().AppDomain; DbgDotNetValueImpl dnExObj = null; try { if (exObj != null && reflectionAppDomain != null) dnExObj = CreateDotNetValue_CorDebug(exObj, reflectionAppDomain, tryCreateStrongHandle: false) as DbgDotNetValueImpl; objectFactory.CreateException(new DbgExceptionId(PredefinedExceptionCategories.DotNet, TryGetExceptionName(dnExObj) ?? "???"), exFlags, TryGetExceptionMessage(dnExObj), TryGetThread(e2.CorThread), module, GetMessageFlags()); e.AddPauseReason(DebuggerPauseReason.Other); } finally { dnExObj?.Dispose(); } break; case DebugCallbackKind.MDANotification: if (dbg.IsEvaluating) break; var mdan = (MDANotificationDebugCallbackEventArgs)e; objectFactory.CreateException(new DbgExceptionId(PredefinedExceptionCategories.MDA, mdan.CorMDA?.Name ?? "???"), DbgExceptionEventFlags.FirstChance, mdan.CorMDA?.Description, TryGetThread(mdan.CorThread), TryGetModule(null, mdan.CorThread), GetMessageFlags()); e.AddPauseReason(DebuggerPauseReason.Other); break; case DebugCallbackKind.LogMessage: if (dbg.IsEvaluating) break; var lmsgArgs = (LogMessageDebugCallbackEventArgs)e; msg = lmsgArgs.Message; if (msg != null) { e.AddPauseReason(DebuggerPauseReason.Other); var thread = TryGetThread(lmsgArgs.CorThread); SendMessage(new DbgMessageProgramMessage(msg, thread, GetMessageFlags())); } break; case DebugCallbackKind.LoadClass: var lcArgs = (LoadClassDebugCallbackEventArgs)e; var cls = lcArgs.CorClass; Debug.Assert(cls != null); if (cls != null) { var dnModule = dbg.TryGetModule(lcArgs.CorAppDomain, cls); if (dnModule.IsDynamic) { UpdateDynamicModuleIds(dnModule); module = TryGetModule(dnModule.CorModule); Debug.Assert(module != null); if (module != null) dbgModuleMemoryRefreshedNotifier.RaiseModulesRefreshed(new[] { module }); if (dnModule?.CorModuleDef != null && module != null) { if (TryGetModuleData(module, out var data)) data.OnLoadClass(); ClassLoaded?.Invoke(this, new ClassLoadedEventArgs(module, cls.Token)); } GetDynamicModuleHelper(dnModule).RaiseTypeLoaded(new DmdTypeLoadedEventArgs((int)cls.Token)); } } break; case DebugCallbackKind.DebuggerError: var deArgs = (DebuggerErrorDebugCallbackEventArgs)e; if (deArgs.HError == CordbgErrors.CORDBG_E_UNCOMPATIBLE_PLATFORMS) msg = GetIncompatiblePlatformErrorMessage(); else msg = string.Format(dnSpy_Debugger_DotNet_CorDebug_Resources.Error_CLRDebuggerErrorOccurred, deArgs.HError, deArgs.ErrorCode); SendMessage(new DbgMessageBreak(msg, GetMessageFlags(pause: true))); break; } }