예제 #1
0
        void DnDebugger_DebugCallbackEvent(DnDebugger dbg, DebugCallbackEventArgs e)
        {
            string msg;

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

                var exObj = e2.CorThread?.CurrentException;
                objectFactory.CreateException(new DbgExceptionId(PredefinedExceptionCategories.DotNet, TryGetExceptionName(exObj) ?? "???"), exFlags, TryGetExceptionMessage(exObj), TryGetThread(e2.CorThread), TryGetModule(e2.CorFrame, e2.CorThread), GetMessageFlags());
                e.AddPauseReason(DebuggerPauseReason.Other);
                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);
                        var 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;
            }
        }
예제 #2
0
        // When a dynamic assembly is created with option Run, a module gets created and its
        // metadata name is "RefEmit_InMemoryManifestModule". Shortly thereafter, its name
        // gets changed to the name the user chose.
        // This name is also saved in ModuleIds, and used when setting breakpoints...
        // There's code that caches ModuleIds, but they don't cache it if IsDynamic is true.
        // This method updates the ModuleId and resets breakpoints in the module.
        void UpdateDynamicModuleIds(DnModule dnModule)
        {
            debuggerThread.VerifyAccess();
            if (!dnModule.IsDynamic)
            {
                return;
            }
            var module = TryGetModule(dnModule.CorModule);

            if (module == null || !TryGetModuleData(module, out var data) || data.HasUpdatedModuleId)
            {
                return;
            }
            List <(DbgModule dbgModule, DnModule dnModule)> updatedModules = null;

            lock (lockObj) {
                if (toAssemblyModules.TryGetValue(dnModule.Assembly, out var modules))
                {
                    for (int i = 0; i < modules.Count; i++)
                    {
                        dnModule = modules[i];
                        if (!dnModule.IsDynamic)
                        {
                            continue;
                        }
                        if (!toEngineModule.TryGetValue(dnModule.CorModule, out var em))
                        {
                            continue;
                        }
                        if (!TryGetModuleData(em.Module, out data))
                        {
                            continue;
                        }
                        dnModule.CorModule.ClearCachedDnlibName();
                        var moduleId = dnModule.DnModuleId.ToModuleId();
                        if (data.ModuleId == moduleId)
                        {
                            continue;
                        }
                        data.UpdateModuleId(moduleId);
                        if (dnModule.CorModuleDef != null)
                        {
                            //TODO: This doesn't update the treeview node
                            dnModule.CorModuleDef.Name = moduleId.ModuleName;
                        }
                        if (updatedModules == null)
                        {
                            updatedModules = new List <(DbgModule, DnModule)>();
                        }
                        updatedModules.Add((em.Module, dnModule));
                    }
                }
            }
            if (updatedModules != null)
            {
                foreach (var info in updatedModules)
                {
                    var mdi       = info.dnModule.CorModule.GetMetaDataInterface <IMetaDataImport2>();
                    var scopeName = MDAPI.GetModuleName(mdi) ?? string.Empty;
                    ((DbgCorDebugInternalModuleImpl)info.dbgModule.InternalModule).ReflectionModule.ScopeName = scopeName;
                }
                dbgModuleMemoryRefreshedNotifier.RaiseModulesRefreshed(updatedModules.Select(a => a.dbgModule).ToArray());
            }
        }