130fdc8d8SChris Lattner //===-- SBThread.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 
104c5de699SEli Friedman #include "lldb/API/SBThread.h"
1130fdc8d8SChris Lattner 
1230fdc8d8SChris Lattner #include "lldb/API/SBSymbolContext.h"
1330fdc8d8SChris Lattner #include "lldb/API/SBFileSpec.h"
14dde9cff3SCaroline Tice #include "lldb/API/SBStream.h"
154e78f606SGreg Clayton #include "lldb/Breakpoint/BreakpointLocation.h"
166611103cSGreg Clayton #include "lldb/Core/Debugger.h"
1730fdc8d8SChris Lattner #include "lldb/Core/Stream.h"
1830fdc8d8SChris Lattner #include "lldb/Core/StreamFile.h"
196611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
2030fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2130fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2230fdc8d8SChris Lattner #include "lldb/Symbol/SymbolContext.h"
2330fdc8d8SChris Lattner #include "lldb/Symbol/CompileUnit.h"
24f4b47e15SGreg Clayton #include "lldb/Target/StopInfo.h"
2530fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2630fdc8d8SChris Lattner #include "lldb/Target/ThreadPlan.h"
2730fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepInstruction.h"
2830fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h"
2930fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepRange.h"
3030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepInRange.h"
3130fdc8d8SChris Lattner 
3230fdc8d8SChris Lattner 
334c5de699SEli Friedman #include "lldb/API/SBAddress.h"
344c5de699SEli Friedman #include "lldb/API/SBDebugger.h"
3573ca05a2SJim Ingham #include "lldb/API/SBFrame.h"
364c5de699SEli Friedman #include "lldb/API/SBProcess.h"
3773ca05a2SJim Ingham #include "lldb/API/SBValue.h"
3830fdc8d8SChris Lattner 
3930fdc8d8SChris Lattner using namespace lldb;
4030fdc8d8SChris Lattner using namespace lldb_private;
4130fdc8d8SChris Lattner 
42cfd1acedSGreg Clayton //----------------------------------------------------------------------
43cfd1acedSGreg Clayton // Constructors
44cfd1acedSGreg Clayton //----------------------------------------------------------------------
4530fdc8d8SChris Lattner SBThread::SBThread () :
467fdf9ef1SGreg Clayton     m_opaque_sp (new ExecutionContextRef())
4730fdc8d8SChris Lattner {
4830fdc8d8SChris Lattner }
4930fdc8d8SChris Lattner 
5030fdc8d8SChris Lattner SBThread::SBThread (const ThreadSP& lldb_object_sp) :
517fdf9ef1SGreg Clayton     m_opaque_sp (new ExecutionContextRef(lldb_object_sp))
5230fdc8d8SChris Lattner {
5330fdc8d8SChris Lattner }
5430fdc8d8SChris Lattner 
5592ef5735SGreg Clayton SBThread::SBThread (const SBThread &rhs) :
567fdf9ef1SGreg Clayton     m_opaque_sp (new ExecutionContextRef(*rhs.m_opaque_sp))
5730fdc8d8SChris Lattner {
587fdf9ef1SGreg Clayton 
5930fdc8d8SChris Lattner }
6030fdc8d8SChris Lattner 
6130fdc8d8SChris Lattner //----------------------------------------------------------------------
62cfd1acedSGreg Clayton // Assignment operator
63cfd1acedSGreg Clayton //----------------------------------------------------------------------
64cfd1acedSGreg Clayton 
65cfd1acedSGreg Clayton const lldb::SBThread &
66cfd1acedSGreg Clayton SBThread::operator = (const SBThread &rhs)
67cfd1acedSGreg Clayton {
68cfd1acedSGreg Clayton     if (this != &rhs)
697fdf9ef1SGreg Clayton         *m_opaque_sp = *rhs.m_opaque_sp;
70cfd1acedSGreg Clayton     return *this;
71cfd1acedSGreg Clayton }
72cfd1acedSGreg Clayton 
73cfd1acedSGreg Clayton //----------------------------------------------------------------------
7430fdc8d8SChris Lattner // Destructor
7530fdc8d8SChris Lattner //----------------------------------------------------------------------
7630fdc8d8SChris Lattner SBThread::~SBThread()
7730fdc8d8SChris Lattner {
7830fdc8d8SChris Lattner }
7930fdc8d8SChris Lattner 
8030fdc8d8SChris Lattner bool
8130fdc8d8SChris Lattner SBThread::IsValid() const
8230fdc8d8SChris Lattner {
837fdf9ef1SGreg Clayton     return m_opaque_sp->GetThreadSP().get() != NULL;
8430fdc8d8SChris Lattner }
8530fdc8d8SChris Lattner 
8648e42549SGreg Clayton void
8748e42549SGreg Clayton SBThread::Clear ()
8848e42549SGreg Clayton {
897fdf9ef1SGreg Clayton     m_opaque_sp->Clear();
9048e42549SGreg Clayton }
9148e42549SGreg Clayton 
9248e42549SGreg Clayton 
9330fdc8d8SChris Lattner StopReason
9430fdc8d8SChris Lattner SBThread::GetStopReason()
9530fdc8d8SChris Lattner {
962d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
97ceb6b139SCaroline Tice 
98ceb6b139SCaroline Tice     StopReason reason = eStopReasonInvalid;
994fc6cb9cSJim Ingham     Mutex::Locker api_locker;
1004fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
1014fc6cb9cSJim Ingham 
1021ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
10330fdc8d8SChris Lattner     {
1047fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
1057fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
1067fdf9ef1SGreg Clayton         {
1071ac04c30SGreg Clayton             StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
108b15bfc75SJim Ingham             if (stop_info_sp)
109ceb6b139SCaroline Tice                 reason =  stop_info_sp->GetStopReason();
11030fdc8d8SChris Lattner         }
111c9858e4dSGreg Clayton         else
112c9858e4dSGreg Clayton         {
113c9858e4dSGreg Clayton             if (log)
114c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetStopReason() => error: process is running", exe_ctx.GetThreadPtr());
115c9858e4dSGreg Clayton         }
1167fdf9ef1SGreg Clayton     }
117ceb6b139SCaroline Tice 
118ceb6b139SCaroline Tice     if (log)
1191ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::GetStopReason () => %s", exe_ctx.GetThreadPtr(),
120750cd175SCaroline Tice                      Thread::StopReasonAsCString (reason));
121ceb6b139SCaroline Tice 
122ceb6b139SCaroline Tice     return reason;
12330fdc8d8SChris Lattner }
12430fdc8d8SChris Lattner 
12530fdc8d8SChris Lattner size_t
1264e78f606SGreg Clayton SBThread::GetStopReasonDataCount ()
1274e78f606SGreg Clayton {
1284fc6cb9cSJim Ingham     Mutex::Locker api_locker;
1294fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
1304fc6cb9cSJim Ingham 
1311ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
1324e78f606SGreg Clayton     {
1337fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
1347fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
1357fdf9ef1SGreg Clayton         {
1361ac04c30SGreg Clayton             StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
1374e78f606SGreg Clayton             if (stop_info_sp)
1384e78f606SGreg Clayton             {
1394e78f606SGreg Clayton                 StopReason reason = stop_info_sp->GetStopReason();
1404e78f606SGreg Clayton                 switch (reason)
1414e78f606SGreg Clayton                 {
1424e78f606SGreg Clayton                 case eStopReasonInvalid:
1434e78f606SGreg Clayton                 case eStopReasonNone:
1444e78f606SGreg Clayton                 case eStopReasonTrace:
1454e78f606SGreg Clayton                 case eStopReasonPlanComplete:
1464e78f606SGreg Clayton                     // There is no data for these stop reasons.
1474e78f606SGreg Clayton                     return 0;
1484e78f606SGreg Clayton 
1494e78f606SGreg Clayton                 case eStopReasonBreakpoint:
1504e78f606SGreg Clayton                     {
1514e78f606SGreg Clayton                         break_id_t site_id = stop_info_sp->GetValue();
1521ac04c30SGreg Clayton                         lldb::BreakpointSiteSP bp_site_sp (exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID (site_id));
1534e78f606SGreg Clayton                         if (bp_site_sp)
1544e78f606SGreg Clayton                             return bp_site_sp->GetNumberOfOwners () * 2;
1554e78f606SGreg Clayton                         else
1564e78f606SGreg Clayton                             return 0; // Breakpoint must have cleared itself...
1574e78f606SGreg Clayton                     }
1584e78f606SGreg Clayton                     break;
1594e78f606SGreg Clayton 
1604e78f606SGreg Clayton                 case eStopReasonWatchpoint:
161290fa41bSJohnny Chen                     return 1;
1624e78f606SGreg Clayton 
1634e78f606SGreg Clayton                 case eStopReasonSignal:
1644e78f606SGreg Clayton                     return 1;
1654e78f606SGreg Clayton 
1664e78f606SGreg Clayton                 case eStopReasonException:
1674e78f606SGreg Clayton                     return 1;
1684e78f606SGreg Clayton                 }
1694e78f606SGreg Clayton             }
1704e78f606SGreg Clayton         }
171c9858e4dSGreg Clayton         else
172c9858e4dSGreg Clayton         {
173c9858e4dSGreg Clayton             LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
174c9858e4dSGreg Clayton             if (log)
175c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetStopReasonDataCount() => error: process is running", exe_ctx.GetThreadPtr());
176c9858e4dSGreg Clayton         }
1777fdf9ef1SGreg Clayton     }
1784e78f606SGreg Clayton     return 0;
1794e78f606SGreg Clayton }
1804e78f606SGreg Clayton 
1814e78f606SGreg Clayton uint64_t
1824e78f606SGreg Clayton SBThread::GetStopReasonDataAtIndex (uint32_t idx)
1834e78f606SGreg Clayton {
1844fc6cb9cSJim Ingham     Mutex::Locker api_locker;
1854fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
1864fc6cb9cSJim Ingham 
1871ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
1884e78f606SGreg Clayton     {
1897fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
1907fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
1917fdf9ef1SGreg Clayton         {
1921ac04c30SGreg Clayton             Thread *thread = exe_ctx.GetThreadPtr();
1931ac04c30SGreg Clayton             StopInfoSP stop_info_sp = thread->GetStopInfo ();
1944e78f606SGreg Clayton             if (stop_info_sp)
1954e78f606SGreg Clayton             {
1964e78f606SGreg Clayton                 StopReason reason = stop_info_sp->GetStopReason();
1974e78f606SGreg Clayton                 switch (reason)
1984e78f606SGreg Clayton                 {
1994e78f606SGreg Clayton                 case eStopReasonInvalid:
2004e78f606SGreg Clayton                 case eStopReasonNone:
2014e78f606SGreg Clayton                 case eStopReasonTrace:
2024e78f606SGreg Clayton                 case eStopReasonPlanComplete:
2034e78f606SGreg Clayton                     // There is no data for these stop reasons.
2044e78f606SGreg Clayton                     return 0;
2054e78f606SGreg Clayton 
2064e78f606SGreg Clayton                 case eStopReasonBreakpoint:
2074e78f606SGreg Clayton                     {
2084e78f606SGreg Clayton                         break_id_t site_id = stop_info_sp->GetValue();
2091ac04c30SGreg Clayton                         lldb::BreakpointSiteSP bp_site_sp (exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID (site_id));
2104e78f606SGreg Clayton                         if (bp_site_sp)
2114e78f606SGreg Clayton                         {
2124e78f606SGreg Clayton                             uint32_t bp_index = idx / 2;
2134e78f606SGreg Clayton                             BreakpointLocationSP bp_loc_sp (bp_site_sp->GetOwnerAtIndex (bp_index));
2144e78f606SGreg Clayton                             if (bp_loc_sp)
2154e78f606SGreg Clayton                             {
2164e78f606SGreg Clayton                                 if (bp_index & 1)
2174e78f606SGreg Clayton                                 {
2184e78f606SGreg Clayton                                     // Odd idx, return the breakpoint location ID
2194e78f606SGreg Clayton                                     return bp_loc_sp->GetID();
2204e78f606SGreg Clayton                                 }
2214e78f606SGreg Clayton                                 else
2224e78f606SGreg Clayton                                 {
2234e78f606SGreg Clayton                                     // Even idx, return the breakpoint ID
2244e78f606SGreg Clayton                                     return bp_loc_sp->GetBreakpoint().GetID();
2254e78f606SGreg Clayton                                 }
2264e78f606SGreg Clayton                             }
2274e78f606SGreg Clayton                         }
2284e78f606SGreg Clayton                         return LLDB_INVALID_BREAK_ID;
2294e78f606SGreg Clayton                     }
2304e78f606SGreg Clayton                     break;
2314e78f606SGreg Clayton 
2324e78f606SGreg Clayton                 case eStopReasonWatchpoint:
233290fa41bSJohnny Chen                     return stop_info_sp->GetValue();
2344e78f606SGreg Clayton 
2354e78f606SGreg Clayton                 case eStopReasonSignal:
2364e78f606SGreg Clayton                     return stop_info_sp->GetValue();
2374e78f606SGreg Clayton 
2384e78f606SGreg Clayton                 case eStopReasonException:
2394e78f606SGreg Clayton                     return stop_info_sp->GetValue();
2404e78f606SGreg Clayton                 }
2414e78f606SGreg Clayton             }
2424e78f606SGreg Clayton         }
243c9858e4dSGreg Clayton         else
244c9858e4dSGreg Clayton         {
245c9858e4dSGreg Clayton             LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
246c9858e4dSGreg Clayton             if (log)
247c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetStopReasonDataAtIndex() => error: process is running", exe_ctx.GetThreadPtr());
248c9858e4dSGreg Clayton         }
2497fdf9ef1SGreg Clayton     }
2504e78f606SGreg Clayton     return 0;
2514e78f606SGreg Clayton }
2524e78f606SGreg Clayton 
2534e78f606SGreg Clayton size_t
25430fdc8d8SChris Lattner SBThread::GetStopDescription (char *dst, size_t dst_len)
25530fdc8d8SChris Lattner {
2562d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
257ceb6b139SCaroline Tice 
2584fc6cb9cSJim Ingham     Mutex::Locker api_locker;
2594fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
2604fc6cb9cSJim Ingham 
2611ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
26230fdc8d8SChris Lattner     {
2637fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
2647fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
2657fdf9ef1SGreg Clayton         {
2667fdf9ef1SGreg Clayton 
2671ac04c30SGreg Clayton             StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
268b15bfc75SJim Ingham             if (stop_info_sp)
26930fdc8d8SChris Lattner             {
270b15bfc75SJim Ingham                 const char *stop_desc = stop_info_sp->GetDescription();
27130fdc8d8SChris Lattner                 if (stop_desc)
27230fdc8d8SChris Lattner                 {
273ceb6b139SCaroline Tice                     if (log)
2744838131bSGreg Clayton                         log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"",
2751ac04c30SGreg Clayton                                      exe_ctx.GetThreadPtr(), stop_desc);
27630fdc8d8SChris Lattner                     if (dst)
27730fdc8d8SChris Lattner                         return ::snprintf (dst, dst_len, "%s", stop_desc);
27830fdc8d8SChris Lattner                     else
27930fdc8d8SChris Lattner                     {
28030fdc8d8SChris Lattner                         // NULL dst passed in, return the length needed to contain the description
28130fdc8d8SChris Lattner                         return ::strlen (stop_desc) + 1; // Include the NULL byte for size
28230fdc8d8SChris Lattner                     }
28330fdc8d8SChris Lattner                 }
28430fdc8d8SChris Lattner                 else
28530fdc8d8SChris Lattner                 {
28630fdc8d8SChris Lattner                     size_t stop_desc_len = 0;
287b15bfc75SJim Ingham                     switch (stop_info_sp->GetStopReason())
28830fdc8d8SChris Lattner                     {
28930fdc8d8SChris Lattner                     case eStopReasonTrace:
29030fdc8d8SChris Lattner                     case eStopReasonPlanComplete:
29130fdc8d8SChris Lattner                         {
29230fdc8d8SChris Lattner                             static char trace_desc[] = "step";
29330fdc8d8SChris Lattner                             stop_desc = trace_desc;
29430fdc8d8SChris Lattner                             stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
29530fdc8d8SChris Lattner                         }
29630fdc8d8SChris Lattner                         break;
29730fdc8d8SChris Lattner 
29830fdc8d8SChris Lattner                     case eStopReasonBreakpoint:
29930fdc8d8SChris Lattner                         {
30030fdc8d8SChris Lattner                             static char bp_desc[] = "breakpoint hit";
30130fdc8d8SChris Lattner                             stop_desc = bp_desc;
30230fdc8d8SChris Lattner                             stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
30330fdc8d8SChris Lattner                         }
30430fdc8d8SChris Lattner                         break;
30530fdc8d8SChris Lattner 
30630fdc8d8SChris Lattner                     case eStopReasonWatchpoint:
30730fdc8d8SChris Lattner                         {
30830fdc8d8SChris Lattner                             static char wp_desc[] = "watchpoint hit";
30930fdc8d8SChris Lattner                             stop_desc = wp_desc;
31030fdc8d8SChris Lattner                             stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
31130fdc8d8SChris Lattner                         }
31230fdc8d8SChris Lattner                         break;
31330fdc8d8SChris Lattner 
31430fdc8d8SChris Lattner                     case eStopReasonSignal:
31530fdc8d8SChris Lattner                         {
3161ac04c30SGreg Clayton                             stop_desc = exe_ctx.GetProcessPtr()->GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue());
31730fdc8d8SChris Lattner                             if (stop_desc == NULL || stop_desc[0] == '\0')
31830fdc8d8SChris Lattner                             {
31930fdc8d8SChris Lattner                                 static char signal_desc[] = "signal";
32030fdc8d8SChris Lattner                                 stop_desc = signal_desc;
32130fdc8d8SChris Lattner                                 stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
32230fdc8d8SChris Lattner                             }
32330fdc8d8SChris Lattner                         }
32430fdc8d8SChris Lattner                         break;
32530fdc8d8SChris Lattner 
32630fdc8d8SChris Lattner                     case eStopReasonException:
32730fdc8d8SChris Lattner                         {
32830fdc8d8SChris Lattner                             char exc_desc[] = "exception";
32930fdc8d8SChris Lattner                             stop_desc = exc_desc;
33030fdc8d8SChris Lattner                             stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
33130fdc8d8SChris Lattner                         }
33230fdc8d8SChris Lattner                         break;
333c982c768SGreg Clayton 
334c982c768SGreg Clayton                     default:
335c982c768SGreg Clayton                         break;
33630fdc8d8SChris Lattner                     }
33730fdc8d8SChris Lattner 
33830fdc8d8SChris Lattner                     if (stop_desc && stop_desc[0])
33930fdc8d8SChris Lattner                     {
340ceb6b139SCaroline Tice                         if (log)
34193aa84e8SGreg Clayton                             log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'",
3421ac04c30SGreg Clayton                                          exe_ctx.GetThreadPtr(), stop_desc);
343ceb6b139SCaroline Tice 
34430fdc8d8SChris Lattner                         if (dst)
34530fdc8d8SChris Lattner                             return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
34630fdc8d8SChris Lattner 
34730fdc8d8SChris Lattner                         if (stop_desc_len == 0)
34830fdc8d8SChris Lattner                             stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
34930fdc8d8SChris Lattner 
35030fdc8d8SChris Lattner                         return stop_desc_len;
35130fdc8d8SChris Lattner                     }
35230fdc8d8SChris Lattner                 }
35330fdc8d8SChris Lattner             }
35430fdc8d8SChris Lattner         }
355c9858e4dSGreg Clayton         else
356c9858e4dSGreg Clayton         {
357c9858e4dSGreg Clayton             LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
358c9858e4dSGreg Clayton             if (log)
359c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetStopDescription() => error: process is running", exe_ctx.GetThreadPtr());
360c9858e4dSGreg Clayton         }
3617fdf9ef1SGreg Clayton     }
36230fdc8d8SChris Lattner     if (dst)
36330fdc8d8SChris Lattner         *dst = 0;
36430fdc8d8SChris Lattner     return 0;
36530fdc8d8SChris Lattner }
36630fdc8d8SChris Lattner 
36773ca05a2SJim Ingham SBValue
36873ca05a2SJim Ingham SBThread::GetStopReturnValue ()
36973ca05a2SJim Ingham {
370c9858e4dSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
37173ca05a2SJim Ingham     ValueObjectSP return_valobj_sp;
3724fc6cb9cSJim Ingham     Mutex::Locker api_locker;
3734fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
3744fc6cb9cSJim Ingham 
3751ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
37673ca05a2SJim Ingham     {
3777fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
3787fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
3797fdf9ef1SGreg Clayton         {
3801ac04c30SGreg Clayton             StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
38173ca05a2SJim Ingham             if (stop_info_sp)
38273ca05a2SJim Ingham             {
38373ca05a2SJim Ingham                 return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
38473ca05a2SJim Ingham             }
38573ca05a2SJim Ingham         }
386c9858e4dSGreg Clayton         else
387c9858e4dSGreg Clayton         {
388c9858e4dSGreg Clayton             if (log)
389c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetStopReturnValue() => error: process is running", exe_ctx.GetThreadPtr());
390c9858e4dSGreg Clayton         }
3917fdf9ef1SGreg Clayton     }
39273ca05a2SJim Ingham 
39373ca05a2SJim Ingham     if (log)
3941ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::GetStopReturnValue () => %s", exe_ctx.GetThreadPtr(),
39573ca05a2SJim Ingham                                                                   return_valobj_sp.get()
39673ca05a2SJim Ingham                                                                       ? return_valobj_sp->GetValueAsCString()
39773ca05a2SJim Ingham                                                                         : "<no return value>");
39873ca05a2SJim Ingham 
39973ca05a2SJim Ingham     return SBValue (return_valobj_sp);
40073ca05a2SJim Ingham }
40173ca05a2SJim Ingham 
40230fdc8d8SChris Lattner void
40330fdc8d8SChris Lattner SBThread::SetThread (const ThreadSP& lldb_object_sp)
40430fdc8d8SChris Lattner {
4057fdf9ef1SGreg Clayton     m_opaque_sp->SetThreadSP (lldb_object_sp);
40630fdc8d8SChris Lattner }
40730fdc8d8SChris Lattner 
40830fdc8d8SChris Lattner 
40930fdc8d8SChris Lattner lldb::tid_t
41030fdc8d8SChris Lattner SBThread::GetThreadID () const
41130fdc8d8SChris Lattner {
4127fdf9ef1SGreg Clayton     ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
41317a6ad05SGreg Clayton     if (thread_sp)
4141ac04c30SGreg Clayton         return thread_sp->GetID();
4151ac04c30SGreg Clayton     return LLDB_INVALID_THREAD_ID;
41630fdc8d8SChris Lattner }
41730fdc8d8SChris Lattner 
41830fdc8d8SChris Lattner uint32_t
41930fdc8d8SChris Lattner SBThread::GetIndexID () const
42030fdc8d8SChris Lattner {
4217fdf9ef1SGreg Clayton     ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
42217a6ad05SGreg Clayton     if (thread_sp)
42317a6ad05SGreg Clayton         return thread_sp->GetIndexID();
42430fdc8d8SChris Lattner     return LLDB_INVALID_INDEX32;
42530fdc8d8SChris Lattner }
4261ac04c30SGreg Clayton 
42730fdc8d8SChris Lattner const char *
42830fdc8d8SChris Lattner SBThread::GetName () const
42930fdc8d8SChris Lattner {
430c9858e4dSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
4314838131bSGreg Clayton     const char *name = NULL;
4324fc6cb9cSJim Ingham     Mutex::Locker api_locker;
4334fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
4344fc6cb9cSJim Ingham 
4351ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
436af67cecdSGreg Clayton     {
4377fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
4387fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
4397fdf9ef1SGreg Clayton         {
4401ac04c30SGreg Clayton             name = exe_ctx.GetThreadPtr()->GetName();
441af67cecdSGreg Clayton         }
442c9858e4dSGreg Clayton         else
443c9858e4dSGreg Clayton         {
444c9858e4dSGreg Clayton             if (log)
445c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetName() => error: process is running", exe_ctx.GetThreadPtr());
446c9858e4dSGreg Clayton         }
4477fdf9ef1SGreg Clayton     }
448ceb6b139SCaroline Tice 
449ceb6b139SCaroline Tice     if (log)
4501ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::GetName () => %s", exe_ctx.GetThreadPtr(), name ? name : "NULL");
451ceb6b139SCaroline Tice 
4524838131bSGreg Clayton     return name;
45330fdc8d8SChris Lattner }
45430fdc8d8SChris Lattner 
45530fdc8d8SChris Lattner const char *
45630fdc8d8SChris Lattner SBThread::GetQueueName () const
45730fdc8d8SChris Lattner {
4584838131bSGreg Clayton     const char *name = NULL;
4594fc6cb9cSJim Ingham     Mutex::Locker api_locker;
4604fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
4614fc6cb9cSJim Ingham 
462c9858e4dSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
4631ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
464af67cecdSGreg Clayton     {
4657fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
4667fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
4677fdf9ef1SGreg Clayton         {
4681ac04c30SGreg Clayton             name = exe_ctx.GetThreadPtr()->GetQueueName();
469af67cecdSGreg Clayton         }
470c9858e4dSGreg Clayton         else
471c9858e4dSGreg Clayton         {
472c9858e4dSGreg Clayton             if (log)
473c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetQueueName() => error: process is running", exe_ctx.GetThreadPtr());
474c9858e4dSGreg Clayton         }
4757fdf9ef1SGreg Clayton     }
476ceb6b139SCaroline Tice 
477ceb6b139SCaroline Tice     if (log)
4781ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::GetQueueName () => %s", exe_ctx.GetThreadPtr(), name ? name : "NULL");
479ceb6b139SCaroline Tice 
4804838131bSGreg Clayton     return name;
48130fdc8d8SChris Lattner }
48230fdc8d8SChris Lattner 
48364e7ead1SJim Ingham SBError
48464e7ead1SJim Ingham SBThread::ResumeNewPlan (ExecutionContext &exe_ctx, ThreadPlan *new_plan)
48564e7ead1SJim Ingham {
48664e7ead1SJim Ingham     SBError sb_error;
48764e7ead1SJim Ingham 
48864e7ead1SJim Ingham     Process *process = exe_ctx.GetProcessPtr();
48964e7ead1SJim Ingham     if (!process)
49064e7ead1SJim Ingham     {
49164e7ead1SJim Ingham         sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
49264e7ead1SJim Ingham         return sb_error;
49364e7ead1SJim Ingham     }
49464e7ead1SJim Ingham 
49564e7ead1SJim Ingham     Thread *thread = exe_ctx.GetThreadPtr();
49664e7ead1SJim Ingham     if (!thread)
49764e7ead1SJim Ingham     {
49864e7ead1SJim Ingham         sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
49964e7ead1SJim Ingham         return sb_error;
50064e7ead1SJim Ingham     }
50164e7ead1SJim Ingham 
50264e7ead1SJim Ingham     // User level plans should be Master Plans so they can be interrupted, other plans executed, and
50364e7ead1SJim Ingham     // then a "continue" will resume the plan.
50464e7ead1SJim Ingham     if (new_plan != NULL)
50564e7ead1SJim Ingham     {
50664e7ead1SJim Ingham         new_plan->SetIsMasterPlan(true);
50764e7ead1SJim Ingham         new_plan->SetOkayToDiscard(false);
50864e7ead1SJim Ingham     }
50964e7ead1SJim Ingham 
51064e7ead1SJim Ingham     // Why do we need to set the current thread by ID here???
51164e7ead1SJim Ingham     process->GetThreadList().SetSelectedThreadByID (thread->GetID());
51264e7ead1SJim Ingham     sb_error.ref() = process->Resume();
51364e7ead1SJim Ingham 
51464e7ead1SJim Ingham     if (sb_error.Success())
51564e7ead1SJim Ingham     {
51664e7ead1SJim Ingham         // If we are doing synchronous mode, then wait for the
51764e7ead1SJim Ingham         // process to stop yet again!
51864e7ead1SJim Ingham         if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
51964e7ead1SJim Ingham             process->WaitForProcessToStop (NULL);
52064e7ead1SJim Ingham     }
52164e7ead1SJim Ingham 
52264e7ead1SJim Ingham     return sb_error;
52364e7ead1SJim Ingham }
52430fdc8d8SChris Lattner 
52530fdc8d8SChris Lattner void
52630fdc8d8SChris Lattner SBThread::StepOver (lldb::RunMode stop_other_threads)
52730fdc8d8SChris Lattner {
5282d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
529ceb6b139SCaroline Tice 
5304fc6cb9cSJim Ingham     Mutex::Locker api_locker;
5314fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
5324fc6cb9cSJim Ingham 
53317a6ad05SGreg Clayton 
534ceb6b139SCaroline Tice     if (log)
5351ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::StepOver (stop_other_threads='%s')", exe_ctx.GetThreadPtr(),
536ceb6b139SCaroline Tice                      Thread::RunModeAsCString (stop_other_threads));
537ceb6b139SCaroline Tice 
5381ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
53930fdc8d8SChris Lattner     {
5401ac04c30SGreg Clayton         Thread *thread = exe_ctx.GetThreadPtr();
5417ba6e991SJim Ingham         bool abort_other_plans = false;
5421ac04c30SGreg Clayton         StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));
54364e7ead1SJim Ingham         ThreadPlan *new_plan = NULL;
54430fdc8d8SChris Lattner 
54530fdc8d8SChris Lattner         if (frame_sp)
54630fdc8d8SChris Lattner         {
54730fdc8d8SChris Lattner             if (frame_sp->HasDebugInformation ())
54830fdc8d8SChris Lattner             {
54930fdc8d8SChris Lattner                 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
55064e7ead1SJim Ingham                 new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
55130fdc8d8SChris Lattner                                                                 eStepTypeOver,
55230fdc8d8SChris Lattner                                                                 sc.line_entry.range,
55330fdc8d8SChris Lattner                                                                 sc,
554474966a4SGreg Clayton                                                                 stop_other_threads,
555474966a4SGreg Clayton                                                                 false);
55630fdc8d8SChris Lattner 
55730fdc8d8SChris Lattner             }
55830fdc8d8SChris Lattner             else
55930fdc8d8SChris Lattner             {
56064e7ead1SJim Ingham                 new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
56130fdc8d8SChris Lattner                                                                             abort_other_plans,
56230fdc8d8SChris Lattner                                                                             stop_other_threads);
56330fdc8d8SChris Lattner             }
56430fdc8d8SChris Lattner         }
56530fdc8d8SChris Lattner 
56664e7ead1SJim Ingham         // This returns an error, we should use it!
56764e7ead1SJim Ingham         ResumeNewPlan (exe_ctx, new_plan);
56830fdc8d8SChris Lattner     }
56930fdc8d8SChris Lattner }
57030fdc8d8SChris Lattner 
57130fdc8d8SChris Lattner void
57230fdc8d8SChris Lattner SBThread::StepInto (lldb::RunMode stop_other_threads)
57330fdc8d8SChris Lattner {
5742d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
575ceb6b139SCaroline Tice 
5764fc6cb9cSJim Ingham     Mutex::Locker api_locker;
5774fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
57817a6ad05SGreg Clayton 
57917a6ad05SGreg Clayton     if (log)
5801ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::StepInto (stop_other_threads='%s')", exe_ctx.GetThreadPtr(),
58117a6ad05SGreg Clayton                      Thread::RunModeAsCString (stop_other_threads));
5821ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
58330fdc8d8SChris Lattner     {
5847ba6e991SJim Ingham         bool abort_other_plans = false;
58530fdc8d8SChris Lattner 
5861ac04c30SGreg Clayton         Thread *thread = exe_ctx.GetThreadPtr();
5871ac04c30SGreg Clayton         StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));
58864e7ead1SJim Ingham         ThreadPlan *new_plan = NULL;
58930fdc8d8SChris Lattner 
59030fdc8d8SChris Lattner         if (frame_sp && frame_sp->HasDebugInformation ())
59130fdc8d8SChris Lattner         {
592474966a4SGreg Clayton             bool avoid_code_without_debug_info = true;
59330fdc8d8SChris Lattner             SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
59464e7ead1SJim Ingham             new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
59530fdc8d8SChris Lattner                                                             eStepTypeInto,
59630fdc8d8SChris Lattner                                                             sc.line_entry.range,
59730fdc8d8SChris Lattner                                                             sc,
598474966a4SGreg Clayton                                                             stop_other_threads,
599474966a4SGreg Clayton                                                             avoid_code_without_debug_info);
60030fdc8d8SChris Lattner         }
60130fdc8d8SChris Lattner         else
60230fdc8d8SChris Lattner         {
60364e7ead1SJim Ingham             new_plan = thread->QueueThreadPlanForStepSingleInstruction (false,
60430fdc8d8SChris Lattner                                                                         abort_other_plans,
60530fdc8d8SChris Lattner                                                                         stop_other_threads);
60630fdc8d8SChris Lattner         }
60730fdc8d8SChris Lattner 
60864e7ead1SJim Ingham         // This returns an error, we should use it!
60964e7ead1SJim Ingham         ResumeNewPlan (exe_ctx, new_plan);
61030fdc8d8SChris Lattner     }
61130fdc8d8SChris Lattner }
61230fdc8d8SChris Lattner 
61330fdc8d8SChris Lattner void
61430fdc8d8SChris Lattner SBThread::StepOut ()
61530fdc8d8SChris Lattner {
6162d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
617ceb6b139SCaroline Tice 
6184fc6cb9cSJim Ingham     Mutex::Locker api_locker;
6194fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
6204fc6cb9cSJim Ingham 
621ceb6b139SCaroline Tice 
62217a6ad05SGreg Clayton     if (log)
6231ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::StepOut ()", exe_ctx.GetThreadPtr());
62417a6ad05SGreg Clayton 
6251ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
62630fdc8d8SChris Lattner     {
6277ba6e991SJim Ingham         bool abort_other_plans = false;
62830fdc8d8SChris Lattner         bool stop_other_threads = true;
62930fdc8d8SChris Lattner 
6301ac04c30SGreg Clayton         Thread *thread = exe_ctx.GetThreadPtr();
6311ac04c30SGreg Clayton 
63264e7ead1SJim Ingham         ThreadPlan *new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
633481cef25SGreg Clayton                                                                   NULL,
634481cef25SGreg Clayton                                                                   false,
635481cef25SGreg Clayton                                                                   stop_other_threads,
636481cef25SGreg Clayton                                                                   eVoteYes,
637481cef25SGreg Clayton                                                                   eVoteNoOpinion,
638481cef25SGreg Clayton                                                                   0);
639481cef25SGreg Clayton 
64064e7ead1SJim Ingham         // This returns an error, we should use it!
64164e7ead1SJim Ingham         ResumeNewPlan (exe_ctx, new_plan);
642481cef25SGreg Clayton     }
643481cef25SGreg Clayton }
644481cef25SGreg Clayton 
645481cef25SGreg Clayton void
646481cef25SGreg Clayton SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame)
647481cef25SGreg Clayton {
648481cef25SGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
649481cef25SGreg Clayton 
6504fc6cb9cSJim Ingham     Mutex::Locker api_locker;
6514fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
6524fc6cb9cSJim Ingham 
653b9556accSGreg Clayton     StackFrameSP frame_sp (sb_frame.GetFrameSP());
654481cef25SGreg Clayton     if (log)
655481cef25SGreg Clayton     {
656481cef25SGreg Clayton         SBStream frame_desc_strm;
657481cef25SGreg Clayton         sb_frame.GetDescription (frame_desc_strm);
6581ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)", exe_ctx.GetThreadPtr(), frame_sp.get(), frame_desc_strm.GetData());
659481cef25SGreg Clayton     }
660481cef25SGreg Clayton 
6611ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
662481cef25SGreg Clayton     {
6637ba6e991SJim Ingham         bool abort_other_plans = false;
664481cef25SGreg Clayton         bool stop_other_threads = true;
6651ac04c30SGreg Clayton         Thread *thread = exe_ctx.GetThreadPtr();
666481cef25SGreg Clayton 
66764e7ead1SJim Ingham         ThreadPlan *new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
668481cef25SGreg Clayton                                                                     NULL,
669481cef25SGreg Clayton                                                                     false,
670481cef25SGreg Clayton                                                                     stop_other_threads,
671481cef25SGreg Clayton                                                                     eVoteYes,
672481cef25SGreg Clayton                                                                     eVoteNoOpinion,
673b9556accSGreg Clayton                                                                     frame_sp->GetFrameIndex());
67430fdc8d8SChris Lattner 
67564e7ead1SJim Ingham         // This returns an error, we should use it!
67664e7ead1SJim Ingham         ResumeNewPlan (exe_ctx, new_plan);
67730fdc8d8SChris Lattner     }
67830fdc8d8SChris Lattner }
67930fdc8d8SChris Lattner 
68030fdc8d8SChris Lattner void
68130fdc8d8SChris Lattner SBThread::StepInstruction (bool step_over)
68230fdc8d8SChris Lattner {
6832d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
684ceb6b139SCaroline Tice 
6854fc6cb9cSJim Ingham     Mutex::Locker api_locker;
6864fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
6874fc6cb9cSJim Ingham 
6881ac04c30SGreg Clayton 
689ceb6b139SCaroline Tice 
69017a6ad05SGreg Clayton     if (log)
6911ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::StepInstruction (step_over=%i)", exe_ctx.GetThreadPtr(), step_over);
69217a6ad05SGreg Clayton 
6931ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
69430fdc8d8SChris Lattner     {
6951ac04c30SGreg Clayton         Thread *thread = exe_ctx.GetThreadPtr();
69664e7ead1SJim Ingham         ThreadPlan *new_plan = thread->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
69764e7ead1SJim Ingham 
69864e7ead1SJim Ingham         // This returns an error, we should use it!
69964e7ead1SJim Ingham         ResumeNewPlan (exe_ctx, new_plan);
70030fdc8d8SChris Lattner     }
70130fdc8d8SChris Lattner }
70230fdc8d8SChris Lattner 
70330fdc8d8SChris Lattner void
70430fdc8d8SChris Lattner SBThread::RunToAddress (lldb::addr_t addr)
70530fdc8d8SChris Lattner {
7062d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
707ceb6b139SCaroline Tice 
7084fc6cb9cSJim Ingham     Mutex::Locker api_locker;
7094fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
7104fc6cb9cSJim Ingham 
711ceb6b139SCaroline Tice 
71217a6ad05SGreg Clayton     if (log)
7131ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::RunToAddress (addr=0x%llx)", exe_ctx.GetThreadPtr(), addr);
71417a6ad05SGreg Clayton 
7151ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
71630fdc8d8SChris Lattner     {
7177ba6e991SJim Ingham         bool abort_other_plans = false;
71830fdc8d8SChris Lattner         bool stop_other_threads = true;
71930fdc8d8SChris Lattner 
720e72dfb32SGreg Clayton         Address target_addr (addr);
72130fdc8d8SChris Lattner 
7221ac04c30SGreg Clayton         Thread *thread = exe_ctx.GetThreadPtr();
7231ac04c30SGreg Clayton 
72464e7ead1SJim Ingham         ThreadPlan *new_plan = thread->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
72564e7ead1SJim Ingham 
72664e7ead1SJim Ingham         // This returns an error, we should use it!
72764e7ead1SJim Ingham         ResumeNewPlan (exe_ctx, new_plan);
72830fdc8d8SChris Lattner     }
72930fdc8d8SChris Lattner }
73030fdc8d8SChris Lattner 
731481cef25SGreg Clayton SBError
732481cef25SGreg Clayton SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
733481cef25SGreg Clayton                          lldb::SBFileSpec &sb_file_spec,
734481cef25SGreg Clayton                          uint32_t line)
735481cef25SGreg Clayton {
736481cef25SGreg Clayton     SBError sb_error;
737481cef25SGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
738481cef25SGreg Clayton     char path[PATH_MAX];
739481cef25SGreg Clayton 
7404fc6cb9cSJim Ingham     Mutex::Locker api_locker;
7414fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
7424fc6cb9cSJim Ingham 
743b9556accSGreg Clayton     StackFrameSP frame_sp (sb_frame.GetFrameSP());
74417a6ad05SGreg Clayton 
745481cef25SGreg Clayton     if (log)
746481cef25SGreg Clayton     {
747481cef25SGreg Clayton         SBStream frame_desc_strm;
748481cef25SGreg Clayton         sb_frame.GetDescription (frame_desc_strm);
749481cef25SGreg Clayton         sb_file_spec->GetPath (path, sizeof(path));
750481cef25SGreg Clayton         log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)",
7511ac04c30SGreg Clayton                      exe_ctx.GetThreadPtr(),
752b9556accSGreg Clayton                      frame_sp.get(),
753481cef25SGreg Clayton                      frame_desc_strm.GetData(),
754481cef25SGreg Clayton                      path, line);
755481cef25SGreg Clayton     }
756481cef25SGreg Clayton 
7571ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
758481cef25SGreg Clayton     {
7591ac04c30SGreg Clayton         Target *target = exe_ctx.GetTargetPtr();
7601ac04c30SGreg Clayton         Thread *thread = exe_ctx.GetThreadPtr();
761481cef25SGreg Clayton 
762481cef25SGreg Clayton         if (line == 0)
763481cef25SGreg Clayton         {
764481cef25SGreg Clayton             sb_error.SetErrorString("invalid line argument");
765481cef25SGreg Clayton             return sb_error;
766481cef25SGreg Clayton         }
767481cef25SGreg Clayton 
768481cef25SGreg Clayton         StackFrameSP frame_sp;
769b9556accSGreg Clayton         if (!frame_sp)
770481cef25SGreg Clayton         {
7711ac04c30SGreg Clayton             frame_sp = thread->GetSelectedFrame ();
772481cef25SGreg Clayton             if (!frame_sp)
7731ac04c30SGreg Clayton                 frame_sp = thread->GetStackFrameAtIndex (0);
774481cef25SGreg Clayton         }
775481cef25SGreg Clayton 
776481cef25SGreg Clayton         SymbolContext frame_sc;
777481cef25SGreg Clayton         if (!frame_sp)
778481cef25SGreg Clayton         {
779481cef25SGreg Clayton             sb_error.SetErrorString("no valid frames in thread to step");
780481cef25SGreg Clayton             return sb_error;
781481cef25SGreg Clayton         }
782481cef25SGreg Clayton 
783481cef25SGreg Clayton         // If we have a frame, get its line
784481cef25SGreg Clayton         frame_sc = frame_sp->GetSymbolContext (eSymbolContextCompUnit  |
785481cef25SGreg Clayton                                                eSymbolContextFunction  |
786481cef25SGreg Clayton                                                eSymbolContextLineEntry |
787481cef25SGreg Clayton                                                eSymbolContextSymbol    );
788481cef25SGreg Clayton 
789481cef25SGreg Clayton         if (frame_sc.comp_unit == NULL)
790481cef25SGreg Clayton         {
791481cef25SGreg Clayton             sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex());
792481cef25SGreg Clayton             return sb_error;
793481cef25SGreg Clayton         }
794481cef25SGreg Clayton 
795481cef25SGreg Clayton         FileSpec step_file_spec;
796481cef25SGreg Clayton         if (sb_file_spec.IsValid())
797481cef25SGreg Clayton         {
798481cef25SGreg Clayton             // The file spec passed in was valid, so use it
799481cef25SGreg Clayton             step_file_spec = sb_file_spec.ref();
800481cef25SGreg Clayton         }
801481cef25SGreg Clayton         else
802481cef25SGreg Clayton         {
803481cef25SGreg Clayton             if (frame_sc.line_entry.IsValid())
804481cef25SGreg Clayton                 step_file_spec = frame_sc.line_entry.file;
805481cef25SGreg Clayton             else
806481cef25SGreg Clayton             {
807481cef25SGreg Clayton                 sb_error.SetErrorString("invalid file argument or no file for frame");
808481cef25SGreg Clayton                 return sb_error;
809481cef25SGreg Clayton             }
810481cef25SGreg Clayton         }
811481cef25SGreg Clayton 
8129b70ddb3SJim Ingham         // Grab the current function, then we will make sure the "until" address is
8139b70ddb3SJim Ingham         // within the function.  We discard addresses that are out of the current
8149b70ddb3SJim Ingham         // function, and then if there are no addresses remaining, give an appropriate
8159b70ddb3SJim Ingham         // error message.
8169b70ddb3SJim Ingham 
8179b70ddb3SJim Ingham         bool all_in_function = true;
8189b70ddb3SJim Ingham         AddressRange fun_range = frame_sc.function->GetAddressRange();
8199b70ddb3SJim Ingham 
820481cef25SGreg Clayton         std::vector<addr_t> step_over_until_addrs;
8217ba6e991SJim Ingham         const bool abort_other_plans = false;
822481cef25SGreg Clayton         const bool stop_other_threads = true;
823481cef25SGreg Clayton         const bool check_inlines = true;
824481cef25SGreg Clayton         const bool exact = false;
825481cef25SGreg Clayton 
826481cef25SGreg Clayton         SymbolContextList sc_list;
8279b70ddb3SJim Ingham         const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext (step_file_spec,
8289b70ddb3SJim Ingham                                                                                line,
8299b70ddb3SJim Ingham                                                                                check_inlines,
8309b70ddb3SJim Ingham                                                                                exact,
8319b70ddb3SJim Ingham                                                                                eSymbolContextLineEntry,
8329b70ddb3SJim Ingham                                                                                sc_list);
833481cef25SGreg Clayton         if (num_matches > 0)
834481cef25SGreg Clayton         {
835481cef25SGreg Clayton             SymbolContext sc;
836481cef25SGreg Clayton             for (uint32_t i=0; i<num_matches; ++i)
837481cef25SGreg Clayton             {
838481cef25SGreg Clayton                 if (sc_list.GetContextAtIndex(i, sc))
839481cef25SGreg Clayton                 {
8409b70ddb3SJim Ingham                     addr_t step_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
841481cef25SGreg Clayton                     if (step_addr != LLDB_INVALID_ADDRESS)
842481cef25SGreg Clayton                     {
8439b70ddb3SJim Ingham                         if (fun_range.ContainsLoadAddress(step_addr, target))
844481cef25SGreg Clayton                             step_over_until_addrs.push_back(step_addr);
8459b70ddb3SJim Ingham                         else
8469b70ddb3SJim Ingham                             all_in_function = false;
847481cef25SGreg Clayton                     }
848481cef25SGreg Clayton                 }
849481cef25SGreg Clayton             }
850481cef25SGreg Clayton         }
851481cef25SGreg Clayton 
852481cef25SGreg Clayton         if (step_over_until_addrs.empty())
853481cef25SGreg Clayton         {
8549b70ddb3SJim Ingham             if (all_in_function)
8559b70ddb3SJim Ingham             {
856481cef25SGreg Clayton                 step_file_spec.GetPath (path, sizeof(path));
857fd54b368SJason Molenda                 sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path, line);
858481cef25SGreg Clayton             }
859481cef25SGreg Clayton             else
86086edbf41SGreg Clayton                 sb_error.SetErrorString ("step until target not in current function");
8619b70ddb3SJim Ingham         }
8629b70ddb3SJim Ingham         else
863481cef25SGreg Clayton         {
86464e7ead1SJim Ingham             ThreadPlan *new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans,
865481cef25SGreg Clayton                                                                         &step_over_until_addrs[0],
866481cef25SGreg Clayton                                                                         step_over_until_addrs.size(),
867481cef25SGreg Clayton                                                                         stop_other_threads,
868481cef25SGreg Clayton                                                                         frame_sp->GetFrameIndex());
869481cef25SGreg Clayton 
87064e7ead1SJim Ingham             sb_error = ResumeNewPlan (exe_ctx, new_plan);
871481cef25SGreg Clayton         }
872481cef25SGreg Clayton     }
873481cef25SGreg Clayton     else
874481cef25SGreg Clayton     {
875481cef25SGreg Clayton         sb_error.SetErrorString("this SBThread object is invalid");
876481cef25SGreg Clayton     }
877481cef25SGreg Clayton     return sb_error;
878481cef25SGreg Clayton }
879481cef25SGreg Clayton 
8804413758cSJim Ingham SBError
881*cb640dd8SJim Ingham SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value)
8824413758cSJim Ingham {
8834413758cSJim Ingham     SBError sb_error;
8844413758cSJim Ingham 
8854413758cSJim Ingham     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
8864413758cSJim Ingham 
8874413758cSJim Ingham     Mutex::Locker api_locker;
8884413758cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
8894413758cSJim Ingham 
8904413758cSJim Ingham 
8914413758cSJim Ingham     if (log)
892*cb640dd8SJim Ingham         log->Printf ("SBThread(%p)::ReturnFromFrame (frame=%d)", exe_ctx.GetThreadPtr(), frame.GetFrameID());
8934413758cSJim Ingham 
8944413758cSJim Ingham     if (exe_ctx.HasThreadScope())
8954413758cSJim Ingham     {
8964413758cSJim Ingham         Thread *thread = exe_ctx.GetThreadPtr();
897*cb640dd8SJim Ingham         sb_error.SetError (thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
8984413758cSJim Ingham     }
8994413758cSJim Ingham 
9004413758cSJim Ingham     return sb_error;
9014413758cSJim Ingham }
9024413758cSJim Ingham 
903481cef25SGreg Clayton 
904722a0cdcSGreg Clayton bool
905722a0cdcSGreg Clayton SBThread::Suspend()
906722a0cdcSGreg Clayton {
907c9858e4dSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
9087fdf9ef1SGreg Clayton     ExecutionContext exe_ctx (m_opaque_sp.get());
909c9858e4dSGreg Clayton     bool result = false;
9101ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
911722a0cdcSGreg Clayton     {
912c9858e4dSGreg Clayton         Process::StopLocker stop_locker;
913c9858e4dSGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
914c9858e4dSGreg Clayton         {
9151ac04c30SGreg Clayton             exe_ctx.GetThreadPtr()->SetResumeState (eStateSuspended);
916c9858e4dSGreg Clayton             result = true;
917722a0cdcSGreg Clayton         }
918c9858e4dSGreg Clayton         else
919c9858e4dSGreg Clayton         {
920c9858e4dSGreg Clayton             if (log)
921c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::Suspend() => error: process is running", exe_ctx.GetThreadPtr());
922c9858e4dSGreg Clayton         }
923c9858e4dSGreg Clayton     }
924c9858e4dSGreg Clayton     if (log)
925c9858e4dSGreg Clayton         log->Printf ("SBThread(%p)::Suspend() => %i", exe_ctx.GetThreadPtr(), result);
926c9858e4dSGreg Clayton     return result;
927722a0cdcSGreg Clayton }
928722a0cdcSGreg Clayton 
929722a0cdcSGreg Clayton bool
930722a0cdcSGreg Clayton SBThread::Resume ()
931722a0cdcSGreg Clayton {
932c9858e4dSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
9337fdf9ef1SGreg Clayton     ExecutionContext exe_ctx (m_opaque_sp.get());
934c9858e4dSGreg Clayton     bool result = false;
9351ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
936722a0cdcSGreg Clayton     {
937c9858e4dSGreg Clayton         Process::StopLocker stop_locker;
938c9858e4dSGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
939c9858e4dSGreg Clayton         {
9401ac04c30SGreg Clayton             exe_ctx.GetThreadPtr()->SetResumeState (eStateRunning);
941c9858e4dSGreg Clayton             result = true;
942722a0cdcSGreg Clayton         }
943c9858e4dSGreg Clayton         else
944c9858e4dSGreg Clayton         {
945c9858e4dSGreg Clayton             if (log)
946c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::Resume() => error: process is running", exe_ctx.GetThreadPtr());
947c9858e4dSGreg Clayton         }
948c9858e4dSGreg Clayton     }
949c9858e4dSGreg Clayton     if (log)
950c9858e4dSGreg Clayton         log->Printf ("SBThread(%p)::Resume() => %i", exe_ctx.GetThreadPtr(), result);
951c9858e4dSGreg Clayton     return result;
952722a0cdcSGreg Clayton }
953722a0cdcSGreg Clayton 
954722a0cdcSGreg Clayton bool
955722a0cdcSGreg Clayton SBThread::IsSuspended()
956722a0cdcSGreg Clayton {
9577fdf9ef1SGreg Clayton     ExecutionContext exe_ctx (m_opaque_sp.get());
9581ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
9591ac04c30SGreg Clayton         return exe_ctx.GetThreadPtr()->GetResumeState () == eStateSuspended;
960722a0cdcSGreg Clayton     return false;
961722a0cdcSGreg Clayton }
962722a0cdcSGreg Clayton 
96330fdc8d8SChris Lattner SBProcess
96430fdc8d8SChris Lattner SBThread::GetProcess ()
96530fdc8d8SChris Lattner {
966ceb6b139SCaroline Tice 
967b9556accSGreg Clayton     SBProcess sb_process;
968b9556accSGreg Clayton     ProcessSP process_sp;
9697fdf9ef1SGreg Clayton     ExecutionContext exe_ctx (m_opaque_sp.get());
9701ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
97130fdc8d8SChris Lattner     {
97230fdc8d8SChris Lattner         // Have to go up to the target so we can get a shared pointer to our process...
9731ac04c30SGreg Clayton         sb_process.SetSP (exe_ctx.GetProcessSP());
97430fdc8d8SChris Lattner     }
975ceb6b139SCaroline Tice 
9762d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
977ceb6b139SCaroline Tice     if (log)
978ceb6b139SCaroline Tice     {
979481cef25SGreg Clayton         SBStream frame_desc_strm;
980b9556accSGreg Clayton         sb_process.GetDescription (frame_desc_strm);
9811ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s", exe_ctx.GetThreadPtr(),
982b9556accSGreg Clayton                      process_sp.get(), frame_desc_strm.GetData());
983ceb6b139SCaroline Tice     }
984ceb6b139SCaroline Tice 
985b9556accSGreg Clayton     return sb_process;
98630fdc8d8SChris Lattner }
98730fdc8d8SChris Lattner 
98830fdc8d8SChris Lattner uint32_t
98930fdc8d8SChris Lattner SBThread::GetNumFrames ()
99030fdc8d8SChris Lattner {
9912d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
992ceb6b139SCaroline Tice 
993ceb6b139SCaroline Tice     uint32_t num_frames = 0;
9944fc6cb9cSJim Ingham     Mutex::Locker api_locker;
9954fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
9964fc6cb9cSJim Ingham 
9971ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
998af67cecdSGreg Clayton     {
9997fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
10007fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
10017fdf9ef1SGreg Clayton         {
10021ac04c30SGreg Clayton             num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
1003af67cecdSGreg Clayton         }
1004c9858e4dSGreg Clayton         else
1005c9858e4dSGreg Clayton         {
1006c9858e4dSGreg Clayton             if (log)
1007c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetNumFrames() => error: process is running", exe_ctx.GetThreadPtr());
1008c9858e4dSGreg Clayton         }
10097fdf9ef1SGreg Clayton     }
1010ceb6b139SCaroline Tice 
1011ceb6b139SCaroline Tice     if (log)
10121ac04c30SGreg Clayton         log->Printf ("SBThread(%p)::GetNumFrames () => %u", exe_ctx.GetThreadPtr(), num_frames);
1013ceb6b139SCaroline Tice 
1014ceb6b139SCaroline Tice     return num_frames;
101530fdc8d8SChris Lattner }
101630fdc8d8SChris Lattner 
101730fdc8d8SChris Lattner SBFrame
101830fdc8d8SChris Lattner SBThread::GetFrameAtIndex (uint32_t idx)
101930fdc8d8SChris Lattner {
10202d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1021ceb6b139SCaroline Tice 
102230fdc8d8SChris Lattner     SBFrame sb_frame;
1023b9556accSGreg Clayton     StackFrameSP frame_sp;
10244fc6cb9cSJim Ingham     Mutex::Locker api_locker;
10254fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
10264fc6cb9cSJim Ingham 
10271ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
1028af67cecdSGreg Clayton     {
10297fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
10307fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
10317fdf9ef1SGreg Clayton         {
10321ac04c30SGreg Clayton             frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex (idx);
1033b9556accSGreg Clayton             sb_frame.SetFrameSP (frame_sp);
1034af67cecdSGreg Clayton         }
1035c9858e4dSGreg Clayton         else
1036c9858e4dSGreg Clayton         {
1037c9858e4dSGreg Clayton             if (log)
1038c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetFrameAtIndex() => error: process is running", exe_ctx.GetThreadPtr());
1039c9858e4dSGreg Clayton         }
10407fdf9ef1SGreg Clayton     }
1041ceb6b139SCaroline Tice 
1042ceb6b139SCaroline Tice     if (log)
1043ceb6b139SCaroline Tice     {
1044481cef25SGreg Clayton         SBStream frame_desc_strm;
1045481cef25SGreg Clayton         sb_frame.GetDescription (frame_desc_strm);
10464838131bSGreg Clayton         log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
10471ac04c30SGreg Clayton                      exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData());
1048ceb6b139SCaroline Tice     }
1049ceb6b139SCaroline Tice 
105030fdc8d8SChris Lattner     return sb_frame;
105130fdc8d8SChris Lattner }
105230fdc8d8SChris Lattner 
1053f028a1fbSGreg Clayton lldb::SBFrame
1054f028a1fbSGreg Clayton SBThread::GetSelectedFrame ()
1055f028a1fbSGreg Clayton {
1056f028a1fbSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1057f028a1fbSGreg Clayton 
1058f028a1fbSGreg Clayton     SBFrame sb_frame;
1059b9556accSGreg Clayton     StackFrameSP frame_sp;
10604fc6cb9cSJim Ingham     Mutex::Locker api_locker;
10614fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
10624fc6cb9cSJim Ingham 
10631ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
1064af67cecdSGreg Clayton     {
10657fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
10667fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
10677fdf9ef1SGreg Clayton         {
10681ac04c30SGreg Clayton             frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame ();
1069b9556accSGreg Clayton             sb_frame.SetFrameSP (frame_sp);
1070af67cecdSGreg Clayton         }
1071c9858e4dSGreg Clayton         else
1072c9858e4dSGreg Clayton         {
1073c9858e4dSGreg Clayton             if (log)
1074c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::GetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr());
1075c9858e4dSGreg Clayton         }
10767fdf9ef1SGreg Clayton     }
1077f028a1fbSGreg Clayton 
1078f028a1fbSGreg Clayton     if (log)
1079f028a1fbSGreg Clayton     {
1080481cef25SGreg Clayton         SBStream frame_desc_strm;
1081481cef25SGreg Clayton         sb_frame.GetDescription (frame_desc_strm);
1082f028a1fbSGreg Clayton         log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
10831ac04c30SGreg Clayton                      exe_ctx.GetThreadPtr(), frame_sp.get(), frame_desc_strm.GetData());
1084f028a1fbSGreg Clayton     }
1085f028a1fbSGreg Clayton 
1086f028a1fbSGreg Clayton     return sb_frame;
1087f028a1fbSGreg Clayton }
1088f028a1fbSGreg Clayton 
1089f028a1fbSGreg Clayton lldb::SBFrame
1090f028a1fbSGreg Clayton SBThread::SetSelectedFrame (uint32_t idx)
1091f028a1fbSGreg Clayton {
1092f028a1fbSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1093f028a1fbSGreg Clayton 
1094f028a1fbSGreg Clayton     SBFrame sb_frame;
1095b9556accSGreg Clayton     StackFrameSP frame_sp;
10964fc6cb9cSJim Ingham     Mutex::Locker api_locker;
10974fc6cb9cSJim Ingham     ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
10984fc6cb9cSJim Ingham 
10991ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
1100f028a1fbSGreg Clayton     {
11017fdf9ef1SGreg Clayton         Process::StopLocker stop_locker;
11027fdf9ef1SGreg Clayton         if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
11037fdf9ef1SGreg Clayton         {
11041ac04c30SGreg Clayton             Thread *thread = exe_ctx.GetThreadPtr();
11051ac04c30SGreg Clayton             frame_sp = thread->GetStackFrameAtIndex (idx);
1106f028a1fbSGreg Clayton             if (frame_sp)
1107f028a1fbSGreg Clayton             {
11081ac04c30SGreg Clayton                 thread->SetSelectedFrame (frame_sp.get());
1109b9556accSGreg Clayton                 sb_frame.SetFrameSP (frame_sp);
1110f028a1fbSGreg Clayton             }
1111f028a1fbSGreg Clayton         }
1112c9858e4dSGreg Clayton         else
1113c9858e4dSGreg Clayton         {
1114c9858e4dSGreg Clayton             if (log)
1115c9858e4dSGreg Clayton                 log->Printf ("SBThread(%p)::SetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr());
1116c9858e4dSGreg Clayton         }
11177fdf9ef1SGreg Clayton     }
1118f028a1fbSGreg Clayton 
1119f028a1fbSGreg Clayton     if (log)
1120f028a1fbSGreg Clayton     {
1121481cef25SGreg Clayton         SBStream frame_desc_strm;
1122481cef25SGreg Clayton         sb_frame.GetDescription (frame_desc_strm);
1123f028a1fbSGreg Clayton         log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
11241ac04c30SGreg Clayton                      exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData());
1125f028a1fbSGreg Clayton     }
1126f028a1fbSGreg Clayton     return sb_frame;
1127f028a1fbSGreg Clayton }
1128f028a1fbSGreg Clayton 
1129f028a1fbSGreg Clayton 
113030fdc8d8SChris Lattner bool
113130fdc8d8SChris Lattner SBThread::operator == (const SBThread &rhs) const
113230fdc8d8SChris Lattner {
11337fdf9ef1SGreg Clayton     return m_opaque_sp->GetThreadSP().get() == rhs.m_opaque_sp->GetThreadSP().get();
113430fdc8d8SChris Lattner }
113530fdc8d8SChris Lattner 
113630fdc8d8SChris Lattner bool
113730fdc8d8SChris Lattner SBThread::operator != (const SBThread &rhs) const
113830fdc8d8SChris Lattner {
11397fdf9ef1SGreg Clayton     return m_opaque_sp->GetThreadSP().get() != rhs.m_opaque_sp->GetThreadSP().get();
114030fdc8d8SChris Lattner }
1141dde9cff3SCaroline Tice 
1142dde9cff3SCaroline Tice bool
1143ceb6b139SCaroline Tice SBThread::GetDescription (SBStream &description) const
1144ceb6b139SCaroline Tice {
1145da7bc7d0SGreg Clayton     Stream &strm = description.ref();
1146da7bc7d0SGreg Clayton 
11477fdf9ef1SGreg Clayton     ExecutionContext exe_ctx (m_opaque_sp.get());
11481ac04c30SGreg Clayton     if (exe_ctx.HasThreadScope())
1149ceb6b139SCaroline Tice     {
11501ac04c30SGreg Clayton         strm.Printf("SBThread: tid = 0x%4.4llx", exe_ctx.GetThreadPtr()->GetID());
1151ceb6b139SCaroline Tice     }
1152ceb6b139SCaroline Tice     else
1153da7bc7d0SGreg Clayton         strm.PutCString ("No value");
1154ceb6b139SCaroline Tice 
1155ceb6b139SCaroline Tice     return true;
1156ceb6b139SCaroline Tice }
1157