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