public object[] GetAllArgumentValues(DkmStackWalkFrame frame)
 {
     object[] arguments = new object[_parameters.Count];
       for (int i = 0; i < _parameters.Count; ++i)
     arguments[i] = GetArgumentValue(frame, i);
       return arguments;
 }
    public override object GetArgumentValue(DkmStackWalkFrame frame, int index) {
      ulong esp = (uint)frame.Registers.GetStackPointer();
      uint esp2 = frame.VscxGetRegisterValue32(CpuRegister.Esp);
      uint ebp = frame.VscxGetRegisterValue32(CpuRegister.Ebp);
      ulong frameBase = (uint)frame.FrameBase;

      int stackOffset = 0;
      for (int i = 0; i < index; ++i)
        stackOffset += _parameters[i].GetPaddedSize(WordSize);

      // The return address (4 bytes) is at the top of the stack, so offset by 4 to skip the return
      // address.
      ulong stackAddress = esp + 4 + (ulong)stackOffset;
      int paramSize = _parameters[index].GetSize(WordSize);
      byte[] parameter = new byte[paramSize];

      frame.Process.ReadMemory(stackAddress, DkmReadMemoryFlags.None, parameter);
      switch (paramSize) {
        case 4:
          return BitConverter.ToUInt32(parameter, 0);
        case 8:
          return BitConverter.ToUInt64(parameter, 0);
        default:
          return parameter;
      }
    }
Example #3
0
        public static unsafe PyFrameObject TryCreate(DkmStackWalkFrame frame) {
            var process = frame.Process;

            if (frame.InstructionAddress == null) {
                return null;
            } 
            if (frame.RuntimeInstance.Id.RuntimeType != Guids.PythonRuntimeTypeGuid && !IsInEvalFrame(frame)) {
                return null;
            }

            var cppLanguage = DkmLanguage.Create("C++", new DkmCompilerId(Guids.MicrosoftVendorGuid, Guids.CppLanguageGuid));
            var inspectionSession = DkmInspectionSession.Create(process, null);
            var inspectionContext = DkmInspectionContext.Create(inspectionSession, process.GetNativeRuntimeInstance(), frame.Thread, 0,
                DkmEvaluationFlags.TreatAsExpression | DkmEvaluationFlags.NoSideEffects, DkmFuncEvalFlags.None, 10, cppLanguage, null);

            CppExpressionEvaluator cppEval;
            try {
                cppEval = new CppExpressionEvaluator(inspectionContext, frame);
            } catch (ArgumentException) {
                Debug.Fail("Failed to create C++ expression evaluator while obtaining PyFrameObject from a native frame.");
                return null;
            }

            ulong framePtr;
            try {
                framePtr = cppEval.EvaluateUInt64("f");
            } catch (CppEvaluationException) {
                Debug.Fail("Failed to evaluate the 'f' parameter to PyEval_EvalFrameEx while obtaining PyFrameObject from a native frame.");
                return null;
            }

            return new PyFrameObject(frame.Process, framePtr);
        }
 private DkmSuccessEvaluationResult(
     DkmInspectionContext inspectionContext,
     DkmStackWalkFrame stackFrame,
     string name,
     string fullName,
     DkmEvaluationResultFlags flags,
     string value,
     string editableValue,
     string type,
     DkmEvaluationResultCategory category,
     DkmEvaluationResultAccessType access,
     DkmEvaluationResultStorageType storageType,
     DkmEvaluationResultTypeModifierFlags typeModifierFlags,
     DkmDataAddress address,
     ReadOnlyCollection<DkmCustomUIVisualizerInfo> customUIVisualizers,
     ReadOnlyCollection<DkmModuleInstance> externalModules,
     DkmDataItem dataItem) :
     base(inspectionContext, stackFrame, name, fullName, flags, type, dataItem)
 {
     this.Value = value;
     this.EditableValue = editableValue;
     this.Category = category;
     this.Access = access;
     this.StorageType = storageType;
     this.TypeModifierFlags = typeModifierFlags;
     this.CustomUIVisualizers = customUIVisualizers;
 }
