Exemplo n.º 1
0
            public void getset_set(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string descrVar = useRegisters ? "((PyGetSetDescrObject*)@rcx)" : "descr";

                ulong set = cppEval.EvaluateUInt64(descrVar + "->d_getset->set");

                _owner.OnPotentialRuntimeExit(thread, set);
            }
Exemplo n.º 2
0
            public void PyType_GenericNew(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string typeVar = useRegisters ? "((PyTypeObject*)@rcx)" : "type";

                ulong tp_alloc = cppEval.EvaluateUInt64(typeVar + "->tp_alloc");

                _owner.OnPotentialRuntimeExit(thread, tp_alloc);
            }
Exemplo n.º 3
0
            public void builtin_next(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string argsVar = useRegisters ? "((PyTupleObject*)@rdx)" : "((PyTupleObject*)args)";

                ulong tp_iternext = cppEval.EvaluateUInt64(argsVar + "->ob_item[0]->ob_type->tp_iternext");

                _owner.OnPotentialRuntimeExit(thread, tp_iternext);
            }
Exemplo n.º 4
0
            public void PyCFunction_Call(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                ulong ml_meth = cppEval.EvaluateUInt64(
                    "((PyObject*){0})->ob_type == &PyCFunction_Type ? ((PyCFunctionObject*){0})->m_ml->ml_meth : 0",
                    useRegisters ? "@rcx" : "func");

                _owner.OnPotentialRuntimeExit(thread, ml_meth);
            }
Exemplo n.º 5
0
            public void PyObject_Str(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string vVar = useRegisters ? "((PyObject*)@rcx)" : "v";

                ulong tp_str = cppEval.EvaluateUInt64(vVar + "->ob_type->tp_str");

                _owner.OnPotentialRuntimeExit(thread, tp_str);
            }
            public void new_threadstate(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                // Addressing this local by name does not work for release builds, so read the return value directly from the register instead.
                var tstate = PyThreadState.TryCreate(process, cppEval.EvaluateReturnValueUInt64());

                if (tstate == null)
                {
                    return;
                }

                _owner.RegisterTracing(tstate);
            }
            public void do_richcompare(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string vVar = useRegisters ? "((PyObject*)@rcx)" : "v";
                string wVar = useRegisters ? "((PyObject*)@rdx)" : "w";

                ulong tp_richcompare1 = cppEval.EvaluateUInt64(vVar + "->ob_type->tp_richcompare");

                _owner.OnPotentialRuntimeExit(thread, tp_richcompare1);

                ulong tp_richcompare2 = cppEval.EvaluateUInt64(wVar + "->ob_type->tp_richcompare");

                _owner.OnPotentialRuntimeExit(thread, tp_richcompare2);
            }
            public void PyInterpreterState_New(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                var istate = PyInterpreterState.TryCreate(process, cppEval.EvaluateReturnValueUInt64());

                if (istate == null)
                {
                    return;
                }

                if (process.GetPythonRuntimeInfo().LanguageVersion >= PythonLanguageVersion.V36)
                {
                    _owner.RegisterJITTracing(istate);
                }
            }
            public void call_function(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                int oparg = cppEval.EvaluateInt32(useRegisters ? "@rdx" : "oparg");

                int na = oparg & 0xff;
                int nk = (oparg >> 8) & 0xff;
                int n  = na + 2 * nk;

                ulong func = cppEval.EvaluateUInt64(
                    "*((*(PyObject***){0}) - {1} - 1)",
                    useRegisters ? "@rcx" : "pp_stack",
                    n);
                var   obj     = PyObject.FromAddress(process, func);
                ulong ml_meth = cppEval.EvaluateUInt64(
                    "((PyObject*){0})->ob_type == &PyCFunction_Type ? ((PyCFunctionObject*){0})->m_ml->ml_meth : 0",
                    func);

                _owner.OnPotentialRuntimeExit(thread, ml_meth);
            }
Exemplo n.º 10
0
            public static void PyCode_NewEmpty(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress)
            {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                ulong filenamePtr = cppEval.EvaluateUInt64("filename");

                if (filenamePtr == 0)
                {
                    return;
                }

                string filename = new CStringProxy(process, filenamePtr).ReadUnicode();

                if (process.GetPythonRuntimeInstance().GetModuleInstances().Any(mi => mi.FullName == filename))
                {
                    return;
                }

                new RemoteComponent.CreateModuleRequest {
                    ModuleId = Guid.NewGuid(),
                    FileName = filename
                }.SendLower(process);
            }
