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