Skip to content

Cppia debugger: read a function's variables from the right frame base - #1426

Open
robknopf wants to merge 1 commit into
HaxeFoundation:masterfrom
robknopf:fix-cppia-scriptable-frame
Open

robknopf wants to merge 1 commit into
HaxeFoundation:masterfrom
robknopf:fix-cppia-scriptable-frame

Conversation

@robknopf

Copy link
Copy Markdown

With HXCPP_STACK_SCRIPTABLE, the debugger reads a cppia function's this and local variables relative to the function's hx::StackFrame, taking the frame base to be inStack - stackSize. That isn't where the frame starts.

At a call, ctx->frame is set to the stack pointer before this and the arguments are pushed (pushArgs plus AutoStack), and the function's StackLayout already counts the this slot and the arguments (the layout starts at sizeof(void *) and CppiaStackVar::link adds each argument). runFunction then does pointer += stackSize, which allocates the whole layout again on top of what was pushed, and CPPIA_STACK_FRAME pushes the StackFrame there. So the frame sits at

frame + sizeof(hx::Object *) + argBytes + stackSize

and inStack - stackSize lands on the first argument (or on the first local, when there are none), not on this.

Symptom: with hxcpp-debugger, inspecting variables inside a cppia function that has arguments reads an Int argument as this and crashes the debuggee; locals read from the wrong slots.

Fix: scriptableBase() computes the base from the StackFrame by subtracting the layout size, the this slot and the arguments' bytes (from sTypeSize[argType]), and getScriptableVariables, getScriptableValue and setScriptableValue use it. The closure path (CppiaClosure::doRun) writes this to ctx->frame and lays the stack out the same way, so it's covered as well.

This is the variable-reading half of what I've been running for a few months in a fork, together with hxcpp-debugger, to debug hot-reloaded cppia code (whirlinggizmo/hotreload-hx). It's independent of the HXCPP_API_LEVEL >= 500 gate on the cppia debug hook: with the gate, the fix matters on Haxe 5; without it (in my fork), on 4.x too. This PR leaves the gate alone.

With HXCPP_STACK_SCRIPTABLE, the debugger reads a cppia function's `this` and
variables relative to its hx::StackFrame, taking the frame base to be
`inStack - stackSize`. That isn't where the frame starts. At a call, ctx->frame is
set to the stack pointer before `this` and the arguments are pushed (pushArgs /
AutoStack), and the function's StackLayout already counts the `this` slot and the
arguments, so runFunction's `pointer += stackSize` allocates the whole layout again on
top of them. The StackFrame is then pushed at

    frame + sizeof(hx::Object *) + argBytes + stackSize

so `inStack - stackSize` lands on the first argument (or the first local, with no
arguments), not on `this`. Inspecting variables in a cppia function with arguments
read an Int argument as `this` and crashed; locals read from the wrong slots.

scriptableBase() computes the base from the StackFrame by subtracting the layout
size, the `this` slot and the arguments' bytes, and getScriptableVariables,
getScriptableValue and setScriptableValue use it. The closure path (CppiaClosure::doRun)
writes `this` to ctx->frame and lays out the same, so it's covered too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant