[lldb-dev] Continue misfiring after expression evaluation

Kopec, Matt matt.kopec at intel.com
Thu Dec 6 13:01:25 PST 2012


Daniel and I saw the same behaviour as Andy on Mac recently though we reproduced it differently. If I recall what was happening on Mac correctly, the expression to be evaluated didn't require MCJIT/executing in the target process (for instance, printing a register value - expr pc) but on Linux did require MCJIT/running in the target. However, evaluating a function call expression did reproduce the problem on Mac since this did go through the MCJIT route. Could you try this to see if it reproduces the problem?

Thanks,
Matt
________________________________________
From: lldb-dev-bounces at cs.uiuc.edu [lldb-dev-bounces at cs.uiuc.edu] on behalf of Jim Ingham [jingham at apple.com]
Sent: Thursday, December 06, 2012 2:05 PM
To: Kaylor, Andrew
Cc: lldb-dev at cs.uiuc.edu
Subject: Re: [lldb-dev] Continue misfiring after expression evaluation

Yeah, after taking a quick look at the code last night, I'm curious too.

I am in the middle of something right now, but as soon as I get a chance, I'll step through it and see what's going on.

Thinking about it a little bit more, I can't see any reason why Process::RunThreadPlan should not clear the evidence of its work from the plan stack.  It should only do this if the plan succeeds, or if it is going to unwind on error.  If you're going to stop because you hit a breakpoint in the middle of a function call, you don't want to change the plan stack state (just like you don't want to restore the old stop info.)  And I think it would be wrong to erase the whole completed plan stack, better to mark the position on entry, and restore it to the state it had when you entered RunThreadPlan.

Jim

On Dec 6, 2012, at 10:54 AM, "Kaylor, Andrew" <andrew.kaylor at intel.com> wrote:

> I updated to the latest code and I'm still seeing the same behavior.
>
> That is, thread_plan_sp->RestoreThreadState() is being called, and it does restore the stop info for the thread to the old stop info, but when Thread::SetupForResume() calls Thread::GetStopInfo() that function creates stop info based on the completed thread plan stack rather than using m_actual_stop_info_sp.
>
> Any suggestions?  I'd be curious to know why this doesn't happen on Mac OS X because it looks like it would.
>
> -Andy
>
> -----Original Message-----
> From: lldb-dev-bounces at cs.uiuc.edu [mailto:lldb-dev-bounces at cs.uiuc.edu] On Behalf Of Kaylor, Andrew
> Sent: Wednesday, December 05, 2012 4:38 PM
> To: Jim Ingham
> Cc: lldb-dev at cs.uiuc.edu
> Subject: Re: [lldb-dev] Continue misfiring after expression evaluation
>
> Hi Jim,
>
> I am working with an old version of the code, so things were in a bit different state for me.  I was seeing Thread::RestoreThreadStateFromCheckpoint() being called.  The problem is that when Thread::SetupForResume() calls Thread::GetStopInfo(), the latter does this:
>
>    ThreadPlanSP plan_sp (GetCompletedPlan());
>    if (plan_sp && plan_sp->PlanSucceeded())
>        return StopInfo::CreateStopReasonWithPlan (plan_sp, GetReturnValueObject());
>    else
>    {
>        ProcessSP process_sp (GetProcess());
>        if (process_sp
>            && m_actual_stop_info_sp
>            && m_actual_stop_info_sp->IsValid()
>            && m_thread_stop_reason_stop_id == process_sp->GetStopID())
>            return m_actual_stop_info_sp;
>        else
>            return GetPrivateStopReason ();
>    }
>
> Since the completed stop plan from the expression command is still around, the stop info comes from there.  The thread's m_actual_stop_info seems to be correct, but the code doesn't get to the point where it would use it.
>
> I'll update to the latest code and see if this is still happening, but I wanted to tell you what I knew while I was still in a known state.  I'll let you know what happens with the new code.
>
> -Andy
>
> -----Original Message-----
> From: Jim Ingham [mailto:jingham at apple.com]
> Sent: Wednesday, December 05, 2012 3:50 PM
> To: Kaylor, Andrew
> Cc: lldb-dev at cs.uiuc.edu
> Subject: Re: [lldb-dev] Continue misfiring after expression evaluation
>
> I don't see this happening on Mac OS X.  That test succeeds, and I don't see the behavior you describe.
>
> You should not need to clear the completed plan stack.  The way it is supposed to work is as follows:
>
> Running functions is always done by Process::RunThreadPlan.  After the ThreadPlanCallFunction gets done running in that function, we do this bit of code:
>
>        // Restore the thread state if we are going to discard the plan execution.
>
>        if (return_value == eExecutionCompleted || discard_on_error)
>        {
>            thread_plan_sp->RestoreThreadState();
>        }
>
> That should set the StopInfo that was squirreled away in Thread::CheckpointThreadState back as the current StopInfo for the thread.  Is that getting called?  If not, why not?  If it is getting called, why isn't it succeeding in resetting the thread's StopInfo back to the old reason?
>
> Note, up till a couple of weeks ago this work was done in the DoTakedown method of ThreadPlanCallFunction, but I moved resetting the StopInfo out of that function (which gets called while the stop event for the function call is still being processed) to here, because otherwise it might trigger the original StopInfo's PerformAction while you are in the middle of handing the ThreadPlanCallFunction's execution, which isn't right.
>
> Hope that helps.
>
> Jim
>
> On Dec 5, 2012, at 3:28 PM, "Kaylor, Andrew" <andrew.kaylor at intel.com> wrote:
>
>> Hi all,
>>
>> I've been debugging a problem on Linux where if you hit a breakpoint, then evaluate an expression that requires JITing, then continue LLDB will break at the line you were already on.  I don't know if this problem is specific to Linux, but that's where I'm debugging it.  This problem appears in the 'lang/c/setvalues/TestSetValues.py' test case, but can also be reproduced manually.
>>
>> What I'm seeing is that when the 'continue' handling calls Thread::SetupForResume() the current Thread reports its stop reason as 'eStopReasonPlanComplete' because the ThreadPlan for evaluating the expression is still on the completed plans stack.  As a result, the ThreadPlanStepOverBreakpoint plan doesn't get queued.  If I add calls to 'm_completed_plan_stack.clear()' and 'm_discarded_plan_stack.clear()' at the top of the 'if (GetResumeState() == eStateSuspended)' block in Thread::SetupForResume() then everything works as expected.
>>
>> Obviously, that feels like a pretty risky thing to do, at best.  It seems like the expression command handling should have done something to clear the completed plan stack when it was finished, but as of yet I haven't found a place where that is appropriate.
>>
>> Can anyone give me guidance on this issue?
>>
>> Thanks,
>> Andy
>> _______________________________________________
>> lldb-dev mailing list
>> lldb-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
>
>
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

_______________________________________________
lldb-dev mailing list
lldb-dev at cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev




More information about the lldb-dev mailing list