Example #5
0
 public object GetArgumentValue(DkmStackWalkFrame frame, string name) {
   for (int i = 0; i < _parameters.Count; ++i) {
     if (_parameters[i].Name.Equals(name))
       return GetArgumentValue(frame, i);
   }
   return null;
 }
        private static string TryGetFrameReturnTypeHelper(DkmInspectionContext inspectionContext, DkmStackWalkFrame frame)
        {
            ImportedMethod currentMethod = TryGetCurrentMethod(inspectionContext, frame);
            if (currentMethod == null)
                return null;

            return currentMethod.ReturnType.ToString();
        }
 /// <summary>
 /// This method is called by the debug engine to get the text representation of the return
 /// value of a stack frame.
 /// </summary>
 /// <param name="inspectionContext">Context of the evaluation.  This contains options/flags
 /// to be used during compilation. It also contains the InspectionSession.  The inspection
 /// session is the object that provides lifetime management for our objects.  When the user
 /// steps or continues the process, the debug engine will dispose of the inspection session</param>
 /// <param name="workList">The current work list.  This is used to batch asynchronous
 /// work items.  If any asynchronous calls are needed later, this is the work list to pass
 /// to the asynchronous call.  It's not needed in our case.</param>
 /// <param name="frame">The frame to get the text representation of the return value for</param>
 /// <param name="completionRoutine">Completion routine to call when work is completed</param>
 void IDkmLanguageFrameDecoder.GetFrameReturnType(
     DkmInspectionContext inspectionContext,
     DkmWorkList workList,
     DkmStackWalkFrame frame,
     DkmCompletionRoutine<DkmGetFrameReturnTypeAsyncResult> completionRoutine)
 {
     string name = TryGetFrameReturnTypeHelper(inspectionContext, frame) ?? "<Unknown>";
     completionRoutine(new DkmGetFrameReturnTypeAsyncResult(name));
 }
 public static DkmEvaluationResultEnumContext Create(int Count, DkmStackWalkFrame StackFrame, DkmInspectionContext InspectionContext, DkmDataItem DataItem)
 {
     var enumContext = new DkmEvaluationResultEnumContext(Count, InspectionContext);
     if (DataItem != null)
     {
         enumContext.SetDataItem(DkmDataCreationDisposition.CreateNew, DataItem);
     }
     return enumContext;
 }
 /// <summary>
 /// This method is called by the debug engine to get the text representation of a stack
 /// frame.
 /// </summary>
 /// <param name="inspectionContext">Context of the evaluation.  This contains options/flags
 /// to be used during compilation. It also contains the InspectionSession.  The inspection
 /// session is the object that provides lifetime management for our objects.  When the user
 /// steps or continues the process, the debug engine will dispose of the inspection session</param>
 /// <param name="workList">The current work list.  This is used to batch asynchronous
 /// work items.  If any asynchronous calls are needed later, this is the work list to pass
 /// to the asynchronous call.  It's not needed in our case.</param>
 /// <param name="frame">The frame to get the text representation for</param>
 /// <param name="argumentFlags">Option flags to change the way we format frames</param>
 /// <param name="completionRoutine">Completion routine to call when work is completed</param>
 void IDkmLanguageFrameDecoder.GetFrameName(
     DkmInspectionContext inspectionContext,
     DkmWorkList workList,
     DkmStackWalkFrame frame,
     DkmVariableInfoFlags argumentFlags,
     DkmCompletionRoutine<DkmGetFrameNameAsyncResult> completionRoutine)
 {
     string name = TryGetFrameNameHelper(inspectionContext, frame, argumentFlags) ?? "<Unknown Method>";
     completionRoutine(new DkmGetFrameNameAsyncResult(name));
 }
		private static DkmInspectionContext CreateInspectionContext(DkmStackContext stackContext, DkmStackWalkFrame frame)
		{
			return DkmInspectionContext.Create(
				stackContext.InspectionSession,
				frame.RuntimeInstance,
				frame.Thread,
				1000,
				DkmEvaluationFlags.None,
				DkmFuncEvalFlags.None,
				10,
				CppLanguage,
				null);
		}
