blob: e52496a699ffa6f811e3a375873b8b033ed7a11a [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
Eli Friedman7a62c8b2010-06-09 07:44:37 +000010#include "lldb/API/SBThread.h"
Chris Lattner24943d22010-06-08 16:52:24 +000011
12#include "lldb/API/SBSymbolContext.h"
13#include "lldb/API/SBFileSpec.h"
Greg Clayton63094e02010-06-23 01:19:29 +000014#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000015#include "lldb/Core/Stream.h"
16#include "lldb/Core/StreamFile.h"
Greg Clayton63094e02010-06-23 01:19:29 +000017#include "lldb/Interpreter/CommandInterpreter.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Target/Thread.h"
19#include "lldb/Target/Process.h"
20#include "lldb/Symbol/SymbolContext.h"
21#include "lldb/Symbol/CompileUnit.h"
22#include "lldb/Target/Target.h"
23#include "lldb/Target/ThreadPlan.h"
Chris Lattner24943d22010-06-08 16:52:24 +000024#include "lldb/Target/ThreadPlanStepInstruction.h"
25#include "lldb/Target/ThreadPlanStepOut.h"
26#include "lldb/Target/ThreadPlanStepRange.h"
27#include "lldb/Target/ThreadPlanStepInRange.h"
28
29
Eli Friedman7a62c8b2010-06-09 07:44:37 +000030#include "lldb/API/SBAddress.h"
31#include "lldb/API/SBFrame.h"
32#include "lldb/API/SBSourceManager.h"
33#include "lldb/API/SBDebugger.h"
34#include "lldb/API/SBProcess.h"
Chris Lattner24943d22010-06-08 16:52:24 +000035
36using namespace lldb;
37using namespace lldb_private;
38
39SBThread::SBThread () :
Greg Clayton63094e02010-06-23 01:19:29 +000040 m_opaque_sp ()
Chris Lattner24943d22010-06-08 16:52:24 +000041{
42}
43
44//----------------------------------------------------------------------
45// Thread constructor
46//----------------------------------------------------------------------
47SBThread::SBThread (const ThreadSP& lldb_object_sp) :
Greg Clayton63094e02010-06-23 01:19:29 +000048 m_opaque_sp (lldb_object_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000049{
50}
51
52SBThread::SBThread (const SBThread &rhs)
53{
Greg Clayton63094e02010-06-23 01:19:29 +000054 m_opaque_sp = rhs.m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +000055}
56
57//----------------------------------------------------------------------
58// Destructor
59//----------------------------------------------------------------------
60SBThread::~SBThread()
61{
62}
63
64bool
65SBThread::IsValid() const
66{
Greg Clayton63094e02010-06-23 01:19:29 +000067 return m_opaque_sp != NULL;
Chris Lattner24943d22010-06-08 16:52:24 +000068}
69
Greg Clayton43490d12010-07-30 20:12:55 +000070void
71SBThread::Clear ()
72{
73 m_opaque_sp.reset();
74}
75
76
Chris Lattner24943d22010-06-08 16:52:24 +000077StopReason
78SBThread::GetStopReason()
79{
Greg Clayton63094e02010-06-23 01:19:29 +000080 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000081 {
82 lldb_private::Thread::StopInfo thread_stop_info;
Greg Clayton63094e02010-06-23 01:19:29 +000083 if (m_opaque_sp->GetStopInfo(&thread_stop_info))
Chris Lattner24943d22010-06-08 16:52:24 +000084 return thread_stop_info.GetStopReason();
85 }
86 return eStopReasonInvalid;
87}
88
89size_t
90SBThread::GetStopDescription (char *dst, size_t dst_len)
91{
Greg Clayton63094e02010-06-23 01:19:29 +000092 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000093 {
94 lldb_private::Thread::StopInfo thread_stop_info;
Greg Clayton63094e02010-06-23 01:19:29 +000095 if (m_opaque_sp->GetStopInfo(&thread_stop_info))
Chris Lattner24943d22010-06-08 16:52:24 +000096 {
97 const char *stop_desc = thread_stop_info.GetStopDescription();
98 if (stop_desc)
99 {
100 if (dst)
101 return ::snprintf (dst, dst_len, "%s", stop_desc);
102 else
103 {
104 // NULL dst passed in, return the length needed to contain the description
105 return ::strlen (stop_desc) + 1; // Include the NULL byte for size
106 }
107 }
108 else
109 {
Chris Lattner24943d22010-06-08 16:52:24 +0000110 size_t stop_desc_len = 0;
111 switch (thread_stop_info.GetStopReason())
112 {
113 case eStopReasonTrace:
114 case eStopReasonPlanComplete:
115 {
116 static char trace_desc[] = "step";
117 stop_desc = trace_desc;
118 stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
119 }
120 break;
121
122 case eStopReasonBreakpoint:
123 {
124 static char bp_desc[] = "breakpoint hit";
125 stop_desc = bp_desc;
126 stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
127 }
128 break;
129
130 case eStopReasonWatchpoint:
131 {
132 static char wp_desc[] = "watchpoint hit";
133 stop_desc = wp_desc;
134 stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
135 }
136 break;
137
138 case eStopReasonSignal:
139 {
Greg Clayton63094e02010-06-23 01:19:29 +0000140 stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (thread_stop_info.GetSignal());
Chris Lattner24943d22010-06-08 16:52:24 +0000141 if (stop_desc == NULL || stop_desc[0] == '\0')
142 {
143 static char signal_desc[] = "signal";
144 stop_desc = signal_desc;
145 stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
146 }
147 }
148 break;
149
150 case eStopReasonException:
151 {
152 char exc_desc[] = "exception";
153 stop_desc = exc_desc;
154 stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
155 }
Greg Clayton54e7afa2010-07-09 20:39:50 +0000156 break;
157
158 default:
159 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000160 }
161
162 if (stop_desc && stop_desc[0])
163 {
164 if (dst)
165 return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
166
167 if (stop_desc_len == 0)
168 stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
169
170 return stop_desc_len;
171 }
172 }
173 }
174 }
175 if (dst)
176 *dst = 0;
177 return 0;
178}
179
180void
181SBThread::SetThread (const ThreadSP& lldb_object_sp)
182{
Greg Clayton63094e02010-06-23 01:19:29 +0000183 m_opaque_sp = lldb_object_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000184}
185
186
187lldb::tid_t
188SBThread::GetThreadID () const
189{
Greg Clayton63094e02010-06-23 01:19:29 +0000190 if (m_opaque_sp)
191 return m_opaque_sp->GetID();
Chris Lattner24943d22010-06-08 16:52:24 +0000192 else
193 return LLDB_INVALID_THREAD_ID;
194}
195
196uint32_t
197SBThread::GetIndexID () const
198{
Greg Clayton63094e02010-06-23 01:19:29 +0000199 if (m_opaque_sp)
200 return m_opaque_sp->GetIndexID();
Chris Lattner24943d22010-06-08 16:52:24 +0000201 return LLDB_INVALID_INDEX32;
202}
203const char *
204SBThread::GetName () const
205{
Greg Clayton63094e02010-06-23 01:19:29 +0000206 if (m_opaque_sp)
207 return m_opaque_sp->GetName();
Chris Lattner24943d22010-06-08 16:52:24 +0000208 return NULL;
209}
210
211const char *
212SBThread::GetQueueName () const
213{
Greg Clayton63094e02010-06-23 01:19:29 +0000214 if (m_opaque_sp)
215 return m_opaque_sp->GetQueueName();
Chris Lattner24943d22010-06-08 16:52:24 +0000216 return NULL;
217}
218
219
220void
221SBThread::DisplayFramesForCurrentContext (FILE *out,
222 FILE *err,
223 uint32_t first_frame,
224 uint32_t num_frames,
225 bool show_frame_info,
226 uint32_t num_frames_with_source,
227 uint32_t source_lines_before,
228 uint32_t source_lines_after)
229{
230 if ((out == NULL) || (err == NULL))
231 return;
232
Greg Clayton63094e02010-06-23 01:19:29 +0000233 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000234 {
Greg Clayton63094e02010-06-23 01:19:29 +0000235 uint32_t num_stack_frames = m_opaque_sp->GetStackFrameCount ();
Chris Lattner24943d22010-06-08 16:52:24 +0000236 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000237 uint32_t frame_idx = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000238
239 for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx)
240 {
241 if (frame_idx >= num_stack_frames)
242 break;
243
Greg Clayton63094e02010-06-23 01:19:29 +0000244 frame_sp = m_opaque_sp->GetStackFrameAtIndex (frame_idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000245 if (!frame_sp)
246 break;
247
248 SBFrame sb_frame (frame_sp);
249 if (DisplaySingleFrameForCurrentContext (out,
250 err,
251 sb_frame,
252 show_frame_info,
253 num_frames_with_source > first_frame - frame_idx,
254 source_lines_before,
255 source_lines_after) == false)
256 break;
257 }
258 }
259}
260
261bool
262SBThread::DisplaySingleFrameForCurrentContext (FILE *out,
263 FILE *err,
264 SBFrame &frame,
265 bool show_frame_info,
266 bool show_source,
267 uint32_t source_lines_after,
268 uint32_t source_lines_before)
269{
270 bool success = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000271
272 if ((out == NULL) || (err == NULL))
Chris Lattner24943d22010-06-08 16:52:24 +0000273 return false;
Greg Clayton63094e02010-06-23 01:19:29 +0000274
275 if (m_opaque_sp && frame.IsValid())
Chris Lattner24943d22010-06-08 16:52:24 +0000276 {
Chris Lattner24943d22010-06-08 16:52:24 +0000277 StreamFile str (out);
Greg Clayton63094e02010-06-23 01:19:29 +0000278
Chris Lattner24943d22010-06-08 16:52:24 +0000279 SBSymbolContext sc(frame.GetSymbolContext(eSymbolContextEverything));
Greg Clayton63094e02010-06-23 01:19:29 +0000280
Chris Lattner24943d22010-06-08 16:52:24 +0000281 if (show_frame_info && sc.IsValid())
282 {
283 user_id_t frame_idx = (user_id_t) frame.GetFrameID();
284 lldb::addr_t pc = frame.GetPC();
285 ::fprintf (out,
286 " frame #%u: tid = 0x%4.4x, pc = 0x%llx ",
287 frame_idx,
288 GetThreadID(),
Eli Friedman0a164a12010-07-09 22:53:18 +0000289 (long long)pc);
Greg Clayton63094e02010-06-23 01:19:29 +0000290 sc->DumpStopContext (&str, &m_opaque_sp->GetProcess(), *frame.GetPCAddress());
Chris Lattner24943d22010-06-08 16:52:24 +0000291 fprintf (out, "\n");
292 success = true;
293 }
Greg Clayton63094e02010-06-23 01:19:29 +0000294
Chris Lattner24943d22010-06-08 16:52:24 +0000295 SBCompileUnit comp_unit(sc.GetCompileUnit());
296 if (show_source && comp_unit.IsValid())
297 {
Greg Clayton63094e02010-06-23 01:19:29 +0000298 success = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000299 SBLineEntry line_entry;
300 if (line_entry.IsValid())
301 {
Greg Clayton63094e02010-06-23 01:19:29 +0000302 SourceManager& source_manager = m_opaque_sp->GetProcess().GetTarget().GetDebugger().GetSourceManager();
303 SBFileSpec line_entry_file_spec (line_entry.GetFileSpec());
304
Chris Lattner24943d22010-06-08 16:52:24 +0000305 if (line_entry_file_spec.IsValid())
306 {
Greg Clayton63094e02010-06-23 01:19:29 +0000307 source_manager.DisplaySourceLinesWithLineNumbers (line_entry_file_spec.ref(),
Chris Lattner24943d22010-06-08 16:52:24 +0000308 line_entry.GetLine(),
309 source_lines_after,
310 source_lines_before, "->",
Greg Clayton63094e02010-06-23 01:19:29 +0000311 &str);
Chris Lattner24943d22010-06-08 16:52:24 +0000312 success = true;
313 }
314 }
315 }
316 }
317 return success;
318}
319
320void
321SBThread::StepOver (lldb::RunMode stop_other_threads)
322{
Greg Clayton63094e02010-06-23 01:19:29 +0000323 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000324 {
325 bool abort_other_plans = true;
Greg Clayton63094e02010-06-23 01:19:29 +0000326 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
Chris Lattner24943d22010-06-08 16:52:24 +0000327
328 if (frame_sp)
329 {
330 if (frame_sp->HasDebugInformation ())
331 {
332 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
Greg Clayton63094e02010-06-23 01:19:29 +0000333 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
Chris Lattner24943d22010-06-08 16:52:24 +0000334 eStepTypeOver,
335 sc.line_entry.range,
336 sc,
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000337 stop_other_threads,
338 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000339
340 }
341 else
342 {
Greg Clayton63094e02010-06-23 01:19:29 +0000343 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true,
Chris Lattner24943d22010-06-08 16:52:24 +0000344 abort_other_plans,
345 stop_other_threads);
346 }
347 }
348
Greg Clayton63094e02010-06-23 01:19:29 +0000349 Process &process = m_opaque_sp->GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +0000350 // Why do we need to set the current thread by ID here???
Greg Clayton63094e02010-06-23 01:19:29 +0000351 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000352 process.Resume();
353 }
354}
355
356void
357SBThread::StepInto (lldb::RunMode stop_other_threads)
358{
Greg Clayton63094e02010-06-23 01:19:29 +0000359 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000360 {
361 bool abort_other_plans = true;
362
Greg Clayton63094e02010-06-23 01:19:29 +0000363 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
Chris Lattner24943d22010-06-08 16:52:24 +0000364
365 if (frame_sp && frame_sp->HasDebugInformation ())
366 {
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000367 bool avoid_code_without_debug_info = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000368 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
Greg Clayton63094e02010-06-23 01:19:29 +0000369 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000370 eStepTypeInto,
371 sc.line_entry.range,
372 sc,
373 stop_other_threads,
374 avoid_code_without_debug_info);
Chris Lattner24943d22010-06-08 16:52:24 +0000375 }
376 else
377 {
Greg Clayton63094e02010-06-23 01:19:29 +0000378 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false,
Chris Lattner24943d22010-06-08 16:52:24 +0000379 abort_other_plans,
380 stop_other_threads);
381 }
382
Greg Clayton63094e02010-06-23 01:19:29 +0000383 Process &process = m_opaque_sp->GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +0000384 // Why do we need to set the current thread by ID here???
Greg Clayton63094e02010-06-23 01:19:29 +0000385 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000386 process.Resume();
387
388 }
389}
390
391void
392SBThread::StepOut ()
393{
Greg Clayton63094e02010-06-23 01:19:29 +0000394 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000395 {
396 bool abort_other_plans = true;
397 bool stop_other_threads = true;
398
Greg Clayton63094e02010-06-23 01:19:29 +0000399 m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion);
Chris Lattner24943d22010-06-08 16:52:24 +0000400
Greg Clayton63094e02010-06-23 01:19:29 +0000401 Process &process = m_opaque_sp->GetProcess();
402 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000403 process.Resume();
404 }
405}
406
407void
408SBThread::StepInstruction (bool step_over)
409{
Greg Clayton63094e02010-06-23 01:19:29 +0000410 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000411 {
Greg Clayton63094e02010-06-23 01:19:29 +0000412 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
413 Process &process = m_opaque_sp->GetProcess();
414 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000415 process.Resume();
416 }
417}
418
419void
420SBThread::RunToAddress (lldb::addr_t addr)
421{
Greg Clayton63094e02010-06-23 01:19:29 +0000422 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000423 {
424 bool abort_other_plans = true;
425 bool stop_other_threads = true;
426
427 Address target_addr (NULL, addr);
428
Greg Clayton63094e02010-06-23 01:19:29 +0000429 m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
430 Process &process = m_opaque_sp->GetProcess();
431 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000432 process.Resume();
433 }
434
435}
436
Chris Lattner24943d22010-06-08 16:52:24 +0000437SBProcess
438SBThread::GetProcess ()
439{
440 SBProcess process;
Greg Clayton63094e02010-06-23 01:19:29 +0000441 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000442 {
443 // Have to go up to the target so we can get a shared pointer to our process...
Greg Clayton63094e02010-06-23 01:19:29 +0000444 process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP());
Chris Lattner24943d22010-06-08 16:52:24 +0000445 }
446 return process;
447}
448
449uint32_t
450SBThread::GetNumFrames ()
451{
Greg Clayton63094e02010-06-23 01:19:29 +0000452 if (m_opaque_sp)
453 return m_opaque_sp->GetStackFrameCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000454 return 0;
455}
456
457SBFrame
458SBThread::GetFrameAtIndex (uint32_t idx)
459{
460 SBFrame sb_frame;
Greg Clayton63094e02010-06-23 01:19:29 +0000461 if (m_opaque_sp)
462 sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000463 return sb_frame;
464}
465
466const lldb::SBThread &
467SBThread::operator = (const lldb::SBThread &rhs)
468{
Greg Clayton63094e02010-06-23 01:19:29 +0000469 m_opaque_sp = rhs.m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000470 return *this;
471}
472
473bool
474SBThread::operator == (const SBThread &rhs) const
475{
Greg Clayton63094e02010-06-23 01:19:29 +0000476 return m_opaque_sp.get() == rhs.m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000477}
478
479bool
480SBThread::operator != (const SBThread &rhs) const
481{
Greg Clayton63094e02010-06-23 01:19:29 +0000482 return m_opaque_sp.get() != rhs.m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000483}
484
485lldb_private::Thread *
486SBThread::GetLLDBObjectPtr ()
487{
Greg Clayton63094e02010-06-23 01:19:29 +0000488 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000489}
490
491const lldb_private::Thread *
492SBThread::operator->() const
493{
Greg Clayton63094e02010-06-23 01:19:29 +0000494 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000495}
496
497const lldb_private::Thread &
498SBThread::operator*() const
499{
Greg Clayton63094e02010-06-23 01:19:29 +0000500 return *m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000501}
502
503lldb_private::Thread *
504SBThread::operator->()
505{
Greg Clayton63094e02010-06-23 01:19:29 +0000506 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000507}
508
509lldb_private::Thread &
510SBThread::operator*()
511{
Greg Clayton63094e02010-06-23 01:19:29 +0000512 return *m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000513}