void IFunctionTracer.OnEntryBreakpointHit(DkmRuntimeBreakpoint bp, DkmThread thread, bool hasException) { // The function was just entered. Install the exit breakpoint on the calling thread at the // return address, and notify any listeners. DkmStackWalkFrame frame = thread.GetTopStackWalkFrame(bp.RuntimeInstance); bool suppressExitBreakpoint = false; if (OnFunctionEntered != null) { OnFunctionEntered(frame, frameAnalyzer, out suppressExitBreakpoint); } if (!suppressExitBreakpoint) { ulong ret = frame.VscxGetReturnAddress(); DkmInstructionAddress retAddr = thread.Process.CreateNativeInstructionAddress(ret); DkmRuntimeInstructionBreakpoint exitBp = DkmRuntimeInstructionBreakpoint.Create( Guids.Source.FunctionTraceExit, thread, retAddr, false, null); // Capture the value of every argument now, since when the exit breakpoint gets hit, the // target function will have already returned and its frame will be cleaned up. exitBp.SetDataItem(DkmDataCreationDisposition.CreateAlways, new FunctionTraceEntryDataItem { EntryArgumentValues = frameAnalyzer.GetAllArgumentValues(frame) }); exitBp.SetDataItem(DkmDataCreationDisposition.CreateAlways, new FunctionTraceDataItem { Tracer = this }); exitBp.Enable(); } }
internal static DkmEvaluationResult GetLuaFunctionChildAtIndex(DkmInspectionContext inspectionContext, DkmStackWalkFrame stackFrame, string fullName, LuaClosureData value, int index) { var process = stackFrame.Process; var processData = DebugHelpers.GetOrCreateDataItem <LuaLocalProcessData>(process); if (index == 0) { if (value == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, "[function]", $"{fullName}.!function", "null", DkmEvaluationResultFlags.Invalid, null)); } var functionData = value.ReadFunction(process); if (functionData == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, "[function]", $"{fullName}.!function", "[internal error: failed to read Proto]", DkmEvaluationResultFlags.Invalid, null)); } string source = functionData.ReadSource(process); if (source == null) { return(DkmFailedEvaluationResult.Create(inspectionContext, stackFrame, "[function]", $"{fullName}.!function", "[internal error: failed to read source]", DkmEvaluationResultFlags.Invalid, null)); } int line = functionData.definitionStartLine_opt; DkmEvaluationResultCategory category = DkmEvaluationResultCategory.Method; DkmEvaluationResultTypeModifierFlags typeModifiers = DkmEvaluationResultTypeModifierFlags.None; DkmEvaluationResultAccessType access = DkmEvaluationResultAccessType.Public; DkmEvaluationResultStorageType storage = DkmEvaluationResultStorageType.Global; LuaAddressEntityData entityData = new LuaAddressEntityData { source = source, line = line, functionAddress = 0, functionInstructionPointer = 0, }; var entityDataBytes = entityData.Encode(); DkmInstructionAddress instructionAddress = DkmCustomInstructionAddress.Create(processData.runtimeInstance, processData.moduleInstance, entityDataBytes, (ulong)((line << 16) + 0), null, null); DkmDataAddress dataAddress = DkmDataAddress.Create(processData.runtimeInstance, value.functionAddress, instructionAddress); return(DkmSuccessEvaluationResult.Create(inspectionContext, stackFrame, "[function]", $"{fullName}.!function", DkmEvaluationResultFlags.ReadOnly | DkmEvaluationResultFlags.Address, $"{source}:{line}", null, "Proto*", category, access, storage, typeModifiers, dataAddress, null, null, null)); } Debug.Assert(false, "Invalid child index"); return(null); }
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 }); }