コード例 #1
0
 public static DkmProcess GetDebuggedProcess(Debugger debugger)
 {
     DkmProcess[] procs = DkmProcess.GetProcesses();
     if (procs.Length == 1)
     {
         return procs[0];
     }
     else if (procs.Length > 1)
     {
         foreach (DkmProcess proc in procs)
         {
             if (proc.Path == debugger.CurrentProcess.Name)
                 return proc;
         }
     }
     return null;
 }
コード例 #2
0
 private static DkmProcess GetDebuggedProcess(Debugger debugger)
 {
     DkmProcess[] procs = DkmProcess.GetProcesses();
     if (procs.Length == 1)
     {
         return(procs[0]);
     }
     else if (procs.Length > 1)
     {
         foreach (DkmProcess proc in procs)
         {
             if (proc.Path == debugger.CurrentProcess.Name)
             {
                 return(proc);
             }
         }
     }
     return(null);
 }
コード例 #3
0
        // https://stackoverflow.com/questions/45570027/retrieving-data-from-arbitrary-memory-addresses-using-vsix
        // https://social.msdn.microsoft.com/Forums/en-US/030cef1c-ee79-46e9-8e40-bfc59f14cc34/how-can-i-send-a-custom-debug-event-to-my-idebugeventcallback2-handler?forum=vsdebug
        // https://macropolygon.wordpress.com/2012/12/16/evaluating-debugged-process-memory-in-a-visual-studio-extension/
        private static DkmProcess GetDebuggedProcess(Debugger debugger)
        {
            /*
             * // EnvDTE90a
             * StackFrame2 currentFrame2 = debugger.CurrentStackFrame as StackFrame2;
             * if (currentFrame2 != null)
             * {
             *  uint currentFrameDepth = currentFrame2.Depth - 1;
             * }
             */
            /*
             * DkmStackFrame dkmFrame = DkmStackFrame.ExtractFromDTEObject(debugger.CurrentStackFrame);
             * if (dkmFrame != null)
             * {
             *  var dkmThread = dkmFrame.Thread;
             *  var dkmProcess = dkmFrame.Process;
             * }
             */
            /*
             * DkmStackFrame frame = DkmStackFrame.ExtractFromDTEObject(debugger.CurrentStackFrame);
             * if (frame == null)
             *  return null;
             * return frame.Process;
             */

            DkmProcess[] procs = DkmProcess.GetProcesses();
            if (procs.Length == 1)
            {
                return(procs[0]);
            }
            else if (procs.Length > 1)
            {
                foreach (DkmProcess proc in procs)
                {
                    if (proc.Path == debugger.CurrentProcess.Name)
                    {
                        return(proc);
                    }
                }
            }
            return(null);
        }
コード例 #4
0
        private static DkmClrModuleInstance FindClrModuleInstance(Guid mvid)
        {
            foreach (var process in DkmProcess.GetProcesses())
            {
                foreach (var runtimeInstance in process.GetRuntimeInstances())
                {
                    if (runtimeInstance.TagValue == DkmRuntimeInstance.Tag.ClrRuntimeInstance)
                    {
                        foreach (var moduleInstance in runtimeInstance.GetModuleInstances())
                        {
                            if (moduleInstance.TagValue == DkmModuleInstance.Tag.ClrModuleInstance &&
                                moduleInstance is DkmClrModuleInstance clrModuleInstance &&
                                clrModuleInstance.Mvid == mvid)
                            {
                                return(clrModuleInstance);
                            }
                        }
                    }
                }
            }

            return(null);
        }