Exemplo n.º 11
0
        /// <summary>
        /// Create a DkmEvaluationResult representing a Python object.
        /// </summary>
        /// <param name="cppEval">C++ evaluator to use to provide the [C++ view] node for this object.</param>
        /// <param name="cppTypeName">
        /// C++ struct name corresponding to this object type, for use by [C++ view] node. If not specified, it will be inferred from values of 
        /// various function pointers in <c>ob_type</c>, if possible. <c>PyObject</c> is the ultimate fallback.
        /// </param>
        public DkmEvaluationResult CreatePyObjectEvaluationResult(DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, string parentName, PythonEvaluationResult pyEvalResult, CppExpressionEvaluator cppEval, string cppTypeName = null, bool hasCppView = false, bool isOwned = false) {
            var name = pyEvalResult.Name;
            var valueStore = pyEvalResult.ValueStore as IValueStore<PyObject>;
            if (valueStore == null) {
                Debug.Fail("Non-PyObject PythonEvaluationResult passed to CreateEvaluationResult.");
                throw new ArgumentException();
            }

            var valueObj = valueStore.Read();
            string typeName = valueObj.ob_type.Read().tp_name.Read().ReadUnicode();

            var reprOptions = new ReprOptions(inspectionContext);
            string repr = valueObj.Repr(reprOptions);

            var flags = pyEvalResult.Flags;
            if (DebuggerOptions.ShowCppViewNodes || valueObj.GetDebugChildren(reprOptions).Any()) {
                flags |= DkmEvaluationResultFlags.Expandable;
            }
            if (!(valueStore is IWritableDataProxy)) {
                flags |= DkmEvaluationResultFlags.ReadOnly;
            }
            if (valueObj is IPyBaseStringObject) {
                flags |= DkmEvaluationResultFlags.RawString;
            }

            var boolObj = valueObj as IPyBoolObject;
            if (boolObj != null) {
                flags |= DkmEvaluationResultFlags.Boolean;
                if (boolObj.ToBoolean()) {
                    flags |= DkmEvaluationResultFlags.BooleanTrue;
                }
            }

            string fullName = name;
            if (parentName != null) {
                if (!fullName.StartsWith("[")) {
                    fullName = "." + fullName;
                }
                fullName = parentName + fullName;
            }

            var pyObjEvalResult = new PyObjectEvaluationResult(stackFrame.Process, fullName, valueStore, cppTypeName, hasCppView, isOwned);
            return DkmSuccessEvaluationResult.Create(
                inspectionContext, stackFrame, name, fullName, flags, repr, null, typeName, pyEvalResult.Category,
                pyEvalResult.AccessType, pyEvalResult.StorageType, pyEvalResult.TypeModifierFlags, null, null, null,
                pyObjEvalResult);
        }