Example #11
0
        public CppExpressionEvaluator(DkmThread thread, ulong frameBase, ulong vframe) {
            _process = thread.Process;

            var inspectionSession = DkmInspectionSession.Create(_process, null);
            _cppInspectionContext = DkmInspectionContext.Create(inspectionSession, _process.GetNativeRuntimeInstance(), thread, Timeout,
                DkmEvaluationFlags.TreatAsExpression | DkmEvaluationFlags.NoSideEffects, DkmFuncEvalFlags.None, 10, CppLanguage, null);

            const int CV_ALLREG_VFRAME = 0x00007536;
            var vframeReg = DkmUnwoundRegister.Create(CV_ALLREG_VFRAME, new ReadOnlyCollection<byte>(BitConverter.GetBytes(vframe)));
            var regs = thread.GetCurrentRegisters(new[] { vframeReg });
            var iaddr = _process.CreateNativeInstructionAddress(regs.GetInstructionPointer());
            _nativeFrame = DkmStackWalkFrame.Create(thread, iaddr, frameBase, 0, DkmStackWalkFrameFlags.None, null, regs, null);
        }
 private DkmFailedEvaluationResult(
     DkmInspectionContext inspectionContext,
     DkmStackWalkFrame stackFrame,
     string name,
     string fullName,
     string errorMessage,
     DkmEvaluationResultFlags flags,
     string type,
     DkmDataItem dataItem) :
     base(inspectionContext, stackFrame, name, fullName, flags, type, dataItem)
 {
     this.ErrorMessage = errorMessage;
 }
        private static string TryGetFrameNameHelper(DkmInspectionContext inspectionContext, DkmStackWalkFrame frame, DkmVariableInfoFlags argumentFlags)
        {
            ImportedMethod currentMethod = TryGetCurrentMethod(inspectionContext, frame);
            if (currentMethod == null)
                return null;

            string name = currentMethod.Name;
            if (string.Equals(name, "$.main", StringComparison.Ordinal))
                return "<Main Block>";

            if (argumentFlags == DkmVariableInfoFlags.None)
                return name;

            Variable[] args = currentMethod.GetParameters();
            if (args.Length == 0)
                return name;

            StringBuilder nameBuilder = new StringBuilder();
            nameBuilder.Append(name);
            nameBuilder.Append('(');

            bool first = true;
            bool showTypes = argumentFlags.HasFlag(DkmVariableInfoFlags.Types);
            bool showNames = argumentFlags.HasFlag(DkmVariableInfoFlags.Names);
            foreach (Variable arg in args)
            {
                if (first)
                    first = false;
                else
                    nameBuilder.Append("; ");

                IrisType argType = arg.Type;
                if (argType.IsByRef)
                {
                    nameBuilder.Append("var ");
                    argType = argType.GetElementType();
                }

                if (showNames)
                    nameBuilder.Append(arg.Name);

                if (showNames && showTypes)
                    nameBuilder.Append(" : ");

                if (showTypes)
                    nameBuilder.Append(argType);
            }

            nameBuilder.Append(')');
            return nameBuilder.ToString();
        }
		public DkmStackWalkFrame[] FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input)
		{
			if (input == null) // after last frame
				return null;

			if (input.InstructionAddress == null) // error case
				return new[] { input };

			if (input.InstructionAddress.ModuleInstance != null) // code in existing module
				return new[] { input };

			var runner = new PmipRunner(stackContext, input);
			return new[] { runner.PmipStackFrame() };
		}
        DkmStackWalkFrame[] IDkmCallStackFilter.FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input)
        {
            // The HelloWorld sample is a very simple debugger component which modified the call stack
            // so that there is a '[Hello World]' frame at the top of the call stack. All the frames
            // below this are left the same.

            if (input == null) // null input frame indicates the end of the call stack. This sample does nothing on end-of-stack.
                return null;

            // Get the HelloWorldDataItem which is associated with this stack walk. This
            // lets us keep data associated with this stack walk.
            HelloWordDataItem dataItem = HelloWordDataItem.GetInstance(stackContext);
            DkmStackWalkFrame[] frames;

            // Now use this data item to see if we are looking at the first (top-most) frame
            if (dataItem.State == State.Initial)
            {
                // On the top most frame, we want to return back two different frames. First 
                // we place the '[Hello World]' frame, and under that we put the input frame.

                frames = new DkmStackWalkFrame[2];

                // Create the hello world frame object, and stick it in the array
                frames[0] = DkmStackWalkFrame.Create(
                    stackContext.Thread,
                    null,                          // Annotated frame, so no instruction address
                    input.FrameBase,               // Use the same frame base as the input frame
                    0,                             // annoted frame uses zero bytes
                    DkmStackWalkFrameFlags.None,
                    "[Hello World]",               // Description of the frame which will appear in the call stack
                    null,                          // Annotated frame, so no registers
                    null
                    );

                // Add the input frame into the array as well
                frames[1] = input;

                // Update our state so that on the next frame we know not to add '[Hello World]' again.
                dataItem.State = State.HelloWorldFrameAdded;
            }
            else
            {
                // We have already added '[Hello World]' to this call stack, so just return
                // the input frame.

                frames = new DkmStackWalkFrame[1] { input };
            }

            return frames;
        }
 private DkmIntermediateEvaluationResult(
     DkmInspectionContext inspectionContext,
     DkmStackWalkFrame stackFrame,
     string name,
     string fullName,
     string expression,
     DkmLanguage intermediateLanguage,
     DkmRuntimeInstance targetRuntime,
     DkmDataItem dataItem)
     : base(inspectionContext, stackFrame, name, fullName, DkmEvaluationResultFlags.None, null, dataItem)
 {
     this.Expression = expression;
     this.IntermediateLanguage = intermediateLanguage;
     this.TargetRuntime = targetRuntime;
 }
        public static DkmFailedEvaluationResult Create(DkmInspectionContext InspectionContext, DkmStackWalkFrame StackFrame, string Name, string FullName, string ErrorMessage, DkmEvaluationResultFlags Flags, string Type, DkmDataItem DataItem)
        {
            DkmFailedEvaluationResult result = new DkmFailedEvaluationResult
            {
                InspectionContext = InspectionContext,
                Name = Name,
                FullName = FullName,
                ErrorMessage = ErrorMessage,
                Flags = Flags,
                Type = Type
            };

            if (DataItem != null)
            {
                result.SetDataItem(DkmDataCreationDisposition.CreateNew, DataItem);
            }

            return result;
        }
