Esempio n. 1
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);
            }
Esempio n. 2
0
            void IDkmRuntimeMonitorBreakpointHandler.DisableRuntimeBreakpoint(DkmRuntimeBreakpoint runtimeBreakpoint)
            {
                var breakpointData = runtimeBreakpoint.GetDataItem <NullcBreakpointDataItem>();

                if (breakpointData != null)
                {
                    var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(runtimeBreakpoint.Process);

                    var address = breakpointData.instructionAddress.CPUInstructionPart.InstructionPointer;

                    runtimeBreakpoint.Process.InvisibleWriteMemory(breakpointData.instructionAddress.CPUInstructionPart.InstructionPointer, breakpointData.prevValue);

                    // Skip internal breakpoints used in stepper
                    if (runtimeBreakpoint.SourceId != DebugHelpers.NullcStepperBreakpointSourceId)
                    {
                        if (processData.activeBreakpointLocations.Contains(address))
                        {
                            processData.activeBreakpointLocations.Remove(address);
                        }

                        // If we were planning to restore the breakpoint, forget about it
                        if (processData.lastHitBreakpointLocation == address)
                        {
                            processData.lastHitBreakpointLocation = 0;
                        }
                    }
                }
            }
Esempio n. 3
0
            void IDkmProcessExecutionNotification.OnProcessResume(DkmProcess process, DkmProcessExecutionCounters processCounters)
            {
                var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(process);

                // Third stage of breakpoint handling - schedule a single step so we will move from the instruction location where debug break instruction must be restored (int 3)
                if (processData.lastHitBreakpointLocation != 0)
                {
                    var singleStepRequest = DkmSingleStepRequest.Create(DebugHelpers.NullcStepperBreakpointSourceId, processData.singleStepThread);

                    singleStepRequest.EnableSingleStep();
                }
            }
Esempio n. 4
0
            void IDkmRuntimeMonitorBreakpointHandler.EnableRuntimeBreakpoint(DkmRuntimeBreakpoint runtimeBreakpoint)
            {
                var instructionBreakpoint = (runtimeBreakpoint as DkmRuntimeInstructionBreakpoint);

                if (instructionBreakpoint != null)
                {
                    var nativeInstructionAddress = instructionBreakpoint.InstructionAddress as DkmNativeInstructionAddress;

                    if (nativeInstructionAddress == null)
                    {
                        Debug.WriteLine("Missing breakpoint address");
                        return;
                    }

                    ulong address = instructionBreakpoint.InstructionAddress.CPUInstructionPart.InstructionPointer;

                    byte[] prevValue = new byte[1];

                    if (runtimeBreakpoint.Process.ReadMemory(address, DkmReadMemoryFlags.ExecutableOnly, prevValue) == 0)
                    {
                        Debug.WriteLine("Failed to read current instruction");
                        return;
                    }

                    var breakpointData = DebugHelpers.GetOrCreateDataItem <NullcBreakpointDataItem>(runtimeBreakpoint);

                    breakpointData.instructionAddress = nativeInstructionAddress;
                    breakpointData.prevValue          = prevValue;

                    // Write an 'int 3' instruction
                    runtimeBreakpoint.Process.InvisibleWriteMemory(address, new byte[1] {
                        0xcc
                    });

                    // Remember locations of the active user breakpoint instructions, skip internal breakpoints used in stepper
                    if (runtimeBreakpoint.SourceId != DebugHelpers.NullcStepperBreakpointSourceId)
                    {
                        var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(instructionBreakpoint.Process);

                        if (!processData.activeBreakpointLocations.Contains(address))
                        {
                            processData.activeBreakpointLocations.Add(address);
                        }
                    }

                    return;
                }

                Debug.WriteLine("Failed to enable the breakpoint");
            }
Esempio n. 5
0
            bool IDkmModuleUserCodeDeterminer.IsUserCode(DkmModuleInstance moduleInstance)
            {
                var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(moduleInstance.Process);

                if (processData != null)
                {
                    if (moduleInstance.LoadContext == "nullc embedded code")
                    {
                        return(true);
                    }
                }

                return(moduleInstance.IsUserCode());
            }
