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 }
53 
54 SBThread::SBThread (const SBThread &rhs)
55 {
56     m_opaque_sp = rhs.m_opaque_sp;
57 }
58 
59 //----------------------------------------------------------------------
60 // Destructor
61 //----------------------------------------------------------------------
62 SBThread::~SBThread()
63 {
64 }
65 
66 bool
67 SBThread::IsValid() const
68 {
69     return m_opaque_sp != NULL;
70 }
71 
72 void
73 SBThread::Clear ()
74 {
75     m_opaque_sp.reset();
76 }
77 
78 
79 StopReason
80 SBThread::GetStopReason()
81 {
82     if (m_opaque_sp)
83     {
84         StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo ();
85         if (stop_info_sp)
86             return stop_info_sp->GetStopReason();
87     }
88     return eStopReasonInvalid;
89 }
90 
91 size_t
92 SBThread::GetStopDescription (char *dst, size_t dst_len)
93 {
94     if (m_opaque_sp)
95     {
96         StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo ();
97         if (stop_info_sp)
98         {
99             const char *stop_desc = stop_info_sp->GetDescription();
100             if (stop_desc)
101             {
102                 if (dst)
103                     return ::snprintf (dst, dst_len, "%s", stop_desc);
104                 else
105                 {
106                     // NULL dst passed in, return the length needed to contain the description
107                     return ::strlen (stop_desc) + 1; // Include the NULL byte for size
108                 }
109             }
110             else
111             {
112                 size_t stop_desc_len = 0;
113                 switch (stop_info_sp->GetStopReason())
114                 {
115                 case eStopReasonTrace:
116                 case eStopReasonPlanComplete:
117                     {
118                         static char trace_desc[] = "step";
119                         stop_desc = trace_desc;
120                         stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
121                     }
122                     break;
123 
124                 case eStopReasonBreakpoint:
125                     {
126                         static char bp_desc[] = "breakpoint hit";
127                         stop_desc = bp_desc;
128                         stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
129                     }
130                     break;
131 
132                 case eStopReasonWatchpoint:
133                     {
134                         static char wp_desc[] = "watchpoint hit";
135                         stop_desc = wp_desc;
136                         stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
137                     }
138                     break;
139 
140                 case eStopReasonSignal:
141                     {
142                         stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue());
143                         if (stop_desc == NULL || stop_desc[0] == '\0')
144                         {
145                             static char signal_desc[] = "signal";
146                             stop_desc = signal_desc;
147                             stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
148                         }
149                     }
150                     break;
151 
152                 case eStopReasonException:
153                     {
154                         char exc_desc[] = "exception";
155                         stop_desc = exc_desc;
156                         stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
157                     }
158                     break;
159 
160                 default:
161                     break;
162                 }
163 
164                 if (stop_desc && stop_desc[0])
165                 {
166                     if (dst)
167                         return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
168 
169                     if (stop_desc_len == 0)
170                         stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
171 
172                     return stop_desc_len;
173                 }
174             }
175         }
176     }
177     if (dst)
178         *dst = 0;
179     return 0;
180 }
181 
182 void
183 SBThread::SetThread (const ThreadSP& lldb_object_sp)
184 {
185     m_opaque_sp = lldb_object_sp;
186 }
187 
188 
189 lldb::tid_t
190 SBThread::GetThreadID () const
191 {
192     if (m_opaque_sp)
193         return m_opaque_sp->GetID();
194     else
195         return LLDB_INVALID_THREAD_ID;
196 }
197 
198 uint32_t
199 SBThread::GetIndexID () const
200 {
201     if (m_opaque_sp)
202         return m_opaque_sp->GetIndexID();
203     return LLDB_INVALID_INDEX32;
204 }
205 const char *
206 SBThread::GetName () const
207 {
208     if (m_opaque_sp)
209         return m_opaque_sp->GetName();
210     return NULL;
211 }
212 
213 const char *
214 SBThread::GetQueueName () const
215 {
216     if (m_opaque_sp)
217         return m_opaque_sp->GetQueueName();
218     return NULL;
219 }
220 
221 
222 void
223 SBThread::StepOver (lldb::RunMode stop_other_threads)
224 {
225     if (m_opaque_sp)
226     {
227         bool abort_other_plans = true;
228         StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
229 
230         if (frame_sp)
231         {
232             if (frame_sp->HasDebugInformation ())
233             {
234                 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
235                 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
236                                                           eStepTypeOver,
237                                                           sc.line_entry.range,
238                                                           sc,
239                                                           stop_other_threads,
240                                                           false);
241 
242             }
243             else
244             {
245                 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true,
246                                                                       abort_other_plans,
247                                                                       stop_other_threads);
248             }
249         }
250 
251         Process &process = m_opaque_sp->GetProcess();
252         // Why do we need to set the current thread by ID here???
253         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
254         Error error (process.Resume());
255         if (error.Success())
256         {
257             // If we are doing synchronous mode, then wait for the
258             // process to stop yet again!
259             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
260                 process.WaitForProcessToStop (NULL);
261         }
262     }
263 }
264 
265 void
266 SBThread::StepInto (lldb::RunMode stop_other_threads)
267 {
268     if (m_opaque_sp)
269     {
270         bool abort_other_plans = true;
271 
272         StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
273 
274         if (frame_sp && frame_sp->HasDebugInformation ())
275         {
276             bool avoid_code_without_debug_info = true;
277             SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
278             m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
279                                                       eStepTypeInto,
280                                                       sc.line_entry.range,
281                                                       sc,
282                                                       stop_other_threads,
283                                                       avoid_code_without_debug_info);
284         }
285         else
286         {
287             m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false,
288                                                                   abort_other_plans,
289                                                                   stop_other_threads);
290         }
291 
292         Process &process = m_opaque_sp->GetProcess();
293         // Why do we need to set the current thread by ID here???
294         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
295         Error error (process.Resume());
296         if (error.Success())
297         {
298             // If we are doing synchronous mode, then wait for the
299             // process to stop yet again!
300             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
301                 process.WaitForProcessToStop (NULL);
302         }
303     }
304 }
305 
306 void
307 SBThread::StepOut ()
308 {
309     if (m_opaque_sp)
310     {
311         bool abort_other_plans = true;
312         bool stop_other_threads = true;
313 
314         m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion);
315 
316         Process &process = m_opaque_sp->GetProcess();
317         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
318         Error error (process.Resume());
319         if (error.Success())
320         {
321             // If we are doing synchronous mode, then wait for the
322             // process to stop yet again!
323             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
324                 process.WaitForProcessToStop (NULL);
325         }
326     }
327 }
328 
329 void
330 SBThread::StepInstruction (bool step_over)
331 {
332     if (m_opaque_sp)
333     {
334         m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
335         Process &process = m_opaque_sp->GetProcess();
336         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
337         Error error (process.Resume());
338         if (error.Success())
339         {
340             // If we are doing synchronous mode, then wait for the
341             // process to stop yet again!
342             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
343                 process.WaitForProcessToStop (NULL);
344         }
345     }
346 }
347 
348 void
349 SBThread::RunToAddress (lldb::addr_t addr)
350 {
351     if (m_opaque_sp)
352     {
353         bool abort_other_plans = true;
354         bool stop_other_threads = true;
355 
356         Address target_addr (NULL, addr);
357 
358         m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
359         Process &process = m_opaque_sp->GetProcess();
360         process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
361         Error error (process.Resume());
362         if (error.Success())
363         {
364             // If we are doing synchronous mode, then wait for the
365             // process to stop yet again!
366             if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
367                 process.WaitForProcessToStop (NULL);
368         }
369     }
370 
371 }
372 
373 SBProcess
374 SBThread::GetProcess ()
375 {
376     SBProcess process;
377     if (m_opaque_sp)
378     {
379         // Have to go up to the target so we can get a shared pointer to our process...
380         process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP());
381     }
382     return process;
383 }
384 
385 uint32_t
386 SBThread::GetNumFrames ()
387 {
388     if (m_opaque_sp)
389         return m_opaque_sp->GetStackFrameCount();
390     return 0;
391 }
392 
393 SBFrame
394 SBThread::GetFrameAtIndex (uint32_t idx)
395 {
396     SBFrame sb_frame;
397     if (m_opaque_sp)
398         sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx));
399     return sb_frame;
400 }
401 
402 const lldb::SBThread &
403 SBThread::operator = (const lldb::SBThread &rhs)
404 {
405     m_opaque_sp = rhs.m_opaque_sp;
406     return *this;
407 }
408 
409 bool
410 SBThread::operator == (const SBThread &rhs) const
411 {
412     return m_opaque_sp.get() == rhs.m_opaque_sp.get();
413 }
414 
415 bool
416 SBThread::operator != (const SBThread &rhs) const
417 {
418     return m_opaque_sp.get() != rhs.m_opaque_sp.get();
419 }
420 
421 lldb_private::Thread *
422 SBThread::GetLLDBObjectPtr ()
423 {
424     return m_opaque_sp.get();
425 }
426 
427 const lldb_private::Thread *
428 SBThread::operator->() const
429 {
430     return m_opaque_sp.get();
431 }
432 
433 const lldb_private::Thread &
434 SBThread::operator*() const
435 {
436     return *m_opaque_sp;
437 }
438 
439 lldb_private::Thread *
440 SBThread::operator->()
441 {
442     return m_opaque_sp.get();
443 }
444 
445 lldb_private::Thread &
446 SBThread::operator*()
447 {
448     return *m_opaque_sp;
449 }
450 
451 bool
452 SBThread::GetDescription (SBStream &description)
453 {
454     if (m_opaque_sp)
455     {
456         StreamString strm;
457         description.Printf("SBThread: tid = 0x%4.4x", m_opaque_sp->GetID());
458     }
459     else
460         description.Printf ("No value");
461 
462     return true;
463 }
464