Exemplo n.º 12
0
        public void GetFrameLocals(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmStackWalkFrame stackFrame, DkmCompletionRoutine<DkmGetFrameLocalsAsyncResult> completionRoutine) {
            var pythonFrame = PyFrameObject.TryCreate(stackFrame);
            if (pythonFrame == null) {
                Debug.Fail("Non-Python frame passed to GetFrameLocals.");
                throw new NotSupportedException();
            }

            var cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame);
            var evalResults = new List<DkmEvaluationResult>();

            var f_code = pythonFrame.f_code.Read();
            var f_localsplus = pythonFrame.f_localsplus;

            // Process cellvars and freevars first, because function arguments can appear in both cellvars and varnames if the argument is captured by a closure,
            // in which case we want to use the cellvar because the regular var slot will then be unused by Python (and in Python 3.4+, nulled out).
            var namesSeen = new HashSet<string>();
            var cellNames = f_code.co_cellvars.Read().ReadElements().Concat(f_code.co_freevars.Read().ReadElements());
            var cellSlots = f_localsplus.Skip(f_code.co_nlocals.Read());
            foreach (var pair in cellNames.Zip(cellSlots, (nameObj, cellSlot) => new { nameObj, cellSlot = cellSlot })) {
                var nameObj = pair.nameObj;
                var cellSlot = pair.cellSlot;

                var name = (nameObj.Read() as IPyBaseStringObject).ToStringOrNull();
                if (name == null) {
                    continue;
                }
                namesSeen.Add(name);

                if (cellSlot.IsNull) {
                    continue;
                }

                var cell = cellSlot.Read() as PyCellObject;
                if (cell == null) {
                    continue;
                }

                var localPtr = cell.ob_ref;
                if (localPtr.IsNull) {
                    continue;
                }

                var evalResult = CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, new PythonEvaluationResult(localPtr, name), cppEval);
                evalResults.Add(evalResult);
            }

            PyTupleObject co_varnames = f_code.co_varnames.Read();
            foreach (var pair in co_varnames.ReadElements().Zip(f_localsplus, (nameObj, varSlot) => new { nameObj, cellSlot = varSlot })) {
                var nameObj = pair.nameObj;
                var varSlot = pair.cellSlot;

                var name = (nameObj.Read() as IPyBaseStringObject).ToStringOrNull();
                if (name == null) {
                    continue;
                }

                // Check for function argument that was promoted to a cell.
                if (!namesSeen.Add(name)) {
                    continue;
                }

                if (varSlot.IsNull) {
                    continue;
                }

                var evalResult = CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, new PythonEvaluationResult(varSlot, name), cppEval);
                evalResults.Add(evalResult);
            }

            var globals = pythonFrame.f_globals.TryRead();
            if (globals != null) {
                var globalsEvalResult = new GlobalsEvaluationResult { Globals = globals };
                DkmEvaluationResult evalResult = DkmSuccessEvaluationResult.Create(
                    inspectionContext, stackFrame, "[Globals]", null,
                    DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Expandable,
                    null, null, null,
                    DkmEvaluationResultCategory.Property,
                    DkmEvaluationResultAccessType.None,
                    DkmEvaluationResultStorageType.None,
                    DkmEvaluationResultTypeModifierFlags.None,
                    null, null, null, globalsEvalResult);

                // If it is a top-level module frame, show globals inline; otherwise, show them under the [Globals] node.
                if (f_code.co_name.Read().ToStringOrNull() == "<module>") {
                    evalResults.AddRange(globalsEvalResult.GetChildren(this, evalResult, inspectionContext));
                } else {
                    evalResults.Add(evalResult);

                    // Show any globals that are directly referenced by the function inline even in local frames.
                    var globalVars = (from pair in globals.ReadElements()
                                      let nameObj = pair.Key as IPyBaseStringObject
                                      where nameObj != null
                                      select new { Name = nameObj.ToString(), Value = pair.Value }
                                     ).ToLookup(v => v.Name, v => v.Value);

                    PyTupleObject co_names = f_code.co_names.Read();
                    foreach (var nameObj in co_names.ReadElements()) {
                        var name = (nameObj.Read() as IPyBaseStringObject).ToStringOrNull();
                        if (name == null) {
                            continue;
                        }

                        // If this is a used name but it was not in varnames or freevars, it is a directly referenced global.
                        if (!namesSeen.Add(name)) {
                            continue;
                        }

                        var varSlot = globalVars[name].FirstOrDefault();
                        if (varSlot.Process != null) {
                            evalResult = CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, new PythonEvaluationResult(varSlot, name), cppEval);
                            evalResults.Add(evalResult);
                        }
                    }
                }
            }

            var enumContext = DkmEvaluationResultEnumContext.Create(evalResults.Count, stackFrame, inspectionContext,
                new EvaluationResults { Results = evalResults.OrderBy(er => er.Name) });
            completionRoutine(new DkmGetFrameLocalsAsyncResult(enumContext));
        }