Esempio n. 6
0
            void IDkmSingleStepCompleteReceived.OnSingleStepCompleteReceived(DkmSingleStepRequest singleStepRequest, DkmEventDescriptorS eventDescriptor)
            {
                var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(singleStepRequest.Thread.Process);

                // Last stage of breakpoint handling - restore debug break instruction now that we have moved from the breakpoint location
                if (processData.lastHitBreakpointLocation != 0)
                {
                    // Restore breakpoint instruction
                    singleStepRequest.Thread.Process.InvisibleWriteMemory(processData.lastHitBreakpointLocation, new byte[1] {
                        0xcc
                    });

                    processData.lastHitBreakpointLocation = 0;

                    eventDescriptor.Suppress();
                }
            }
Esempio n. 7
0
            void IDkmDebugMonitorExceptionNotification.OnDebugMonitorException(DkmExceptionInformation exception, DkmWorkList workList, DkmEventDescriptorS eventDescriptor)
            {
                var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(exception.Process);

                if (exception.InstructionAddress == null)
                {
                    return;
                }

                ulong address = exception.InstructionAddress.CPUInstructionPart.InstructionPointer;

                // Breakpoint
                if (exception.Code == 0x80000003)
                {
                    // Internal stepper breakpoints are silenced but te debugger is notified to break the process
                    if (processData.stepBreakpoint != null && processData.stepBreakpoint.InstructionAddress.CPUInstructionPart.InstructionPointer == address)
                    {
                        eventDescriptor.Suppress();

                        exception.Thread.OnEmbeddedBreakpointHit(exception.InstructionAddress, false);
                    }

                    if (processData.secondaryStepBreakpoint != null && processData.secondaryStepBreakpoint.InstructionAddress.CPUInstructionPart.InstructionPointer == address)
                    {
                        eventDescriptor.Suppress();

                        exception.Thread.OnEmbeddedBreakpointHit(exception.InstructionAddress, false);
                    }

                    // Second stage of breakpoint handling - supress exception, notify debugger to break the process and remember what breakpoint has to be resotred later
                    if (processData.activeBreakpointLocations.Contains(address))
                    {
                        eventDescriptor.Suppress();

                        exception.Thread.OnEmbeddedBreakpointHit(exception.InstructionAddress, false);

                        // Schedule restore of this breakpoint when process continues
                        processData.lastHitBreakpointLocation = address;

                        processData.singleStepThread = exception.Thread;
                    }
                }
            }
Esempio n. 8
0
            void IDkmInstructionAddressProvider.GetInstructionAddress(DkmProcess process, DkmWorkList workList, ulong instructionPointer, DkmCompletionRoutine <DkmGetInstructionAddressAsyncResult> completionRoutine)
            {
                var processData = DebugHelpers.GetOrCreateDataItem <NullcModuleDataItem>(process);

                if (!processData.nullcIsMissing && processData.moduleBase == 0)
                {
                    processData.moduleBase = DebugHelpers.ReadPointerVariable(process, "nullcModuleStartAddress").GetValueOrDefault(0);

                    processData.moduleSize = (uint)(DebugHelpers.ReadPointerVariable(process, "nullcModuleEndAddress").GetValueOrDefault(0) - processData.moduleBase);

                    processData.nullcIsMissing = processData.moduleBase == 0;
                }

                if (processData.moduleBase != 0)
                {
                    if (instructionPointer >= processData.moduleBase && instructionPointer < processData.moduleBase + processData.moduleSize)
                    {
                        DkmInstructionAddress address;

                        if (DebugHelpers.useNativeInterfaces)
                        {
                            var nullcNativeRuntime  = DebugHelpers.useDefaultRuntimeInstance ? process.GetNativeRuntimeInstance() : process.GetRuntimeInstances().OfType <DkmNativeRuntimeInstance>().FirstOrDefault(el => el.Id.RuntimeType == DebugHelpers.NullcRuntimeGuid);
                            var nullcModuleInstance = nullcNativeRuntime.GetModuleInstances().OfType <DkmNativeModuleInstance>().FirstOrDefault(el => el.Module != null && el.Module.CompilerId.VendorId == DebugHelpers.NullcCompilerGuid);

                            address = DkmNativeInstructionAddress.Create(nullcNativeRuntime, nullcModuleInstance, (uint)(instructionPointer - processData.moduleBase), new DkmInstructionAddress.CPUInstruction(instructionPointer));
                        }
                        else
                        {
                            var nullcNativeRuntime  = process.GetRuntimeInstances().OfType <DkmCustomRuntimeInstance>().FirstOrDefault(el => el.Id.RuntimeType == DebugHelpers.NullcRuntimeGuid);
                            var nullcModuleInstance = nullcNativeRuntime.GetModuleInstances().OfType <DkmCustomModuleInstance>().FirstOrDefault(el => el.Module != null && el.Module.CompilerId.VendorId == DebugHelpers.NullcCompilerGuid);

                            address = DkmCustomInstructionAddress.Create(nullcNativeRuntime, nullcModuleInstance, null, instructionPointer, null, new DkmInstructionAddress.CPUInstruction(instructionPointer));
                        }

                        completionRoutine(new DkmGetInstructionAddressAsyncResult(address, true));
                        return;
                    }
                }

                process.GetInstructionAddress(workList, instructionPointer, completionRoutine);
            }
