1 //===-- SBThread.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/API/SBThread.h"
11 
12 #include "lldb/API/SBSymbolContext.h"
13 #include "lldb/API/SBFileSpec.h"
14 #include "lldb/API/SBStream.h"
15 #include "lldb/Breakpoint/BreakpointLocation.h"
16 #include "lldb/Core/Debugger.h"
17 #include "lldb/Core/Stream.h"
18 #include "lldb/Core/StreamFile.h"
19 #include "lldb/Interpreter/CommandInterpreter.h"
20 #include "lldb/Target/Thread.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Symbol/SymbolContext.h"
23 #include "lldb/Symbol/CompileUnit.h"
24 #include "lldb/Target/StopInfo.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/ThreadPlan.h"
27 #include "lldb/Target/ThreadPlanStepInstruction.h"
28 #include "lldb/Target/ThreadPlanStepOut.h"
29 #include "lldb/Target/ThreadPlanStepRange.h"
30 #include "lldb/Target/ThreadPlanStepInRange.h"
31 
32 
33 #include "lldb/API/SBAddress.h"
34 #include "lldb/API/SBDebugger.h"
35 #include "lldb/API/SBFrame.h"
36 #include "lldb/API/SBProcess.h"
37 #include "lldb/API/SBValue.h"
38 
39 using namespace lldb;
40 using namespace lldb_private;
41 
42 //----------------------------------------------------------------------
43 // Constructors
44 //----------------------------------------------------------------------
45 SBThread::SBThread () :
46     m_opaque_wp ()
47 {
48 }
49 
50 SBThread::SBThread (const ThreadSP& lldb_object_sp) :
51     m_opaque_wp (lldb_object_sp)
52 {
53 }
54 
55 SBThread::SBThread (const SBThread &rhs) :
56     m_opaque_wp (rhs.m_opaque_wp)
57 {
58 }
59 
60 //----------------------------------------------------------------------
61 // Assignment operator
62 //----------------------------------------------------------------------
63 
64 const lldb::SBThread &
65 SBThread::operator = (const SBThread &rhs)
66 {
67     if (this != &rhs)
68         m_opaque_wp = rhs.m_opaque_wp;
69     return *this;
70 }
71 
72 //----------------------------------------------------------------------
73 // Destructor
74 //----------------------------------------------------------------------
75 SBThread::~SBThread()
76 {
77 }
78 
79 bool
80 SBThread::IsValid() const
81 {
82     return !m_opaque_wp.expired();
83 }
84 
85 void
86 SBThread::Clear ()
87 {
88     m_opaque_wp.reset();
89 }
90 
91 
92 StopReason
93 SBThread::GetStopReason()
94 {
95     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
96 
97     StopReason reason = eStopReasonInvalid;
98     ThreadSP thread_sp(m_opaque_wp.lock());
99     if (thread_sp)
100     {
101         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
102         StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
103         if (stop_info_sp)
104             reason =  stop_info_sp->GetStopReason();
105     }
106 
107     if (log)
108         log->Printf ("SBThread(%p)::GetStopReason () => %s", thread_sp.get(),
109                      Thread::StopReasonAsCString (reason));
110 
111     return reason;
112 }
113 
114 size_t
115 SBThread::GetStopReasonDataCount ()
116 {
117     ThreadSP thread_sp(m_opaque_wp.lock());
118     if (thread_sp)
119     {
120         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
121         StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
122         if (stop_info_sp)
123         {
124             StopReason reason = stop_info_sp->GetStopReason();
125             switch (reason)
126             {
127             case eStopReasonInvalid:
128             case eStopReasonNone:
129             case eStopReasonTrace:
130             case eStopReasonPlanComplete:
131                 // There is no data for these stop reasons.
132                 return 0;
133 
134             case eStopReasonBreakpoint:
135                 {
136                     break_id_t site_id = stop_info_sp->GetValue();
137                     lldb::BreakpointSiteSP bp_site_sp (thread_sp->GetProcess().GetBreakpointSiteList().FindByID (site_id));
138                     if (bp_site_sp)
139                         return bp_site_sp->GetNumberOfOwners () * 2;
140                     else
141                         return 0; // Breakpoint must have cleared itself...
142                 }
143                 break;
144 
145             case eStopReasonWatchpoint:
146                 return 1;
147 
148             case eStopReasonSignal:
149                 return 1;
150 
151             case eStopReasonException:
152                 return 1;
153             }
154         }
155     }
156     return 0;
157 }
158 
159 uint64_t
160 SBThread::GetStopReasonDataAtIndex (uint32_t idx)
161 {
162     ThreadSP thread_sp(m_opaque_wp.lock());
163     if (thread_sp)
164     {
165         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
166         StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
167         if (stop_info_sp)
168         {
169             StopReason reason = stop_info_sp->GetStopReason();
170             switch (reason)
171             {
172             case eStopReasonInvalid:
173             case eStopReasonNone:
174             case eStopReasonTrace:
175             case eStopReasonPlanComplete:
176                 // There is no data for these stop reasons.
177                 return 0;
178 
179             case eStopReasonBreakpoint:
180                 {
181                     break_id_t site_id = stop_info_sp->GetValue();
182                     lldb::BreakpointSiteSP bp_site_sp (thread_sp->GetProcess().GetBreakpointSiteList().FindByID (site_id));
183                     if (bp_site_sp)
184                     {
185                         uint32_t bp_index = idx / 2;
186                         BreakpointLocationSP bp_loc_sp (bp_site_sp->GetOwnerAtIndex (bp_index));
187                         if (bp_loc_sp)
188                         {
189                             if (bp_index & 1)
190                             {
191                                 // Odd idx, return the breakpoint location ID
192                                 return bp_loc_sp->GetID();
193                             }
194                             else
195                             {
196                                 // Even idx, return the breakpoint ID
197                                 return bp_loc_sp->GetBreakpoint().GetID();
198                             }
199                         }
200                     }
201                     return LLDB_INVALID_BREAK_ID;
202                 }
203                 break;
204 
205             case eStopReasonWatchpoint:
206                 return stop_info_sp->GetValue();
207 
208             case eStopReasonSignal:
209                 return stop_info_sp->GetValue();
210 
211             case eStopReasonException:
212                 return stop_info_sp->GetValue();
213             }
214         }
215     }
216     return 0;
217 }
218 
219 size_t
220 SBThread::GetStopDescription (char *dst, size_t dst_len)
221 {
222     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
223 
224     ThreadSP thread_sp(m_opaque_wp.lock());
225     if (thread_sp)
226     {
227         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
228         StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
229         if (stop_info_sp)
230         {
231             const char *stop_desc = stop_info_sp->GetDescription();
232             if (stop_desc)
233             {
234                 if (log)
235                     log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"",
236                                  thread_sp.get(), stop_desc);
237                 if (dst)
238                     return ::snprintf (dst, dst_len, "%s", stop_desc);
239                 else
240                 {
241                     // NULL dst passed in, return the length needed to contain the description
242                     return ::strlen (stop_desc) + 1; // Include the NULL byte for size
243                 }
244             }
245             else
246             {
247                 size_t stop_desc_len = 0;
248                 switch (stop_info_sp->GetStopReason())
249                 {
250                 case eStopReasonTrace:
251                 case eStopReasonPlanComplete:
252                     {
253                         static char trace_desc[] = "step";
254                         stop_desc = trace_desc;
255                         stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
256                     }
257                     break;
258 
259                 case eStopReasonBreakpoint:
260                     {
261                         static char bp_desc[] = "breakpoint hit";
262                         stop_desc = bp_desc;
263                         stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
264                     }
265                     break;
266 
267                 case eStopReasonWatchpoint:
268                     {
269                         static char wp_desc[] = "watchpoint hit";
270                         stop_desc = wp_desc;
271                         stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
272                     }
273                     break;
274 
275                 case eStopReasonSignal:
276                     {
277                         stop_desc = thread_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue());
278                         if (stop_desc == NULL || stop_desc[0] == '\0')
279                         {
280                             static char signal_desc[] = "signal";
281                             stop_desc = signal_desc;
282                             stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
283                         }
284                     }
285                     break;
286 
287                 case eStopReasonException:
288                     {
289                         char exc_desc[] = "exception";
290                         stop_desc = exc_desc;
291                         stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
292                     }
293                     break;
294 
295                 default:
296                     break;
297                 }
298 
299                 if (stop_desc && stop_desc[0])
300                 {
301                     if (log)
302                         log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'",
303                                      thread_sp.get(), stop_desc);
304 
305                     if (dst)
306                         return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
307 
308                     if (stop_desc_len == 0)
309                         stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
310 
311                     return stop_desc_len;
312                 }
313             }
314         }
315     }
316     if (dst)
317         *dst = 0;
318     return 0;
319 }
320 
321 SBValue
322 SBThread::GetStopReturnValue ()
323 {
324     ValueObjectSP return_valobj_sp;
325     ThreadSP thread_sp(m_opaque_wp.lock());
326     if (thread_sp)
327     {
328         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
329         StopInfoSP stop_info_sp = thread_sp->GetStopInfo ();
330         if (stop_info_sp)
331         {
332             return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
333         }
334     }
335 
336     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
337     if (log)
338         log->Printf ("SBThread(%p)::GetStopReturnValue () => %s", thread_sp.get(),
339                                                                   return_valobj_sp.get()
340                                                                       ? return_valobj_sp->GetValueAsCString()
341                                                                         : "<no return value>");
342 
343     return SBValue (return_valobj_sp);
344 }
345 
346 void
347 SBThread::SetThread (const ThreadSP& lldb_object_sp)
348 {
349     m_opaque_wp = lldb_object_sp;
350 }
351 
352 
353 lldb::tid_t
354 SBThread::GetThreadID () const
355 {
356     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
357 
358     lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
359     ThreadSP thread_sp(m_opaque_wp.lock());
360     if (thread_sp)
361         tid = thread_sp->GetID();
362 
363     if (log)
364         log->Printf ("SBThread(%p)::GetThreadID () => 0x%4.4llx", thread_sp.get(), tid);
365 
366     return tid;
367 }
368 
369 uint32_t
370 SBThread::GetIndexID () const
371 {
372     ThreadSP thread_sp(m_opaque_wp.lock());
373     if (thread_sp)
374         return thread_sp->GetIndexID();
375     return LLDB_INVALID_INDEX32;
376 }
377 const char *
378 SBThread::GetName () const
379 {
380     const char *name = NULL;
381     ThreadSP thread_sp(m_opaque_wp.lock());
382     if (thread_sp)
383     {
384         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
385         name = thread_sp->GetName();
386     }
387 
388     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
389     if (log)
390         log->Printf ("SBThread(%p)::GetName () => %s", thread_sp.get(), name ? name : "NULL");
391 
392     return name;
393 }
394 
395 const char *
396 SBThread::GetQueueName () const
397 {
398     const char *name = NULL;
399     ThreadSP thread_sp(m_opaque_wp.lock());
400     if (thread_sp)
401     {
402         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
403         name = thread_sp->GetQueueName();
404     }
405 
406     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
407     if (log)
408         log->Printf ("SBThread(%p)::GetQueueName () => %s", thread_sp.get(), name ? name : "NULL");
409 
410     return name;
411 }
412 
413 
414 void
415 SBThread::StepOver (lldb::RunMode stop_other_threads)
416 {
417     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
418 
419     ThreadSP thread_sp(m_opaque_wp.lock());
420 
421     if (log)
422         log->Printf ("SBThread(%p)::StepOver (stop_other_threads='%s')", thread_sp.get(),
423                      Thread::RunModeAsCString (stop_other_threads));
424 
425     if (thread_sp)
426     {
427         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
428         bool abort_other_plans = true;
429         StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex (0));
430 
431         if (frame_sp)
432         {
433             if (frame_sp->HasDebugInformation ())
434             {
435                 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
436                 thread_sp->QueueThreadPlanForStepRange (abort_other_plans,
437                                                         eStepTypeOver,
438                                                         sc.line_entry.range,
439                                                         sc,
440                                                         stop_other_threads,
441                                                         false);
442 
443             }
444             else
445             {
446                 thread_sp->QueueThreadPlanForStepSingleInstruction (true,
447                                                                     abort_other_plans,
448                                                                     stop_other_threads);
449             }
450         }
451 
452         Process &process = thread_sp->GetProcess();
453         // Why do we need to set the current thread by ID here???
454         process.GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
455         Error error (process.Resume());
456         if (error.Success())
457         {
458             // If we are doing synchronous mode, then wait for the
459             // process to stop yet again!
460             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
461                 process.WaitForProcessToStop (NULL);
462         }
463     }
464 }
465 
466 void
467 SBThread::StepInto (lldb::RunMode stop_other_threads)
468 {
469     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
470 
471 
472     ThreadSP thread_sp(m_opaque_wp.lock());
473 
474     if (log)
475         log->Printf ("SBThread(%p)::StepInto (stop_other_threads='%s')", thread_sp.get(),
476                      Thread::RunModeAsCString (stop_other_threads));
477     if (thread_sp)
478     {
479         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
480         bool abort_other_plans = true;
481 
482         StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex (0));
483 
484         if (frame_sp && frame_sp->HasDebugInformation ())
485         {
486             bool avoid_code_without_debug_info = true;
487             SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
488             thread_sp->QueueThreadPlanForStepRange (abort_other_plans,
489                                                     eStepTypeInto,
490                                                     sc.line_entry.range,
491                                                     sc,
492                                                     stop_other_threads,
493                                                     avoid_code_without_debug_info);
494         }
495         else
496         {
497             thread_sp->QueueThreadPlanForStepSingleInstruction (false,
498                                                                 abort_other_plans,
499                                                                 stop_other_threads);
500         }
501 
502         Process &process = thread_sp->GetProcess();
503         // Why do we need to set the current thread by ID here???
504         process.GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
505         Error error (process.Resume());
506         if (error.Success())
507         {
508             // If we are doing synchronous mode, then wait for the
509             // process to stop yet again!
510             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
511                 process.WaitForProcessToStop (NULL);
512         }
513     }
514 }
515 
516 void
517 SBThread::StepOut ()
518 {
519     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
520 
521     ThreadSP thread_sp(m_opaque_wp.lock());
522 
523     if (log)
524         log->Printf ("SBThread(%p)::StepOut ()", thread_sp.get());
525 
526     if (thread_sp)
527     {
528         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
529         bool abort_other_plans = true;
530         bool stop_other_threads = true;
531 
532         thread_sp->QueueThreadPlanForStepOut (abort_other_plans,
533                                               NULL,
534                                               false,
535                                               stop_other_threads,
536                                               eVoteYes,
537                                               eVoteNoOpinion,
538                                               0);
539 
540         Process &process = thread_sp->GetProcess();
541         process.GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
542         Error error (process.Resume());
543         if (error.Success())
544         {
545             // If we are doing synchronous mode, then wait for the
546             // process to stop yet again!
547             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
548                 process.WaitForProcessToStop (NULL);
549         }
550     }
551 }
552 
553 void
554 SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame)
555 {
556     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
557 
558     ThreadSP thread_sp(m_opaque_wp.lock());
559 
560     StackFrameSP frame_sp (sb_frame.GetFrameSP());
561     if (log)
562     {
563         SBStream frame_desc_strm;
564         sb_frame.GetDescription (frame_desc_strm);
565         log->Printf ("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)", thread_sp.get(), frame_sp.get(), frame_desc_strm.GetData());
566     }
567 
568     if (thread_sp)
569     {
570         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
571         bool abort_other_plans = true;
572         bool stop_other_threads = true;
573 
574         thread_sp->QueueThreadPlanForStepOut (abort_other_plans,
575                                               NULL,
576                                               false,
577                                               stop_other_threads,
578                                               eVoteYes,
579                                               eVoteNoOpinion,
580                                               frame_sp->GetFrameIndex());
581 
582         Process &process = thread_sp->GetProcess();
583         process.GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
584         Error error (process.Resume());
585         if (error.Success())
586         {
587             // If we are doing synchronous mode, then wait for the
588             // process to stop yet again!
589             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
590                 process.WaitForProcessToStop (NULL);
591         }
592     }
593 }
594 
595 void
596 SBThread::StepInstruction (bool step_over)
597 {
598     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
599 
600     ThreadSP thread_sp(m_opaque_wp.lock());
601 
602     if (log)
603         log->Printf ("SBThread(%p)::StepInstruction (step_over=%i)", thread_sp.get(), step_over);
604 
605     if (thread_sp)
606     {
607         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
608         thread_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
609         Process &process = thread_sp->GetProcess();
610         process.GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
611         Error error (process.Resume());
612         if (error.Success())
613         {
614             // If we are doing synchronous mode, then wait for the
615             // process to stop yet again!
616             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
617                 process.WaitForProcessToStop (NULL);
618         }
619     }
620 }
621 
622 void
623 SBThread::RunToAddress (lldb::addr_t addr)
624 {
625     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
626 
627     ThreadSP thread_sp(m_opaque_wp.lock());
628 
629     if (log)
630         log->Printf ("SBThread(%p)::RunToAddress (addr=0x%llx)", thread_sp.get(), addr);
631 
632     if (thread_sp)
633     {
634         bool abort_other_plans = true;
635         bool stop_other_threads = true;
636 
637         Address target_addr (NULL, addr);
638 
639         thread_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
640         Process &process = thread_sp->GetProcess();
641         process.GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
642         Error error (process.Resume());
643         if (error.Success())
644         {
645             // If we are doing synchronous mode, then wait for the
646             // process to stop yet again!
647             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
648                 process.WaitForProcessToStop (NULL);
649         }
650     }
651 }
652 
653 SBError
654 SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
655                          lldb::SBFileSpec &sb_file_spec,
656                          uint32_t line)
657 {
658     SBError sb_error;
659     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
660     char path[PATH_MAX];
661 
662     ThreadSP thread_sp(m_opaque_wp.lock());
663     StackFrameSP frame_sp (sb_frame.GetFrameSP());
664 
665     if (log)
666     {
667         SBStream frame_desc_strm;
668         sb_frame.GetDescription (frame_desc_strm);
669         sb_file_spec->GetPath (path, sizeof(path));
670         log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)",
671                      thread_sp.get(),
672                      frame_sp.get(),
673                      frame_desc_strm.GetData(),
674                      path, line);
675     }
676 
677     if (thread_sp)
678     {
679         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
680 
681         if (line == 0)
682         {
683             sb_error.SetErrorString("invalid line argument");
684             return sb_error;
685         }
686 
687         StackFrameSP frame_sp;
688         if (!frame_sp)
689         {
690             frame_sp = thread_sp->GetSelectedFrame ();
691             if (!frame_sp)
692                 frame_sp = thread_sp->GetStackFrameAtIndex (0);
693         }
694 
695         SymbolContext frame_sc;
696         if (!frame_sp)
697         {
698             sb_error.SetErrorString("no valid frames in thread to step");
699             return sb_error;
700         }
701 
702         // If we have a frame, get its line
703         frame_sc = frame_sp->GetSymbolContext (eSymbolContextCompUnit  |
704                                                eSymbolContextFunction  |
705                                                eSymbolContextLineEntry |
706                                                eSymbolContextSymbol    );
707 
708         if (frame_sc.comp_unit == NULL)
709         {
710             sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex());
711             return sb_error;
712         }
713 
714         FileSpec step_file_spec;
715         if (sb_file_spec.IsValid())
716         {
717             // The file spec passed in was valid, so use it
718             step_file_spec = sb_file_spec.ref();
719         }
720         else
721         {
722             if (frame_sc.line_entry.IsValid())
723                 step_file_spec = frame_sc.line_entry.file;
724             else
725             {
726                 sb_error.SetErrorString("invalid file argument or no file for frame");
727                 return sb_error;
728             }
729         }
730 
731         // Grab the current function, then we will make sure the "until" address is
732         // within the function.  We discard addresses that are out of the current
733         // function, and then if there are no addresses remaining, give an appropriate
734         // error message.
735 
736         bool all_in_function = true;
737         AddressRange fun_range = frame_sc.function->GetAddressRange();
738 
739         std::vector<addr_t> step_over_until_addrs;
740         const bool abort_other_plans = true;
741         const bool stop_other_threads = true;
742         const bool check_inlines = true;
743         const bool exact = false;
744         Target *target = &thread_sp->GetProcess().GetTarget();
745 
746         SymbolContextList sc_list;
747         const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext (step_file_spec,
748                                                                                line,
749                                                                                check_inlines,
750                                                                                exact,
751                                                                                eSymbolContextLineEntry,
752                                                                                sc_list);
753         if (num_matches > 0)
754         {
755             SymbolContext sc;
756             for (uint32_t i=0; i<num_matches; ++i)
757             {
758                 if (sc_list.GetContextAtIndex(i, sc))
759                 {
760                     addr_t step_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
761                     if (step_addr != LLDB_INVALID_ADDRESS)
762                     {
763                         if (fun_range.ContainsLoadAddress(step_addr, target))
764                             step_over_until_addrs.push_back(step_addr);
765                         else
766                             all_in_function = false;
767                     }
768                 }
769             }
770         }
771 
772         if (step_over_until_addrs.empty())
773         {
774             if (all_in_function)
775             {
776                 step_file_spec.GetPath (path, sizeof(path));
777                 sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path, line);
778             }
779             else
780                 sb_error.SetErrorString ("step until target not in current function");
781         }
782         else
783         {
784             thread_sp->QueueThreadPlanForStepUntil (abort_other_plans,
785                                                     &step_over_until_addrs[0],
786                                                     step_over_until_addrs.size(),
787                                                     stop_other_threads,
788                                                     frame_sp->GetFrameIndex());
789 
790             thread_sp->GetProcess().GetThreadList().SetSelectedThreadByID (thread_sp->GetID());
791             sb_error.ref() = thread_sp->GetProcess().Resume();
792             if (sb_error->Success())
793             {
794                 // If we are doing synchronous mode, then wait for the
795                 // process to stop yet again!
796                 if (thread_sp->GetProcess().GetTarget().GetDebugger().GetAsyncExecution () == false)
797                     thread_sp->GetProcess().WaitForProcessToStop (NULL);
798             }
799         }
800     }
801     else
802     {
803         sb_error.SetErrorString("this SBThread object is invalid");
804     }
805     return sb_error;
806 }
807 
808 
809 bool
810 SBThread::Suspend()
811 {
812     ThreadSP thread_sp(m_opaque_wp.lock());
813     if (thread_sp)
814     {
815         thread_sp->SetResumeState (eStateSuspended);
816         return true;
817     }
818     return false;
819 }
820 
821 bool
822 SBThread::Resume ()
823 {
824     ThreadSP thread_sp(m_opaque_wp.lock());
825     if (thread_sp)
826     {
827         thread_sp->SetResumeState (eStateRunning);
828         return true;
829     }
830     return false;
831 }
832 
833 bool
834 SBThread::IsSuspended()
835 {
836     ThreadSP thread_sp(m_opaque_wp.lock());
837     if (thread_sp)
838         return thread_sp->GetResumeState () == eStateSuspended;
839     return false;
840 }
841 
842 SBProcess
843 SBThread::GetProcess ()
844 {
845 
846     SBProcess sb_process;
847     ProcessSP process_sp;
848     ThreadSP thread_sp(m_opaque_wp.lock());
849     if (thread_sp)
850     {
851         // Have to go up to the target so we can get a shared pointer to our process...
852         process_sp = thread_sp->GetProcess().GetTarget().GetProcessSP();
853         sb_process.SetSP (process_sp);
854     }
855 
856     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
857     if (log)
858     {
859         SBStream frame_desc_strm;
860         sb_process.GetDescription (frame_desc_strm);
861         log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s", thread_sp.get(),
862                      process_sp.get(), frame_desc_strm.GetData());
863     }
864 
865     return sb_process;
866 }
867 
868 uint32_t
869 SBThread::GetNumFrames ()
870 {
871     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
872 
873     uint32_t num_frames = 0;
874     ThreadSP thread_sp(m_opaque_wp.lock());
875     if (thread_sp)
876     {
877         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
878         num_frames = thread_sp->GetStackFrameCount();
879     }
880 
881     if (log)
882         log->Printf ("SBThread(%p)::GetNumFrames () => %u", thread_sp.get(), num_frames);
883 
884     return num_frames;
885 }
886 
887 SBFrame
888 SBThread::GetFrameAtIndex (uint32_t idx)
889 {
890     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
891 
892     SBFrame sb_frame;
893     StackFrameSP frame_sp;
894     ThreadSP thread_sp(m_opaque_wp.lock());
895     if (thread_sp)
896     {
897         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
898         frame_sp = thread_sp->GetStackFrameAtIndex (idx);
899         sb_frame.SetFrameSP (frame_sp);
900     }
901 
902     if (log)
903     {
904         SBStream frame_desc_strm;
905         sb_frame.GetDescription (frame_desc_strm);
906         log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
907                      thread_sp.get(), idx, frame_sp.get(), frame_desc_strm.GetData());
908     }
909 
910     return sb_frame;
911 }
912 
913 lldb::SBFrame
914 SBThread::GetSelectedFrame ()
915 {
916     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
917 
918     SBFrame sb_frame;
919     StackFrameSP frame_sp;
920     ThreadSP thread_sp(m_opaque_wp.lock());
921     if (thread_sp)
922     {
923         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
924         frame_sp = thread_sp->GetSelectedFrame ();
925         sb_frame.SetFrameSP (frame_sp);
926     }
927 
928     if (log)
929     {
930         SBStream frame_desc_strm;
931         sb_frame.GetDescription (frame_desc_strm);
932         log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
933                      thread_sp.get(), frame_sp.get(), frame_desc_strm.GetData());
934     }
935 
936     return sb_frame;
937 }
938 
939 lldb::SBFrame
940 SBThread::SetSelectedFrame (uint32_t idx)
941 {
942     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
943 
944     SBFrame sb_frame;
945     StackFrameSP frame_sp;
946     ThreadSP thread_sp(m_opaque_wp.lock());
947     if (thread_sp)
948     {
949         Mutex::Locker api_locker (thread_sp->GetProcess().GetTarget().GetAPIMutex());
950         frame_sp = thread_sp->GetStackFrameAtIndex (idx);
951         if (frame_sp)
952         {
953             thread_sp->SetSelectedFrame (frame_sp.get());
954             sb_frame.SetFrameSP (frame_sp);
955         }
956     }
957 
958     if (log)
959     {
960         SBStream frame_desc_strm;
961         sb_frame.GetDescription (frame_desc_strm);
962         log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
963                      thread_sp.get(), idx, frame_sp.get(), frame_desc_strm.GetData());
964     }
965     return sb_frame;
966 }
967 
968 
969 bool
970 SBThread::operator == (const SBThread &rhs) const
971 {
972     return m_opaque_wp.lock().get() == rhs.m_opaque_wp.lock().get();
973 }
974 
975 bool
976 SBThread::operator != (const SBThread &rhs) const
977 {
978     return m_opaque_wp.lock().get() != rhs.m_opaque_wp.lock().get();
979 }
980 
981 bool
982 SBThread::GetDescription (SBStream &description) const
983 {
984     Stream &strm = description.ref();
985 
986     ThreadSP thread_sp(m_opaque_wp.lock());
987     if (thread_sp)
988     {
989         strm.Printf("SBThread: tid = 0x%4.4llx", thread_sp->GetID());
990     }
991     else
992         strm.PutCString ("No value");
993 
994     return true;
995 }
996