public static PyUnicodeObject33 Create(DkmProcess process, string value)
        {
            var allocator = process.GetDataItem <PyObjectAllocator>();

            Debug.Assert(allocator != null);

            var result = allocator.Allocate <PyUnicodeObject33>(value.Length * sizeof(char));

            result._asciiObject.hash.Write(-1);
            result._asciiObject.length.Write(value.Length);
            result._compactObject.wstr_length.Write(value.Length);

            var state = new State {
                interned = Interned.SSTATE_NOT_INTERNED,
                kind     = PyUnicode_Kind.PyUnicode_2BYTE_KIND,
                compact  = true,
                ascii    = false,
                ready    = true
            };

            result._asciiObject.state.Write((byte)state);

            ulong dataPtr = result.Address.OffsetBy(StructProxy.SizeOf <PyCompactUnicodeObject>(process));

            result._asciiObject.wstr.Write(dataPtr);
            process.WriteMemory(dataPtr, Encoding.Unicode.GetBytes(value));

            return(result);
        }
예제 #2
0
파일: LocalComponent.cs 프로젝트: krus/PTVS
            public override void Handle(DkmProcess process)
            {
                var ee = process.GetDataItem <ExpressionEvaluator>();

                if (ee != null)
                {
                    var thread = process.GetThreads().Single(t => t.UniqueId == ThreadId);
                    ee.OnAsyncBreakComplete(thread);
                }
            }
예제 #3
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);
        }
예제 #4
0
        public static PyIntObject Create(DkmProcess process, int value)
        {
            var allocator = process.GetDataItem <PyObjectAllocator>();

            Debug.Assert(allocator != null);

            var result = allocator.Allocate <PyIntObject>();

            result.ob_ival.Write(value);
            return(result);
        }
예제 #5
0
        public static void VscxOnModuleInstanceLoad(this DkmProcess process, DkmModuleInstance module, DkmWorkList workList)
        {
            AutoAttachToChildHandler handler = process.GetDataItem <AutoAttachToChildHandler>();

            if (handler == null || module.TagValue != DkmModuleInstance.Tag.NativeModuleInstance)
            {
                return;
            }

            handler.OnModuleInstanceLoad((DkmNativeModuleInstance)module, workList);
        }
예제 #6
0
파일: LocalComponent.cs 프로젝트: krus/PTVS
            public override void Handle(DkmProcess process)
            {
                var traceHelper = process.GetDataItem <TraceManagerLocalHelper>();

                if (traceHelper == null)
                {
                    Debug.Fail("LocalComponent received a StepCompleteNotification, but there is no TraceManagerLocalHelper to handle it.");
                    throw new InvalidOperationException();
                }

                traceHelper.OnStepComplete();
            }
예제 #7
0
        public static PyComplexObject Create(DkmProcess process, Complex value)
        {
            var allocator = process.GetDataItem <PyObjectAllocator>();

            Debug.Assert(allocator != null);

            var result = allocator.Allocate <PyComplexObject>();

            result.cval.real.Write(value.Real);
            result.cval.imag.Write(value.Imaginary);
            return(result);
        }
예제 #8
0
        public static PyLongObject Create(DkmProcess process, BigInteger value)
        {
            var allocator = process.GetDataItem <PyObjectAllocator>();

            Debug.Assert(allocator != null);

            var bitsInDigit  = process.Is64Bit() ? 30 : 15;
            var bytesInDigit = process.Is64Bit() ? 4 : 2;

            var  absValue  = BigInteger.Abs(value);
            long numDigits = 0;

            for (var t = absValue; t != 0;)
            {
                ++numDigits;
                t >>= bitsInDigit;
            }

            var result = allocator.Allocate <PyLongObject>(numDigits * bytesInDigit);

            if (value == 0)
            {
                result.ob_size.Write(0);
            }
            else if (value > 0)
            {
                result.ob_size.Write(numDigits);
            }
            else if (value < 0)
            {
                result.ob_size.Write(-numDigits);
            }

            if (bitsInDigit == 15)
            {
                for (var digitPtr = new UInt16Proxy(process, result.ob_digit.Address); absValue != 0; digitPtr = digitPtr.GetAdjacentProxy(1))
                {
                    digitPtr.Write((ushort)(absValue % (1 << bitsInDigit)));
                    absValue >>= bitsInDigit;
                }
            }
            else
            {
                for (var digitPtr = new UInt32Proxy(process, result.ob_digit.Address); absValue != 0; digitPtr = digitPtr.GetAdjacentProxy(1))
                {
                    digitPtr.Write((uint)(absValue % (1 << bitsInDigit)));
                    absValue >>= bitsInDigit;
                }
            }

            return(result);
        }