コード例 #5
0
        /// <summary>
        /// Retrieves active statements from the debuggee process.
        /// Shall only be called while in debug mode.
        /// Can be invoked on any thread.
        /// </summary>
        public Task <ImmutableArray <ActiveStatementDebugInfo> > GetActiveStatementsAsync(CancellationToken cancellationToken)
        {
            using (DebuggerComponent.ManagedEditAndContinueService())
            {
                // TODO: return empty outside of debug session.
                // https://github.com/dotnet/roslyn/issues/24325

                int unexpectedError = 0;
                var completion      = new TaskCompletionSource <ImmutableArray <ActiveStatementDebugInfo> >();
                var builders        = default(ArrayBuilder <ArrayBuilder <ActiveStatementDebugInfo> >);
                int pendingRuntimes = 0;
                int runtimeCount    = 0;

                var workList = DkmWorkList.Create(CompletionRoutine: _ =>
                {
                    completion.TrySetException(new InvalidOperationException($"Unexpected error enumerating active statements: 0x{unexpectedError:X8}"));
                });

                void CancelWork()
                {
                    if (builders != null)
                    {
                        FreeBuilders(builders);
                        builders = null;

                        // TODO: DkmWorkList.Cancel doesn't currently work when invoked on the completion callback.
                        // We continue execute all the queued callbacks -- they will be no-ops.
                        // See https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems/edit/562781.
                        //
                        // workList.Cancel();

                        // make sure we cancel with the token we received from the caller:
                        completion.TrySetCanceled(cancellationToken);
                    }
                }

                foreach (var process in DkmProcess.GetProcesses())
                {
                    foreach (var runtimeInstance in process.GetRuntimeInstances())
                    {
                        if (runtimeInstance.TagValue == DkmRuntimeInstance.Tag.ClrRuntimeInstance)
                        {
                            var clrRuntimeInstance = (DkmClrRuntimeInstance)runtimeInstance;

                            int runtimeIndex = runtimeCount;
                            runtimeCount++;

                            clrRuntimeInstance.GetActiveStatements(workList, activeStatementsResult =>
                            {
                                if (cancellationToken.IsCancellationRequested)
                                {
                                    CancelWork();
                                    return;
                                }

                                if (activeStatementsResult.ErrorCode != 0)
                                {
                                    unexpectedError = activeStatementsResult.ErrorCode;
                                    return;
                                }

                                // group active statement by instruction and aggregate flags and threads:
                                var instructionMap = PooledDictionary <ActiveInstructionId, (DkmInstructionSymbol Symbol, ArrayBuilder <Guid> Threads, int Index, ActiveStatementFlags Flags)> .GetInstance();

                                GroupActiveStatementsByInstructionId(instructionMap, activeStatementsResult.ActiveStatements);

                                int pendingStatements        = instructionMap.Count;
                                builders[runtimeIndex]       = ArrayBuilder <ActiveStatementDebugInfo> .GetInstance(pendingStatements);
                                builders[runtimeIndex].Count = pendingStatements;

                                foreach (var(instructionId, (symbol, threads, index, flags)) in instructionMap)
                                {
                                    var immutableThreads = threads.ToImmutableAndFree();

                                    symbol.GetSourcePosition(workList, DkmSourcePositionFlags.None, InspectionSession: null, sourcePositionResult =>
                                    {
                                        if (cancellationToken.IsCancellationRequested)
                                        {
                                            CancelWork();
                                            return;
                                        }

                                        int errorCode = sourcePositionResult.ErrorCode;
                                        if (errorCode != 0)
                                        {
                                            unexpectedError = errorCode;
                                        }

                                        DkmSourcePosition position;
                                        string documentNameOpt;
                                        LinePositionSpan span;
                                        if (errorCode == 0 && (position = sourcePositionResult.SourcePosition) != null)
                                        {
                                            documentNameOpt = position.DocumentName;
                                            span            = ToLinePositionSpan(position.TextSpan);
                                        }
                                        else
                                        {
                                            // The debugger can't determine source location for the active statement.
                                            // The PDB might not be available or the statement is in a method that doesn't have debug information.
                                            documentNameOpt = null;
                                            span            = default;
                                        }

                                        builders[runtimeIndex][index] = new ActiveStatementDebugInfo(
                                            instructionId,
                                            documentNameOpt,
                                            span,
                                            immutableThreads,
                                            flags);

                                        // the last active statement of the current runtime has been processed:
                                        if (Interlocked.Decrement(ref pendingStatements) == 0)
                                        {
                                            // the last active statement of the last runtime has been processed:
                                            if (Interlocked.Decrement(ref pendingRuntimes) == 0)
                                            {
                                                completion.TrySetResult(builders.ToFlattenedImmutableArrayAndFree());
                                            }
                                        }
                                    });
                                }

                                instructionMap.Free();
                            });
コード例 #6
0
 private static DkmProcess GetProcess(uint processId)
 {
     return(DkmProcess.GetProcesses()[(int)processId]);
 }
コード例 #7
0
        /// <summary>
        /// Retrieves active statements from the debuggee process.
        /// Shall only be called while in debug mode.
        /// Can be invoked on any thread.
        /// </summary>
        public Task <ImmutableArray <ActiveStatementDebugInfo> > GetActiveStatementsAsync(CancellationToken cancellationToken)
        {
            using (DebuggerComponent.ManagedEditAndContinueService())
            {
                // TODO: return empty outside of debug session.
                // https://github.com/dotnet/roslyn/issues/24325

                var completion      = new TaskCompletionSource <ImmutableArray <ActiveStatementDebugInfo> >();
                var builders        = default(ArrayBuilder <ArrayBuilder <ActiveStatementDebugInfo> >);
                int pendingRuntimes = 0;
                int runtimeCount    = 0;

                // No exception should be thrown in case of errors on the debugger side.
                // The debugger is responsible to provide telemetry for error cases.
                // The callback should not be called, but it's there to guarantee that the task completes and a hang is avoided.
                var workList = DkmWorkList.Create(_ => { completion.TrySetResult(ImmutableArray <ActiveStatementDebugInfo> .Empty); });

                void CancelWork()
                {
                    if (builders != null)
                    {
                        FreeBuilders(builders);
                        builders = null;

                        workList.Cancel(blockOnCompletion: false);

                        // make sure we cancel with the token we received from the caller:
                        completion.TrySetCanceled(cancellationToken);
                    }
                }

                foreach (var process in DkmProcess.GetProcesses())
                {
                    foreach (var runtimeInstance in process.GetRuntimeInstances())
                    {
                        if (runtimeInstance.TagValue == DkmRuntimeInstance.Tag.ClrRuntimeInstance)
                        {
                            var clrRuntimeInstance = (DkmClrRuntimeInstance)runtimeInstance;

                            int runtimeIndex = runtimeCount;
                            runtimeCount++;

                            clrRuntimeInstance.GetActiveStatements(workList, activeStatementsResult =>
                            {
                                try
                                {
                                    if (cancellationToken.IsCancellationRequested)
                                    {
                                        CancelWork();
                                        return;
                                    }

                                    var localBuilders = builders;
                                    if (localBuilders == null) // e.g. cancelled
                                    {
                                        return;
                                    }

                                    if (activeStatementsResult.ErrorCode != 0)
                                    {
                                        localBuilders[runtimeIndex] = ArrayBuilder <ActiveStatementDebugInfo> .GetInstance(0);

                                        // the last active statement of the last runtime has been processed:
                                        if (Interlocked.Decrement(ref pendingRuntimes) == 0)
                                        {
                                            completion.TrySetResult(localBuilders.ToFlattenedImmutableArrayAndFree());
                                        }

                                        return;
                                    }

                                    // group active statement by instruction and aggregate flags and threads:
                                    var instructionMap = PooledDictionary <ActiveInstructionId, (DkmInstructionSymbol Symbol, ArrayBuilder <Guid> Threads, int Index, ActiveStatementFlags Flags)> .GetInstance();

                                    GroupActiveStatementsByInstructionId(instructionMap, activeStatementsResult.ActiveStatements);

                                    int pendingStatements             = instructionMap.Count;
                                    localBuilders[runtimeIndex]       = ArrayBuilder <ActiveStatementDebugInfo> .GetInstance(pendingStatements);
                                    localBuilders[runtimeIndex].Count = pendingStatements;

                                    if (instructionMap.Count == 0)
                                    {
                                        if (Interlocked.Decrement(ref pendingRuntimes) == 0)
                                        {
                                            completion.TrySetResult(localBuilders.ToFlattenedImmutableArrayAndFree());
                                        }

                                        return;
                                    }

                                    foreach (var(instructionId, (symbol, threads, index, flags)) in instructionMap)
                                    {
                                        var immutableThreads = threads.ToImmutableAndFree();

                                        symbol.GetSourcePosition(workList, DkmSourcePositionFlags.None, InspectionSession: null, sourcePositionResult =>
                                        {
                                            try
                                            {
                                                if (cancellationToken.IsCancellationRequested)
                                                {
                                                    CancelWork();
                                                    return;
                                                }

                                                DkmSourcePosition position;
                                                string documentNameOpt;
                                                LinePositionSpan span;
                                                if (sourcePositionResult.ErrorCode == 0 && (position = sourcePositionResult.SourcePosition) != null)
                                                {
                                                    documentNameOpt = position.DocumentName;
                                                    span            = ToLinePositionSpan(position.TextSpan);
                                                }
                                                else
                                                {
                                                    // The debugger can't determine source location for the active statement.
                                                    // The PDB might not be available or the statement is in a method that doesn't have debug information.
                                                    documentNameOpt = null;
                                                    span            = default;
                                                }

                                                localBuilders[runtimeIndex][index] = new ActiveStatementDebugInfo(
                                                    instructionId,
                                                    documentNameOpt,
                                                    span,
                                                    immutableThreads,
                                                    flags);

                                                // the last active statement of the current runtime has been processed:
                                                if (Interlocked.Decrement(ref pendingStatements) == 0)
                                                {
                                                    // the last active statement of the last runtime has been processed:
                                                    if (Interlocked.Decrement(ref pendingRuntimes) == 0)
                                                    {
                                                        completion.TrySetResult(localBuilders.ToFlattenedImmutableArrayAndFree());
                                                    }
                                                }
                                            }
                                            catch (Exception e)
                                            {
                                                completion.TrySetException(e);
                                            }
                                        });
                                    }

                                    instructionMap.Free();
                                }