Example #1
0
        public void Step(DkmStepper stepper, DkmStepArbitrationReason reason)
        {
            var thread  = stepper.Thread;
            var process = thread.Process;

            if (stepper.StepKind == DkmStepKind.StepIntoSpecific)
            {
                throw new NotSupportedException();
            }
            else if (_stepper != null)
            {
                _stepper.CancelStepper(process.GetPythonRuntimeInstance());
                _stepper = null;
            }

            // Check if this was a step out (or step over/in that fell through) from native to Python.
            // If so, we consider the step done, since we can report the correct callstack at this point.
            if (reason == DkmStepArbitrationReason.TransitionModule)
            {
                var beginState = stepper.GetDataItem <StepBeginState>();
                if (beginState != null)
                {
                    thread.GetCurrentFrameInfo(out global::System.UInt64 retAddr, out global::System.UInt64 frameBase, out global::System.UInt64 vframe);
                    if (frameBase >= beginState.FrameBase)
                    {
                        stepper.OnStepComplete(thread, false);
                        return;
                    }
                }
            }

            if (stepper.StepKind == DkmStepKind.Into)
            {
                new LocalComponent.BeginStepInNotification
                {
                    ThreadId = thread.UniqueId
                }.SendHigher(process);
            }

            _stepper = stepper;
            _stepKind.Write((int)stepper.StepKind + 1);
            _stepThreadId.Write((uint)thread.SystemPart.Id);
            _steppingStackDepth.Write(0);
        }
        void IDkmRuntimeStepper.TakeStepControl(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, bool leaveGuardsInPlace, DkmStepArbitrationReason reason, DkmRuntimeInstance callingRuntimeInstance)
        {
            var process = runtimeInstance.Process;

            var processData = DebugHelpers.GetOrCreateDataItem <LuaRemoteProcessData>(runtimeInstance.Process);

            ClearStepperData(process, processData);
        }
 bool IDkmRuntimeStepper.StepControlRequested(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason, DkmRuntimeInstance callingRuntimeInstance)
 {
     return(true);
 }
        void IDkmRuntimeStepper.OnNewControllingRuntimeInstance(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason, DkmRuntimeInstance controllingRuntimeInstance)
        {
            var process = runtimeInstance.Process;

            var processData = DebugHelpers.GetOrCreateDataItem <LuaRemoteProcessData>(runtimeInstance.Process);

            ClearStepperData(process, processData);
        }
 void IDkmRuntimeStepper.AfterSteppingArbitration(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason, DkmRuntimeInstance newControllingRuntimeInstance)
 {
     // Don't have anything to do here right now
 }
        void IDkmRuntimeStepper.Step(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason)
        {
            var process = runtimeInstance.Process;

            var processData = DebugHelpers.GetOrCreateDataItem <LuaRemoteProcessData>(runtimeInstance.Process);

            if (stepper.StepKind == DkmStepKind.StepIntoSpecific)
            {
                throw new NotSupportedException();
            }

            if (processData.activeStepper != null)
            {
                processData.activeStepper.CancelStepper(processData.runtimeInstance);
                processData.activeStepper = null;
            }

            if (stepper.StepKind == DkmStepKind.Over)
            {
                DebugHelpers.TryWriteIntVariable(process, processData.locations.helperStepOverAddress, 1);
            }
            else if (stepper.StepKind == DkmStepKind.Into)
            {
                DebugHelpers.TryWriteIntVariable(process, processData.locations.helperStepOverAddress, 1);
                DebugHelpers.TryWriteIntVariable(process, processData.locations.helperStepIntoAddress, 1);
            }
            else if (stepper.StepKind == DkmStepKind.Out)
            {
                DebugHelpers.TryWriteIntVariable(process, processData.locations.helperStepOutAddress, 1);
            }

            processData.activeStepper = stepper;

            processData.hadActiveStepper = true;

            UpdateHooks(process, processData);
        }
        bool IDkmRuntimeStepper.OwnsCurrentExecutionLocation(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason)
        {
            var processData = DebugHelpers.GetOrCreateDataItem <LuaRemoteProcessData>(runtimeInstance.Process);

            // Can't handle steps without an address
            if (stepper.StartingAddress == null)
            {
                return(false);
            }

            // Stepping can be performed if we are inside the debug helper or inside luaV_execute
            var instructionAddress = stepper.StartingAddress.CPUInstructionPart.InstructionPointer;

            if (processData.locations == null)
            {
                return(false);
            }

            if (instructionAddress >= processData.locations.helperStartAddress && instructionAddress < processData.locations.helperEndAddress)
            {
                return(true);
            }

            if (instructionAddress >= processData.locations.executionStartAddress && instructionAddress < processData.locations.executionEndAddress)
            {
                return(true);
            }

            return(false);
        }