Exemplo n.º 13
0
            public List<DkmEvaluationResult> GetChildren(ExpressionEvaluator exprEval, DkmEvaluationResult result, DkmInspectionContext inspectionContext) {
                var stackFrame = result.StackFrame;
                var cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame);
                var obj = ValueStore.Read();
                var evalResults = new List<DkmEvaluationResult>();
                var reprOptions = new ReprOptions(inspectionContext);
                var reprBuilder = new ReprBuilder(reprOptions);

                if (DebuggerOptions.ShowCppViewNodes && !HasCppView) {
                    if (CppTypeName == null) {
                        // Try to guess the object's C++ type by looking at function pointers in its PyTypeObject. If they are pointing
                        // into a module for which symbols are available, C++ EE should be able to resolve them into something like
                        // "0x1e120d50 {python33_d.dll!list_dealloc(PyListObject *)}". If we are lucky, one of those functions will have
                        // the first argument declared as a strongly typed pointer, rather than PyObject* or void*.
                        CppTypeName = "PyObject";
                        CppTypeModuleName = null;
                        foreach (string methodField in _methodFields) {
                            var funcPtrEvalResult = cppEval.TryEvaluateObject(null, "PyObject", obj.Address, ".ob_type->" + methodField) as DkmSuccessEvaluationResult;
                            if (funcPtrEvalResult == null || funcPtrEvalResult.Value.IndexOf('{') < 0) {
                                continue;
                            }

                            var match = _cppFirstArgTypeFromFuncPtrRegex.Match(funcPtrEvalResult.Value);
                            string module = match.Groups["module"].Value;
                            string firstArgType = match.Groups["type"].Value;
                            if (firstArgType != "void" && firstArgType != "PyObject" && firstArgType != "_object") {
                                CppTypeName = firstArgType;
                                CppTypeModuleName = module;
                                break;
                            }
                        }
                    }

                    string cppExpr = CppExpressionEvaluator.GetExpressionForObject(CppTypeModuleName, CppTypeName, obj.Address, ",!");
                    var evalResult = DkmIntermediateEvaluationResult.Create(
                        inspectionContext, stackFrame, "[C++ view]", "{C++}" + cppExpr, cppExpr,
                        CppExpressionEvaluator.CppLanguage, stackFrame.Process.GetNativeRuntimeInstance(), null);
                    evalResults.Add(evalResult);
                }

                int i = 0;
                foreach (var child in obj.GetDebugChildren(reprOptions).Take(MaxDebugChildren)) {
                    if (child.Name == null) {
                        reprBuilder.Clear();
                        reprBuilder.AppendFormat("[{0:PY}]", i++);
                        child.Name = reprBuilder.ToString();
                    }

                    DkmEvaluationResult evalResult;
                    if (child.ValueStore is IValueStore<PyObject>) {
                        evalResult = exprEval.CreatePyObjectEvaluationResult(inspectionContext, stackFrame, FullName, child, cppEval);
                    } else {
                        var value = child.ValueStore.Read();
                        reprBuilder.Clear();
                        reprBuilder.AppendLiteral(value);

                        string type = null;
                        if (Process.GetPythonRuntimeInfo().LanguageVersion <= PythonLanguageVersion.V27) {
                            _typeMapping2x.TryGetValue(value.GetType(), out type);
                        }
                        if (type == null) {
                            _typeMapping.TryGetValue(value.GetType(), out type);
                        }

                        var flags = DkmEvaluationResultFlags.ReadOnly;
                        if (value is string) {
                            flags |= DkmEvaluationResultFlags.RawString;
                        }

                        string childFullName = child.Name;
                        if (FullName != null) {
                            if (childFullName.EndsWith("()")) { // len()
                                childFullName = childFullName.Substring(0, childFullName.Length - 2) + "(" + FullName + ")";
                            } else {
                                if (!childFullName.StartsWith("[")) { // [0], ['fob'] etc
                                    childFullName = "." + childFullName;
                                }
                                childFullName = FullName + childFullName;
                            }
                        }

                        evalResult = DkmSuccessEvaluationResult.Create(
                            inspectionContext, stackFrame, child.Name, childFullName, flags, reprBuilder.ToString(), null, type,
                            child.Category, child.AccessType, child.StorageType, child.TypeModifierFlags, null, null, null,
                            new RawEvaluationResult { Value = value });
                    }

                    evalResults.Add(evalResult);
                }

                return evalResults;
            }
Exemplo n.º 14
0
            public List<DkmEvaluationResult> GetChildren(ExpressionEvaluator exprEval, DkmEvaluationResult result, DkmInspectionContext inspectionContext) {
                var stackFrame = result.StackFrame;
                var cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame);
                var evalResults = new List<DkmEvaluationResult>();

                foreach (var pair in Globals.ReadElements()) {
                    var name = pair.Key as IPyBaseStringObject;
                    if (name == null) {
                        continue;
                    }

                    var evalResult = exprEval.CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, new PythonEvaluationResult(pair.Value, name.ToString()), cppEval);
                    evalResults.Add(evalResult);
                }

                return evalResults.OrderBy(er => er.Name).ToList();
            }
Exemplo n.º 15
0
 // This step-in gate is not marked [StepInGate] because it doesn't live in pythonXX.dll, and so we register it manually.
 public void _call_function_pointer(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
     var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);
     ulong pProc = cppEval.EvaluateUInt64(useRegisters ? "@rdx" : "pProc");
     _owner.OnPotentialRuntimeExit(thread, pProc);
 }
