1 //===-- BreakpointLocation.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 #include <string>
13 
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Breakpoint/BreakpointID.h"
18 #include "lldb/Breakpoint/StoppointCallbackContext.h"
19 #include "lldb/Core/Log.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Target/ThreadPlan.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Core/StreamString.h"
24 #include "lldb/lldb-private-log.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Target/ThreadSpec.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
31 BreakpointLocation::BreakpointLocation
32 (
33     break_id_t loc_id,
34     Breakpoint &owner,
35     const Address &addr,
36     lldb::tid_t tid,
37     bool hardware
38 ) :
39     StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware),
40     m_address (addr),
41     m_owner (owner),
42     m_options_ap (),
43     m_bp_site_sp ()
44 {
45     SetThreadID (tid);
46 }
47 
48 BreakpointLocation::~BreakpointLocation()
49 {
50     ClearBreakpointSite();
51 }
52 
53 lldb::addr_t
54 BreakpointLocation::GetLoadAddress () const
55 {
56     return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget());
57 }
58 
59 Address &
60 BreakpointLocation::GetAddress ()
61 {
62     return m_address;
63 }
64 
65 Breakpoint &
66 BreakpointLocation::GetBreakpoint ()
67 {
68     return m_owner;
69 }
70 
71 bool
72 BreakpointLocation::IsEnabled ()
73 {
74     if (!m_owner.IsEnabled())
75         return false;
76     else if (m_options_ap.get() != NULL)
77         return m_options_ap->IsEnabled();
78     else
79         return true;
80 }
81 
82 void
83 BreakpointLocation::SetEnabled (bool enabled)
84 {
85     GetLocationOptions()->SetEnabled(enabled);
86     if (enabled)
87     {
88         ResolveBreakpointSite();
89     }
90     else
91     {
92         ClearBreakpointSite();
93     }
94 }
95 
96 void
97 BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
98 {
99     if (thread_id != LLDB_INVALID_THREAD_ID)
100         GetLocationOptions()->SetThreadID(thread_id);
101     else
102     {
103         // If we're resetting this to an invalid thread id, then
104         // don't make an options pointer just to do that.
105         if (m_options_ap.get() != NULL)
106             m_options_ap->SetThreadID (thread_id);
107     }
108 }
109 
110 bool
111 BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
112 {
113     if (m_options_ap.get() != NULL && m_options_ap->HasCallback())
114         return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
115     else
116         return m_owner.InvokeCallback (context, GetID());
117 }
118 
119 void
120 BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton,
121                  bool is_synchronous)
122 {
123     // The default "Baton" class will keep a copy of "baton" and won't free
124     // or delete it when it goes goes out of scope.
125     GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
126 }
127 
128 void
129 BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp,
130                  bool is_synchronous)
131 {
132     GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
133 }
134 
135 
136 void
137 BreakpointLocation::ClearCallback ()
138 {
139     GetLocationOptions()->ClearCallback();
140 }
141 
142 void
143 BreakpointLocation::SetCondition (const char *condition)
144 {
145     GetLocationOptions()->SetCondition (condition);
146 }
147 
148 ThreadPlan *
149 BreakpointLocation::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, Stream &error)
150 {
151     lldb::BreakpointLocationSP my_sp(m_owner.GetLocationSP(this));
152     if (m_options_ap.get())
153         return m_options_ap->GetThreadPlanToTestCondition (exe_ctx, my_sp, error);
154     else
155         return m_owner.GetThreadPlanToTestCondition (exe_ctx, my_sp, error);
156 }
157 
158 const char *
159 BreakpointLocation::GetConditionText ()
160 {
161     return GetLocationOptions()->GetConditionText();
162 }
163 
164 uint32_t
165 BreakpointLocation::GetIgnoreCount ()
166 {
167     return GetOptionsNoCreate()->GetIgnoreCount();
168 }
169 
170 void
171 BreakpointLocation::SetIgnoreCount (uint32_t n)
172 {
173     GetLocationOptions()->SetIgnoreCount(n);
174 }
175 
176 const BreakpointOptions *
177 BreakpointLocation::GetOptionsNoCreate () const
178 {
179     if (m_options_ap.get() != NULL)
180         return m_options_ap.get();
181     else
182         return m_owner.GetOptions ();
183 }
184 
185 BreakpointOptions *
186 BreakpointLocation::GetLocationOptions ()
187 {
188     // If we make the copy we don't copy the callbacks because that is potentially
189     // expensive and we don't want to do that for the simple case where someone is
190     // just disabling the location.
191     if (m_options_ap.get() == NULL)
192         m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
193 
194     return m_options_ap.get();
195 }
196 
197 bool
198 BreakpointLocation::ValidForThisThread (Thread *thread)
199 {
200     return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
201 }
202 
203 // RETURNS - true if we should stop at this breakpoint, false if we
204 // should continue.  Note, we don't check the thread spec for the breakpoint
205 // here, since if the breakpoint is not for this thread, then the event won't
206 // even get reported, so the check is redundant.
207 
208 bool
209 BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
210 {
211     bool should_stop = true;
212     LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
213 
214     m_hit_count++;
215 
216     if (!IsEnabled())
217         return false;
218 
219     if (m_hit_count <= GetIgnoreCount())
220         return false;
221 
222     // Next in order of importance is the condition.  See if it is true:
223     StreamString errors;
224 
225     // We only run synchronous callbacks in ShouldStop:
226     context->is_synchronous = true;
227     should_stop = InvokeCallback (context);
228 
229     // The SYNCHRONOUS callback says we should stop, next try the condition.
230 
231     if (should_stop)
232     {
233         ThreadPlanSP condition_plan_sp(GetThreadPlanToTestCondition(context->exe_ctx, errors));
234         log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
235         if (log && errors.GetSize() > 0)
236         {
237             log->Printf("Error evaluating condition: \"%s\".\n", errors.GetData());
238         }
239         else if (condition_plan_sp != NULL)
240         {
241             context->exe_ctx.thread->QueueThreadPlan(condition_plan_sp, false);
242             return false;
243         }
244     }
245 
246     if (should_stop)
247     {
248         log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
249         if (log)
250         {
251             StreamString s;
252             GetDescription (&s, lldb::eDescriptionLevelVerbose);
253             log->Printf ("Hit breakpoint location: %s\n", s.GetData());
254         }
255     }
256     return should_stop;
257 }
258 
259 bool
260 BreakpointLocation::IsResolved () const
261 {
262     return m_bp_site_sp.get() != NULL;
263 }
264 
265 lldb::BreakpointSiteSP
266 BreakpointLocation::GetBreakpointSite() const
267 {
268     return m_bp_site_sp;
269 }
270 
271 bool
272 BreakpointLocation::ResolveBreakpointSite ()
273 {
274     if (m_bp_site_sp)
275         return true;
276 
277     Process *process = m_owner.GetTarget().GetProcessSP().get();
278     if (process == NULL)
279         return false;
280 
281     if (m_owner.GetTarget().GetSectionLoadList().IsEmpty())
282         return false;
283 
284     BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this));
285 
286     lldb::break_id_t new_id = process->CreateBreakpointSite (myself_sp, false);
287 
288     if (new_id == LLDB_INVALID_BREAK_ID)
289     {
290         LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
291         if (log)
292             log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
293                           m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()));
294         return false;
295     }
296 
297     return true;
298 }
299 
300 bool
301 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
302 {
303     m_bp_site_sp = bp_site_sp;
304     return true;
305 }
306 
307 bool
308 BreakpointLocation::ClearBreakpointSite ()
309 {
310     if (m_bp_site_sp.get())
311     {
312         m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
313                                                                            GetID(), m_bp_site_sp);
314         m_bp_site_sp.reset();
315         return true;
316     }
317     return false;
318 }
319 
320 void
321 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
322 {
323     SymbolContext sc;
324     s->Indent();
325     BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
326 
327     if (level == lldb::eDescriptionLevelBrief)
328         return;
329 
330     s->PutCString(": ");
331 
332     if (level == lldb::eDescriptionLevelVerbose)
333         s->IndentMore();
334 
335     if (m_address.IsSectionOffset())
336     {
337         m_address.CalculateSymbolContext(&sc);
338 
339         if (level == lldb::eDescriptionLevelFull)
340         {
341             s->PutCString("where = ");
342             sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
343         }
344         else
345         {
346             if (sc.module_sp)
347             {
348                 s->EOL();
349                 s->Indent("module = ");
350                 sc.module_sp->GetFileSpec().Dump (s);
351             }
352 
353             if (sc.comp_unit != NULL)
354             {
355                 s->EOL();
356                 s->Indent("compile unit = ");
357                 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
358 
359                 if (sc.function != NULL)
360                 {
361                     s->EOL();
362                     s->Indent("function = ");
363                     s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
364                 }
365 
366                 if (sc.line_entry.line > 0)
367                 {
368                     s->EOL();
369                     s->Indent("location = ");
370                     sc.line_entry.DumpStopContext (s, true);
371                 }
372 
373             }
374             else
375             {
376                 // If we don't have a comp unit, see if we have a symbol we can print.
377                 if (sc.symbol)
378                 {
379                     s->EOL();
380                     s->Indent("symbol = ");
381                     s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
382                 }
383             }
384         }
385     }
386 
387     if (level == lldb::eDescriptionLevelVerbose)
388     {
389         s->EOL();
390         s->Indent();
391     }
392     s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : "");
393     ExecutionContextScope *exe_scope = NULL;
394     Target *target = &m_owner.GetTarget();
395     if (target)
396         exe_scope = target->GetProcessSP().get();
397     if (exe_scope == NULL)
398         exe_scope = target;
399 
400     m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
401 
402     if (level == lldb::eDescriptionLevelVerbose)
403     {
404         s->EOL();
405         s->Indent();
406         s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
407 
408         s->Indent();
409         s->Printf ("hit count = %-4u\n", GetHitCount());
410 
411         if (m_options_ap.get())
412         {
413             s->Indent();
414             m_options_ap->GetDescription (s, level);
415             s->EOL();
416         }
417         s->IndentLess();
418     }
419     else
420     {
421         s->Printf(", %sresolved, hit count = %u ",
422                   (IsResolved() ? "" : "un"),
423                   GetHitCount());
424         if (m_options_ap.get())
425         {
426             m_options_ap->GetDescription (s, level);
427         }
428     }
429 }
430 
431 void
432 BreakpointLocation::Dump(Stream *s) const
433 {
434     if (s == NULL)
435         return;
436 
437     s->Printf("BreakpointLocation %u: tid = %4.4x  load addr = 0x%8.8llx  state = %s  type = %s breakpoint  "
438               "hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
439             GetID(),
440             GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
441             (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
442             (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
443             IsHardware() ? "hardware" : "software",
444             GetHardwareIndex(),
445             GetHitCount(),
446             m_options_ap.get() ? m_options_ap->GetIgnoreCount() : m_owner.GetIgnoreCount());
447 }
448