예제 #1
0
        public DkmCustomMessage SendLower(DkmCustomMessage customMessage)
        {
            try {
                Debug.Assert(customMessage.SourceId == PackageServices.VsDebuggerMessageGuid);
                VsDebuggerMessage code = (VsDebuggerMessage)customMessage.MessageCode;
                switch (code)
                {
                case VsDebuggerMessage.EnableChildProcessDebugging:
                    Guid       processGuid = (Guid)customMessage.Parameter1;
                    DkmProcess process     = DkmProcess.FindProcess(processGuid);
                    if (process != null)
                    {
                        process.SetDataItem(
                            DkmDataCreationDisposition.CreateNew,
                            new RuntimeBreakpointHandler());
                        process.SetDataItem(
                            DkmDataCreationDisposition.CreateNew,
                            new AutoAttachToChildHandler());
                        Logger.LogInfo(
                            "Successfully delay-enabled child debugging for process {0}.",
                            processGuid);
                    }
                    else
                    {
                        Logger.LogError(
                            "Unable to find process {0} while trying to enable child process debugging.",
                            processGuid);
                    }
                    break;

                default:
                    Logger.LogError("Debug component received unknown message code {0}.", code);
                    break;
                }
            } catch (DkmException exception) {
                Logger.LogError(
                    exception,
                    "An error occurred while handling a debugger message.  HR = 0x{0:X}",
                    exception.HResult);
            }
            return(null);
        }
예제 #2
0
파일: LocalComponent.cs 프로젝트: krus/PTVS
        private static void InjectHelperDll(DkmProcess process)
        {
            var injectionData = process.GetDataItem <HelperDllInjectionDataHolder>();

            if (injectionData != null)
            {
                // Injection is already in progress.
                return;
            }

            injectionData = new HelperDllInjectionDataHolder();
            process.SetDataItem(DkmDataCreationDisposition.CreateNew, injectionData);

            var pyrtInfo = process.GetPythonRuntimeInfo();

            // Loading the helper is done via CreateRemoteThread(LoadLibrary), which is inherently asynchronous.
            // On the other hand, we will not handle breakpoints until it is loaded - they won't even be bound.
            // If any Python code is running in the meantime, this may cause us to skip breakpoints, which is
            // very surprising in the run (F5) scenario, as the user expects all preset breakpoints to be hit.
            // To fix that, we need block the Python interpreter loop until the helper is fully loaded.
            //
            // Pausing all threads is not a good way to do this, because one of the threads may be holding the
            // loader lock, which will prevent the helper from loading and result in a deadlock. So instead,
            // block at a known location at the beginning of PyInitialize_Ex, and only freeze the thread that
            // calls it - this is sufficient to prevent execution of Python code in run scenario before helper
            // is loaded.
            //
            // For attach-to-running-process scenario, we do nothing because the attach itself is inherently
            // asynchronous, and so there's no user expectation that breakpoints light up instantly.

            // If Python is already initialized, this is attach-to-running-process - don't block.
            var initialized = pyrtInfo.DLLs.Python.GetStaticVariable <Int32Proxy>(
                "initialized",
                GetPyInitializeObjectFile(pyrtInfo.LanguageVersion)
                );

            if (initialized.Read() == 0)
            {
                // When Py_InitializeEx is hit, suspend the thread.
                DkmRuntimeBreakpoint makePendingCallsBP = null;
                makePendingCallsBP = CreateRuntimeDllExportedFunctionBreakpoint(pyrtInfo.DLLs.Python, "Py_InitializeEx", (thread, frameBase, vFrame) => {
                    makePendingCallsBP.Close();
                    if (process.GetPythonRuntimeInstance() == null)
                    {
                        thread.Suspend(true);
                        injectionData.SuspendedThread = thread;
                    }
                });
                makePendingCallsBP.Enable();
            }

            // Inject the helper DLL; OnHelperDllInitialized will resume the thread once the DLL is loaded and initialized.
            DebugAttach.AttachDkm(process.LivePart.Id);
        }
        public static void VscxOnRuntimeInstanceLoad(this DkmRuntimeInstance runtime)
        {
            if (runtime.TagValue != DkmRuntimeInstance.Tag.NativeRuntimeInstance)
            {
                return;
            }

            DkmNativeRuntimeInstance nativeRuntime = (DkmNativeRuntimeInstance)runtime;
            bool isChrome      = false;
            bool isTestProcess = false;

            // Check if the process is a chrome executable, and if so, attach a CallstackFilter to the DkmProcess.
            if (ChromeUtility.IsChromeProcess(nativeRuntime.Process.Path))
            {
                isChrome = true;
            }
#if DEBUG
            string fileName = Path.GetFileName(nativeRuntime.Process.Path);
            if (fileName.Equals("vistest.exe", StringComparison.CurrentCultureIgnoreCase))
            {
                isTestProcess = true;
            }
#endif

            if (isTestProcess || isChrome)
            {
                DkmProcess process = nativeRuntime.Process;

                DebugProcessOptions         options         = DebugProcessOptions.Create(process.DebugLaunchSettings.OptionsString);
                ProcessDebugOptionsDataItem optionsDataItem = new ProcessDebugOptionsDataItem(options);
                process.SetDataItem(DkmDataCreationDisposition.CreateAlways, optionsDataItem);

                if (isTestProcess || ShouldEnableChildDebugging(nativeRuntime.Process, options))
                {
                    process.SetDataItem(DkmDataCreationDisposition.CreateAlways, new RuntimeBreakpointHandler());
                    process.SetDataItem(DkmDataCreationDisposition.CreateAlways, new AutoAttachToChildHandler());
                }
            }
        }
예제 #4
0
        public static StructMetadata GetStructMetadata <TStruct>(DkmProcess process)
            where TStruct : StructProxy
        {
            var metadata = process.GetDataItem <StructMetadata <TStruct> >();

            if (metadata != null)
            {
                return(metadata);
            }

            metadata = new StructMetadata <TStruct>(process);
            process.SetDataItem(DkmDataCreationDisposition.CreateNew, metadata);
            return(metadata);
        }
예제 #5
0
            public override void Handle(DkmProcess process)
            {
                var pyrtInfo      = process.GetPythonRuntimeInfo();
                var nativeModules = process.GetNativeRuntimeInstance().GetNativeModuleInstances();

                pyrtInfo.DLLs.Python = nativeModules.Single(mi => mi.UniqueId == PythonDllModuleInstanceId);
                pyrtInfo.DLLs.Python.FlagAsTransitionModule();

                if (DebuggerHelperDllModuleInstanceId != Guid.Empty)
                {
                    pyrtInfo.DLLs.DebuggerHelper = nativeModules.Single(mi => mi.UniqueId == DebuggerHelperDllModuleInstanceId);
                    pyrtInfo.DLLs.DebuggerHelper.FlagAsTransitionModule();

                    process.SetDataItem(DkmDataCreationDisposition.CreateNew, new TraceManager(process));
                }

                var runtimeId       = new DkmRuntimeInstanceId(Guids.PythonRuntimeTypeGuid, 0);
                var runtimeInstance = DkmCustomRuntimeInstance.Create(process, runtimeId, null);

                new CreateModuleRequest {
                    ModuleId = Guids.UnknownPythonModuleGuid
                }.Handle(process);
            }