Exemplo n.º 16
0
            public void builtin_next(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string argsVar = useRegisters ? "((PyTupleObject*)@rdx)" : "((PyTupleObject*)args)";

                ulong tp_iternext = cppEval.EvaluateUInt64(argsVar + "->ob_item[0]->ob_type->tp_iternext");
                _owner.OnPotentialRuntimeExit(thread, tp_iternext);
            }
Exemplo n.º 17
0
            public void PyObject_Call(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string funcVar = useRegisters ? "((PyObject*)@rcx)" : "func";

                ulong tp_call = cppEval.EvaluateUInt64(funcVar + "->ob_type->tp_call");
                _owner.OnPotentialRuntimeExit(thread, tp_call);
            }
Exemplo n.º 18
0
            public static void PyCode_New(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                var filenamePtr = cppEval.EvaluateUInt64("filename");
                var filenameObj = PyObject.FromAddress(process, filenamePtr) as IPyBaseStringObject;
                if (filenameObj == null) {
                    return;
                }

                string filename = filenameObj.ToString();
                if (process.GetPythonRuntimeInstance().GetModuleInstances().Any(mi => mi.FullName == filename)) {
                    return;
                }

                new RemoteComponent.CreateModuleRequest {
                    ModuleId = Guid.NewGuid(),
                    FileName = filename
                }.SendLower(process);
            }
Exemplo n.º 19
0
        private DkmEvaluationResult GetPythonView(DkmVisualizedExpression visualizedExpression) {
            var stackFrame = visualizedExpression.StackFrame;
            var process = stackFrame.Process;
            var pythonRuntime = process.GetPythonRuntimeInstance();
            if (pythonRuntime == null) {
                return null;
            }

            var home = visualizedExpression.ValueHome as DkmPointerValueHome;
            if (home == null) {
                Debug.Fail("PythonViewNativeVisualizer given a visualized expression that has a non-DkmPointerValueHome home.");
                return null;
            } else if (home.Address == 0) {
                return null;
            }

            var exprEval = process.GetDataItem<ExpressionEvaluator>();
            if (exprEval == null) {
                Debug.Fail("PythonViewNativeVisualizer failed to obtain an instance of ExpressionEvaluator.");
                return null;
            }

            string cppTypeName = null;
            var childExpr = visualizedExpression as DkmChildVisualizedExpression;
            if (childExpr != null) {
                var evalResult = childExpr.EvaluationResult as DkmSuccessEvaluationResult;
                cppTypeName = evalResult.Type;
            } else {
                object punkTypeSymbol;
                visualizedExpression.GetSymbolInterface(typeof(IDiaSymbol).GUID, out punkTypeSymbol);
                using (ComPtr.Create(punkTypeSymbol)) {
                    var typeSymbol = punkTypeSymbol as IDiaSymbol;
                    if (typeSymbol != null) {
                        cppTypeName = typeSymbol.name;
                    }
                }
            }

            PyObject objRef;
            try {
                objRef = PyObject.FromAddress(process, home.Address);
            } catch {
                return null;
            }

            var pyEvalResult = new PythonEvaluationResult(objRef, "[Python view]")
            {
                Category = DkmEvaluationResultCategory.Property,
                AccessType = DkmEvaluationResultAccessType.Private
            };

            var inspectionContext = visualizedExpression.InspectionContext;
            CppExpressionEvaluator cppEval;
            try {
                cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame);
            } catch {
                return null;
            }

            var pythonContext = DkmInspectionContext.Create(visualizedExpression.InspectionSession, pythonRuntime, stackFrame.Thread,
                inspectionContext.Timeout, inspectionContext.EvaluationFlags, inspectionContext.FuncEvalFlags, inspectionContext.Radix,
                DkmLanguage.Create("Python", new DkmCompilerId(Guids.MicrosoftVendorGuid, Guids.PythonLanguageGuid)), null);
            try {
                return exprEval.CreatePyObjectEvaluationResult(pythonContext, stackFrame, null, pyEvalResult, cppEval, cppTypeName, hasCppView: true);
            } catch {
                return null;
            }
        }