Example #8
0
        void IDkmRuntimeStepper.TakeStepControl(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, bool leaveGuardsInPlace, DkmStepArbitrationReason reason, DkmRuntimeInstance callingRuntimeInstance)
        {
            var traceManager = runtimeInstance.Process.GetDataItem <TraceManager>();

            if (traceManager == null)
            {
                Debug.Fail("TakeStepControl called before TraceMananger is initialized.");
                throw new InvalidOperationException();
            }

            traceManager.CancelStep(stepper);
        }
Example #9
0
        void IDkmRuntimeStepper.Step(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason)
        {
            var traceManager = runtimeInstance.Process.GetDataItem <TraceManager>();

            if (traceManager == null)
            {
                Debug.Fail("Step called before TraceMananger is initialized.");
                throw new InvalidOperationException();
            }

            traceManager.Step(stepper, reason);
        }
Example #10
0
        bool IDkmRuntimeStepper.OwnsCurrentExecutionLocation(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason)
        {
            if (!DebuggerOptions.UsePythonStepping)
            {
                return(false);
            }

            var process  = runtimeInstance.Process;
            var pyrtInfo = process.GetPythonRuntimeInfo();

            if (pyrtInfo.DLLs.Python == null)
            {
                return(false);
            }

            var thread = stepper.Thread;
            var ip     = thread.GetCurrentRegisters(new DkmUnwoundRegister[0]).GetInstructionPointer();

            return(pyrtInfo.DLLs.Python.ContainsAddress(ip) ||
                   (pyrtInfo.DLLs.DebuggerHelper != null && pyrtInfo.DLLs.DebuggerHelper.ContainsAddress(ip)) ||
                   (pyrtInfo.DLLs.CTypes != null && pyrtInfo.DLLs.CTypes.ContainsAddress(ip)));
        }
Example #11
0
 void IDkmRuntimeStepper.AfterSteppingArbitration(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason, DkmRuntimeInstance newControllingRuntimeInstance)
 {
 }
Example #12
0
 void IDkmRuntimeStepper.TakeStepControl(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, bool leaveGuardsInPlace, DkmStepArbitrationReason reason, DkmRuntimeInstance callingRuntimeInstance)
 {
     runtimeInstance.StopStep(stepper);
 }
Example #13
0
 void IDkmRuntimeStepper.OnNewControllingRuntimeInstance(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason, DkmRuntimeInstance controllingRuntimeInstance)
 {
     // Don't have anything to do here
 }
