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