Example #18
0
        private static bool IsInEvalFrame(DkmStackWalkFrame frame) {
            var process = frame.Process;
            var pythonInfo = process.GetPythonRuntimeInfo();
            ulong addr = 0;
            if (pythonInfo.LanguageVersion <= PythonLanguageVersion.V35) {
                if (frame.ModuleInstance == pythonInfo.DLLs.Python) {
                    addr = pythonInfo.DLLs.Python.GetFunctionAddress("PyEval_EvalFrameEx");
                }
            } else {
                if (frame.ModuleInstance == pythonInfo.DLLs.DebuggerHelper) {
                    addr = pythonInfo.DLLs.DebuggerHelper.GetFunctionAddress("EvalFrameFunc");
                }
            }

            if (addr == 0) {
                return false;
            }

            return frame.InstructionAddress.IsInSameFunction(process.CreateNativeInstructionAddress(addr));
        }
 public static DkmFailedEvaluationResult Create(
     DkmInspectionContext InspectionContext,
     DkmStackWalkFrame StackFrame,
     string Name,
     string FullName,
     string ErrorMessage,
     DkmEvaluationResultFlags Flags,
     string Type,
     DkmDataItem DataItem)
 {
     return new DkmFailedEvaluationResult(
         InspectionContext,
         StackFrame,
         Name,
         FullName,
         ErrorMessage,
         Flags,
         Type,
         DataItem);
 }
 public static DkmIntermediateEvaluationResult Create(
     DkmInspectionContext InspectionContext,
     DkmStackWalkFrame StackFrame,
     string Name,
     string FullName,
     string Expression,
     DkmLanguage IntermediateLanguage,
     DkmRuntimeInstance TargetRuntime,
     DkmDataItem DataItem)
 {
     return new DkmIntermediateEvaluationResult(
         InspectionContext,
         StackFrame,
         Name,
         FullName,
         Expression,
         IntermediateLanguage,
         TargetRuntime,
         DataItem);
 }
