130fdc8d8SChris Lattner //===-- ThreadPlanStepInstruction.cpp ---------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner 
1130fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepInstruction.h"
1230fdc8d8SChris Lattner 
1330fdc8d8SChris Lattner // C Includes
1430fdc8d8SChris Lattner // C++ Includes
1530fdc8d8SChris Lattner // Other libraries and framework includes
1630fdc8d8SChris Lattner // Project includes
1730fdc8d8SChris Lattner #include "lldb/lldb-private-log.h"
1830fdc8d8SChris Lattner #include "lldb/Core/Log.h"
1930fdc8d8SChris Lattner #include "lldb/Core/Stream.h"
2030fdc8d8SChris Lattner #include "lldb/Target/Process.h"
21f4b47e15SGreg Clayton #include "lldb/Target/RegisterContext.h"
22f4b47e15SGreg Clayton #include "lldb/Target/RegisterContext.h"
23f4b47e15SGreg Clayton #include "lldb/Target/StopInfo.h"
24f4b47e15SGreg Clayton #include "lldb/Target/Target.h"
2530fdc8d8SChris Lattner 
2630fdc8d8SChris Lattner using namespace lldb;
2730fdc8d8SChris Lattner using namespace lldb_private;
2830fdc8d8SChris Lattner 
2930fdc8d8SChris Lattner //----------------------------------------------------------------------
3030fdc8d8SChris Lattner // ThreadPlanStepInstruction: Step over the current instruction
3130fdc8d8SChris Lattner //----------------------------------------------------------------------
3230fdc8d8SChris Lattner 
3330fdc8d8SChris Lattner ThreadPlanStepInstruction::ThreadPlanStepInstruction
3430fdc8d8SChris Lattner (
3530fdc8d8SChris Lattner     Thread &thread,
3630fdc8d8SChris Lattner     bool step_over,
3730fdc8d8SChris Lattner     bool stop_other_threads,
3830fdc8d8SChris Lattner     Vote stop_vote,
3930fdc8d8SChris Lattner     Vote run_vote
4030fdc8d8SChris Lattner ) :
41b01e742aSJim Ingham     ThreadPlan (ThreadPlan::eKindStepInstruction, "Step over single instruction", thread, stop_vote, run_vote),
4230fdc8d8SChris Lattner     m_instruction_addr (0),
431ee0d4f7SBenjamin Kramer     m_stop_other_threads (stop_other_threads),
446b35c86fSJim Ingham     m_step_over (step_over)
451ee0d4f7SBenjamin Kramer {
4630fdc8d8SChris Lattner     m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
47*b57e4a1bSJason Molenda     StackFrameSP m_start_frame_sp(m_thread.GetStackFrameAtIndex(0));
48a7d4822cSJim Ingham     m_stack_id = m_start_frame_sp->GetStackID();
49a7d4822cSJim Ingham 
50a7d4822cSJim Ingham     m_start_has_symbol = m_start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL;
51a7d4822cSJim Ingham 
52*b57e4a1bSJason Molenda     StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1);
53886a3e2cSJim Ingham     if (parent_frame_sp)
54886a3e2cSJim Ingham         m_parent_frame_id = parent_frame_sp->GetStackID();
5530fdc8d8SChris Lattner }
5630fdc8d8SChris Lattner 
5730fdc8d8SChris Lattner ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
5830fdc8d8SChris Lattner {
5930fdc8d8SChris Lattner }
6030fdc8d8SChris Lattner 
6130fdc8d8SChris Lattner void
6230fdc8d8SChris Lattner ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level)
6330fdc8d8SChris Lattner {
6430fdc8d8SChris Lattner     if (level == lldb::eDescriptionLevelBrief)
6530fdc8d8SChris Lattner     {
6630fdc8d8SChris Lattner         if (m_step_over)
6730fdc8d8SChris Lattner             s->Printf ("instruction step over");
6830fdc8d8SChris Lattner         else
6930fdc8d8SChris Lattner             s->Printf ("instruction step into");
7030fdc8d8SChris Lattner     }
7130fdc8d8SChris Lattner     else
7230fdc8d8SChris Lattner     {
7330fdc8d8SChris Lattner         s->Printf ("Stepping one instruction past ");
7430fdc8d8SChris Lattner         s->Address(m_instruction_addr, sizeof (addr_t));
75a7d4822cSJim Ingham         if (!m_start_has_symbol)
76a7d4822cSJim Ingham             s->Printf(" which has no symbol");
77a7d4822cSJim Ingham 
7830fdc8d8SChris Lattner         if (m_step_over)
7930fdc8d8SChris Lattner             s->Printf(" stepping over calls");
8030fdc8d8SChris Lattner         else
8130fdc8d8SChris Lattner             s->Printf(" stepping into calls");
8230fdc8d8SChris Lattner     }
8330fdc8d8SChris Lattner }
8430fdc8d8SChris Lattner 
8530fdc8d8SChris Lattner bool
8630fdc8d8SChris Lattner ThreadPlanStepInstruction::ValidatePlan (Stream *error)
8730fdc8d8SChris Lattner {
8830fdc8d8SChris Lattner     // Since we read the instruction we're stepping over from the thread,
8930fdc8d8SChris Lattner     // this plan will always work.
9030fdc8d8SChris Lattner     return true;
9130fdc8d8SChris Lattner }
9230fdc8d8SChris Lattner 
9330fdc8d8SChris Lattner bool
94221d51cfSJim Ingham ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr)
9530fdc8d8SChris Lattner {
9660c4118cSJim Ingham     StopInfoSP stop_info_sp = GetPrivateStopInfo ();
97b15bfc75SJim Ingham     if (stop_info_sp)
9830fdc8d8SChris Lattner     {
99b15bfc75SJim Ingham         StopReason reason = stop_info_sp->GetStopReason();
10030fdc8d8SChris Lattner         if (reason == eStopReasonTrace || reason == eStopReasonNone)
10130fdc8d8SChris Lattner             return true;
10230fdc8d8SChris Lattner         else
10330fdc8d8SChris Lattner             return false;
10430fdc8d8SChris Lattner     }
10530fdc8d8SChris Lattner     return false;
10630fdc8d8SChris Lattner }
10730fdc8d8SChris Lattner 
10830fdc8d8SChris Lattner bool
10930fdc8d8SChris Lattner ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
11030fdc8d8SChris Lattner {
11130fdc8d8SChris Lattner     if (m_step_over)
11230fdc8d8SChris Lattner     {
1135160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
1146b35c86fSJim Ingham 
1156b35c86fSJim Ingham         StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
1166b35c86fSJim Ingham 
1176b35c86fSJim Ingham         if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id)
11830fdc8d8SChris Lattner         {
11930fdc8d8SChris Lattner             if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
12030fdc8d8SChris Lattner             {
12130fdc8d8SChris Lattner                 SetPlanComplete();
12230fdc8d8SChris Lattner                 return true;
12330fdc8d8SChris Lattner             }
12430fdc8d8SChris Lattner             else
12530fdc8d8SChris Lattner                 return false;
12630fdc8d8SChris Lattner         }
12730fdc8d8SChris Lattner         else
12830fdc8d8SChris Lattner         {
12930fdc8d8SChris Lattner             // We've stepped in, step back out again:
130*b57e4a1bSJason Molenda             StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
13130fdc8d8SChris Lattner             if (return_frame)
13230fdc8d8SChris Lattner             {
133a7d4822cSJim Ingham                 if (return_frame->GetStackID() != m_parent_frame_id || m_start_has_symbol)
134886a3e2cSJim Ingham                 {
13530fdc8d8SChris Lattner                     if (log)
13630fdc8d8SChris Lattner                     {
13730fdc8d8SChris Lattner                         StreamString s;
13830fdc8d8SChris Lattner                         s.PutCString ("Stepped in to: ");
1399da7bd07SGreg Clayton                         addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
1401ac04c30SGreg Clayton                         s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
14130fdc8d8SChris Lattner                         s.PutCString (" stepping out to: ");
1429da7bd07SGreg Clayton                         addr_t return_addr = return_frame->GetRegisterContext()->GetPC();
1431ac04c30SGreg Clayton                         s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
14430fdc8d8SChris Lattner                         log->Printf("%s.", s.GetData());
14530fdc8d8SChris Lattner                     }
1464a58e968SJim Ingham 
1474a58e968SJim Ingham                     // StepInstruction should probably have the tri-state RunMode, but for now it is safer to
1484a58e968SJim Ingham                     // run others.
1494a58e968SJim Ingham                     const bool stop_others = false;
15064e7ead1SJim Ingham                     m_thread.QueueThreadPlanForStepOut(false,
15164e7ead1SJim Ingham                                                        NULL,
15264e7ead1SJim Ingham                                                        true,
1534a58e968SJim Ingham                                                        stop_others,
15464e7ead1SJim Ingham                                                        eVoteNo,
15564e7ead1SJim Ingham                                                        eVoteNoOpinion,
15664e7ead1SJim Ingham                                                        0);
15730fdc8d8SChris Lattner                     return false;
15830fdc8d8SChris Lattner                 }
15930fdc8d8SChris Lattner                 else
16030fdc8d8SChris Lattner                 {
16130fdc8d8SChris Lattner                     if (log)
162886a3e2cSJim Ingham                     {
163a7d4822cSJim Ingham                         log->PutCString("The stack id we are stepping in changed, but our parent frame did not when stepping from code with no symbols.  "
164886a3e2cSJim Ingham                         "We are probably just confused about where we are, stopping.");
165886a3e2cSJim Ingham                     }
166886a3e2cSJim Ingham                     SetPlanComplete();
167886a3e2cSJim Ingham                     return true;
168886a3e2cSJim Ingham                 }
169886a3e2cSJim Ingham             }
170886a3e2cSJim Ingham             else
171886a3e2cSJim Ingham             {
172886a3e2cSJim Ingham                 if (log)
17330fdc8d8SChris Lattner                     log->Printf("Could not find previous frame, stopping.");
17430fdc8d8SChris Lattner                 SetPlanComplete();
17530fdc8d8SChris Lattner                 return true;
17630fdc8d8SChris Lattner             }
17730fdc8d8SChris Lattner 
17830fdc8d8SChris Lattner         }
17930fdc8d8SChris Lattner 
18030fdc8d8SChris Lattner     }
18130fdc8d8SChris Lattner     else
18230fdc8d8SChris Lattner     {
18330fdc8d8SChris Lattner         if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
18430fdc8d8SChris Lattner         {
18530fdc8d8SChris Lattner             SetPlanComplete();
18630fdc8d8SChris Lattner             return true;
18730fdc8d8SChris Lattner         }
18830fdc8d8SChris Lattner         else
18930fdc8d8SChris Lattner             return false;
19030fdc8d8SChris Lattner     }
19130fdc8d8SChris Lattner }
19230fdc8d8SChris Lattner 
19330fdc8d8SChris Lattner bool
19430fdc8d8SChris Lattner ThreadPlanStepInstruction::StopOthers ()
19530fdc8d8SChris Lattner {
19630fdc8d8SChris Lattner     return m_stop_other_threads;
19730fdc8d8SChris Lattner }
19830fdc8d8SChris Lattner 
19930fdc8d8SChris Lattner StateType
20006e827ccSJim Ingham ThreadPlanStepInstruction::GetPlanRunState ()
20130fdc8d8SChris Lattner {
20230fdc8d8SChris Lattner     return eStateStepping;
20330fdc8d8SChris Lattner }
20430fdc8d8SChris Lattner 
20530fdc8d8SChris Lattner bool
20630fdc8d8SChris Lattner ThreadPlanStepInstruction::WillStop ()
20730fdc8d8SChris Lattner {
20830fdc8d8SChris Lattner     return true;
20930fdc8d8SChris Lattner }
21030fdc8d8SChris Lattner 
21130fdc8d8SChris Lattner bool
21230fdc8d8SChris Lattner ThreadPlanStepInstruction::MischiefManaged ()
21330fdc8d8SChris Lattner {
21430fdc8d8SChris Lattner     if (IsPlanComplete())
21530fdc8d8SChris Lattner     {
2165160ce5cSGreg Clayton         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
21730fdc8d8SChris Lattner         if (log)
21830fdc8d8SChris Lattner             log->Printf("Completed single instruction step plan.");
21930fdc8d8SChris Lattner         ThreadPlan::MischiefManaged ();
22030fdc8d8SChris Lattner         return true;
22130fdc8d8SChris Lattner     }
22230fdc8d8SChris Lattner     else
22330fdc8d8SChris Lattner     {
22430fdc8d8SChris Lattner         return false;
22530fdc8d8SChris Lattner     }
22630fdc8d8SChris Lattner }
22730fdc8d8SChris Lattner 
228