Esempio n. 9
0
            DkmStackWalkFrame[] IDkmCallStackFilter.FilterNextFrame(DkmStackContext stackContext, DkmStackWalkFrame input)
            {
                if (input == null) // null input frame indicates the end of the call stack. This sample does nothing on end-of-stack.
                {
                    var processData = DebugHelpers.GetOrCreateDataItem <NullcStackFilterDataItem>(stackContext.InspectionSession.Process);

                    processData.nullcFramePosition = 1;

                    return(null);
                }

                if (input.InstructionAddress == null)
                {
                    return(new DkmStackWalkFrame[1] {
                        input
                    });
                }

                if (input.InstructionAddress.ModuleInstance != null)
                {
                    if (input.BasicSymbolInfo != null && input.BasicSymbolInfo.MethodName == "ExecutorRegVm::RunCode")
                    {
                        var processData = DebugHelpers.GetOrCreateDataItem <NullcStackFilterDataItem>(input.Thread.Process);

                        InitNullcDebugFunctions(processData, input.RuntimeInstance);

                        if (processData.nullcIsMissing)
                        {
                            return(new DkmStackWalkFrame[1] {
                                input
                            });
                        }

                        string vmInstructionStr = ExecuteExpression("instruction - codeBase", stackContext, input, true);

                        string ptrValue = DebugHelpers.Is64Bit(input.Thread.Process) ? "longValue" : "intValue";

                        string vmDataOffsetStr = ExecuteExpression($"(unsigned long long)regFilePtr[1].{ptrValue} - (unsigned long long)rvm->dataStack.data", stackContext, input, true);

                        if (vmInstructionStr != null && vmDataOffsetStr != null)
                        {
                            ulong vmInstruction = ulong.Parse(vmInstructionStr);

                            string stackFrameDesc = ExecuteExpression($"((char*(*)(unsigned, unsigned)){processData.nullcDebugGetVmAddressLocation})({vmInstruction}, 0),sb", stackContext, input, false);

                            var nullcCustomRuntime = input.Thread.Process.GetRuntimeInstances().OfType <DkmCustomRuntimeInstance>().FirstOrDefault(el => el.Id.RuntimeType == DebugHelpers.NullcVmRuntimeGuid);

                            if (stackFrameDesc != null && nullcCustomRuntime != null)
                            {
                                var flags = input.Flags;

                                flags = flags & ~(DkmStackWalkFrameFlags.NonuserCode | DkmStackWalkFrameFlags.UserStatusNotDetermined);
                                flags = flags | DkmStackWalkFrameFlags.InlineOptimized;

                                DkmCustomModuleInstance nullcModuleInstance = nullcCustomRuntime.GetModuleInstances().OfType <DkmCustomModuleInstance>().FirstOrDefault(el => el.Module != null && el.Module.CompilerId.VendorId == DebugHelpers.NullcCompilerGuid);

                                if (nullcModuleInstance != null)
                                {
                                    DkmInstructionAddress instructionAddress = DkmCustomInstructionAddress.Create(nullcCustomRuntime, nullcModuleInstance, null, vmInstruction, null, null);

                                    var rawAnnotations = new List <DkmStackWalkFrameAnnotation>();

                                    // Additional unique request id
                                    rawAnnotations.Add(DkmStackWalkFrameAnnotation.Create(DebugHelpers.NullcCallStackDataBaseGuid, ulong.Parse(vmDataOffsetStr)));

                                    var annotations = new ReadOnlyCollection <DkmStackWalkFrameAnnotation>(rawAnnotations);

                                    DkmStackWalkFrame frame = DkmStackWalkFrame.Create(stackContext.Thread, instructionAddress, input.FrameBase, input.FrameSize, flags, stackFrameDesc, input.Registers, annotations, nullcModuleInstance, null, null);

                                    return(new DkmStackWalkFrame[2] {
                                        frame, input
                                    });
                                }
                            }
                        }
                    }

                    return(new DkmStackWalkFrame[1] {
                        input
                    });
                }

                // Currently we want to provide info only for JiT frames
                if (!input.Flags.HasFlag(DkmStackWalkFrameFlags.UserStatusNotDetermined))
                {
                    return(new DkmStackWalkFrame[1] {
                        input
                    });
                }

                try
                {
                    var processData = DebugHelpers.GetOrCreateDataItem <NullcStackFilterDataItem>(input.Thread.Process);

                    InitNullcDebugFunctions(processData, input.RuntimeInstance);

                    if (processData.nullcIsMissing)
                    {
                        return new DkmStackWalkFrame[1] {
                                   input
                        }
                    }
                    ;

                    string stackFrameDesc = ExecuteExpression($"((char*(*)(void*, unsigned)){processData.nullcDebugGetNativeAddressLocation})((void*)0x{input.InstructionAddress.CPUInstructionPart.InstructionPointer:X}, 0),sb", stackContext, input, false);

                    if (stackFrameDesc != null)
                    {
                        var flags = input.Flags;

                        flags = flags & ~(DkmStackWalkFrameFlags.NonuserCode | DkmStackWalkFrameFlags.UserStatusNotDetermined);

                        if (stackFrameDesc == "[Transition to nullc]")
                        {
                            return(new DkmStackWalkFrame[1] {
                                DkmStackWalkFrame.Create(stackContext.Thread, input.InstructionAddress, input.FrameBase, input.FrameSize, flags, stackFrameDesc, input.Registers, input.Annotations)
                            });
                        }

                        DkmStackWalkFrame frame = null;

                        var nullcCustomRuntime = input.Thread.Process.GetRuntimeInstances().OfType <DkmCustomRuntimeInstance>().FirstOrDefault(el => el.Id.RuntimeType == DebugHelpers.NullcRuntimeGuid);
                        var nullcNativeRuntime = DebugHelpers.useDefaultRuntimeInstance ? input.Thread.Process.GetNativeRuntimeInstance() : input.Thread.Process.GetRuntimeInstances().OfType <DkmNativeRuntimeInstance>().FirstOrDefault(el => el.Id.RuntimeType == DebugHelpers.NullcRuntimeGuid);

                        if (DebugHelpers.useNativeInterfaces ? nullcNativeRuntime != null : nullcCustomRuntime != null)
                        {
                            DkmModuleInstance nullcModuleInstance;

                            if (DebugHelpers.useNativeInterfaces)
                            {
                                nullcModuleInstance = nullcNativeRuntime.GetModuleInstances().OfType <DkmNativeModuleInstance>().FirstOrDefault(el => el.Module != null && el.Module.CompilerId.VendorId == DebugHelpers.NullcCompilerGuid);
                            }
                            else
                            {
                                nullcModuleInstance = nullcCustomRuntime.GetModuleInstances().OfType <DkmCustomModuleInstance>().FirstOrDefault(el => el.Module != null && el.Module.CompilerId.VendorId == DebugHelpers.NullcCompilerGuid);
                            }

                            if (nullcModuleInstance != null)
                            {
                                // If the top of the call stack is a nullc frame, nullc call stack wont have an entry for it and we start from 0, otherwise we start from default value of 1
                                if (input.Flags.HasFlag(DkmStackWalkFrameFlags.TopFrame))
                                {
                                    processData.nullcFramePosition = 0;
                                }

                                string stackFrameBase = ExecuteExpression($"((unsigned(*)(unsigned)){processData.nullcDebugGetReversedStackDataBase})({processData.nullcFramePosition})", stackContext, input, true);

                                processData.nullcFramePosition++;

                                if (int.TryParse(stackFrameBase, out int stackFrameBaseValue))
                                {
                                    DkmInstructionAddress instructionAddress;

                                    if (DebugHelpers.useNativeInterfaces)
                                    {
                                        var rva = (uint)(input.InstructionAddress.CPUInstructionPart.InstructionPointer - nullcModuleInstance.BaseAddress);

                                        instructionAddress = DkmNativeInstructionAddress.Create(nullcNativeRuntime, nullcModuleInstance as DkmNativeModuleInstance, rva, input.InstructionAddress.CPUInstructionPart);
                                    }
                                    else
                                    {
                                        instructionAddress = DkmCustomInstructionAddress.Create(nullcCustomRuntime, nullcModuleInstance as DkmCustomModuleInstance, null, input.InstructionAddress.CPUInstructionPart.InstructionPointer, null, input.InstructionAddress.CPUInstructionPart);
                                    }

                                    var rawAnnotations = new List <DkmStackWalkFrameAnnotation>();

                                    // Additional unique request id
                                    rawAnnotations.Add(DkmStackWalkFrameAnnotation.Create(DebugHelpers.NullcCallStackDataBaseGuid, (ulong)(stackFrameBaseValue)));

                                    var annotations = new ReadOnlyCollection <DkmStackWalkFrameAnnotation>(rawAnnotations);

                                    frame = DkmStackWalkFrame.Create(stackContext.Thread, instructionAddress, input.FrameBase, input.FrameSize, flags, stackFrameDesc, input.Registers, annotations, nullcModuleInstance, null, null);
                                }
                            }
                        }

                        if (frame == null)
                        {
                            frame = DkmStackWalkFrame.Create(stackContext.Thread, input.InstructionAddress, input.FrameBase, input.FrameSize, flags, stackFrameDesc, input.Registers, input.Annotations);
                        }

                        return(new DkmStackWalkFrame[1] {
                            frame
                        });
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Failed to evaluate: " + ex.ToString());
                }

                return(new DkmStackWalkFrame[1] {
                    input
                });
            }
Esempio n. 10
0
            void IDkmProcessExecutionNotification.OnProcessPause(DkmProcess process, DkmProcessExecutionCounters processCounters)
            {
                try
                {
                    ulong?moduleBaseOpt = DebugHelpers.ReadPointerVariable(process, "nullcModuleStartAddress");

                    // Check if nullc is available
                    if (moduleBaseOpt == null)
                    {
                        return;
                    }

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

                    if (processData.language == null)
                    {
                        processData.compilerId = new DkmCompilerId(DebugHelpers.NullcCompilerGuid, DebugHelpers.NullcLanguageGuid);

                        processData.language = DkmLanguage.Create("nullc", processData.compilerId);
                    }

                    // Create VM runtime and module
                    if (processData.vmRuntimeInstance == null)
                    {
                        DkmRuntimeInstanceId runtimeId = new DkmRuntimeInstanceId(DebugHelpers.NullcVmRuntimeGuid, 0);

                        processData.vmRuntimeInstance = DkmCustomRuntimeInstance.Create(process, runtimeId, null);
                    }

                    if (processData.vmModule == null)
                    {
                        DkmModuleId moduleId = new DkmModuleId(Guid.NewGuid(), DebugHelpers.NullcSymbolProviderGuid);

                        processData.vmModule = DkmModule.Create(moduleId, "nullc.vm.code", processData.compilerId, process.Connection, null);
                    }

                    if (processData.vmModuleInstance == null)
                    {
                        DkmDynamicSymbolFileId symbolFileId = DkmDynamicSymbolFileId.Create(DebugHelpers.NullcSymbolProviderGuid);

                        processData.vmModuleInstance = DkmCustomModuleInstance.Create("nullc_vm", "nullc.vm.code", 0, processData.vmRuntimeInstance, null, symbolFileId, DkmModuleFlags.None, DkmModuleMemoryLayout.Unknown, 0, 1, 0, "nullc vm code", false, null, null, null);

                        processData.vmModuleInstance.SetModule(processData.vmModule, true); // Can use reload?
                    }

                    ulong moduleBase = moduleBaseOpt.GetValueOrDefault(0);

                    uint moduleSize = (uint)(DebugHelpers.ReadPointerVariable(process, "nullcModuleEndAddress").GetValueOrDefault(0) - moduleBase);

                    // Create JiT runtime and module
                    if (moduleBase != 0 && moduleSize != 0)
                    {
                        if (processData.runtimeInstance == null && processData.nativeRuntimeInstance == null)
                        {
                            DkmRuntimeInstanceId runtimeId = new DkmRuntimeInstanceId(DebugHelpers.NullcRuntimeGuid, 0);

                            if (DebugHelpers.useNativeInterfaces)
                            {
                                processData.nativeRuntimeInstance = DebugHelpers.useDefaultRuntimeInstance ? process.GetNativeRuntimeInstance() : DkmNativeRuntimeInstance.Create(process, runtimeId, DkmRuntimeCapabilities.None, process.GetNativeRuntimeInstance(), null);
                            }
                            else
                            {
                                processData.runtimeInstance = DkmCustomRuntimeInstance.Create(process, runtimeId, null);
                            }
                        }

                        if (processData.module == null)
                        {
                            DkmModuleId moduleId = new DkmModuleId(Guid.NewGuid(), DebugHelpers.NullcSymbolProviderGuid);

                            processData.module = DkmModule.Create(moduleId, "nullc.embedded.code", processData.compilerId, process.Connection, null);
                        }

                        if (processData.moduleInstance == null && processData.nativeModuleInstance == null)
                        {
                            DkmDynamicSymbolFileId symbolFileId = DkmDynamicSymbolFileId.Create(DebugHelpers.NullcSymbolProviderGuid);

                            if (DebugHelpers.useNativeInterfaces)
                            {
                                processData.nativeModuleInstance = DkmNativeModuleInstance.Create("nullc", "nullc.embedded.code", 0, null, symbolFileId, DkmModuleFlags.None, DkmModuleMemoryLayout.Unknown, 1, "nullc embedded code", processData.nativeRuntimeInstance, moduleBase, moduleSize, Microsoft.VisualStudio.Debugger.Clr.DkmClrHeaderStatus.NativeBinary, false, null, null, null);

                                processData.nativeModuleInstance.SetModule(processData.module, true); // Can use reload?
                            }
                            else
                            {
                                processData.moduleInstance = DkmCustomModuleInstance.Create("nullc", "nullc.embedded.code", 0, processData.runtimeInstance, null, symbolFileId, DkmModuleFlags.None, DkmModuleMemoryLayout.Unknown, moduleBase, 1, moduleSize, "nullc embedded code", false, null, null, null);

                                processData.moduleInstance.SetModule(processData.module, true); // Can use reload?
                            }
                        }
                    }

                    // Update bytecode
                    var moduleBytecodeVersion = DebugHelpers.ReadPointerVariable(process, "nullcModuleBytecodeVersion").GetValueOrDefault(0);

                    if (processData.moduleBytecodeLocation != 0 && moduleBytecodeVersion != processData.moduleBytecodeVersion)
                    {
                        processData.moduleBytecodeLocation = 0;
                        processData.moduleBytecodeSize     = 0;
                        processData.moduleBytecodeRaw      = null;
                        processData.bytecode = null;
                    }

                    if (processData.moduleBytecodeLocation == 0)
                    {
                        processData.moduleBytecodeLocation = DebugHelpers.ReadPointerVariable(process, "nullcModuleBytecodeLocation").GetValueOrDefault(0);
                        processData.moduleBytecodeSize     = DebugHelpers.ReadPointerVariable(process, "nullcModuleBytecodeSize").GetValueOrDefault(0);
                        processData.moduleBytecodeVersion  = moduleBytecodeVersion;

                        if (processData.moduleBytecodeLocation != 0)
                        {
                            processData.moduleBytecodeRaw = new byte[processData.moduleBytecodeSize];
                            process.ReadMemory(processData.moduleBytecodeLocation, DkmReadMemoryFlags.None, processData.moduleBytecodeRaw);

                            processData.bytecode = new NullcBytecode();
                            processData.bytecode.ReadFrom(processData.moduleBytecodeRaw, DebugHelpers.Is64Bit(process));

                            // Notify local component about bytecode update
                            var message = DkmCustomMessage.Create(process.Connection, process, DebugHelpers.NullcReloadSymbolsMessageGuid, 1, null, null);

                            message.SendHigher();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("OnProcessPause failed with: " + ex.ToString());
                }
            }
Esempio n. 11
0
            void IDkmRuntimeStepper.NotifyStepComplete(DkmRuntimeInstance runtimeInstance, DkmStepper stepper)
            {
                var processData = DebugHelpers.GetOrCreateDataItem <NullcRemoteProcessDataItem>(runtimeInstance.Process);

                ClearStepBreakpoints(processData);
            }
Esempio n. 12
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();
                }
            }