blob: c5285fdbd41c852411f66804c3793c4ebe694a7f [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"
Greg Clayton643ee732010-08-04 01:40:35 +000022#include "lldb/Target/StopInfo.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Target/Target.h"
24#include "lldb/Target/ThreadPlan.h"
Chris Lattner24943d22010-06-08 16:52:24 +000025#include "lldb/Target/ThreadPlanStepInstruction.h"
26#include "lldb/Target/ThreadPlanStepOut.h"
27#include "lldb/Target/ThreadPlanStepRange.h"
28#include "lldb/Target/ThreadPlanStepInRange.h"
29
30
Eli Friedman7a62c8b2010-06-09 07:44:37 +000031#include "lldb/API/SBAddress.h"
32#include "lldb/API/SBFrame.h"
33#include "lldb/API/SBSourceManager.h"
34#include "lldb/API/SBDebugger.h"
35#include "lldb/API/SBProcess.h"
Chris Lattner24943d22010-06-08 16:52:24 +000036
37using namespace lldb;
38using namespace lldb_private;
39
40SBThread::SBThread () :
Greg Clayton63094e02010-06-23 01:19:29 +000041 m_opaque_sp ()
Chris Lattner24943d22010-06-08 16:52:24 +000042{
43}
44
45//----------------------------------------------------------------------
46// Thread constructor
47//----------------------------------------------------------------------
48SBThread::SBThread (const ThreadSP& lldb_object_sp) :
Greg Clayton63094e02010-06-23 01:19:29 +000049 m_opaque_sp (lldb_object_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000050{
51}
52
53SBThread::SBThread (const SBThread &rhs)
54{
Greg Clayton63094e02010-06-23 01:19:29 +000055 m_opaque_sp = rhs.m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +000056}
57
58//----------------------------------------------------------------------
59// Destructor
60//----------------------------------------------------------------------
61SBThread::~SBThread()
62{
63}
64
65bool
66SBThread::IsValid() const
67{
Greg Clayton63094e02010-06-23 01:19:29 +000068 return m_opaque_sp != NULL;
Chris Lattner24943d22010-06-08 16:52:24 +000069}
70
Greg Clayton43490d12010-07-30 20:12:55 +000071void
72SBThread::Clear ()
73{
74 m_opaque_sp.reset();
75}
76
77
Chris Lattner24943d22010-06-08 16:52:24 +000078StopReason
79SBThread::GetStopReason()
80{
Greg Clayton63094e02010-06-23 01:19:29 +000081 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000082 {
Greg Clayton643ee732010-08-04 01:40:35 +000083 lldb_private::StopInfo *stop_info = m_opaque_sp->GetStopInfo ();
84 if (stop_info)
85 return stop_info->GetStopReason();
Chris Lattner24943d22010-06-08 16:52:24 +000086 }
87 return eStopReasonInvalid;
88}
89
90size_t
91SBThread::GetStopDescription (char *dst, size_t dst_len)
92{
Greg Clayton63094e02010-06-23 01:19:29 +000093 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +000094 {
Greg Clayton643ee732010-08-04 01:40:35 +000095 lldb_private::StopInfo *stop_info = m_opaque_sp->GetStopInfo ();
96 if (stop_info)
Chris Lattner24943d22010-06-08 16:52:24 +000097 {
Greg Clayton643ee732010-08-04 01:40:35 +000098 const char *stop_desc = stop_info->GetDescription();
Chris Lattner24943d22010-06-08 16:52:24 +000099 if (stop_desc)
100 {
101 if (dst)
102 return ::snprintf (dst, dst_len, "%s", stop_desc);
103 else
104 {
105 // NULL dst passed in, return the length needed to contain the description
106 return ::strlen (stop_desc) + 1; // Include the NULL byte for size
107 }
108 }
109 else
110 {
Chris Lattner24943d22010-06-08 16:52:24 +0000111 size_t stop_desc_len = 0;
Greg Clayton643ee732010-08-04 01:40:35 +0000112 switch (stop_info->GetStopReason())
Chris Lattner24943d22010-06-08 16:52:24 +0000113 {
114 case eStopReasonTrace:
115 case eStopReasonPlanComplete:
116 {
117 static char trace_desc[] = "step";
118 stop_desc = trace_desc;
119 stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
120 }
121 break;
122
123 case eStopReasonBreakpoint:
124 {
125 static char bp_desc[] = "breakpoint hit";
126 stop_desc = bp_desc;
127 stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
128 }
129 break;
130
131 case eStopReasonWatchpoint:
132 {
133 static char wp_desc[] = "watchpoint hit";
134 stop_desc = wp_desc;
135 stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
136 }
137 break;
138
139 case eStopReasonSignal:
140 {
Greg Clayton643ee732010-08-04 01:40:35 +0000141 stop_desc = m_opaque_sp->GetProcess().GetUnixSignals ().GetSignalAsCString (stop_info->GetValue());
Chris Lattner24943d22010-06-08 16:52:24 +0000142 if (stop_desc == NULL || stop_desc[0] == '\0')
143 {
144 static char signal_desc[] = "signal";
145 stop_desc = signal_desc;
146 stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
147 }
148 }
149 break;
150
151 case eStopReasonException:
152 {
153 char exc_desc[] = "exception";
154 stop_desc = exc_desc;
155 stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
156 }
Greg Clayton54e7afa2010-07-09 20:39:50 +0000157 break;
158
159 default:
160 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000161 }
162
163 if (stop_desc && stop_desc[0])
164 {
165 if (dst)
166 return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
167
168 if (stop_desc_len == 0)
169 stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
170
171 return stop_desc_len;
172 }
173 }
174 }
175 }
176 if (dst)
177 *dst = 0;
178 return 0;
179}
180
181void
182SBThread::SetThread (const ThreadSP& lldb_object_sp)
183{
Greg Clayton63094e02010-06-23 01:19:29 +0000184 m_opaque_sp = lldb_object_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000185}
186
187
188lldb::tid_t
189SBThread::GetThreadID () const
190{
Greg Clayton63094e02010-06-23 01:19:29 +0000191 if (m_opaque_sp)
192 return m_opaque_sp->GetID();
Chris Lattner24943d22010-06-08 16:52:24 +0000193 else
194 return LLDB_INVALID_THREAD_ID;
195}
196
197uint32_t
198SBThread::GetIndexID () const
199{
Greg Clayton63094e02010-06-23 01:19:29 +0000200 if (m_opaque_sp)
201 return m_opaque_sp->GetIndexID();
Chris Lattner24943d22010-06-08 16:52:24 +0000202 return LLDB_INVALID_INDEX32;
203}
204const char *
205SBThread::GetName () const
206{
Greg Clayton63094e02010-06-23 01:19:29 +0000207 if (m_opaque_sp)
208 return m_opaque_sp->GetName();
Chris Lattner24943d22010-06-08 16:52:24 +0000209 return NULL;
210}
211
212const char *
213SBThread::GetQueueName () const
214{
Greg Clayton63094e02010-06-23 01:19:29 +0000215 if (m_opaque_sp)
216 return m_opaque_sp->GetQueueName();
Chris Lattner24943d22010-06-08 16:52:24 +0000217 return NULL;
218}
219
220
221void
222SBThread::DisplayFramesForCurrentContext (FILE *out,
223 FILE *err,
224 uint32_t first_frame,
225 uint32_t num_frames,
226 bool show_frame_info,
227 uint32_t num_frames_with_source,
228 uint32_t source_lines_before,
229 uint32_t source_lines_after)
230{
231 if ((out == NULL) || (err == NULL))
232 return;
233
Greg Clayton63094e02010-06-23 01:19:29 +0000234 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000235 {
Greg Clayton63094e02010-06-23 01:19:29 +0000236 uint32_t num_stack_frames = m_opaque_sp->GetStackFrameCount ();
Chris Lattner24943d22010-06-08 16:52:24 +0000237 StackFrameSP frame_sp;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000238 uint32_t frame_idx = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000239
240 for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx)
241 {
242 if (frame_idx >= num_stack_frames)
243 break;
244
Greg Clayton63094e02010-06-23 01:19:29 +0000245 frame_sp = m_opaque_sp->GetStackFrameAtIndex (frame_idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000246 if (!frame_sp)
247 break;
248
249 SBFrame sb_frame (frame_sp);
250 if (DisplaySingleFrameForCurrentContext (out,
251 err,
252 sb_frame,
253 show_frame_info,
254 num_frames_with_source > first_frame - frame_idx,
255 source_lines_before,
256 source_lines_after) == false)
257 break;
258 }
259 }
260}
261
262bool
263SBThread::DisplaySingleFrameForCurrentContext (FILE *out,
264 FILE *err,
265 SBFrame &frame,
266 bool show_frame_info,
267 bool show_source,
268 uint32_t source_lines_after,
269 uint32_t source_lines_before)
270{
271 bool success = false;
Greg Clayton63094e02010-06-23 01:19:29 +0000272
273 if ((out == NULL) || (err == NULL))
Chris Lattner24943d22010-06-08 16:52:24 +0000274 return false;
Greg Clayton63094e02010-06-23 01:19:29 +0000275
276 if (m_opaque_sp && frame.IsValid())
Chris Lattner24943d22010-06-08 16:52:24 +0000277 {
Chris Lattner24943d22010-06-08 16:52:24 +0000278 StreamFile str (out);
Greg Clayton63094e02010-06-23 01:19:29 +0000279
Chris Lattner24943d22010-06-08 16:52:24 +0000280 SBSymbolContext sc(frame.GetSymbolContext(eSymbolContextEverything));
Greg Clayton63094e02010-06-23 01:19:29 +0000281
Chris Lattner24943d22010-06-08 16:52:24 +0000282 if (show_frame_info && sc.IsValid())
283 {
284 user_id_t frame_idx = (user_id_t) frame.GetFrameID();
285 lldb::addr_t pc = frame.GetPC();
286 ::fprintf (out,
287 " frame #%u: tid = 0x%4.4x, pc = 0x%llx ",
288 frame_idx,
289 GetThreadID(),
Eli Friedman0a164a12010-07-09 22:53:18 +0000290 (long long)pc);
Greg Clayton63094e02010-06-23 01:19:29 +0000291 sc->DumpStopContext (&str, &m_opaque_sp->GetProcess(), *frame.GetPCAddress());
Chris Lattner24943d22010-06-08 16:52:24 +0000292 fprintf (out, "\n");
293 success = true;
294 }
Greg Clayton63094e02010-06-23 01:19:29 +0000295
Chris Lattner24943d22010-06-08 16:52:24 +0000296 SBCompileUnit comp_unit(sc.GetCompileUnit());
297 if (show_source && comp_unit.IsValid())
298 {
Greg Clayton63094e02010-06-23 01:19:29 +0000299 success = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000300 SBLineEntry line_entry;
301 if (line_entry.IsValid())
302 {
Greg Clayton63094e02010-06-23 01:19:29 +0000303 SourceManager& source_manager = m_opaque_sp->GetProcess().GetTarget().GetDebugger().GetSourceManager();
304 SBFileSpec line_entry_file_spec (line_entry.GetFileSpec());
305
Chris Lattner24943d22010-06-08 16:52:24 +0000306 if (line_entry_file_spec.IsValid())
307 {
Greg Clayton63094e02010-06-23 01:19:29 +0000308 source_manager.DisplaySourceLinesWithLineNumbers (line_entry_file_spec.ref(),
Chris Lattner24943d22010-06-08 16:52:24 +0000309 line_entry.GetLine(),
310 source_lines_after,
311 source_lines_before, "->",
Greg Clayton63094e02010-06-23 01:19:29 +0000312 &str);
Chris Lattner24943d22010-06-08 16:52:24 +0000313 success = true;
314 }
315 }
316 }
317 }
318 return success;
319}
320
321void
322SBThread::StepOver (lldb::RunMode stop_other_threads)
323{
Greg Clayton63094e02010-06-23 01:19:29 +0000324 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000325 {
326 bool abort_other_plans = true;
Greg Clayton63094e02010-06-23 01:19:29 +0000327 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
Chris Lattner24943d22010-06-08 16:52:24 +0000328
329 if (frame_sp)
330 {
331 if (frame_sp->HasDebugInformation ())
332 {
333 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
Greg Clayton63094e02010-06-23 01:19:29 +0000334 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
Chris Lattner24943d22010-06-08 16:52:24 +0000335 eStepTypeOver,
336 sc.line_entry.range,
337 sc,
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000338 stop_other_threads,
339 false);
Chris Lattner24943d22010-06-08 16:52:24 +0000340
341 }
342 else
343 {
Greg Clayton63094e02010-06-23 01:19:29 +0000344 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (true,
Chris Lattner24943d22010-06-08 16:52:24 +0000345 abort_other_plans,
346 stop_other_threads);
347 }
348 }
349
Greg Clayton63094e02010-06-23 01:19:29 +0000350 Process &process = m_opaque_sp->GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +0000351 // Why do we need to set the current thread by ID here???
Greg Clayton63094e02010-06-23 01:19:29 +0000352 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000353 process.Resume();
354 }
355}
356
357void
358SBThread::StepInto (lldb::RunMode stop_other_threads)
359{
Greg Clayton63094e02010-06-23 01:19:29 +0000360 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000361 {
362 bool abort_other_plans = true;
363
Greg Clayton63094e02010-06-23 01:19:29 +0000364 StackFrameSP frame_sp(m_opaque_sp->GetStackFrameAtIndex (0));
Chris Lattner24943d22010-06-08 16:52:24 +0000365
366 if (frame_sp && frame_sp->HasDebugInformation ())
367 {
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000368 bool avoid_code_without_debug_info = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000369 SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
Greg Clayton63094e02010-06-23 01:19:29 +0000370 m_opaque_sp->QueueThreadPlanForStepRange (abort_other_plans,
Greg Clayton8f5fd6b2010-06-12 18:59:55 +0000371 eStepTypeInto,
372 sc.line_entry.range,
373 sc,
374 stop_other_threads,
375 avoid_code_without_debug_info);
Chris Lattner24943d22010-06-08 16:52:24 +0000376 }
377 else
378 {
Greg Clayton63094e02010-06-23 01:19:29 +0000379 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (false,
Chris Lattner24943d22010-06-08 16:52:24 +0000380 abort_other_plans,
381 stop_other_threads);
382 }
383
Greg Clayton63094e02010-06-23 01:19:29 +0000384 Process &process = m_opaque_sp->GetProcess();
Chris Lattner24943d22010-06-08 16:52:24 +0000385 // Why do we need to set the current thread by ID here???
Greg Clayton63094e02010-06-23 01:19:29 +0000386 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000387 process.Resume();
388
389 }
390}
391
392void
393SBThread::StepOut ()
394{
Greg Clayton63094e02010-06-23 01:19:29 +0000395 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000396 {
397 bool abort_other_plans = true;
398 bool stop_other_threads = true;
399
Greg Clayton63094e02010-06-23 01:19:29 +0000400 m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion);
Chris Lattner24943d22010-06-08 16:52:24 +0000401
Greg Clayton63094e02010-06-23 01:19:29 +0000402 Process &process = m_opaque_sp->GetProcess();
403 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000404 process.Resume();
405 }
406}
407
408void
409SBThread::StepInstruction (bool step_over)
410{
Greg Clayton63094e02010-06-23 01:19:29 +0000411 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000412 {
Greg Clayton63094e02010-06-23 01:19:29 +0000413 m_opaque_sp->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
414 Process &process = m_opaque_sp->GetProcess();
415 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000416 process.Resume();
417 }
418}
419
420void
421SBThread::RunToAddress (lldb::addr_t addr)
422{
Greg Clayton63094e02010-06-23 01:19:29 +0000423 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000424 {
425 bool abort_other_plans = true;
426 bool stop_other_threads = true;
427
428 Address target_addr (NULL, addr);
429
Greg Clayton63094e02010-06-23 01:19:29 +0000430 m_opaque_sp->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
431 Process &process = m_opaque_sp->GetProcess();
432 process.GetThreadList().SetCurrentThreadByID (m_opaque_sp->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000433 process.Resume();
434 }
435
436}
437
Chris Lattner24943d22010-06-08 16:52:24 +0000438SBProcess
439SBThread::GetProcess ()
440{
441 SBProcess process;
Greg Clayton63094e02010-06-23 01:19:29 +0000442 if (m_opaque_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000443 {
444 // Have to go up to the target so we can get a shared pointer to our process...
Greg Clayton63094e02010-06-23 01:19:29 +0000445 process.SetProcess(m_opaque_sp->GetProcess().GetTarget().GetProcessSP());
Chris Lattner24943d22010-06-08 16:52:24 +0000446 }
447 return process;
448}
449
450uint32_t
451SBThread::GetNumFrames ()
452{
Greg Clayton63094e02010-06-23 01:19:29 +0000453 if (m_opaque_sp)
454 return m_opaque_sp->GetStackFrameCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000455 return 0;
456}
457
458SBFrame
459SBThread::GetFrameAtIndex (uint32_t idx)
460{
461 SBFrame sb_frame;
Greg Clayton63094e02010-06-23 01:19:29 +0000462 if (m_opaque_sp)
463 sb_frame.SetFrame (m_opaque_sp->GetStackFrameAtIndex (idx));
Chris Lattner24943d22010-06-08 16:52:24 +0000464 return sb_frame;
465}
466
467const lldb::SBThread &
468SBThread::operator = (const lldb::SBThread &rhs)
469{
Greg Clayton63094e02010-06-23 01:19:29 +0000470 m_opaque_sp = rhs.m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000471 return *this;
472}
473
474bool
475SBThread::operator == (const SBThread &rhs) const
476{
Greg Clayton63094e02010-06-23 01:19:29 +0000477 return m_opaque_sp.get() == rhs.m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000478}
479
480bool
481SBThread::operator != (const SBThread &rhs) const
482{
Greg Clayton63094e02010-06-23 01:19:29 +0000483 return m_opaque_sp.get() != rhs.m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000484}
485
486lldb_private::Thread *
487SBThread::GetLLDBObjectPtr ()
488{
Greg Clayton63094e02010-06-23 01:19:29 +0000489 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000490}
491
492const lldb_private::Thread *
493SBThread::operator->() const
494{
Greg Clayton63094e02010-06-23 01:19:29 +0000495 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000496}
497
498const lldb_private::Thread &
499SBThread::operator*() const
500{
Greg Clayton63094e02010-06-23 01:19:29 +0000501 return *m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000502}
503
504lldb_private::Thread *
505SBThread::operator->()
506{
Greg Clayton63094e02010-06-23 01:19:29 +0000507 return m_opaque_sp.get();
Chris Lattner24943d22010-06-08 16:52:24 +0000508}
509
510lldb_private::Thread &
511SBThread::operator*()
512{
Greg Clayton63094e02010-06-23 01:19:29 +0000513 return *m_opaque_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000514}