mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 10:58:11 +08:00
[lldb][Target] RunThreadPlan to save/restore the ExecutionContext's frame if one exists (#134097)
When using `SBFrame::EvaluateExpression` on a frame that's not the currently selected frame, we would sometimes run into errors such as: ``` error: error: The context has changed before we could JIT the expression! error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression ``` During expression parsing, we call `RunStaticInitializers`. On our internal fork this happens quite frequently because any usage of, e.g., function pointers, will inject ptrauth fixup code into the expression. The static initializers are run using `RunThreadPlan`. The `ExecutionContext::m_frame_sp` going into the `RunThreadPlan` is the `SBFrame` that we called `EvaluateExpression` on. LLDB then tries to save this frame to restore it after the thread-plan ran (the restore occurs by unconditionally overwriting whatever is in `ExecutionContext::m_frame_sp`). However, if the `selected_frame_sp` is not the same as the `SBFrame`, then `RunThreadPlan` would set the `ExecutionContext`'s frame to a different frame than what we started with. When we `PrepareToExecuteJITExpression`, LLDB checks whether the `ExecutionContext` frame changed from when we initially `EvaluateExpression`, and if did, bails out with the error above. One such test-case is attached. This currently passes regardless of the fix because our ptrauth static initializers code isn't upstream yet. But the plan is to upstream it soon. This patch addresses the issue by saving/restoring the frame of the incoming `ExecutionContext`, if such frame exists. Otherwise, fall back to using the selected frame. rdar://147456589
This commit is contained in:
@@ -5080,7 +5080,13 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
|
||||
return eExpressionSetupError;
|
||||
}
|
||||
|
||||
StackID ctx_frame_id = selected_frame_sp->GetStackID();
|
||||
// If the ExecutionContext has a frame, we want to make sure to save/restore
|
||||
// that frame into exe_ctx. This can happen when we run expressions from a
|
||||
// non-selected SBFrame, in which case we don't want some thread-plan
|
||||
// to overwrite the ExecutionContext frame.
|
||||
StackID ctx_frame_id = exe_ctx.HasFrameScope()
|
||||
? exe_ctx.GetFrameRef().GetStackID()
|
||||
: selected_frame_sp->GetStackID();
|
||||
|
||||
// N.B. Running the target may unset the currently selected thread and frame.
|
||||
// We don't want to do that either, so we should arrange to reset them as
|
||||
|
||||
Reference in New Issue
Block a user