예제 #9
0
        public static PyBytesObject Create(DkmProcess process, AsciiString value)
        {
            var allocator = process.GetDataItem <PyObjectAllocator>();

            Debug.Assert(allocator != null);

            var result = allocator.Allocate <PyBytesObject>(value.Bytes.Length);

            result.ob_size.Write(value.Bytes.Length);
            process.WriteMemory(result.ob_sval.Address, value.Bytes);

            return(result);
        }
예제 #10
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);
        }
예제 #11
0
파일: LocalComponent.cs 프로젝트: krus/PTVS
            public override void Handle(DkmProcess process)
            {
                var traceHelper = process.GetDataItem <TraceManagerLocalHelper>();

                if (traceHelper == null)
                {
                    Debug.Fail("LocalComponent received a BeginStepInNotification, but there is no TraceManagerLocalHelper to handle it.");
                    throw new InvalidOperationException();
                }

                var thread = process.GetThreads().Single(t => t.UniqueId == ThreadId);

                traceHelper.OnBeginStepIn(thread);
            }
예제 #12
0
            public override void Handle(DkmProcess process)
            {
                var thread             = process.GetThreads().Single(t => t.UniqueId == ThreadId);
                var runtimeBreakpoints = process.GetDataItem <RuntimeDllBreakpoints>();

                if (runtimeBreakpoints.Handlers.TryGetValue(BreakpointId, out RuntimeDllBreakpointHandler handler))
                {
                    handler(thread, FrameBase, VFrame, ReturnAddress);
                }
                else
                {
                    Debug.Fail("LocalComponent received a HandleBreakpointRequest for a breakpoint that it does not know about.");
                }
            }
예제 #13
0
        public static void VscxOnRuntimeBreakpointReceived(
            this DkmProcess process,
            DkmRuntimeBreakpoint bp,
            DkmThread thread,
            bool hasException,
            DkmEventDescriptorS eventDescriptor)
        {
            RuntimeBreakpointHandler handler = process.GetDataItem <RuntimeBreakpointHandler>();

            if (handler == null)
            {
                return;
            }

            handler.OnRuntimeBreakpointReceived(bp, thread, hasException, eventDescriptor);
        }
        public static PyUnicodeObject27 Create(DkmProcess process, string value)
        {
            // Allocate string buffer together with the object itself in a single block.
            var allocator = process.GetDataItem <PyObjectAllocator>();

            Debug.Assert(allocator != null);

            var result = allocator.Allocate <PyUnicodeObject27>(value.Length * 2);

            result.length.Write(value.Length);

            var str = result.Address.OffsetBy(StructProxy.SizeOf <PyUnicodeObject27>(process));

            result.str.Raw.Write(str);

            var buf = Encoding.Unicode.GetBytes(value);

            process.WriteMemory(str, buf);

            return(result);
        }