Exemplo n.º 20
0
            public void PyObject_SetAttr(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string vVar = useRegisters ? "((PyObject*)@rcx)" : "v";

                ulong tp_setattr = cppEval.EvaluateUInt64(vVar + "->ob_type->tp_setattr");
                _owner.OnPotentialRuntimeExit(thread, tp_setattr);

                ulong tp_setattro = cppEval.EvaluateUInt64(vVar + "->ob_type->tp_setattro");
                _owner.OnPotentialRuntimeExit(thread, tp_setattro);
            }
Exemplo n.º 21
0
        private DkmEvaluationResult GetPythonView(DkmVisualizedExpression visualizedExpression)
        {
            var stackFrame    = visualizedExpression.StackFrame;
            var process       = stackFrame.Process;
            var pythonRuntime = process.GetPythonRuntimeInstance();

            if (pythonRuntime == null)
            {
                return(null);
            }

            var home = visualizedExpression.ValueHome as DkmPointerValueHome;

            if (home == null)
            {
                Debug.Fail("PythonViewNativeVisualizer given a visualized expression that has a non-DkmPointerValueHome home.");
                return(null);
            }
            else if (home.Address == 0)
            {
                return(null);
            }

            var exprEval = process.GetDataItem <ExpressionEvaluator>();

            if (exprEval == null)
            {
                Debug.Fail("PythonViewNativeVisualizer failed to obtain an instance of ExpressionEvaluator.");
                return(null);
            }

            string cppTypeName = null;
            var    childExpr   = visualizedExpression as DkmChildVisualizedExpression;

            if (childExpr != null)
            {
                var evalResult = childExpr.EvaluationResult as DkmSuccessEvaluationResult;
                cppTypeName = evalResult.Type;
            }
            else
            {
                object punkTypeSymbol;
                visualizedExpression.GetSymbolInterface(typeof(IDiaSymbol).GUID, out punkTypeSymbol);
                using (ComPtr.Create(punkTypeSymbol)) {
                    var typeSymbol = punkTypeSymbol as IDiaSymbol;
                    if (typeSymbol != null)
                    {
                        cppTypeName = typeSymbol.name;
                    }
                }
            }

            PyObject objRef;

            try {
                objRef = PyObject.FromAddress(process, home.Address);
            } catch {
                return(null);
            }

            // TODO: Localization - [Python view] also appears in .natvis file, leave as-is for now
            var pyEvalResult = new PythonEvaluationResult(objRef, "[Python view]")
            {
                Category   = DkmEvaluationResultCategory.Property,
                AccessType = DkmEvaluationResultAccessType.Private
            };

            var inspectionContext = visualizedExpression.InspectionContext;
            CppExpressionEvaluator cppEval;

            try {
                cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame);
            } catch {
                return(null);
            }

            var pythonContext = DkmInspectionContext.Create(visualizedExpression.InspectionSession, pythonRuntime, stackFrame.Thread,
                                                            inspectionContext.Timeout, inspectionContext.EvaluationFlags, inspectionContext.FuncEvalFlags, inspectionContext.Radix,
                                                            DkmLanguage.Create("Python", new DkmCompilerId(Guids.MicrosoftVendorGuid, Guids.PythonLanguageGuid)), null);

            try {
                return(exprEval.CreatePyObjectEvaluationResult(pythonContext, stackFrame, null, pyEvalResult, cppEval, cppTypeName, hasCppView: true));
            } catch {
                return(null);
            }
        }
Exemplo n.º 22
0
            public void PyCFunction_Call(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                ulong ml_meth = cppEval.EvaluateUInt64(
                    "((PyObject*){0})->ob_type == &PyCFunction_Type ? ((PyCFunctionObject*){0})->m_ml->ml_meth : 0",
                    useRegisters ? "@rcx" : "func");
                _owner.OnPotentialRuntimeExit(thread, ml_meth);
            }
Exemplo n.º 23
0
            public void call_function(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                int oparg = cppEval.EvaluateInt32(useRegisters ? "@rdx" : "oparg");

                int na = oparg & 0xff;
                int nk = (oparg >> 8) & 0xff;
                int n = na + 2 * nk;

                ulong func = cppEval.EvaluateUInt64(
                    "*((*(PyObject***){0}) - {1} - 1)",
                    useRegisters ? "@rcx" : "pp_stack",
                    n);
                var obj = PyObject.FromAddress(process, func);
                ulong ml_meth = cppEval.EvaluateUInt64(
                    "((PyObject*){0})->ob_type == &PyCFunction_Type ? ((PyCFunctionObject*){0})->m_ml->ml_meth : 0",
                    func);

                _owner.OnPotentialRuntimeExit(thread, ml_meth);
            }
