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/Core/Debugger.h"
16 #include "lldb/Core/Stream.h"
17 #include "lldb/Core/StreamFile.h"
18 #include "lldb/Interpreter/CommandInterpreter.h"
19 #include "lldb/Target/Thread.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Symbol/SymbolContext.h"
22 #include "lldb/Symbol/CompileUnit.h"
23 #include "lldb/Target/StopInfo.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/ThreadPlan.h"
26 #include "lldb/Target/ThreadPlanStepInstruction.h"
27 #include "lldb/Target/ThreadPlanStepOut.h"
28 #include "lldb/Target/ThreadPlanStepRange.h"
29 #include "lldb/Target/ThreadPlanStepInRange.h"
30 
31 
32 #include "lldb/API/SBAddress.h"
33 #include "lldb/API/SBFrame.h"
34 #include "lldb/API/SBSourceManager.h"
35 #include "lldb/API/SBDebugger.h"
36 #include "lldb/API/SBProcess.h"
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 
41 SBThread::SBThread () :
42     m_opaque_sp ()
43 {
44 }
45 
46 //----------------------------------------------------------------------
47 // Thread constructor
48 //----------------------------------------------------------------------
49 SBThread::SBThread (const ThreadSP& lldb_object_sp) :
50     m_opaque_sp (lldb_object_sp)
51 {
52     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
53 
54     if (log)
55     {
56         SBStream sstr;
57         GetDescription (sstr);
58         log->Printf ("SBThread::SBThread (lldb_object_sp=%p) => this.sp = %p (%s)",
59                      lldb_object_sp.get(), m_opaque_sp.get(), sstr.GetData());
60     }
61 }
62 
63 SBThread::SBThread (const SBThread &rhs)
64 {
65     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
66 
67     m_opaque_sp = rhs.m_opaque_sp;
68 
69     if (log)
70         log->Printf ("SBThread::SBThread (rhs.sp=%p) => this.sp = %p",
71                      rhs.m_opaque_sp.get(), m_opaque_sp.get());
72 
73 }
74 
75 //----------------------------------------------------------------------
76 // Destructor
77 //----------------------------------------------------------------------
78 SBThread::~SBThread()
79 {
80 }
81 
82 bool
83 SBThread::IsValid() const
84 {
85     return m_opaque_sp != NULL;
86 }
87 
88 void
89 SBThread::Clear ()
90 {
91     m_opaque_sp.reset();
92 }
93 
94 
95 StopReason
96 SBThread::GetStopReason()
97 {
98     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
99 
100     //if (log)
101     //    log->Printf ("SBThread::GetStopReason ()");
102 
103     StopReason reason = eStopReasonInvalid;
104     if (m_opaque_sp)
105     {
106         StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo ();
107         if (stop_info_sp)
108             reason =  stop_info_sp->GetStopReason();
109     }
110 
111     if (log)
112         log->Printf ("SBThread::GetStopReason (this.sp=%p) => '%s'", m_opaque_sp.get(),
113                      Thread::StopReasonAsCString (reason));
114 
115     return reason;
116 }
117 
118 size_t
119 SBThread::GetStopDescription (char *dst, size_t dst_len)
120 {
121     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
122 
123     //if (log)
124     //    log->Printf ("SBThread::GetStopDescription (char *dst, size_t dst_len)");
125 
126     if (m_opaque_sp)
127     {
128         StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo ();
129         if (stop_info_sp)
130         {
131             const char *stop_desc = stop_info_sp->GetDescription();
132             if (stop_desc)
133             {
134                 if (log)
135                     log->Printf ("SBThread::GetStopDescription (this.sp=%p, dst, dst_len) => '%s'",
136                                  m_opaque_sp.get(), stop_desc);
137                 if (dst)
138                     return ::snprintf (dst, dst_len, "%s", stop_desc);
139                 else
140                 {
141                     // NULL dst passed in, return the length needed to contain the description
142                     return ::strlen (stop_desc) + 1; // Include the NULL byte for size
143                 }
144             }
145             else
146             {
147                 size_t stop_desc_len = 0;
148                 switch (stop_info_sp->GetStopReason())
149                 {
150                 case eStopReasonTrace:
151                 case eStopReasonPlanComplete:
152                     {
153                         static char trace_desc[] = "step";
154                         stop_desc = trace_desc;
155                         stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
156                     }
157                     break;
158 
159                 case eStopReasonBreakpoint:
160                     {
161                         static char bp_desc[] = "breakpoint hit";
162                         stop_desc = bp_desc;
163                         stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
164                     }
165                     break;
166 
167                 case eStopReasonWatchpoint:
168                     {
169                         static char wp_desc[] = "watchpoint hit";
170                         stop_desc = wp_desc;
171                         stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
172                     }
173                     break;
174 
175                 case eStopReasonSignal:
176                     {
177                         stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue());
178                         if (stop_desc == NULL || stop_desc[0] == '\0')
179                         {
180                             static char signal_desc[] = "signal";
181                             stop_desc = signal_desc;
182                             stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
183                         }
184                     }
185                     break;
186 
187                 case eStopReasonException:
188                     {
189                         char exc_desc[] = "exception";
190                         stop_desc = exc_desc;
191                         stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
192                     }
193                     break;
194 
195                 default:
196                     break;
197                 }
198 
199                 if (stop_desc && stop_desc[0])
200                 {
201                     if (log)
202                         log->Printf ("SBThread::GetStopDescription (this.sp=%p, dst, dst_len) => '%s'",
203                                      m_opaque_sp.get(), stop_desc);
204 
205                     if (dst)
206                         return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
207 
208                     if (stop_desc_len == 0)
209                         stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
210 
211                     return stop_desc_len;
212                 }
213             }
214         }
215     }
216     if (dst)
217         *dst = 0;
218     return 0;
219 }
220 
221 void
222 SBThread::SetThread (const ThreadSP& lldb_object_sp)
223 {
224     m_opaque_sp = lldb_object_sp;
225 }
226 
227 
228 lldb::tid_t
229 SBThread::GetThreadID () const
230 {
231     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
232 
233     //if (log)
234     //    log->Printf ("SBThread::GetThreadID()");
235 
236     lldb::tid_t id = LLDB_INVALID_THREAD_ID;
237     if (m_opaque_sp)
238         id = m_opaque_sp->GetID();
239 
240     if (log)
241         log->Printf ("SBThread::GetThreadID (this.sp=%p) => %d", m_opaque_sp.get(), (uint32_t) id);
242 
243     return id;
244 }
245 
246 uint32_t
247 SBThread::GetIndexID () const
248 {
249     if (m_opaque_sp)
250         return m_opaque_sp->GetIndexID();
251     return LLDB_INVALID_INDEX32;
252 }
253 const char *
254 SBThread::GetName () const
255 {
256     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
257 
258     //if (log)
259     //    log->Printf ("SBThread::GetName ()");
260 
261     if (m_opaque_sp)
262     {
263         if (log)
264             log->Printf ("SBThread::GetName (this.sp=%p) => '%s'", m_opaque_sp.get(), m_opaque_sp->GetName());
265         return m_opaque_sp->GetName();
266     }
267 
268     if (log)
269         log->Printf ("SBThread::GetName (this.sp=%p) => NULL", m_opaque_sp.get());
270 
271     return NULL;
272 }
273 
274 const char *
275 SBThread::GetQueueName () const
276 {
277     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
278 
279     //if (log)
280     //    log->Printf ("SBThread::GetQueueName ()");
281 
282     if (m_opaque_sp)
283     {
284         if (log)
285             log->Printf ("SBThread::GetQueueName (this.sp=%p) => '%s'", m_opaque_sp.get(),
286                          m_opaque_sp->GetQueueName());
287         return m_opaque_sp->GetQueueName();
288     }
289 
290     if (log)
291         log->Printf ("SBThread::GetQueueName (this.sp=%p) => NULL", m_opaque_sp.get());
292 
293     return NULL;
294 }
295 
296 
297 void
298 SBThread::StepOver (lldb::RunMode stop_other_threads)
299 {
300     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
301 
302     if (log)
303         log->Printf ("SBThread::StepOver (this.sp=%p, stop_other_threads='%s')", m_opaque_sp.get(),
304                      Thread::RunModeAsCString (stop_other_threads));
305 
306     if (m_opaque_sp)
307     {
308         bool abort_other_plans = true;
309         StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
310 
311         if (frame_sp)
312         {
313             if (frame_sp->HasDebugInformation ())
314             {
315                 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
316                 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
317                                                           eStepTypeOver,
318                                                           sc.line_entry.range,
319                                                           sc,
320                                                           stop_other_threads,
321                                                           false);
322 
323             }
324             else
325             {
326                 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true,
327                                                                       abort_other_plans,
328                                                                       stop_other_threads);
329             }
330         }
331 
332         Process &process = m_opaque_sp->GetProcess();
333         // Why do we need to set the current thread by ID here???
334         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
335         Error error (process.Resume());
336         if (error.Success())
337         {
338             // If we are doing synchronous mode, then wait for the
339             // process to stop yet again!
340             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
341                 process.WaitForProcessToStop (NULL);
342         }
343     }
344 }
345 
346 void
347 SBThread::StepInto (lldb::RunMode stop_other_threads)
348 {
349     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
350 
351     if (log)
352         log->Printf ("SBThread::StepInto (this.sp=%p, stop_other_threads='%s')", m_opaque_sp.get(),
353                      Thread::RunModeAsCString (stop_other_threads));
354 
355     if (m_opaque_sp)
356     {
357         bool abort_other_plans = true;
358 
359         StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
360 
361         if (frame_sp && frame_sp->HasDebugInformation ())
362         {
363             bool avoid_code_without_debug_info = true;
364             SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
365             m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
366                                                       eStepTypeInto,
367                                                       sc.line_entry.range,
368                                                       sc,
369                                                       stop_other_threads,
370                                                       avoid_code_without_debug_info);
371         }
372         else
373         {
374             m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false,
375                                                                   abort_other_plans,
376                                                                   stop_other_threads);
377         }
378 
379         Process &process = m_opaque_sp->GetProcess();
380         // Why do we need to set the current thread by ID here???
381         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
382         Error error (process.Resume());
383         if (error.Success())
384         {
385             // If we are doing synchronous mode, then wait for the
386             // process to stop yet again!
387             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
388                 process.WaitForProcessToStop (NULL);
389         }
390     }
391 }
392 
393 void
394 SBThread::StepOut ()
395 {
396     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
397 
398     if (log)
399         log->Printf ("SBThread::StepOut (this.sp=%p)", m_opaque_sp.get());
400 
401     if (m_opaque_sp)
402     {
403         bool abort_other_plans = true;
404         bool stop_other_threads = true;
405 
406         m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion);
407 
408         Process &process = m_opaque_sp->GetProcess();
409         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
410         Error error (process.Resume());
411         if (error.Success())
412         {
413             // If we are doing synchronous mode, then wait for the
414             // process to stop yet again!
415             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
416                 process.WaitForProcessToStop (NULL);
417         }
418     }
419 }
420 
421 void
422 SBThread::StepInstruction (bool step_over)
423 {
424     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
425 
426     if (log)
427         log->Printf ("SBThread::StepInstruction (this.sp=%p, step_over=%s)", m_opaque_sp.get(),
428                      (step_over ? "true" : "false"));
429 
430     if (m_opaque_sp)
431     {
432         m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
433         Process &process = m_opaque_sp->GetProcess();
434         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
435         Error error (process.Resume());
436         if (error.Success())
437         {
438             // If we are doing synchronous mode, then wait for the
439             // process to stop yet again!
440             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
441                 process.WaitForProcessToStop (NULL);
442         }
443     }
444 }
445 
446 void
447 SBThread::RunToAddress (lldb::addr_t addr)
448 {
449     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
450 
451     if (log)
452         log->Printf ("SBThread::RunToAddress (this.sp=%p, addr=%p)", m_opaque_sp.get(), addr);
453 
454     if (m_opaque_sp)
455     {
456         bool abort_other_plans = true;
457         bool stop_other_threads = true;
458 
459         Address target_addr (NULL, addr);
460 
461         m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
462         Process &process = m_opaque_sp->GetProcess();
463         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
464         Error error (process.Resume());
465         if (error.Success())
466         {
467             // If we are doing synchronous mode, then wait for the
468             // process to stop yet again!
469             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
470                 process.WaitForProcessToStop (NULL);
471         }
472     }
473 
474 }
475 
476 SBProcess
477 SBThread::GetProcess ()
478 {
479     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
480 
481     //if (log)
482     //    log->Printf ("SBThread::GetProcess ()");
483 
484     SBProcess process;
485     if (m_opaque_sp)
486     {
487         // Have to go up to the target so we can get a shared pointer to our process...
488         process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP());
489     }
490 
491     if (log)
492     {
493         SBStream sstr;
494         process.GetDescription (sstr);
495         log->Printf ("SBThread::GetProcess (this.sp=%p) => SBProcess : this.sp = %p, '%s'", m_opaque_sp.get(),
496                      process.get(), sstr.GetData());
497     }
498 
499     return process;
500 }
501 
502 uint32_t
503 SBThread::GetNumFrames ()
504 {
505     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
506 
507     //if (log)
508     //    log->Printf ("SBThread::GetNumFrames ()");
509 
510     uint32_t num_frames = 0;
511     if (m_opaque_sp)
512         num_frames = m_opaque_sp->GetStackFrameCount();
513 
514     if (log)
515         log->Printf ("SBThread::GetNumFrames (this.sp=%p) => %d", m_opaque_sp.get(), num_frames);
516 
517     return num_frames;
518 }
519 
520 SBFrame
521 SBThread::GetFrameAtIndex (uint32_t idx)
522 {
523     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
524 
525     //if (log)
526     //    log->Printf ("SBThread::GetFrameAtIndex (uint32_t idx) idx = %d", idx);
527 
528     SBFrame sb_frame;
529     if (m_opaque_sp)
530         sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx));
531 
532     if (log)
533     {
534         SBStream sstr;
535         sb_frame.GetDescription (sstr);
536         log->Printf ("SBThread::GetFrameAtIndex (this.sp=%p, idx=%d) => SBFrame.sp : this = %p, '%s'",
537                      m_opaque_sp.get(), idx, sb_frame.get(), sstr.GetData());
538     }
539 
540     return sb_frame;
541 }
542 
543 const lldb::SBThread &
544 SBThread::operator = (const lldb::SBThread &rhs)
545 {
546     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API);
547 
548     if (log)
549         log->Printf ("SBThread::operator= (this.sp=%p, rhs.sp=%p)", m_opaque_sp.get(), rhs.m_opaque_sp.get());
550 
551     m_opaque_sp = rhs.m_opaque_sp;
552     return *this;
553 }
554 
555 bool
556 SBThread::operator == (const SBThread &rhs) const
557 {
558     return m_opaque_sp.get() == rhs.m_opaque_sp.get();
559 }
560 
561 bool
562 SBThread::operator != (const SBThread &rhs) const
563 {
564     return m_opaque_sp.get() != rhs.m_opaque_sp.get();
565 }
566 
567 lldb_private::Thread *
568 SBThread::GetLLDBObjectPtr ()
569 {
570     return m_opaque_sp.get();
571 }
572 
573 const lldb_private::Thread *
574 SBThread::operator->() const
575 {
576     return m_opaque_sp.get();
577 }
578 
579 const lldb_private::Thread &
580 SBThread::operator*() const
581 {
582     return *m_opaque_sp;
583 }
584 
585 lldb_private::Thread *
586 SBThread::operator->()
587 {
588     return m_opaque_sp.get();
589 }
590 
591 lldb_private::Thread &
592 SBThread::operator*()
593 {
594     return *m_opaque_sp;
595 }
596 
597 bool
598 SBThread::GetDescription (SBStream &description)
599 {
600     if (m_opaque_sp)
601     {
602         StreamString strm;
603         description.Printf("SBThread: tid = 0x%4.4x", m_opaque_sp->GetID());
604     }
605     else
606         description.Printf ("No value");
607 
608     return true;
609 }
610 
611 bool
612 SBThread::GetDescription (SBStream &description) const
613 {
614     if (m_opaque_sp)
615     {
616         StreamString strm;
617         description.Printf("SBThread: tid = 0x%4.4x", m_opaque_sp->GetID());
618     }
619     else
620         description.Printf ("No value");
621 
622     return true;
623 }
624