예제 #15
0
파일: LocalComponent.cs 프로젝트: krus/PTVS
            public override void Handle(DkmProcess process)
            {
                if (process.LivePart == null)
                {
                    // When debugging dumps, there's no stepping or live expression evaluation. Hence, we don't
                    // need the helper DLL nor _ctypes.pyd for anything, and even if they are loaded in the dump,
                    // we don't care about them at all.
                    return;
                }

                var pyrtInfo       = process.GetPythonRuntimeInfo();
                var moduleInstance = process.GetNativeRuntimeInstance().GetNativeModuleInstances().Single(mi => mi.UniqueId == ModuleInstanceId);

                if (pyrtInfo.DLLs.CTypes == null && PythonDLLs.CTypesNames.Contains(moduleInstance.Name))
                {
                    moduleInstance.TryLoadSymbols();
                    if (moduleInstance.HasSymbols())
                    {
                        pyrtInfo.DLLs.CTypes = moduleInstance;

                        var traceHelper = process.GetDataItem <TraceManagerLocalHelper>();
                        if (traceHelper != null)
                        {
                            traceHelper.OnCTypesLoaded(moduleInstance);
                        }
                    }
                }

                if (process.GetPythonRuntimeInstance() != null)
                {
                    return;
                }

                if (PythonDLLs.GetPythonLanguageVersion(moduleInstance) != PythonLanguageVersion.None)
                {
                    pyrtInfo.DLLs.Python = moduleInstance;
                    for (int i = 0; i < 2; ++i)
                    {
                        if (moduleInstance.HasSymbols())
                        {
                            if (IsModuleCompiledWithPGO(moduleInstance))
                            {
                                pyrtInfo.DLLs.Python = null;
                                var pgoWarnMsg = DkmCustomMessage.Create(process.Connection, process, Guid.Empty, (int)VsPackageMessage.WarnAboutPGO, moduleInstance.Name, null);
                                pgoWarnMsg.SendToVsService(Guids.CustomDebuggerEventHandlerGuid, IsBlocking: true);
                                return;
                            }

                            if (process.LivePart == null)
                            {
                                // If debugging crash dumps, runtime can be created as soon as Python symbols are resolved.
                                CreatePythonRuntimeInstance(process);
                            }
                            else
                            {
                                // If not, we need to check for debugger helper DLL as well, and inject it if it isn't there yet.
                                if (pyrtInfo.DLLs.DebuggerHelper != null)
                                {
                                    CreatePythonRuntimeInstance(process);
                                }
                                else
                                {
                                    InjectHelperDll(process);
                                }
                            }
                            return;
                        }

                        moduleInstance.TryLoadSymbols();
                    }

                    var symWarnMsg = DkmCustomMessage.Create(process.Connection, process, Guid.Empty, (int)VsPackageMessage.WarnAboutPythonSymbols, moduleInstance.Name, null);
                    symWarnMsg.SendToVsService(Guids.CustomDebuggerEventHandlerGuid, IsBlocking: true);
                }
                else if (PythonDLLs.DebuggerHelperNames.Contains(moduleInstance.Name))
                {
                    moduleInstance.TryLoadSymbols();

                    // When the module is reported is loaded, it is not necessarily fully initialized yet - it is possible to get into a state
                    // where its import table is not processed yet. If we register TraceFunc and it gets called by Python when in that state,
                    // we'll get a crash as soon as any imported WinAPI function is called. So check whether DllMain has already run - if it
                    // is, we're good to go, and if not, set a breakpoint on a hook that will be called once it is run, and defer runtime
                    // creation until that breakpoint is hit.

                    bool isInitialized = moduleInstance.GetExportedStaticVariable <ByteProxy>("isInitialized").Read() != 0;
                    if (isInitialized)
                    {
                        OnHelperDllInitialized(moduleInstance);
                    }
                    else
                    {
                        DkmRuntimeBreakpoint initBP = null;
                        initBP = CreateRuntimeDllExportedFunctionBreakpoint(moduleInstance, "OnInitialized", (thread, frameBase, vFrame) => {
                            initBP.Close();
                            OnHelperDllInitialized(moduleInstance);
                        });
                        initBP.Enable();
                    }
                }
            }