Home | History | Annotate | Download | only in Target
      1 //===-- ThreadPlanStepInstruction.cpp ---------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 
     11 #include "lldb/Target/ThreadPlanStepInstruction.h"
     12 
     13 // C Includes
     14 // C++ Includes
     15 // Other libraries and framework includes
     16 // Project includes
     17 #include "lldb/lldb-private-log.h"
     18 #include "lldb/Core/Log.h"
     19 #include "lldb/Core/Stream.h"
     20 #include "lldb/Target/Process.h"
     21 #include "lldb/Target/RegisterContext.h"
     22 #include "lldb/Target/RegisterContext.h"
     23 #include "lldb/Target/StopInfo.h"
     24 #include "lldb/Target/Target.h"
     25 
     26 using namespace lldb;
     27 using namespace lldb_private;
     28 
     29 //----------------------------------------------------------------------
     30 // ThreadPlanStepInstruction: Step over the current instruction
     31 //----------------------------------------------------------------------
     32 
     33 ThreadPlanStepInstruction::ThreadPlanStepInstruction
     34 (
     35     Thread &thread,
     36     bool step_over,
     37     bool stop_other_threads,
     38     Vote stop_vote,
     39     Vote run_vote
     40 ) :
     41     ThreadPlan (ThreadPlan::eKindStepInstruction, "Step over single instruction", thread, stop_vote, run_vote),
     42     m_instruction_addr (0),
     43     m_stop_other_threads (stop_other_threads),
     44     m_step_over (step_over)
     45 {
     46     m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0);
     47     StackFrameSP m_start_frame_sp(m_thread.GetStackFrameAtIndex(0));
     48     m_stack_id = m_start_frame_sp->GetStackID();
     49 
     50     m_start_has_symbol = m_start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL;
     51 
     52     StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1);
     53     if (parent_frame_sp)
     54         m_parent_frame_id = parent_frame_sp->GetStackID();
     55 }
     56 
     57 ThreadPlanStepInstruction::~ThreadPlanStepInstruction ()
     58 {
     59 }
     60 
     61 void
     62 ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level)
     63 {
     64     if (level == lldb::eDescriptionLevelBrief)
     65     {
     66         if (m_step_over)
     67             s->Printf ("instruction step over");
     68         else
     69             s->Printf ("instruction step into");
     70     }
     71     else
     72     {
     73         s->Printf ("Stepping one instruction past ");
     74         s->Address(m_instruction_addr, sizeof (addr_t));
     75         if (!m_start_has_symbol)
     76             s->Printf(" which has no symbol");
     77 
     78         if (m_step_over)
     79             s->Printf(" stepping over calls");
     80         else
     81             s->Printf(" stepping into calls");
     82     }
     83 }
     84 
     85 bool
     86 ThreadPlanStepInstruction::ValidatePlan (Stream *error)
     87 {
     88     // Since we read the instruction we're stepping over from the thread,
     89     // this plan will always work.
     90     return true;
     91 }
     92 
     93 bool
     94 ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr)
     95 {
     96     StopInfoSP stop_info_sp = GetPrivateStopInfo ();
     97     if (stop_info_sp)
     98     {
     99         StopReason reason = stop_info_sp->GetStopReason();
    100         if (reason == eStopReasonTrace || reason == eStopReasonNone)
    101             return true;
    102         else
    103             return false;
    104     }
    105     return false;
    106 }
    107 
    108 bool
    109 ThreadPlanStepInstruction::ShouldStop (Event *event_ptr)
    110 {
    111     if (m_step_over)
    112     {
    113         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    114 
    115         StackID cur_frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
    116 
    117         if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id)
    118         {
    119             if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
    120             {
    121                 SetPlanComplete();
    122                 return true;
    123             }
    124             else
    125                 return false;
    126         }
    127         else
    128         {
    129             // We've stepped in, step back out again:
    130             StackFrame *return_frame = m_thread.GetStackFrameAtIndex(1).get();
    131             if (return_frame)
    132             {
    133                 if (return_frame->GetStackID() != m_parent_frame_id || m_start_has_symbol)
    134                 {
    135                     if (log)
    136                     {
    137                         StreamString s;
    138                         s.PutCString ("Stepped in to: ");
    139                         addr_t stop_addr = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
    140                         s.Address (stop_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
    141                         s.PutCString (" stepping out to: ");
    142                         addr_t return_addr = return_frame->GetRegisterContext()->GetPC();
    143                         s.Address (return_addr, m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
    144                         log->Printf("%s.", s.GetData());
    145                     }
    146 
    147                     // StepInstruction should probably have the tri-state RunMode, but for now it is safer to
    148                     // run others.
    149                     const bool stop_others = false;
    150                     m_thread.QueueThreadPlanForStepOut(false,
    151                                                        NULL,
    152                                                        true,
    153                                                        stop_others,
    154                                                        eVoteNo,
    155                                                        eVoteNoOpinion,
    156                                                        0);
    157                     return false;
    158                 }
    159                 else
    160                 {
    161                     if (log)
    162                     {
    163                         log->PutCString("The stack id we are stepping in changed, but our parent frame did not when stepping from code with no symbols.  "
    164                         "We are probably just confused about where we are, stopping.");
    165                     }
    166                     SetPlanComplete();
    167                     return true;
    168                 }
    169             }
    170             else
    171             {
    172                 if (log)
    173                     log->Printf("Could not find previous frame, stopping.");
    174                 SetPlanComplete();
    175                 return true;
    176             }
    177 
    178         }
    179 
    180     }
    181     else
    182     {
    183         if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr)
    184         {
    185             SetPlanComplete();
    186             return true;
    187         }
    188         else
    189             return false;
    190     }
    191 }
    192 
    193 bool
    194 ThreadPlanStepInstruction::StopOthers ()
    195 {
    196     return m_stop_other_threads;
    197 }
    198 
    199 StateType
    200 ThreadPlanStepInstruction::GetPlanRunState ()
    201 {
    202     return eStateStepping;
    203 }
    204 
    205 bool
    206 ThreadPlanStepInstruction::WillStop ()
    207 {
    208     return true;
    209 }
    210 
    211 bool
    212 ThreadPlanStepInstruction::MischiefManaged ()
    213 {
    214     if (IsPlanComplete())
    215     {
    216         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    217         if (log)
    218             log->Printf("Completed single instruction step plan.");
    219         ThreadPlan::MischiefManaged ();
    220         return true;
    221     }
    222     else
    223     {
    224         return false;
    225     }
    226 }
    227 
    228