Home | History | Annotate | Download | only in Target
      1 //===-- ThreadPlan.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 #include "lldb/lldb-python.h"
     11 
     12 #include "lldb/Target/ThreadPlan.h"
     13 
     14 // C Includes
     15 // C++ Includes
     16 // Other libraries and framework includes
     17 // Project includes
     18 #include "lldb/Core/Debugger.h"
     19 #include "lldb/Core/Log.h"
     20 #include "lldb/Core/State.h"
     21 #include "lldb/Target/RegisterContext.h"
     22 #include "lldb/Target/Thread.h"
     23 #include "lldb/Target/Process.h"
     24 #include "lldb/Target/Target.h"
     25 
     26 using namespace lldb;
     27 using namespace lldb_private;
     28 
     29 //----------------------------------------------------------------------
     30 // ThreadPlan constructor
     31 //----------------------------------------------------------------------
     32 ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vote stop_vote, Vote run_vote) :
     33     m_thread (thread),
     34     m_stop_vote (stop_vote),
     35     m_run_vote (run_vote),
     36     m_kind (kind),
     37     m_name (name),
     38     m_plan_complete_mutex (Mutex::eMutexTypeRecursive),
     39     m_cached_plan_explains_stop (eLazyBoolCalculate),
     40     m_plan_complete (false),
     41     m_plan_private (false),
     42     m_okay_to_discard (true),
     43     m_is_master_plan (false),
     44     m_plan_succeeded(true)
     45 {
     46     SetID (GetNextID());
     47 }
     48 
     49 //----------------------------------------------------------------------
     50 // Destructor
     51 //----------------------------------------------------------------------
     52 ThreadPlan::~ThreadPlan()
     53 {
     54 }
     55 
     56 bool
     57 ThreadPlan::PlanExplainsStop (Event *event_ptr)
     58 {
     59     if (m_cached_plan_explains_stop == eLazyBoolCalculate)
     60     {
     61         bool actual_value = DoPlanExplainsStop(event_ptr);
     62         m_cached_plan_explains_stop = actual_value ? eLazyBoolYes : eLazyBoolNo;
     63         return actual_value;
     64     }
     65     else
     66     {
     67         return m_cached_plan_explains_stop == eLazyBoolYes;
     68     }
     69 }
     70 
     71 bool
     72 ThreadPlan::IsPlanComplete ()
     73 {
     74     Mutex::Locker locker(m_plan_complete_mutex);
     75     return m_plan_complete;
     76 }
     77 
     78 void
     79 ThreadPlan::SetPlanComplete (bool success)
     80 {
     81     Mutex::Locker locker(m_plan_complete_mutex);
     82     m_plan_complete = true;
     83     m_plan_succeeded = success;
     84 }
     85 
     86 bool
     87 ThreadPlan::MischiefManaged ()
     88 {
     89     Mutex::Locker locker(m_plan_complete_mutex);
     90     // Mark the plan is complete, but don't override the success flag.
     91     m_plan_complete = true;
     92     return true;
     93 }
     94 
     95 Vote
     96 ThreadPlan::ShouldReportStop (Event *event_ptr)
     97 {
     98     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
     99 
    100     if (m_stop_vote == eVoteNoOpinion)
    101     {
    102         ThreadPlan *prev_plan = GetPreviousPlan ();
    103         if (prev_plan)
    104         {
    105             Vote prev_vote = prev_plan->ShouldReportStop (event_ptr);
    106             if (log)
    107                 log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s",
    108                              GetVoteAsCString (prev_vote));
    109             return prev_vote;
    110         }
    111     }
    112     if (log)
    113         log->Printf ("ThreadPlan::ShouldReportStop() returning vote: %s", GetVoteAsCString (m_stop_vote));
    114     return m_stop_vote;
    115 }
    116 
    117 Vote
    118 ThreadPlan::ShouldReportRun (Event *event_ptr)
    119 {
    120     if (m_run_vote == eVoteNoOpinion)
    121     {
    122         ThreadPlan *prev_plan = GetPreviousPlan ();
    123         if (prev_plan)
    124             return prev_plan->ShouldReportRun (event_ptr);
    125     }
    126     return m_run_vote;
    127 }
    128 
    129 bool
    130 ThreadPlan::StopOthers ()
    131 {
    132     ThreadPlan *prev_plan;
    133     prev_plan = GetPreviousPlan ();
    134     if (prev_plan == NULL)
    135         return false;
    136     else
    137         return prev_plan->StopOthers();
    138 }
    139 
    140 void
    141 ThreadPlan::SetStopOthers (bool new_value)
    142 {
    143 	// SetStopOthers doesn't work up the hierarchy.  You have to set the
    144     // explicit ThreadPlan you want to affect.
    145 }
    146 
    147 bool
    148 ThreadPlan::WillResume (StateType resume_state, bool current_plan)
    149 {
    150     m_cached_plan_explains_stop = eLazyBoolCalculate;
    151 
    152     if (current_plan)
    153     {
    154         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
    155 
    156         if (log)
    157         {
    158             RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
    159             addr_t pc = reg_ctx->GetPC();
    160             addr_t sp = reg_ctx->GetSP();
    161             addr_t fp = reg_ctx->GetFP();
    162             log->Printf("%s Thread #%u (0x%p): tid = 0x%4.4" PRIx64 ", pc = 0x%8.8" PRIx64 ", sp = 0x%8.8" PRIx64 ", fp = 0x%8.8" PRIx64 ", "
    163                         "plan = '%s', state = %s, stop others = %d",
    164                         __FUNCTION__,
    165                         m_thread.GetIndexID(),
    166                         &m_thread,
    167                         m_thread.GetID(),
    168                         (uint64_t)pc,
    169                         (uint64_t)sp,
    170                         (uint64_t)fp,
    171                         m_name.c_str(),
    172                         StateAsCString(resume_state),
    173                         StopOthers());
    174         }
    175     }
    176     return DoWillResume (resume_state, current_plan);
    177 }
    178 
    179 lldb::user_id_t
    180 ThreadPlan::GetNextID()
    181 {
    182     static uint32_t g_nextPlanID = 0;
    183     return ++g_nextPlanID;
    184 }
    185 
    186 void
    187 ThreadPlan::DidPush()
    188 {
    189 }
    190 
    191 void
    192 ThreadPlan::WillPop()
    193 {
    194 }
    195 
    196 bool
    197 ThreadPlan::OkayToDiscard()
    198 {
    199     if (!IsMasterPlan())
    200         return true;
    201     else
    202         return m_okay_to_discard;
    203 }
    204 
    205 lldb::StateType
    206 ThreadPlan::RunState ()
    207 {
    208     if (m_tracer_sp && m_tracer_sp->TracingEnabled() && m_tracer_sp->SingleStepEnabled())
    209         return eStateStepping;
    210     else
    211         return GetPlanRunState();
    212 }
    213 
    214 //----------------------------------------------------------------------
    215 // ThreadPlanNull
    216 //----------------------------------------------------------------------
    217 
    218 ThreadPlanNull::ThreadPlanNull (Thread &thread) :
    219     ThreadPlan (ThreadPlan::eKindNull,
    220                 "Null Thread Plan",
    221                 thread,
    222                 eVoteNoOpinion,
    223                 eVoteNoOpinion)
    224 {
    225 }
    226 
    227 ThreadPlanNull::~ThreadPlanNull ()
    228 {
    229 }
    230 
    231 void
    232 ThreadPlanNull::GetDescription (Stream *s,
    233                                 lldb::DescriptionLevel level)
    234 {
    235     s->PutCString("Null thread plan - thread has been destroyed.");
    236 }
    237 
    238 bool
    239 ThreadPlanNull::ValidatePlan (Stream *error)
    240 {
    241 #ifdef LLDB_CONFIGURATION_DEBUG
    242     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    243             __PRETTY_FUNCTION__,
    244             m_thread.GetID(),
    245             m_thread.GetProtocolID());
    246 #else
    247     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
    248     if (log)
    249         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    250                     __PRETTY_FUNCTION__,
    251                     m_thread.GetID(),
    252                     m_thread.GetProtocolID());
    253 #endif
    254     return true;
    255 }
    256 
    257 bool
    258 ThreadPlanNull::ShouldStop (Event *event_ptr)
    259 {
    260 #ifdef LLDB_CONFIGURATION_DEBUG
    261     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    262             __PRETTY_FUNCTION__,
    263             m_thread.GetID(),
    264             m_thread.GetProtocolID());
    265 #else
    266     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
    267     if (log)
    268         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    269                     __PRETTY_FUNCTION__,
    270                     m_thread.GetID(),
    271                     m_thread.GetProtocolID());
    272 #endif
    273     return true;
    274 }
    275 
    276 bool
    277 ThreadPlanNull::WillStop ()
    278 {
    279 #ifdef LLDB_CONFIGURATION_DEBUG
    280     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    281             __PRETTY_FUNCTION__,
    282             m_thread.GetID(),
    283             m_thread.GetProtocolID());
    284 #else
    285     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
    286     if (log)
    287         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    288                     __PRETTY_FUNCTION__,
    289                     m_thread.GetID(),
    290                     m_thread.GetProtocolID());
    291 #endif
    292     return true;
    293 }
    294 
    295 bool
    296 ThreadPlanNull::DoPlanExplainsStop (Event *event_ptr)
    297 {
    298 #ifdef LLDB_CONFIGURATION_DEBUG
    299     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    300             __PRETTY_FUNCTION__,
    301             m_thread.GetID(),
    302             m_thread.GetProtocolID());
    303 #else
    304     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
    305     if (log)
    306         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    307                    __PRETTY_FUNCTION__,
    308                    m_thread.GetID(),
    309                    m_thread.GetProtocolID());
    310 #endif
    311     return true;
    312 }
    313 
    314 // The null plan is never done.
    315 bool
    316 ThreadPlanNull::MischiefManaged ()
    317 {
    318     // The null plan is never done.
    319 #ifdef LLDB_CONFIGURATION_DEBUG
    320     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    321             __PRETTY_FUNCTION__,
    322             m_thread.GetID(),
    323             m_thread.GetProtocolID());
    324 #else
    325     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
    326     if (log)
    327         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    328                    __PRETTY_FUNCTION__,
    329                    m_thread.GetID(),
    330                    m_thread.GetProtocolID());
    331 #endif
    332     return false;
    333 }
    334 
    335 lldb::StateType
    336 ThreadPlanNull::GetPlanRunState ()
    337 {
    338     // Not sure what to return here.  This is a dead thread.
    339 #ifdef LLDB_CONFIGURATION_DEBUG
    340     fprintf(stderr, "error: %s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    341             __PRETTY_FUNCTION__,
    342             m_thread.GetID(),
    343             m_thread.GetProtocolID());
    344 #else
    345     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
    346     if (log)
    347         log->Error("%s called on thread that has been destroyed (tid = 0x%" PRIx64 ", ptid = 0x%" PRIx64 ")",
    348                    __PRETTY_FUNCTION__,
    349                    m_thread.GetID(),
    350                    m_thread.GetProtocolID());
    351 #endif
    352     return eStateRunning;
    353 }
    354