SBThread.cpp revision 6b70f0317707698df7c26bdfebbe90b41087e0ab
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/Breakpoint/BreakpointLocation.h"
16#include "lldb/Core/Debugger.h"
17#include "lldb/Core/Stream.h"
18#include "lldb/Core/StreamFile.h"
19#include "lldb/Interpreter/CommandInterpreter.h"
20#include "lldb/Target/Thread.h"
21#include "lldb/Target/Process.h"
22#include "lldb/Symbol/SymbolContext.h"
23#include "lldb/Symbol/CompileUnit.h"
24#include "lldb/Target/StopInfo.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Target/ThreadPlan.h"
27#include "lldb/Target/ThreadPlanStepInstruction.h"
28#include "lldb/Target/ThreadPlanStepOut.h"
29#include "lldb/Target/ThreadPlanStepRange.h"
30#include "lldb/Target/ThreadPlanStepInRange.h"
31
32
33#include "lldb/API/SBAddress.h"
34#include "lldb/API/SBDebugger.h"
35#include "lldb/API/SBFrame.h"
36#include "lldb/API/SBProcess.h"
37#include "lldb/API/SBValue.h"
38
39using namespace lldb;
40using namespace lldb_private;
41
42//----------------------------------------------------------------------
43// Constructors
44//----------------------------------------------------------------------
45SBThread::SBThread () :
46    m_opaque_sp (new ExecutionContextRef())
47{
48}
49
50SBThread::SBThread (const ThreadSP& lldb_object_sp) :
51    m_opaque_sp (new ExecutionContextRef(lldb_object_sp))
52{
53}
54
55SBThread::SBThread (const SBThread &rhs) :
56    m_opaque_sp (new ExecutionContextRef(*rhs.m_opaque_sp))
57{
58
59}
60
61//----------------------------------------------------------------------
62// Assignment operator
63//----------------------------------------------------------------------
64
65const lldb::SBThread &
66SBThread::operator = (const SBThread &rhs)
67{
68    if (this != &rhs)
69        *m_opaque_sp = *rhs.m_opaque_sp;
70    return *this;
71}
72
73//----------------------------------------------------------------------
74// Destructor
75//----------------------------------------------------------------------
76SBThread::~SBThread()
77{
78}
79
80bool
81SBThread::IsValid() const
82{
83    return m_opaque_sp->GetThreadSP().get() != NULL;
84}
85
86void
87SBThread::Clear ()
88{
89    m_opaque_sp->Clear();
90}
91
92
93StopReason
94SBThread::GetStopReason()
95{
96    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
97
98    StopReason reason = eStopReasonInvalid;
99    Mutex::Locker api_locker;
100    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
101
102    if (exe_ctx.HasThreadScope())
103    {
104        Process::StopLocker stop_locker;
105        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
106        {
107            StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
108            if (stop_info_sp)
109                reason =  stop_info_sp->GetStopReason();
110        }
111        else
112        {
113            if (log)
114                log->Printf ("SBThread(%p)::GetStopReason() => error: process is running", exe_ctx.GetThreadPtr());
115        }
116    }
117
118    if (log)
119        log->Printf ("SBThread(%p)::GetStopReason () => %s", exe_ctx.GetThreadPtr(),
120                     Thread::StopReasonAsCString (reason));
121
122    return reason;
123}
124
125size_t
126SBThread::GetStopReasonDataCount ()
127{
128    Mutex::Locker api_locker;
129    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
130
131    if (exe_ctx.HasThreadScope())
132    {
133        Process::StopLocker stop_locker;
134        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
135        {
136            StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
137            if (stop_info_sp)
138            {
139                StopReason reason = stop_info_sp->GetStopReason();
140                switch (reason)
141                {
142                case eStopReasonInvalid:
143                case eStopReasonNone:
144                case eStopReasonTrace:
145                case eStopReasonPlanComplete:
146                    // There is no data for these stop reasons.
147                    return 0;
148
149                case eStopReasonBreakpoint:
150                    {
151                        break_id_t site_id = stop_info_sp->GetValue();
152                        lldb::BreakpointSiteSP bp_site_sp (exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID (site_id));
153                        if (bp_site_sp)
154                            return bp_site_sp->GetNumberOfOwners () * 2;
155                        else
156                            return 0; // Breakpoint must have cleared itself...
157                    }
158                    break;
159
160                case eStopReasonWatchpoint:
161                    return 1;
162
163                case eStopReasonSignal:
164                    return 1;
165
166                case eStopReasonException:
167                    return 1;
168                }
169            }
170        }
171        else
172        {
173            LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
174            if (log)
175                log->Printf ("SBThread(%p)::GetStopReasonDataCount() => error: process is running", exe_ctx.GetThreadPtr());
176        }
177    }
178    return 0;
179}
180
181uint64_t
182SBThread::GetStopReasonDataAtIndex (uint32_t idx)
183{
184    Mutex::Locker api_locker;
185    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
186
187    if (exe_ctx.HasThreadScope())
188    {
189        Process::StopLocker stop_locker;
190        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
191        {
192            Thread *thread = exe_ctx.GetThreadPtr();
193            StopInfoSP stop_info_sp = thread->GetStopInfo ();
194            if (stop_info_sp)
195            {
196                StopReason reason = stop_info_sp->GetStopReason();
197                switch (reason)
198                {
199                case eStopReasonInvalid:
200                case eStopReasonNone:
201                case eStopReasonTrace:
202                case eStopReasonPlanComplete:
203                    // There is no data for these stop reasons.
204                    return 0;
205
206                case eStopReasonBreakpoint:
207                    {
208                        break_id_t site_id = stop_info_sp->GetValue();
209                        lldb::BreakpointSiteSP bp_site_sp (exe_ctx.GetProcessPtr()->GetBreakpointSiteList().FindByID (site_id));
210                        if (bp_site_sp)
211                        {
212                            uint32_t bp_index = idx / 2;
213                            BreakpointLocationSP bp_loc_sp (bp_site_sp->GetOwnerAtIndex (bp_index));
214                            if (bp_loc_sp)
215                            {
216                                if (bp_index & 1)
217                                {
218                                    // Odd idx, return the breakpoint location ID
219                                    return bp_loc_sp->GetID();
220                                }
221                                else
222                                {
223                                    // Even idx, return the breakpoint ID
224                                    return bp_loc_sp->GetBreakpoint().GetID();
225                                }
226                            }
227                        }
228                        return LLDB_INVALID_BREAK_ID;
229                    }
230                    break;
231
232                case eStopReasonWatchpoint:
233                    return stop_info_sp->GetValue();
234
235                case eStopReasonSignal:
236                    return stop_info_sp->GetValue();
237
238                case eStopReasonException:
239                    return stop_info_sp->GetValue();
240                }
241            }
242        }
243        else
244        {
245            LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
246            if (log)
247                log->Printf ("SBThread(%p)::GetStopReasonDataAtIndex() => error: process is running", exe_ctx.GetThreadPtr());
248        }
249    }
250    return 0;
251}
252
253size_t
254SBThread::GetStopDescription (char *dst, size_t dst_len)
255{
256    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
257
258    Mutex::Locker api_locker;
259    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
260
261    if (exe_ctx.HasThreadScope())
262    {
263        Process::StopLocker stop_locker;
264        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
265        {
266
267            StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
268            if (stop_info_sp)
269            {
270                const char *stop_desc = stop_info_sp->GetDescription();
271                if (stop_desc)
272                {
273                    if (log)
274                        log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => \"%s\"",
275                                     exe_ctx.GetThreadPtr(), stop_desc);
276                    if (dst)
277                        return ::snprintf (dst, dst_len, "%s", stop_desc);
278                    else
279                    {
280                        // NULL dst passed in, return the length needed to contain the description
281                        return ::strlen (stop_desc) + 1; // Include the NULL byte for size
282                    }
283                }
284                else
285                {
286                    size_t stop_desc_len = 0;
287                    switch (stop_info_sp->GetStopReason())
288                    {
289                    case eStopReasonTrace:
290                    case eStopReasonPlanComplete:
291                        {
292                            static char trace_desc[] = "step";
293                            stop_desc = trace_desc;
294                            stop_desc_len = sizeof(trace_desc); // Include the NULL byte for size
295                        }
296                        break;
297
298                    case eStopReasonBreakpoint:
299                        {
300                            static char bp_desc[] = "breakpoint hit";
301                            stop_desc = bp_desc;
302                            stop_desc_len = sizeof(bp_desc); // Include the NULL byte for size
303                        }
304                        break;
305
306                    case eStopReasonWatchpoint:
307                        {
308                            static char wp_desc[] = "watchpoint hit";
309                            stop_desc = wp_desc;
310                            stop_desc_len = sizeof(wp_desc); // Include the NULL byte for size
311                        }
312                        break;
313
314                    case eStopReasonSignal:
315                        {
316                            stop_desc = exe_ctx.GetProcessPtr()->GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue());
317                            if (stop_desc == NULL || stop_desc[0] == '\0')
318                            {
319                                static char signal_desc[] = "signal";
320                                stop_desc = signal_desc;
321                                stop_desc_len = sizeof(signal_desc); // Include the NULL byte for size
322                            }
323                        }
324                        break;
325
326                    case eStopReasonException:
327                        {
328                            char exc_desc[] = "exception";
329                            stop_desc = exc_desc;
330                            stop_desc_len = sizeof(exc_desc); // Include the NULL byte for size
331                        }
332                        break;
333
334                    default:
335                        break;
336                    }
337
338                    if (stop_desc && stop_desc[0])
339                    {
340                        if (log)
341                            log->Printf ("SBThread(%p)::GetStopDescription (dst, dst_len) => '%s'",
342                                         exe_ctx.GetThreadPtr(), stop_desc);
343
344                        if (dst)
345                            return ::snprintf (dst, dst_len, "%s", stop_desc) + 1; // Include the NULL byte
346
347                        if (stop_desc_len == 0)
348                            stop_desc_len = ::strlen (stop_desc) + 1; // Include the NULL byte
349
350                        return stop_desc_len;
351                    }
352                }
353            }
354        }
355        else
356        {
357            LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
358            if (log)
359                log->Printf ("SBThread(%p)::GetStopDescription() => error: process is running", exe_ctx.GetThreadPtr());
360        }
361    }
362    if (dst)
363        *dst = 0;
364    return 0;
365}
366
367SBValue
368SBThread::GetStopReturnValue ()
369{
370    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
371    ValueObjectSP return_valobj_sp;
372    Mutex::Locker api_locker;
373    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
374
375    if (exe_ctx.HasThreadScope())
376    {
377        Process::StopLocker stop_locker;
378        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
379        {
380            StopInfoSP stop_info_sp = exe_ctx.GetThreadPtr()->GetStopInfo ();
381            if (stop_info_sp)
382            {
383                return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
384            }
385        }
386        else
387        {
388            if (log)
389                log->Printf ("SBThread(%p)::GetStopReturnValue() => error: process is running", exe_ctx.GetThreadPtr());
390        }
391    }
392
393    if (log)
394        log->Printf ("SBThread(%p)::GetStopReturnValue () => %s", exe_ctx.GetThreadPtr(),
395                                                                  return_valobj_sp.get()
396                                                                      ? return_valobj_sp->GetValueAsCString()
397                                                                        : "<no return value>");
398
399    return SBValue (return_valobj_sp);
400}
401
402void
403SBThread::SetThread (const ThreadSP& lldb_object_sp)
404{
405    m_opaque_sp->SetThreadSP (lldb_object_sp);
406}
407
408
409lldb::tid_t
410SBThread::GetThreadID () const
411{
412    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
413    if (thread_sp)
414        return thread_sp->GetID();
415    return LLDB_INVALID_THREAD_ID;
416}
417
418uint32_t
419SBThread::GetIndexID () const
420{
421    ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
422    if (thread_sp)
423        return thread_sp->GetIndexID();
424    return LLDB_INVALID_INDEX32;
425}
426
427const char *
428SBThread::GetName () const
429{
430    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
431    const char *name = NULL;
432    Mutex::Locker api_locker;
433    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
434
435    if (exe_ctx.HasThreadScope())
436    {
437        Process::StopLocker stop_locker;
438        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
439        {
440            name = exe_ctx.GetThreadPtr()->GetName();
441        }
442        else
443        {
444            if (log)
445                log->Printf ("SBThread(%p)::GetName() => error: process is running", exe_ctx.GetThreadPtr());
446        }
447    }
448
449    if (log)
450        log->Printf ("SBThread(%p)::GetName () => %s", exe_ctx.GetThreadPtr(), name ? name : "NULL");
451
452    return name;
453}
454
455const char *
456SBThread::GetQueueName () const
457{
458    const char *name = NULL;
459    Mutex::Locker api_locker;
460    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
461
462    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
463    if (exe_ctx.HasThreadScope())
464    {
465        Process::StopLocker stop_locker;
466        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
467        {
468            name = exe_ctx.GetThreadPtr()->GetQueueName();
469        }
470        else
471        {
472            if (log)
473                log->Printf ("SBThread(%p)::GetQueueName() => error: process is running", exe_ctx.GetThreadPtr());
474        }
475    }
476
477    if (log)
478        log->Printf ("SBThread(%p)::GetQueueName () => %s", exe_ctx.GetThreadPtr(), name ? name : "NULL");
479
480    return name;
481}
482
483SBError
484SBThread::ResumeNewPlan (ExecutionContext &exe_ctx, ThreadPlan *new_plan)
485{
486    SBError sb_error;
487
488    Process *process = exe_ctx.GetProcessPtr();
489    if (!process)
490    {
491        sb_error.SetErrorString("No process in SBThread::ResumeNewPlan");
492        return sb_error;
493    }
494
495    Thread *thread = exe_ctx.GetThreadPtr();
496    if (!thread)
497    {
498        sb_error.SetErrorString("No thread in SBThread::ResumeNewPlan");
499        return sb_error;
500    }
501
502    // User level plans should be Master Plans so they can be interrupted, other plans executed, and
503    // then a "continue" will resume the plan.
504    if (new_plan != NULL)
505    {
506        new_plan->SetIsMasterPlan(true);
507        new_plan->SetOkayToDiscard(false);
508    }
509
510    // Why do we need to set the current thread by ID here???
511    process->GetThreadList().SetSelectedThreadByID (thread->GetID());
512    sb_error.ref() = process->Resume();
513
514    if (sb_error.Success())
515    {
516        // If we are doing synchronous mode, then wait for the
517        // process to stop yet again!
518        if (process->GetTarget().GetDebugger().GetAsyncExecution () == false)
519            process->WaitForProcessToStop (NULL);
520    }
521
522    return sb_error;
523}
524
525void
526SBThread::StepOver (lldb::RunMode stop_other_threads)
527{
528    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
529
530    Mutex::Locker api_locker;
531    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
532
533
534    if (log)
535        log->Printf ("SBThread(%p)::StepOver (stop_other_threads='%s')", exe_ctx.GetThreadPtr(),
536                     Thread::RunModeAsCString (stop_other_threads));
537
538    if (exe_ctx.HasThreadScope())
539    {
540        Thread *thread = exe_ctx.GetThreadPtr();
541        bool abort_other_plans = false;
542        StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));
543        ThreadPlan *new_plan = NULL;
544
545        if (frame_sp)
546        {
547            if (frame_sp->HasDebugInformation ())
548            {
549                SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
550                new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
551                                                                eStepTypeOver,
552                                                                sc.line_entry.range,
553                                                                sc,
554                                                                stop_other_threads,
555                                                                false);
556
557            }
558            else
559            {
560                new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
561                                                                            abort_other_plans,
562                                                                            stop_other_threads);
563            }
564        }
565
566        // This returns an error, we should use it!
567        ResumeNewPlan (exe_ctx, new_plan);
568    }
569}
570
571void
572SBThread::StepInto (lldb::RunMode stop_other_threads)
573{
574    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
575
576    Mutex::Locker api_locker;
577    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
578
579    if (log)
580        log->Printf ("SBThread(%p)::StepInto (stop_other_threads='%s')", exe_ctx.GetThreadPtr(),
581                     Thread::RunModeAsCString (stop_other_threads));
582    if (exe_ctx.HasThreadScope())
583    {
584        bool abort_other_plans = false;
585
586        Thread *thread = exe_ctx.GetThreadPtr();
587        StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));
588        ThreadPlan *new_plan = NULL;
589
590        if (frame_sp && frame_sp->HasDebugInformation ())
591        {
592            bool avoid_code_without_debug_info = true;
593            SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
594            new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
595                                                            eStepTypeInto,
596                                                            sc.line_entry.range,
597                                                            sc,
598                                                            stop_other_threads,
599                                                            avoid_code_without_debug_info);
600        }
601        else
602        {
603            new_plan = thread->QueueThreadPlanForStepSingleInstruction (false,
604                                                                        abort_other_plans,
605                                                                        stop_other_threads);
606        }
607
608        // This returns an error, we should use it!
609        ResumeNewPlan (exe_ctx, new_plan);
610    }
611}
612
613void
614SBThread::StepOut ()
615{
616    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
617
618    Mutex::Locker api_locker;
619    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
620
621
622    if (log)
623        log->Printf ("SBThread(%p)::StepOut ()", exe_ctx.GetThreadPtr());
624
625    if (exe_ctx.HasThreadScope())
626    {
627        bool abort_other_plans = false;
628        bool stop_other_threads = false;
629
630        Thread *thread = exe_ctx.GetThreadPtr();
631
632        ThreadPlan *new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
633                                                                  NULL,
634                                                                  false,
635                                                                  stop_other_threads,
636                                                                  eVoteYes,
637                                                                  eVoteNoOpinion,
638                                                                  0);
639
640        // This returns an error, we should use it!
641        ResumeNewPlan (exe_ctx, new_plan);
642    }
643}
644
645void
646SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame)
647{
648    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
649
650    Mutex::Locker api_locker;
651    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
652
653    StackFrameSP frame_sp (sb_frame.GetFrameSP());
654    if (log)
655    {
656        SBStream frame_desc_strm;
657        sb_frame.GetDescription (frame_desc_strm);
658        log->Printf ("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)", exe_ctx.GetThreadPtr(), frame_sp.get(), frame_desc_strm.GetData());
659    }
660
661    if (exe_ctx.HasThreadScope())
662    {
663        bool abort_other_plans = false;
664        bool stop_other_threads = false;
665        Thread *thread = exe_ctx.GetThreadPtr();
666
667        ThreadPlan *new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
668                                                                    NULL,
669                                                                    false,
670                                                                    stop_other_threads,
671                                                                    eVoteYes,
672                                                                    eVoteNoOpinion,
673                                                                    frame_sp->GetFrameIndex());
674
675        // This returns an error, we should use it!
676        ResumeNewPlan (exe_ctx, new_plan);
677    }
678}
679
680void
681SBThread::StepInstruction (bool step_over)
682{
683    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
684
685    Mutex::Locker api_locker;
686    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
687
688
689
690    if (log)
691        log->Printf ("SBThread(%p)::StepInstruction (step_over=%i)", exe_ctx.GetThreadPtr(), step_over);
692
693    if (exe_ctx.HasThreadScope())
694    {
695        Thread *thread = exe_ctx.GetThreadPtr();
696        ThreadPlan *new_plan = thread->QueueThreadPlanForStepSingleInstruction (step_over, true, true);
697
698        // This returns an error, we should use it!
699        ResumeNewPlan (exe_ctx, new_plan);
700    }
701}
702
703void
704SBThread::RunToAddress (lldb::addr_t addr)
705{
706    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
707
708    Mutex::Locker api_locker;
709    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
710
711
712    if (log)
713        log->Printf ("SBThread(%p)::RunToAddress (addr=0x%llx)", exe_ctx.GetThreadPtr(), addr);
714
715    if (exe_ctx.HasThreadScope())
716    {
717        bool abort_other_plans = false;
718        bool stop_other_threads = true;
719
720        Address target_addr (addr);
721
722        Thread *thread = exe_ctx.GetThreadPtr();
723
724        ThreadPlan *new_plan = thread->QueueThreadPlanForRunToAddress (abort_other_plans, target_addr, stop_other_threads);
725
726        // This returns an error, we should use it!
727        ResumeNewPlan (exe_ctx, new_plan);
728    }
729}
730
731SBError
732SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
733                         lldb::SBFileSpec &sb_file_spec,
734                         uint32_t line)
735{
736    SBError sb_error;
737    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
738    char path[PATH_MAX];
739
740    Mutex::Locker api_locker;
741    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
742
743    StackFrameSP frame_sp (sb_frame.GetFrameSP());
744
745    if (log)
746    {
747        SBStream frame_desc_strm;
748        sb_frame.GetDescription (frame_desc_strm);
749        sb_file_spec->GetPath (path, sizeof(path));
750        log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)",
751                     exe_ctx.GetThreadPtr(),
752                     frame_sp.get(),
753                     frame_desc_strm.GetData(),
754                     path, line);
755    }
756
757    if (exe_ctx.HasThreadScope())
758    {
759        Target *target = exe_ctx.GetTargetPtr();
760        Thread *thread = exe_ctx.GetThreadPtr();
761
762        if (line == 0)
763        {
764            sb_error.SetErrorString("invalid line argument");
765            return sb_error;
766        }
767
768        if (!frame_sp)
769        {
770            frame_sp = thread->GetSelectedFrame ();
771            if (!frame_sp)
772                frame_sp = thread->GetStackFrameAtIndex (0);
773        }
774
775        SymbolContext frame_sc;
776        if (!frame_sp)
777        {
778            sb_error.SetErrorString("no valid frames in thread to step");
779            return sb_error;
780        }
781
782        // If we have a frame, get its line
783        frame_sc = frame_sp->GetSymbolContext (eSymbolContextCompUnit  |
784                                               eSymbolContextFunction  |
785                                               eSymbolContextLineEntry |
786                                               eSymbolContextSymbol    );
787
788        if (frame_sc.comp_unit == NULL)
789        {
790            sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex());
791            return sb_error;
792        }
793
794        FileSpec step_file_spec;
795        if (sb_file_spec.IsValid())
796        {
797            // The file spec passed in was valid, so use it
798            step_file_spec = sb_file_spec.ref();
799        }
800        else
801        {
802            if (frame_sc.line_entry.IsValid())
803                step_file_spec = frame_sc.line_entry.file;
804            else
805            {
806                sb_error.SetErrorString("invalid file argument or no file for frame");
807                return sb_error;
808            }
809        }
810
811        // Grab the current function, then we will make sure the "until" address is
812        // within the function.  We discard addresses that are out of the current
813        // function, and then if there are no addresses remaining, give an appropriate
814        // error message.
815
816        bool all_in_function = true;
817        AddressRange fun_range = frame_sc.function->GetAddressRange();
818
819        std::vector<addr_t> step_over_until_addrs;
820        const bool abort_other_plans = false;
821        const bool stop_other_threads = false;
822        const bool check_inlines = true;
823        const bool exact = false;
824
825        SymbolContextList sc_list;
826        const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext (step_file_spec,
827                                                                               line,
828                                                                               check_inlines,
829                                                                               exact,
830                                                                               eSymbolContextLineEntry,
831                                                                               sc_list);
832        if (num_matches > 0)
833        {
834            SymbolContext sc;
835            for (uint32_t i=0; i<num_matches; ++i)
836            {
837                if (sc_list.GetContextAtIndex(i, sc))
838                {
839                    addr_t step_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
840                    if (step_addr != LLDB_INVALID_ADDRESS)
841                    {
842                        if (fun_range.ContainsLoadAddress(step_addr, target))
843                            step_over_until_addrs.push_back(step_addr);
844                        else
845                            all_in_function = false;
846                    }
847                }
848            }
849        }
850
851        if (step_over_until_addrs.empty())
852        {
853            if (all_in_function)
854            {
855                step_file_spec.GetPath (path, sizeof(path));
856                sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path, line);
857            }
858            else
859                sb_error.SetErrorString ("step until target not in current function");
860        }
861        else
862        {
863            ThreadPlan *new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans,
864                                                                        &step_over_until_addrs[0],
865                                                                        step_over_until_addrs.size(),
866                                                                        stop_other_threads,
867                                                                        frame_sp->GetFrameIndex());
868
869            sb_error = ResumeNewPlan (exe_ctx, new_plan);
870        }
871    }
872    else
873    {
874        sb_error.SetErrorString("this SBThread object is invalid");
875    }
876    return sb_error;
877}
878
879SBError
880SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value)
881{
882    SBError sb_error;
883
884    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
885
886    Mutex::Locker api_locker;
887    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
888
889
890    if (log)
891        log->Printf ("SBThread(%p)::ReturnFromFrame (frame=%d)", exe_ctx.GetThreadPtr(), frame.GetFrameID());
892
893    if (exe_ctx.HasThreadScope())
894    {
895        Thread *thread = exe_ctx.GetThreadPtr();
896        sb_error.SetError (thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
897    }
898
899    return sb_error;
900}
901
902
903bool
904SBThread::Suspend()
905{
906    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
907    ExecutionContext exe_ctx (m_opaque_sp.get());
908    bool result = false;
909    if (exe_ctx.HasThreadScope())
910    {
911        Process::StopLocker stop_locker;
912        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
913        {
914            exe_ctx.GetThreadPtr()->SetResumeState (eStateSuspended);
915            result = true;
916        }
917        else
918        {
919            if (log)
920                log->Printf ("SBThread(%p)::Suspend() => error: process is running", exe_ctx.GetThreadPtr());
921        }
922    }
923    if (log)
924        log->Printf ("SBThread(%p)::Suspend() => %i", exe_ctx.GetThreadPtr(), result);
925    return result;
926}
927
928bool
929SBThread::Resume ()
930{
931    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
932    ExecutionContext exe_ctx (m_opaque_sp.get());
933    bool result = false;
934    if (exe_ctx.HasThreadScope())
935    {
936        Process::StopLocker stop_locker;
937        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
938        {
939            exe_ctx.GetThreadPtr()->SetResumeState (eStateRunning);
940            result = true;
941        }
942        else
943        {
944            if (log)
945                log->Printf ("SBThread(%p)::Resume() => error: process is running", exe_ctx.GetThreadPtr());
946        }
947    }
948    if (log)
949        log->Printf ("SBThread(%p)::Resume() => %i", exe_ctx.GetThreadPtr(), result);
950    return result;
951}
952
953bool
954SBThread::IsSuspended()
955{
956    ExecutionContext exe_ctx (m_opaque_sp.get());
957    if (exe_ctx.HasThreadScope())
958        return exe_ctx.GetThreadPtr()->GetResumeState () == eStateSuspended;
959    return false;
960}
961
962SBProcess
963SBThread::GetProcess ()
964{
965
966    SBProcess sb_process;
967    ProcessSP process_sp;
968    ExecutionContext exe_ctx (m_opaque_sp.get());
969    if (exe_ctx.HasThreadScope())
970    {
971        // Have to go up to the target so we can get a shared pointer to our process...
972        sb_process.SetSP (exe_ctx.GetProcessSP());
973    }
974
975    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
976    if (log)
977    {
978        SBStream frame_desc_strm;
979        sb_process.GetDescription (frame_desc_strm);
980        log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s", exe_ctx.GetThreadPtr(),
981                     process_sp.get(), frame_desc_strm.GetData());
982    }
983
984    return sb_process;
985}
986
987uint32_t
988SBThread::GetNumFrames ()
989{
990    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
991
992    uint32_t num_frames = 0;
993    Mutex::Locker api_locker;
994    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
995
996    if (exe_ctx.HasThreadScope())
997    {
998        Process::StopLocker stop_locker;
999        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
1000        {
1001            num_frames = exe_ctx.GetThreadPtr()->GetStackFrameCount();
1002        }
1003        else
1004        {
1005            if (log)
1006                log->Printf ("SBThread(%p)::GetNumFrames() => error: process is running", exe_ctx.GetThreadPtr());
1007        }
1008    }
1009
1010    if (log)
1011        log->Printf ("SBThread(%p)::GetNumFrames () => %u", exe_ctx.GetThreadPtr(), num_frames);
1012
1013    return num_frames;
1014}
1015
1016SBFrame
1017SBThread::GetFrameAtIndex (uint32_t idx)
1018{
1019    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1020
1021    SBFrame sb_frame;
1022    StackFrameSP frame_sp;
1023    Mutex::Locker api_locker;
1024    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
1025
1026    if (exe_ctx.HasThreadScope())
1027    {
1028        Process::StopLocker stop_locker;
1029        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
1030        {
1031            frame_sp = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex (idx);
1032            sb_frame.SetFrameSP (frame_sp);
1033        }
1034        else
1035        {
1036            if (log)
1037                log->Printf ("SBThread(%p)::GetFrameAtIndex() => error: process is running", exe_ctx.GetThreadPtr());
1038        }
1039    }
1040
1041    if (log)
1042    {
1043        SBStream frame_desc_strm;
1044        sb_frame.GetDescription (frame_desc_strm);
1045        log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
1046                     exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData());
1047    }
1048
1049    return sb_frame;
1050}
1051
1052lldb::SBFrame
1053SBThread::GetSelectedFrame ()
1054{
1055    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1056
1057    SBFrame sb_frame;
1058    StackFrameSP frame_sp;
1059    Mutex::Locker api_locker;
1060    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
1061
1062    if (exe_ctx.HasThreadScope())
1063    {
1064        Process::StopLocker stop_locker;
1065        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
1066        {
1067            frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame ();
1068            sb_frame.SetFrameSP (frame_sp);
1069        }
1070        else
1071        {
1072            if (log)
1073                log->Printf ("SBThread(%p)::GetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr());
1074        }
1075    }
1076
1077    if (log)
1078    {
1079        SBStream frame_desc_strm;
1080        sb_frame.GetDescription (frame_desc_strm);
1081        log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
1082                     exe_ctx.GetThreadPtr(), frame_sp.get(), frame_desc_strm.GetData());
1083    }
1084
1085    return sb_frame;
1086}
1087
1088lldb::SBFrame
1089SBThread::SetSelectedFrame (uint32_t idx)
1090{
1091    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1092
1093    SBFrame sb_frame;
1094    StackFrameSP frame_sp;
1095    Mutex::Locker api_locker;
1096    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);
1097
1098    if (exe_ctx.HasThreadScope())
1099    {
1100        Process::StopLocker stop_locker;
1101        if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
1102        {
1103            Thread *thread = exe_ctx.GetThreadPtr();
1104            frame_sp = thread->GetStackFrameAtIndex (idx);
1105            if (frame_sp)
1106            {
1107                thread->SetSelectedFrame (frame_sp.get());
1108                sb_frame.SetFrameSP (frame_sp);
1109            }
1110        }
1111        else
1112        {
1113            if (log)
1114                log->Printf ("SBThread(%p)::SetSelectedFrame() => error: process is running", exe_ctx.GetThreadPtr());
1115        }
1116    }
1117
1118    if (log)
1119    {
1120        SBStream frame_desc_strm;
1121        sb_frame.GetDescription (frame_desc_strm);
1122        log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
1123                     exe_ctx.GetThreadPtr(), idx, frame_sp.get(), frame_desc_strm.GetData());
1124    }
1125    return sb_frame;
1126}
1127
1128
1129bool
1130SBThread::operator == (const SBThread &rhs) const
1131{
1132    return m_opaque_sp->GetThreadSP().get() == rhs.m_opaque_sp->GetThreadSP().get();
1133}
1134
1135bool
1136SBThread::operator != (const SBThread &rhs) const
1137{
1138    return m_opaque_sp->GetThreadSP().get() != rhs.m_opaque_sp->GetThreadSP().get();
1139}
1140
1141bool
1142SBThread::GetDescription (SBStream &description) const
1143{
1144    Stream &strm = description.ref();
1145
1146    ExecutionContext exe_ctx (m_opaque_sp.get());
1147    if (exe_ctx.HasThreadScope())
1148    {
1149        strm.Printf("SBThread: tid = 0x%4.4llx", exe_ctx.GetThreadPtr()->GetID());
1150    }
1151    else
1152        strm.PutCString ("No value");
1153
1154    return true;
1155}
1156