Exemplo n.º 24
0
        private void EvaluateExpressionViaInterpreter(DkmInspectionContext inspectionContext, DkmWorkList workList, DkmLanguageExpression expression, DkmStackWalkFrame stackFrame, DkmCompletionRoutine<DkmEvaluateExpressionAsyncResult> completionRoutine) {
            var thread = stackFrame.Thread;
            var process = thread.Process;

            if (_evalLoopThreadId.Read() != (ulong)thread.SystemPart.Id) {
                completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create(
                    inspectionContext, stackFrame, expression.Text, expression.Text,
                    "Arbitrary Python expressions can only be evaluated on a thread which is stopped in Python code at a breakpoint or " +
                    "after a step-in or a step-over operation. Only expressions involving global and local variables, object field access, " +
                    "and indexing of built-in collection types with literals can be evaluated in the current context.",
                    DkmEvaluationResultFlags.Invalid, null)));
                return;
            }

            var pythonFrame = PyFrameObject.TryCreate(stackFrame);
            if (pythonFrame == null) {
                completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create(
                    inspectionContext, stackFrame, expression.Text, expression.Text, "Could not obtain a Python frame object for the current frame.",
                    DkmEvaluationResultFlags.Invalid, null)));
                return;
            }

            byte[] input = Encoding.UTF8.GetBytes(expression.Text + "\0");
            if (input.Length > ExpressionEvaluationBufferSize) {
                completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create(
                    inspectionContext, stackFrame, expression.Text, expression.Text, "Expression is too long.",
                    DkmEvaluationResultFlags.Invalid, null)));
                return;
            }

            _evalLoopFrame.Write(pythonFrame.Address);
            process.WriteMemory(_evalLoopInput.Address, input);

            bool timedOut;
            using (_evalCompleteEvent = new AutoResetEvent(false)) {
                thread.BeginFuncEvalExecution(DkmFuncEvalFlags.None);
                timedOut = !_evalCompleteEvent.WaitOne(ExpressionEvaluationTimeout);
                _evalCompleteEvent = null;
            }

            if (timedOut) {
                new RemoteComponent.AbortingEvalExecutionRequest().SendLower(process);

                // We need to stop the process before we can report end of func eval completion
                using (_evalAbortedEvent = new AutoResetEvent(false)) {
                    process.AsyncBreak(false);

                    if (!_evalAbortedEvent.WaitOne(20000)) {
                        // This is a catastrophic error, since we can't report func eval completion unless we can stop the process,
                        // and VS will hang until we do report completion. At this point we can only kill the debuggee so that the
                        // VS at least gets back to a reasonable state.
                        _evalAbortedEvent = null;
                        process.Terminate(1);

                        completionRoutine(DkmEvaluateExpressionAsyncResult.CreateErrorResult(new Exception("Couldn't abort a failed expression evaluation.")));
                        return;
                    }

                    _evalAbortedEvent = null;
                }

                completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create(
                    inspectionContext, stackFrame, expression.Text, expression.Text, "Evaluation timed out.",
                    DkmEvaluationResultFlags.Invalid, null)));
                return;
            }

            ulong objPtr = _evalLoopResult.Read();
            var obj = PyObject.FromAddress(process, objPtr);
            var exc_type = PyObject.FromAddress(process, _evalLoopExcType.Read());
            var exc_value = PyObject.FromAddress(process, _evalLoopExcValue.Read());
            var exc_str = (PyObject.FromAddress(process, _evalLoopExcStr.Read()) as IPyBaseStringObject).ToStringOrNull();
            var sehCode = _evalLoopSEHCode.Read();

            if (obj != null) {
                var cppEval = new CppExpressionEvaluator(inspectionContext, stackFrame);
                var pyEvalResult =  new PythonEvaluationResult(obj, expression.Text) { Flags = DkmEvaluationResultFlags.SideEffect };
                var evalResult = CreatePyObjectEvaluationResult(inspectionContext, stackFrame, null, pyEvalResult, cppEval, null, hasCppView: true, isOwned: true);
                _evalLoopResult.Write(0); // don't let the eval loop decref the object - we will do it ourselves later, when eval result is closed
                completionRoutine(new DkmEvaluateExpressionAsyncResult(evalResult));
            } else if (sehCode != 0) {
                string errorText = string.Format("Structured exception {0:x08} ", sehCode);
                if (Enum.IsDefined(typeof(EXCEPTION_CODE), sehCode)) {
                    errorText += "(" + (EXCEPTION_CODE)sehCode + ") ";
                }
                errorText += "raised while evaluating expression";
                completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create(
                    inspectionContext, stackFrame, expression.Text, expression.Text, errorText,
                    DkmEvaluationResultFlags.Invalid, null)));
            } else if (exc_type != null) {
                string typeName;
                var typeObject = exc_type as PyTypeObject;
                if (typeObject != null) {
                    typeName = typeObject.tp_name.Read().ReadUnicode();
                } else {
                    typeName = "<unknown exception type>";
                }

                completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create(
                    inspectionContext, stackFrame, expression.Text, expression.Text, typeName + " raised while evaluating expression: " + exc_str,
                    DkmEvaluationResultFlags.Invalid, null)));
            } else {
                completionRoutine(new DkmEvaluateExpressionAsyncResult(DkmFailedEvaluationResult.Create(
                    inspectionContext, stackFrame, expression.Text, expression.Text, "Unknown error occurred while evaluating expression.",
                    DkmEvaluationResultFlags.Invalid, null)));
            }
        }