Example #21
0
    public override object GetArgumentValue(DkmStackWalkFrame frame, int index) {
      byte[] argumentBuffer = ReadArgumentBytes(frame);

      int wordZeroIndex = 0;
      for (int i=0; i < index; ++i)
        wordZeroIndex += _parameters[i].GetPaddedSize(WordSize);
      FunctionParameter requestedParameter = _parameters[index];
      int requestedParamSize = requestedParameter.GetSize(WordSize);
      byte[] result = new byte[requestedParamSize];

      Array.ConstrainedCopy(argumentBuffer, wordZeroIndex, result, 0, requestedParamSize);

      switch (requestedParamSize) {
        case 4:
          return BitConverter.ToUInt32(result, 0);
        case 8:
          return BitConverter.ToUInt64(result, 0);
        default:
          return result;
      }
    }
        internal DkmEvaluationResult(
            DkmInspectionContext InspectionContext,
            DkmStackWalkFrame StackFrame,
            string Name,
            string FullName,
            DkmEvaluationResultFlags Flags,
            string Type,
            DkmDataItem DataItem)
        {
            this.InspectionContext = InspectionContext;
            this.StackFrame = StackFrame;
            this.Name = Name;
            this.FullName = FullName;
            this.Flags = Flags;
            this.Type = Type;

            if (DataItem != null)
            {
                this.SetDataItem(DkmDataCreationDisposition.CreateNew, DataItem);
            }
        }
        private byte[] ReadArgumentBytes(DkmStackWalkFrame frame)
        {
            // In the x64 calling convention, the first 4 arguments are passed in registers, and the
              // remaining arguments are passed on the stack.  However, space for all arguments is
              // allocated on the stack, even if the argument is passed one of the first 4 which is passed
              // by register.  Furthermore, a minimum of 4*WordSize bytes is allocated on the stack for
              // function parameters, even if the function accepts less than 4 arguments.
              int bytesRequired = 0;
              foreach (FunctionParameter param in _parameters)
            bytesRequired += param.GetPaddedSize(WordSize);
              byte[] stack = new byte[bytesRequired];

              ulong rsp = frame.Registers.GetStackPointer();
              // The first word on the stack is the return address, similar to in x86 calling conventions.
              frame.Process.ReadMemory(rsp + 8, DkmReadMemoryFlags.None, stack);

              // Since everything is padded, we should have a multiple-of-8 bytes.  The first four
              // arguments may or may not actually be on the stack since it's register spill-over space,
              // but they are guaranteed to be in RCX, RDX, R8, and R9 respectively.  So get their values
              // from the registers and then write them into our copy of the stack.
              Debug.Assert(bytesRequired % 8 == 0);
              if (bytesRequired > 0) {
            ulong rcx = frame.VscxGetRegisterValue64(CpuRegister.Rcx);
            BitConverter.GetBytes(rcx).CopyTo(stack, 0);
              }
              if (bytesRequired > 8) {
            ulong rdx = frame.VscxGetRegisterValue64(CpuRegister.Rdx);
            BitConverter.GetBytes(rdx).CopyTo(stack, 8);
              }
              if (bytesRequired > 16) {
            ulong r8 = frame.VscxGetRegisterValue64(CpuRegister.R8);
            BitConverter.GetBytes(r8).CopyTo(stack, 16);
              }
              if (bytesRequired > 24) {
            ulong r9 = frame.VscxGetRegisterValue64(CpuRegister.R9);
            BitConverter.GetBytes(r9).CopyTo(stack, 24);
              }

              return stack;
        }
        public static DkmSuccessEvaluationResult Create(DkmInspectionContext InspectionContext, DkmStackWalkFrame StackFrame, string Name, string FullName, DkmEvaluationResultFlags Flags, string Value, string EditableValue, string Type, DkmEvaluationResultCategory Category, DkmEvaluationResultAccessType Access, DkmEvaluationResultStorageType StorageType, DkmEvaluationResultTypeModifierFlags TypeModifierFlags, DkmDataAddress Address, ReadOnlyCollection<DkmCustomUIVisualizerInfo> CustomUIVisualizers, ReadOnlyCollection<DkmModuleInstance> ExternalModules, DkmDataItem DataItem)
        {
            DkmSuccessEvaluationResult result = new DkmSuccessEvaluationResult
            {
                InspectionContext = InspectionContext,
                Name = Name,
                FullName = FullName,
                Flags = Flags,
                Value = Value,
                Type = Type,
                Category = Category,
                EditableValue = EditableValue,
                CustomUIVisualizers = CustomUIVisualizers
            };

            if (DataItem != null)
            {
                result.SetDataItem(DkmDataCreationDisposition.CreateNew, DataItem);
            }

            return result;
        }
 public static DkmSuccessEvaluationResult Create(
     DkmInspectionContext InspectionContext,
     DkmStackWalkFrame StackFrame,
     string Name,
     string FullName,
     DkmEvaluationResultFlags Flags,
     string Value,
     string EditableValue,
     string Type,
     DkmEvaluationResultCategory Category,
     DkmEvaluationResultAccessType Access,
     DkmEvaluationResultStorageType StorageType,
     DkmEvaluationResultTypeModifierFlags TypeModifierFlags,
     DkmDataAddress Address,
     ReadOnlyCollection<DkmCustomUIVisualizerInfo> CustomUIVisualizers,
     ReadOnlyCollection<DkmModuleInstance> ExternalModules,
     DkmDataItem DataItem)
 {
     return new DkmSuccessEvaluationResult(
         InspectionContext,
         StackFrame,
         Name,
         FullName,
         Flags,
         Value,
         EditableValue,
         Type,
         Category,
         Access,
         StorageType,
         TypeModifierFlags,
         Address,
         CustomUIVisualizers,
         ExternalModules,
         DataItem);
 }
