blob: 268270597b342b085c3087e58b4305403bee66a4 [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
70StopReason
71SBThread::GetStopReason()
72{
Greg Clayton63094e02010-06-23 01:19:29 +000073 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000074 {
75 lldb_private::Thread::StopInfo thread_stop_info;
Greg Clayton63094e02010-06-23 01:19:29 +000076 if (m_opaque_sp->GetStopInfo(&thread_stop_info))
Chris Lattner24943d22010-06-08 16:52:24 +000077 return thread_stop_info.GetStopReason();
78 }
79 return eStopReasonInvalid;
80}
81
82size_t
83SBThread::GetStopDescription (char *dst, size_t dst_len)
84{
Greg Clayton63094e02010-06-23 01:19:29 +000085 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000086 {
87 lldb_private::Thread::StopInfo thread_stop_info;
Greg Clayton63094e02010-06-23 01:19:29 +000088 if (m_opaque_sp->GetStopInfo(&thread_stop_info))
Chris Lattner24943d22010-06-08 16:52:24 +000089 {
90 const char *stop_desc = thread_stop_info.GetStopDescription();
91 if (stop_desc)
92 {
93 if (dst)
94 return ::snprintf (dst, dst_len, "%s", stop_desc);
95 else
96 {
97 // NULL dst passed in, return the length needed to contain the description
98 return ::strlen (stop_desc) + 1; // Include the NULL byte for size
99 }
100 }
101 else
102 {
Chris Lattner24943d22010-06-08 16:52:24 +0000103 size_t stop_desc_len = 0;
104 switch (thread_stop_info.GetStopReason())
105 {
106 case eStopReasonTrace:
107 case eStopReasonPlanComplete:
108 {
109 static char trace_desc[] = "step";
110 stop_desc = trace_desc;
111 stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
112 }
113 break;
114
115 case eStopReasonBreakpoint:
116 {
117 static char bp_desc[] = "breakpoint hit";
118 stop_desc = bp_desc;
119 stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
120 }
121 break;
122
123 case eStopReasonWatchpoint:
124 {
125 static char wp_desc[] = "watchpoint hit";
126 stop_desc = wp_desc;
127 stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
128 }
129 break;
130
131 case eStopReasonSignal:
132 {
Greg Clayton63094e02010-06-23 01:19:29 +0000133 stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (thread_stop_info.GetSignal());
Chris Lattner24943d22010-06-08 16:52:24 +0000134 if (stop_desc == NULL || stop_desc[0] == '\0')
135 {
136 static char signal_desc[] = "signal";
137 stop_desc = signal_desc;
138 stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
139 }
140 }
141 break;
142
143 case eStopReasonException:
144 {
145 char exc_desc[] = "exception";
146 stop_desc = exc_desc;
147 stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
148 }
Greg Clayton54e7afa2010-07-09 20:39:50 +0000149 break;
150
151 default:
152 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000153 }
154
155 if (stop_desc && stop_desc[0])
156 {
157 if (dst)
158 return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
159
160 if (stop_desc_len == 0)
161 stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
162
163 return stop_desc_len;
164 }
165 }
166 }
167 }
168 if (dst)
169 *dst = 0;
170 return 0;
171}
172
173void
174SBThread::SetThread (const ThreadSP& lldb_object_sp)
175{
Greg Clayton63094e02010-06-23 01:19:29 +0000176 m_opaque_sp = lldb_object_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000177}
178
179
180lldb::tid_t
181SBThread::GetThreadID () const
182{
Greg Clayton63094e02010-06-23 01:19:29 +0000183 if (m_opaque_sp)
184 return m_opaque_sp->GetID();
Chris Lattner24943d22010-06-08 16:52:24 +0000185 else
186 return LLDB_INVALID_THREAD_ID;
187}
188
189uint32_t
190SBThread::GetIndexID () const
191{
Greg Clayton63094e02010-06-23 01:19:29 +0000192 if (m_opaque_sp)
193 return m_opaque_sp->GetIndexID();
Chris Lattner24943d22010-06-08 16:52:24 +0000194 return LLDB_INVALID_INDEX32;
195}
196const char *
197SBThread::GetName () const
198{
Greg Clayton63094e02010-06-23 01:19:29 +0000199 if (m_opaque_sp)
200 return m_opaque_sp->GetName();
Chris Lattner24943d22010-06-08 16:52:24 +0000201 return NULL;
202}
203
204const char *
205SBThread::GetQueueName () const
206{
Greg Clayton63094e02010-06-23 01:19:29 +0000207 if (m_opaque_sp)
208 return m_opaque_sp->GetQueueName();
Chris Lattner24943d22010-06-08 16:52:24 +0000209 return NULL;
210}
211
212
213void
214SBThread::DisplayFramesForCurrentContext (FILE *out,
215 FILE *err,
216 uint32_t first_frame,
217 uint32_t num_frames,
218 bool show_frame_info,
219 uint32_t num_frames_with_source,
220 uint32_t source_lines_before,
221 uint32_t source_lines_after)
222{
223 if ((out == NULL) || (err == NULL))
224 return;
225
Greg Clayton63094e02010-06-23 01:19:29 +0000226 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000227 {
Greg Clayton63094e02010-06-23 01:19:29 +0000228 uint32_t num_stack_frames = m_opaque_sp->GetStackFrameCount ();
Chris Lattner24943d22010-06-08 16:52:24 +0000229 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000230 uint32_t frame_idx = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000231
232 for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx)
233 {
234 if (frame_idx >= num_stack_frames)
235 break;
236
Greg Clayton63094e02010-06-23 01:19:29 +0000237 frame_sp = m_opaque_sp->GetStackFrameAtIndex (frame_idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000238 if (!frame_sp)
239 break;
240
241 SBFrame sb_frame (frame_sp);
242 if (DisplaySingleFrameForCurrentContext (out,
243 err,
244 sb_frame,
245 show_frame_info,
246 num_frames_with_source > first_frame - frame_idx,
247 source_lines_before,
248 source_lines_after) == false)
249 break;
250 }
251 }
252}
253
254bool
255SBThread::DisplaySingleFrameForCurrentContext (FILE *out,
256 FILE *err,
257 SBFrame &frame,
258 bool show_frame_info,
259 bool show_source,
260 uint32_t source_lines_after,
261 uint32_t source_lines_before)
262{
263 bool success = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000264
265 if ((out == NULL) || (err == NULL))
Chris Lattner24943d22010-06-08 16:52:24 +0000266 return false;
Greg Clayton63094e02010-06-23 01:19:29 +0000267
268 if (m_opaque_sp && frame.IsValid())
Chris Lattner24943d22010-06-08 16:52:24 +0000269 {
Chris Lattner24943d22010-06-08 16:52:24 +0000270 StreamFile str (out);
Greg Clayton63094e02010-06-23 01:19:29 +0000271
Chris Lattner24943d22010-06-08 16:52:24 +0000272 SBSymbolContext sc(frame.GetSymbolContext(eSymbolContextEverything));
Greg Clayton63094e02010-06-23 01:19:29 +0000273
Chris Lattner24943d22010-06-08 16:52:24 +0000274 if (show_frame_info && sc.IsValid())
275 {
276 user_id_t frame_idx = (user_id_t) frame.GetFrameID();
277 lldb::addr_t pc = frame.GetPC();
278 ::fprintf (out,
279 " frame #%u: tid = 0x%4.4x, pc = 0x%llx ",
280 frame_idx,
281 GetThreadID(),
Eli Friedman0a164a12010-07-09 22:53:18 +0000282 (long long)pc);
Greg Clayton63094e02010-06-23 01:19:29 +0000283 sc->DumpStopContext (&str, &m_opaque_sp->GetProcess(), *frame.GetPCAddress());
Chris Lattner24943d22010-06-08 16:52:24 +0000284 fprintf (out, "\n");
285 success = true;
286 }
Greg Clayton63094e02010-06-23 01:19:29 +0000287
Chris Lattner24943d22010-06-08 16:52:24 +0000288 SBCompileUnit comp_unit(sc.GetCompileUnit());
289 if (show_source && comp_unit.IsValid())
290 {
Greg Clayton63094e02010-06-23 01:19:29 +0000291 success = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000292 SBLineEntry line_entry;
293 if (line_entry.IsValid())
294 {
Greg Clayton63094e02010-06-23 01:19:29 +0000295 SourceManager& source_manager = m_opaque_sp->GetProcess().GetTarget().GetDebugger().GetSourceManager();
296 SBFileSpec line_entry_file_spec (line_entry.GetFileSpec());
297
Chris Lattner24943d22010-06-08 16:52:24 +0000298 if (line_entry_file_spec.IsValid())
299 {
Greg Clayton63094e02010-06-23 01:19:29 +0000300 source_manager.DisplaySourceLinesWithLineNumbers (line_entry_file_spec.ref(),
Chris Lattner24943d22010-06-08 16:52:24 +0000301 line_entry.GetLine(),
302 source_lines_after,
303 source_lines_before, "->",
Greg Clayton63094e02010-06-23 01:19:29 +0000304 &str);
Chris Lattner24943d22010-06-08 16:52:24 +0000305 success = true;
306 }
307 }
308 }
309 }
310 return success;
311}
312
313void
314SBThread::StepOver (lldb::RunMode stop_other_threads)
315{
Greg Clayton63094e02010-06-23 01:19:29 +0000316 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000317 {
318 bool abort_other_plans = true;
Greg Clayton63094e02010-06-23 01:19:29 +0000319 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
Chris Lattner24943d22010-06-08 16:52:24 +0000320
321 if (frame_sp)
322 {
323 if (frame_sp->HasDebugInformation ())
324 {
325 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
Greg Clayton63094e02010-06-23 01:19:29 +0000326 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
Chris Lattner24943d22010-06-08 16:52:24 +0000327 eStepTypeOver,
328 sc.line_entry.range,
329 sc,
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000330 stop_other_threads,
331 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000332
333 }
334 else
335 {
Greg Clayton63094e02010-06-23 01:19:29 +0000336 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true,
Chris Lattner24943d22010-06-08 16:52:24 +0000337 abort_other_plans,
338 stop_other_threads);
339 }
340 }
341
Greg Clayton63094e02010-06-23 01:19:29 +0000342 Process &process = m_opaque_sp->GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +0000343 // Why do we need to set the current thread by ID here???
Greg Clayton63094e02010-06-23 01:19:29 +0000344 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000345 process.Resume();
346 }
347}
348
349void
350SBThread::StepInto (lldb::RunMode stop_other_threads)
351{
Greg Clayton63094e02010-06-23 01:19:29 +0000352 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000353 {
354 bool abort_other_plans = true;
355
Greg Clayton63094e02010-06-23 01:19:29 +0000356 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
Chris Lattner24943d22010-06-08 16:52:24 +0000357
358 if (frame_sp && frame_sp->HasDebugInformation ())
359 {
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000360 bool avoid_code_without_debug_info = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000361 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
Greg Clayton63094e02010-06-23 01:19:29 +0000362 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000363 eStepTypeInto,
364 sc.line_entry.range,
365 sc,
366 stop_other_threads,
367 avoid_code_without_debug_info);
Chris Lattner24943d22010-06-08 16:52:24 +0000368 }
369 else
370 {
Greg Clayton63094e02010-06-23 01:19:29 +0000371 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false,
Chris Lattner24943d22010-06-08 16:52:24 +0000372 abort_other_plans,
373 stop_other_threads);
374 }
375
Greg Clayton63094e02010-06-23 01:19:29 +0000376 Process &process = m_opaque_sp->GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +0000377 // Why do we need to set the current thread by ID here???
Greg Clayton63094e02010-06-23 01:19:29 +0000378 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000379 process.Resume();
380
381 }
382}
383
384void
385SBThread::StepOut ()
386{
Greg Clayton63094e02010-06-23 01:19:29 +0000387 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000388 {
389 bool abort_other_plans = true;
390 bool stop_other_threads = true;
391
Greg Clayton63094e02010-06-23 01:19:29 +0000392 m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion);
Chris Lattner24943d22010-06-08 16:52:24 +0000393
Greg Clayton63094e02010-06-23 01:19:29 +0000394 Process &process = m_opaque_sp->GetProcess();
395 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000396 process.Resume();
397 }
398}
399
400void
401SBThread::StepInstruction (bool step_over)
402{
Greg Clayton63094e02010-06-23 01:19:29 +0000403 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000404 {
Greg Clayton63094e02010-06-23 01:19:29 +0000405 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
406 Process &process = m_opaque_sp->GetProcess();
407 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000408 process.Resume();
409 }
410}
411
412void
413SBThread::RunToAddress (lldb::addr_t addr)
414{
Greg Clayton63094e02010-06-23 01:19:29 +0000415 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000416 {
417 bool abort_other_plans = true;
418 bool stop_other_threads = true;
419
420 Address target_addr (NULL, addr);
421
Greg Clayton63094e02010-06-23 01:19:29 +0000422 m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
423 Process &process = m_opaque_sp->GetProcess();
424 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000425 process.Resume();
426 }
427
428}
429
Chris Lattner24943d22010-06-08 16:52:24 +0000430SBProcess
431SBThread::GetProcess ()
432{
433 SBProcess process;
Greg Clayton63094e02010-06-23 01:19:29 +0000434 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000435 {
436 // Have to go up to the target so we can get a shared pointer to our process...
Greg Clayton63094e02010-06-23 01:19:29 +0000437 process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP());
Chris Lattner24943d22010-06-08 16:52:24 +0000438 }
439 return process;
440}
441
442uint32_t
443SBThread::GetNumFrames ()
444{
Greg Clayton63094e02010-06-23 01:19:29 +0000445 if (m_opaque_sp)
446 return m_opaque_sp->GetStackFrameCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000447 return 0;
448}
449
450SBFrame
451SBThread::GetFrameAtIndex (uint32_t idx)
452{
453 SBFrame sb_frame;
Greg Clayton63094e02010-06-23 01:19:29 +0000454 if (m_opaque_sp)
455 sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000456 return sb_frame;
457}
458
459const lldb::SBThread &
460SBThread::operator = (const lldb::SBThread &rhs)
461{
Greg Clayton63094e02010-06-23 01:19:29 +0000462 m_opaque_sp = rhs.m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000463 return *this;
464}
465
466bool
467SBThread::operator == (const SBThread &rhs) const
468{
Greg Clayton63094e02010-06-23 01:19:29 +0000469 return m_opaque_sp.get() == rhs.m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000470}
471
472bool
473SBThread::operator != (const SBThread &rhs) const
474{
Greg Clayton63094e02010-06-23 01:19:29 +0000475 return m_opaque_sp.get() != rhs.m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000476}
477
478lldb_private::Thread *
479SBThread::GetLLDBObjectPtr ()
480{
Greg Clayton63094e02010-06-23 01:19:29 +0000481 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000482}
483
484const lldb_private::Thread *
485SBThread::operator->() const
486{
Greg Clayton63094e02010-06-23 01:19:29 +0000487 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000488}
489
490const lldb_private::Thread &
491SBThread::operator*() const
492{
Greg Clayton63094e02010-06-23 01:19:29 +0000493 return *m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000494}
495
496lldb_private::Thread *
497SBThread::operator->()
498{
Greg Clayton63094e02010-06-23 01:19:29 +0000499 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000500}
501
502lldb_private::Thread &
503SBThread::operator*()
504{
Greg Clayton63094e02010-06-23 01:19:29 +0000505 return *m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000506}