microsoft / ConcordExtensibilitySamples

Visual Studio Debug Engine Extensibility Samples
Other
121 stars 50 forks source link

Extending call-stack window with full ReturnStackFrame #113

Closed Juliean closed 5 months ago

Juliean commented 5 months ago

I have an implementation of stackfull coroutines, similar to a fiber, and want to extend the call-stack window to show the original stack. I am able to assemble one single frame from the source-stack using IDkmCallStackFilter:

// create annotated frame to mark transit
var annotatedFrame = DkmStackWalkFrame.Create(
    stackContext.Thread,
    null,
    input.FrameBase,
    input.FrameSize,
    DkmStackWalkFrameFlags.None,
    "[Yield Return]",
    null,
    null
);

// lookup ExecutionState.oldRSP
var previousRsp = input.Process.ReadMemory<ulong>(ptr + 80, DkmReadMemoryFlags.None);
// lookup return-address, after all register have been popped
var previousInstruction = input.Process.ReadMemory<ulong>(previousRsp + 5 * 8, DkmReadMemoryFlags.None);

var instruction = input.Process.CreateNativeInstructionAddress(previousInstruction);

var previousFrame = DkmStackWalkFrame.Create(
    stackContext.Thread,
    instruction,
    previousRsp,
    60, // hardcoded frame-size for now
    DkmStackWalkFrameFlags.ReturnStackFrame,
    null, 
    input.Registers,
    input.Annotations);

return new DkmStackWalkFrame[]
{
    frame,
    annotatedFrame,
    previousFrame
};

The added frame(s) will show up properly, and allow me to step to the source-location that the coroutine started from. However, it will only contain that one frame, and nothing else.

Is there any way to extend this to include all frames from the original stack? I have seen some leads, like DkmStackContext.GetNextFrames, but I don't have a DkmWorkList here, and also I want the frames from another stack.

I would prefer an automatic solution that will get the native stack-walk handler to resume the stack, but if this is not possible I also would not mind a manual way - but I'm kind of some information, like the size of the frames, or potential frame-pointers to calculate all the return-addresses + frameBases.

Juliean commented 5 months ago

I did end up solving it myself, it required creating a custom DkmStackWalkContext, with a modified ThreadContext (see https://stackoverflow.com/a/78176694/13081625 in case someone else has to solve this problem).