Example #26
0
        public CppExpressionEvaluator(DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame) {
            _process = stackFrame.Process;
            var thread = stackFrame.Thread;

            if (stackFrame.InstructionAddress is DkmNativeInstructionAddress) {
                _nativeFrame = stackFrame;
            } else {
                var customAddr = stackFrame.InstructionAddress as DkmCustomInstructionAddress;
                if (customAddr == null) {
                    throw new ArgumentException();
                }

                var loc = new SourceLocation(customAddr.AdditionalData, _process);
                if (loc.NativeAddress == null) {
                    throw new ArgumentException();
                }

                _nativeFrame = DkmStackWalkFrame.Create(thread, loc.NativeAddress, stackFrame.FrameBase, stackFrame.FrameSize,
                    DkmStackWalkFrameFlags.None, null, stackFrame.Registers, null);
            }

            _cppInspectionContext = DkmInspectionContext.Create(inspectionContext.InspectionSession, _process.GetNativeRuntimeInstance(), thread, Timeout,
                DkmEvaluationFlags.TreatAsExpression | DkmEvaluationFlags.NoSideEffects, DkmFuncEvalFlags.None, inspectionContext.Radix, CppLanguage, null);
        }
 private void GetEvaluationResultsAndContinue(ArrayBuilder<EvalResultDataItem> rows, DkmEvaluationResult[] results, int index, int numRows, WorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine completionRoutine)
 {
     if (index < numRows)
     {
         CreateEvaluationResultAndContinue(rows[index], workList, inspectionContext, stackFrame,
             result => workList.ContinueWith(
                 () =>
                 {
                     results[index] = result;
                     GetEvaluationResultsAndContinue(rows, results, index + 1, numRows, workList, inspectionContext, stackFrame, completionRoutine);
                 }));
     }
     else
     {
         completionRoutine();
     }
 }
 private void GetChildrenAndContinue(EvalResultDataItem dataItem, DkmWorkList workList, DkmStackWalkFrame stackFrame, int initialRequestSize, DkmInspectionContext inspectionContext, DkmCompletionRoutine<DkmGetChildrenAsyncResult> completionRoutine)
 {
     var expansion = dataItem.Expansion;
     var rows = ArrayBuilder<EvalResultDataItem>.GetInstance();
     int index = 0;
     if (expansion != null)
     {
         expansion.GetRows(this, rows, inspectionContext, dataItem, dataItem.Value, 0, initialRequestSize, visitAll: true, index: ref index);
     }
     var numRows = rows.Count;
     Debug.Assert(index >= numRows);
     Debug.Assert(initialRequestSize >= numRows);
     var initialChildren = new DkmEvaluationResult[numRows];
     var wl = new WorkList(workList, e => completionRoutine(DkmGetChildrenAsyncResult.CreateErrorResult(e)));
     GetEvaluationResultsAndContinue(rows, initialChildren, 0, numRows, wl, inspectionContext, stackFrame,
         () => wl.ContinueWith(
             () =>
             {
                 var enumContext = DkmEvaluationResultEnumContext.Create(index, stackFrame, inspectionContext, new EnumContextDataItem(dataItem));
                 completionRoutine(new DkmGetChildrenAsyncResult(initialChildren, enumContext));
                 rows.Free();
             }));
     wl.Execute();
 }
 private void CreateEvaluationResultAndContinue(EvalResultDataItem dataItem, WorkList workList, DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, CompletionRoutine<DkmEvaluationResult> completionRoutine)
 {
     switch (dataItem.Kind)
     {
         case ExpansionKind.Error:
             completionRoutine(DkmFailedEvaluationResult.Create(
                 inspectionContext,
                 StackFrame: stackFrame,
                 Name: dataItem.Name,
                 FullName: dataItem.FullName,
                 ErrorMessage: dataItem.DisplayValue,
                 Flags: DkmEvaluationResultFlags.None,
                 Type: null,
                 DataItem: null));
             break;
         case ExpansionKind.NativeView:
             {
                 var value = dataItem.Value;
                 var name = Resources.NativeView;
                 var fullName = dataItem.FullName;
                 var display = dataItem.Name;
                 DkmEvaluationResult evalResult;
                 if (value.IsError())
                 {
                     evalResult = DkmFailedEvaluationResult.Create(
                         inspectionContext,
                         stackFrame,
                         Name: name,
                         FullName: fullName,
                         ErrorMessage: display,
                         Flags: dataItem.Flags,
                         Type: null,
                         DataItem: dataItem);
                 }
                 else
                 {
                     // For Native View, create a DkmIntermediateEvaluationResult.
                     // This will allow the C++ EE to take over expansion.
                     var process = inspectionContext.RuntimeInstance.Process;
                     var cpp = process.EngineSettings.GetLanguage(new DkmCompilerId(DkmVendorId.Microsoft, DkmLanguageId.Cpp));
                     evalResult = DkmIntermediateEvaluationResult.Create(
                         inspectionContext,
                         stackFrame,
                         Name: name,
                         FullName: fullName,
                         Expression: display,
                         IntermediateLanguage: cpp,
                         TargetRuntime: process.GetNativeRuntimeInstance(),
                         DataItem: dataItem);
                 }
                 completionRoutine(evalResult);
             }
             break;
         case ExpansionKind.NonPublicMembers:
             completionRoutine(DkmSuccessEvaluationResult.Create(
                 inspectionContext,
                 stackFrame,
                 Name: Resources.NonPublicMembers,
                 FullName: dataItem.FullName,
                 Flags: dataItem.Flags,
                 Value: null,
                 EditableValue: null,
                 Type: string.Empty,
                 Category: DkmEvaluationResultCategory.Data,
                 Access: DkmEvaluationResultAccessType.None,
                 StorageType: DkmEvaluationResultStorageType.None,
                 TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
                 Address: dataItem.Value.Address,
                 CustomUIVisualizers: null,
                 ExternalModules: null,
                 DataItem: dataItem));
             break;
         case ExpansionKind.StaticMembers:
             completionRoutine(DkmSuccessEvaluationResult.Create(
                 inspectionContext,
                 stackFrame,
                 Name: Formatter.StaticMembersString,
                 FullName: dataItem.FullName,
                 Flags: dataItem.Flags,
                 Value: null,
                 EditableValue: null,
                 Type: string.Empty,
                 Category: DkmEvaluationResultCategory.Class,
                 Access: DkmEvaluationResultAccessType.None,
                 StorageType: DkmEvaluationResultStorageType.None,
                 TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
                 Address: dataItem.Value.Address,
                 CustomUIVisualizers: null,
                 ExternalModules: null,
                 DataItem: dataItem));
             break;
         case ExpansionKind.RawView:
             completionRoutine(DkmSuccessEvaluationResult.Create(
                 inspectionContext,
                 stackFrame,
                 Name: Resources.RawView,
                 FullName: dataItem.FullName,
                 Flags: dataItem.Flags,
                 Value: null,
                 EditableValue: dataItem.EditableValue,
                 Type: string.Empty,
                 Category: DkmEvaluationResultCategory.Data,
                 Access: DkmEvaluationResultAccessType.None,
                 StorageType: DkmEvaluationResultStorageType.None,
                 TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
                 Address: dataItem.Value.Address,
                 CustomUIVisualizers: null,
                 ExternalModules: null,
                 DataItem: dataItem));
             break;
         case ExpansionKind.DynamicView:
         case ExpansionKind.ResultsView:
             completionRoutine(DkmSuccessEvaluationResult.Create(
                 inspectionContext,
                 stackFrame,
                 dataItem.Name,
                 dataItem.FullName,
                 dataItem.Flags,
                 dataItem.DisplayValue,
                 EditableValue: null,
                 Type: string.Empty,
                 Category: DkmEvaluationResultCategory.Method,
                 Access: DkmEvaluationResultAccessType.None,
                 StorageType: DkmEvaluationResultStorageType.None,
                 TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
                 Address: dataItem.Value.Address,
                 CustomUIVisualizers: null,
                 ExternalModules: null,
                 DataItem: dataItem));
             break;
         case ExpansionKind.TypeVariable:
             completionRoutine(DkmSuccessEvaluationResult.Create(
                 inspectionContext,
                 stackFrame,
                 dataItem.Name,
                 dataItem.FullName,
                 dataItem.Flags,
                 dataItem.DisplayValue,
                 EditableValue: null,
                 Type: dataItem.DisplayValue,
                 Category: DkmEvaluationResultCategory.Data,
                 Access: DkmEvaluationResultAccessType.None,
                 StorageType: DkmEvaluationResultStorageType.None,
                 TypeModifierFlags: DkmEvaluationResultTypeModifierFlags.None,
                 Address: dataItem.Value.Address,
                 CustomUIVisualizers: null,
                 ExternalModules: null,
                 DataItem: dataItem));
             break;
         case ExpansionKind.PointerDereference:
         case ExpansionKind.Default:
             // This call will evaluate DebuggerDisplayAttributes.
             GetResultAndContinue(
                 dataItem,
                 workList,
                 declaredType: DkmClrType.Create(dataItem.Value.Type.AppDomain, dataItem.DeclaredTypeAndInfo.Type),
                 declaredTypeInfo: dataItem.DeclaredTypeAndInfo.Info,
                 inspectionContext: inspectionContext,
                 parent: dataItem.Parent,
                 completionRoutine: completionRoutine);
             break;
         default:
             throw ExceptionUtilities.UnexpectedValue(dataItem.Kind);
     }
 }
Example #30
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)));
            }
        }