Example #14
0
            void IDkmRuntimeStepper.Step(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason)
            {
                if (!(this as IDkmRuntimeStepper).OwnsCurrentExecutionLocation(runtimeInstance, stepper, reason))
                {
                    runtimeInstance.Step(stepper, reason);
                    return;
                }

                var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(runtimeInstance.Process);

                if (stepper.StepKind == DkmStepKind.StepIntoSpecific)
                {
                    throw new NotSupportedException();
                }

                if (stepper.StepKind == DkmStepKind.Over || stepper.StepKind == DkmStepKind.Into)
                {
                    ClearStepBreakpoints(processData);

                    int nullcInstruction = processData.bytecode.ConvertNativeAddressToInstruction(stepper.StartingAddress.CPUInstructionPart.InstructionPointer);

                    int line = processData.bytecode.GetInstructionSourceLocationLine(nullcInstruction, out int moduleIndex);

                    // Instruction based stepping
                    int nextNullcInstruction      = nullcInstruction;
                    int secondaryNullcInstruction = 0;

                    while (nextNullcInstruction < processData.bytecode.instructions.Count)
                    {
                        // Walk forward until an instruction with a different line is hit
                        if (processData.bytecode.GetInstructionSourceLocationLine(nextNullcInstruction, out _) != line)
                        {
                            break;
                        }

                        var nextInstruction = processData.bytecode.instructions[nextNullcInstruction];

                        // If there is a jump, place a breakpoint at the target (even if it's on the same line)
                        if (nextInstruction.code == NullcInstructionCode.rviJmp)
                        {
                            nextNullcInstruction = (int)nextInstruction.argument;
                            break;
                        }

                        // If there is a conditional jump, place two breakpoints - one after it and one at the target (even if either of them is on the same line)
                        if (nextInstruction.code == NullcInstructionCode.rviJmpz || nextInstruction.code == NullcInstructionCode.rviJmpnz)
                        {
                            secondaryNullcInstruction = nextNullcInstruction + 1;
                            nextNullcInstruction      = (int)nextInstruction.argument;
                            break;
                        }

                        // If there is a return, I wish I could just fallback to parent runtime to handle it, may be required to place a breakpoint at the call site
                        if (nextInstruction.code == NullcInstructionCode.rviReturn)
                        {
                            ulong address = GetReturnAddress(stepper.Thread);

                            // Address must be within nullc module or we will have to cancel the step
                            if (address >= processData.nativeModuleInstance.BaseAddress && address < processData.nativeModuleInstance.BaseAddress + processData.nativeModuleInstance.Size)
                            {
                                processData.stepBreakpoint = PlaceBreakpointAtAddress(processData, stepper.Thread, address);
                            }
                            else
                            {
                                stepper.OnStepComplete(stepper.Thread, false);
                            }

                            return;
                        }

                        if (stepper.StepKind == DkmStepKind.Into)
                        {
                            if (nextInstruction.code == NullcInstructionCode.rviCall && stepper.StepKind == DkmStepKind.Into)
                            {
                                NullcFuncInfo function = processData.bytecode.functions[(int)nextInstruction.argument];

                                if (function.regVmAddress != ~0u)
                                {
                                    secondaryNullcInstruction = nextNullcInstruction + 1;
                                    nextNullcInstruction      = (int)function.regVmAddress;
                                    break;
                                }
                                else if (function.funcPtrWrap != 0 || function.funcPtrRaw != 0)
                                {
                                    // TODO: Step into an external function
                                    // I've tryied placing a breakpoint at the external call target but it's not getting handled correctly
                                    // Maybe the solution is to single step the process until the stack frame changes
                                }
                            }
                            else if (nextInstruction.code == NullcInstructionCode.rviCallPtr)
                            {
                                // TODO: Step into a function pointer call
                            }
                        }

                        nextNullcInstruction++;
                    }

                    if (nextNullcInstruction != 0)
                    {
                        ulong instructionAddress = processData.bytecode.ConvertInstructionToNativeAddress(nextNullcInstruction);

                        processData.stepBreakpoint = PlaceBreakpointAtAddress(processData, stepper.Thread, instructionAddress);
                    }

                    if (secondaryNullcInstruction != 0)
                    {
                        ulong instructionAddress = processData.bytecode.ConvertInstructionToNativeAddress(secondaryNullcInstruction);

                        processData.secondaryStepBreakpoint = PlaceBreakpointAtAddress(processData, stepper.Thread, instructionAddress);
                    }
                }
                else if (stepper.StepKind == DkmStepKind.Out)
                {
                    ulong address = GetReturnAddress(stepper.Thread);

                    processData.stepBreakpoint = PlaceBreakpointAtAddress(processData, stepper.Thread, address);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
Example #15
0
            bool IDkmRuntimeStepper.OwnsCurrentExecutionLocation(DkmRuntimeInstance runtimeInstance, DkmStepper stepper, DkmStepArbitrationReason reason)
            {
                var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(runtimeInstance.Process);

                // Can't handle steps without an address
                if (stepper.StartingAddress == null)
                {
                    return(false);
                }

                var instructionAddress = stepper.StartingAddress.CPUInstructionPart.InstructionPointer;

                if (DebugHelpers.useNativeInterfaces)
                {
                    if (processData.nativeModuleInstance != null)
                    {
                        if (instructionAddress >= processData.nativeModuleInstance.BaseAddress && instructionAddress < processData.nativeModuleInstance.BaseAddress + processData.nativeModuleInstance.Size)
                        {
                            return(processData.bytecode.ConvertNativeAddressToInstruction(instructionAddress) != 0);
                        }
                    }
                }
                else
                {
                    if (processData.moduleInstance != null)
                    {
                        if (instructionAddress >= processData.moduleInstance.BaseAddress && instructionAddress < processData.moduleInstance.BaseAddress + processData.moduleInstance.Size)
                        {
                            return(processData.bytecode.ConvertNativeAddressToInstruction(instructionAddress) != 0);
                        }
                    }
                }

                return(false);
            }