]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Target/ThreadPlanShouldStopHere.cpp
Merge ^/head r306412 through r306905.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Target / ThreadPlanShouldStopHere.cpp
1 //===-- ThreadPlanShouldStopHere.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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Core/Log.h"
15 #include "lldb/Symbol/Symbol.h"
16 #include "lldb/Target/RegisterContext.h"
17 #include "lldb/Target/Thread.h"
18 #include "lldb/Target/ThreadPlanShouldStopHere.h"
19
20 using namespace lldb;
21 using namespace lldb_private;
22
23 //----------------------------------------------------------------------
24 // ThreadPlanShouldStopHere constructor
25 //----------------------------------------------------------------------
26 ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner) :
27     m_callbacks(),
28     m_baton(nullptr),
29     m_owner(owner),
30     m_flags(ThreadPlanShouldStopHere::eNone)
31 {
32     m_callbacks.should_stop_here_callback = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback;
33     m_callbacks.step_from_here_callback = ThreadPlanShouldStopHere::DefaultStepFromHereCallback;
34 }
35
36 ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, const ThreadPlanShouldStopHereCallbacks *callbacks, void *baton) :
37     m_callbacks (),
38     m_baton (),
39     m_owner (owner),
40     m_flags (ThreadPlanShouldStopHere::eNone)
41 {
42     SetShouldStopHereCallbacks(callbacks, baton);
43 }
44
45 ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere() = default;
46
47 bool
48 ThreadPlanShouldStopHere::InvokeShouldStopHereCallback (FrameComparison operation)
49 {
50     bool should_stop_here = true;
51     if (m_callbacks.should_stop_here_callback)
52     {
53         should_stop_here = m_callbacks.should_stop_here_callback (m_owner, m_flags, operation, m_baton);
54         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
55         if (log)
56         {
57             lldb::addr_t current_addr = m_owner->GetThread().GetRegisterContext()->GetPC(0);
58
59             log->Printf ("ShouldStopHere callback returned %u from 0x%" PRIx64 ".", should_stop_here, current_addr);
60         }
61     }
62     
63     return should_stop_here;
64 }
65
66 bool
67 ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
68                                                          Flags &flags,
69                                                          FrameComparison operation,
70                                                          void *baton)
71 {
72     bool should_stop_here = true;
73     StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
74     if (!frame)
75         return true;
76     
77     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
78
79     if ((operation == eFrameCompareOlder && flags.Test(eStepOutAvoidNoDebug))
80         || (operation == eFrameCompareYounger && flags.Test(eStepInAvoidNoDebug))
81         || (operation == eFrameCompareSameParent && flags.Test(eStepInAvoidNoDebug)))
82     {
83         if (!frame->HasDebugInformation())
84         {
85             if (log)
86                 log->Printf ("Stepping out of frame with no debug info");
87
88             should_stop_here = false;
89         }
90     }
91     
92     // Always avoid code with line number 0.
93     // FIXME: At present the ShouldStop and the StepFromHere calculate this independently.  If this ever
94     // becomes expensive (this one isn't) we can try to have this set a state that the StepFromHere can use.
95     if (frame)
96     {
97         SymbolContext sc;
98         sc = frame->GetSymbolContext (eSymbolContextLineEntry);
99         if (sc.line_entry.line == 0)
100             should_stop_here = false;
101     }
102     
103     return should_stop_here;
104 }
105
106 ThreadPlanSP
107 ThreadPlanShouldStopHere::DefaultStepFromHereCallback (ThreadPlan *current_plan,
108                                                          Flags &flags,
109                                                          FrameComparison operation,
110                                                          void *baton)
111 {
112     const bool stop_others = false;
113     const size_t frame_index = 0;
114     ThreadPlanSP return_plan_sp;
115     // If we are stepping through code at line number 0, then we need to step over this range.  Otherwise
116     // we will step out.
117     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
118
119     StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
120     if (!frame)
121         return return_plan_sp;
122     SymbolContext sc;
123     sc = frame->GetSymbolContext (eSymbolContextLineEntry|eSymbolContextSymbol);
124
125     if (sc.line_entry.line == 0)
126     {
127         AddressRange range = sc.line_entry.range;
128
129         // If the whole function is marked line 0 just step out, that's easier & faster than continuing
130         // to step through it.
131         bool just_step_out = false;
132         if (sc.symbol && sc.symbol->ValueIsAddress())
133         {
134             Address symbol_end = sc.symbol->GetAddress();
135             symbol_end.Slide(sc.symbol->GetByteSize() - 1);
136             if (range.ContainsFileAddress(sc.symbol->GetAddress()) && range.ContainsFileAddress(symbol_end))
137             {
138                 if (log)
139                     log->Printf("Stopped in a function with only line 0 lines, just stepping out.");
140                 just_step_out = true;
141             }
142         }
143         if (!just_step_out)
144         {
145             if (log)
146                 log->Printf ("ThreadPlanShouldStopHere::DefaultStepFromHereCallback Queueing StepInRange plan to step through line 0 code.");
147             
148             return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange(false,
149                                                                                      range,
150                                                                                      sc,
151                                                                                      NULL,
152                                                                                      eOnlyDuringStepping,
153                                                                                      eLazyBoolCalculate,
154                                                                                      eLazyBoolNo);
155         }
156     }
157     
158     if (!return_plan_sp)
159         return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop(false,
160                                                                                          nullptr,
161                                                                                          true,
162                                                                                          stop_others,
163                                                                                          eVoteNo,
164                                                                                          eVoteNoOpinion,
165                                                                                          frame_index,
166                                                                                          true);
167     return return_plan_sp;
168 }
169
170 ThreadPlanSP
171 ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(lldb_private::Flags &flags, lldb::FrameComparison operation)
172 {
173     ThreadPlanSP return_plan_sp;
174     if (m_callbacks.step_from_here_callback)
175     {
176          return_plan_sp = m_callbacks.step_from_here_callback (m_owner, flags, operation, m_baton);
177     }
178     return return_plan_sp;
179 }
180
181 lldb::ThreadPlanSP
182 ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut (lldb::FrameComparison operation)
183 {
184     if (!InvokeShouldStopHereCallback(operation))
185         return QueueStepOutFromHerePlan(m_flags, operation);
186     else
187         return ThreadPlanSP();
188 }