Exemplo n.º 25
0
            public void do_richcompare(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string vVar = useRegisters ? "((PyObject*)@rcx)" : "v";
                string wVar = useRegisters ? "((PyObject*)@rdx)" : "w";

                ulong tp_richcompare1 = cppEval.EvaluateUInt64(vVar + "->ob_type->tp_richcompare");
                _owner.OnPotentialRuntimeExit(thread, tp_richcompare1);

                ulong tp_richcompare2 = cppEval.EvaluateUInt64(wVar + "->ob_type->tp_richcompare");
                _owner.OnPotentialRuntimeExit(thread, tp_richcompare2);
            }
Exemplo n.º 26
0
            public static void PyCode_NewEmpty(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                ulong filenamePtr = cppEval.EvaluateUInt64("filename");
                if (filenamePtr == 0) {
                    return;
                }

                string filename = new CStringProxy(process, filenamePtr).ReadUnicode();
                if (process.GetPythonRuntimeInstance().GetModuleInstances().Any(mi => mi.FullName == filename)) {
                    return;
                }

                new RemoteComponent.CreateModuleRequest {
                    ModuleId = Guid.NewGuid(),
                    FileName = filename
                }.SendLower(process);
            }
Exemplo n.º 27
0
            public void PyIter_Next(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string iterVar = useRegisters ? "((PyObject*)@rcx)" : "iter";

                ulong tp_iternext = cppEval.EvaluateUInt64(iterVar + "->ob_type->tp_iternext");
                _owner.OnPotentialRuntimeExit(thread, tp_iternext);
            }
Exemplo n.º 28
0
            public void getset_set(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string descrVar = useRegisters ? "((PyGetSetDescrObject*)@rcx)" : "descr";

                ulong set = cppEval.EvaluateUInt64(descrVar + "->d_getset->set");
                _owner.OnPotentialRuntimeExit(thread, set);
            }
Exemplo n.º 29
0
            public void new_threadstate(DkmThread thread, ulong frameBase, ulong vframe) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                // Addressing this local by name does not work for release builds, so read the return value directly from the register instead.
                var tstate = new PyThreadState(thread.Process, cppEval.EvaluateReturnValueUInt64());
                if (tstate == null) {
                    return;
                }

                _owner.RegisterTracing(tstate);
            }
Exemplo n.º 30
0
            public void PyType_GenericNew(DkmThread thread, ulong frameBase, ulong vframe, bool useRegisters) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                string typeVar = useRegisters ? "((PyTypeObject*)@rcx)" : "type";

                ulong tp_alloc = cppEval.EvaluateUInt64(typeVar + "->tp_alloc");
                _owner.OnPotentialRuntimeExit(thread, tp_alloc);
            }
Exemplo n.º 31
0
            public void PyInterpreterState_New(DkmThread thread, ulong frameBase, ulong vframe, ulong returnAddress) {
                var process = thread.Process;
                var cppEval = new CppExpressionEvaluator(thread, frameBase, vframe);

                var istate = PyInterpreterState.TryCreate(process, cppEval.EvaluateReturnValueUInt64());
                if (istate == null) {
                    return;
                }

                if (process.GetPythonRuntimeInfo().LanguageVersion >= PythonLanguageVersion.V36) {
                    _owner.RegisterJITTracing(istate);
                }
            }