blob: 45321142adb78611df02312604eea54ada2a90b3 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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"
Jim Inghamd1686902010-10-14 23:45:03 +000021#include "lldb/Target/ThreadPlan.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Target/Process.h"
23#include "lldb/Core/StreamString.h"
24#include "lldb/lldb-private-log.h"
25#include "lldb/Target/Thread.h"
Jim Ingham3c7b5b92010-06-16 02:00:15 +000026#include "lldb/Target/ThreadSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000027
28using namespace lldb;
29using namespace lldb_private;
30
31BreakpointLocation::BreakpointLocation
32(
33 break_id_t loc_id,
34 Breakpoint &owner,
35 Address &addr,
36 lldb::tid_t tid,
37 bool hardware
38) :
Greg Claytoneea26402010-09-14 23:36:40 +000039 StoppointLocation (loc_id, addr.GetLoadAddress(&owner.GetTarget()), hardware),
Chris Lattner24943d22010-06-08 16:52:24 +000040 m_address (addr),
41 m_owner (owner),
42 m_options_ap (),
43 m_bp_site_sp ()
44{
Jim Ingham3c7b5b92010-06-16 02:00:15 +000045 SetThreadID (tid);
Chris Lattner24943d22010-06-08 16:52:24 +000046}
47
48BreakpointLocation::~BreakpointLocation()
49{
50 ClearBreakpointSite();
51}
52
53lldb::addr_t
Greg Clayton273a8e52010-06-14 04:18:27 +000054BreakpointLocation::GetLoadAddress () const
Chris Lattner24943d22010-06-08 16:52:24 +000055{
Greg Claytoneea26402010-09-14 23:36:40 +000056 return m_address.GetLoadAddress(&m_owner.GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +000057}
58
59Address &
60BreakpointLocation::GetAddress ()
61{
62 return m_address;
63}
64
65Breakpoint &
66BreakpointLocation::GetBreakpoint ()
67{
68 return m_owner;
69}
70
71bool
72BreakpointLocation::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
82void
83BreakpointLocation::SetEnabled (bool enabled)
84{
85 GetLocationOptions()->SetEnabled(enabled);
86 if (enabled)
87 {
88 ResolveBreakpointSite();
89 }
90 else
91 {
92 ClearBreakpointSite();
93 }
94}
95
96void
97BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
98{
Jim Ingham3c7b5b92010-06-16 02:00:15 +000099 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 }
Chris Lattner24943d22010-06-08 16:52:24 +0000108}
109
110bool
111BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
112{
Jim Ingham649492b2010-06-18 01:00:58 +0000113 if (m_options_ap.get() != NULL && m_options_ap->HasCallback())
Chris Lattner24943d22010-06-08 16:52:24 +0000114 return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
Jim Ingham649492b2010-06-18 01:00:58 +0000115 else
116 return m_owner.InvokeCallback (context, GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000117}
118
119void
120BreakpointLocation::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
128void
129BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp,
130 bool is_synchronous)
131{
132 GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
133}
134
Jim Inghamd1686902010-10-14 23:45:03 +0000135
Chris Lattner24943d22010-06-08 16:52:24 +0000136void
137BreakpointLocation::ClearCallback ()
138{
139 GetLocationOptions()->ClearCallback();
140}
141
Jim Inghamd1686902010-10-14 23:45:03 +0000142void
143BreakpointLocation::SetCondition (const char *condition)
144{
145 GetLocationOptions()->SetCondition (condition);
146}
147
148ThreadPlan *
149BreakpointLocation::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
158const char *
159BreakpointLocation::GetConditionText ()
160{
161 return GetLocationOptions()->GetConditionText();
162}
163
Greg Clayton54e7afa2010-07-09 20:39:50 +0000164uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000165BreakpointLocation::GetIgnoreCount ()
166{
Jim Ingham9c6898b2010-06-22 21:12:54 +0000167 return GetOptionsNoCreate()->GetIgnoreCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000168}
169
170void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000171BreakpointLocation::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000172{
173 GetLocationOptions()->SetIgnoreCount(n);
174}
175
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000176const BreakpointOptions *
Jim Ingham9c6898b2010-06-22 21:12:54 +0000177BreakpointLocation::GetOptionsNoCreate () const
Chris Lattner24943d22010-06-08 16:52:24 +0000178{
179 if (m_options_ap.get() != NULL)
180 return m_options_ap.get();
181 else
182 return m_owner.GetOptions ();
183}
184
185BreakpointOptions *
186BreakpointLocation::GetLocationOptions ()
187{
Jim Ingham649492b2010-06-18 01:00:58 +0000188 // 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.
Chris Lattner24943d22010-06-08 16:52:24 +0000191 if (m_options_ap.get() == NULL)
Jim Ingham649492b2010-06-18 01:00:58 +0000192 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
193
Chris Lattner24943d22010-06-08 16:52:24 +0000194 return m_options_ap.get();
195}
196
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000197bool
198BreakpointLocation::ValidForThisThread (Thread *thread)
199{
Jim Ingham9c6898b2010-06-22 21:12:54 +0000200 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000201}
202
Chris Lattner24943d22010-06-08 16:52:24 +0000203// RETURNS - true if we should stop at this breakpoint, false if we
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000204// 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.
Chris Lattner24943d22010-06-08 16:52:24 +0000207
208bool
209BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
210{
211 bool should_stop = true;
Greg Claytone005f2c2010-11-06 01:53:30 +0000212 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
Chris Lattner24943d22010-06-08 16:52:24 +0000213
214 m_hit_count++;
215
216 if (!IsEnabled())
217 return false;
218
Chris Lattner24943d22010-06-08 16:52:24 +0000219 if (m_hit_count <= GetIgnoreCount())
220 return false;
221
Jim Inghamd1686902010-10-14 23:45:03 +0000222 // 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:
Chris Lattner24943d22010-06-08 16:52:24 +0000226 context->is_synchronous = true;
227 should_stop = InvokeCallback (context);
Jim Inghamd1686902010-10-14 23:45:03 +0000228
229 // The SYNCHRONOUS callback says we should stop, next try the condition.
230
Chris Lattner24943d22010-06-08 16:52:24 +0000231 if (should_stop)
232 {
Jim Inghamd1686902010-10-14 23:45:03 +0000233 ThreadPlanSP condition_plan_sp(GetThreadPlanToTestCondition(context->exe_ctx, errors));
Caroline Tice926060e2010-10-29 21:48:37 +0000234 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
Jim Inghamd1686902010-10-14 23:45:03 +0000235 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 {
Caroline Tice926060e2010-10-29 21:48:37 +0000248 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
Chris Lattner24943d22010-06-08 16:52:24 +0000249 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
259bool
260BreakpointLocation::IsResolved () const
261{
262 return m_bp_site_sp.get() != NULL;
263}
264
Jim Inghamd1686902010-10-14 23:45:03 +0000265lldb::BreakpointSiteSP
266BreakpointLocation::GetBreakpointSite() const
267{
268 return m_bp_site_sp;
269}
270
Chris Lattner24943d22010-06-08 16:52:24 +0000271bool
272BreakpointLocation::ResolveBreakpointSite ()
273{
274 if (m_bp_site_sp)
275 return true;
276
Greg Claytoneea26402010-09-14 23:36:40 +0000277 Process *process = m_owner.GetTarget().GetProcessSP().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000278 if (process == NULL)
279 return false;
280
Greg Claytoneea26402010-09-14 23:36:40 +0000281 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty())
282 return false;
283
Chris Lattner24943d22010-06-08 16:52:24 +0000284 BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this));
285
Stephen Wilson3fd1f362010-07-17 00:56:13 +0000286 lldb::break_id_t new_id = process->CreateBreakpointSite (myself_sp, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000287
Stephen Wilson3fd1f362010-07-17 00:56:13 +0000288 if (new_id == LLDB_INVALID_BREAK_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000289 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000290 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
Chris Lattner24943d22010-06-08 16:52:24 +0000291 if (log)
292 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
Greg Claytoneea26402010-09-14 23:36:40 +0000293 m_address.GetLoadAddress(&m_owner.GetTarget()));
Chris Lattner24943d22010-06-08 16:52:24 +0000294 return false;
295 }
296
297 return true;
298}
299
300bool
301BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
302{
303 m_bp_site_sp = bp_site_sp;
304 return true;
305}
306
307bool
308BreakpointLocation::ClearBreakpointSite ()
309{
310 if (m_bp_site_sp.get())
311 {
Jim Ingham649492b2010-06-18 01:00:58 +0000312 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
313 GetID(), m_bp_site_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000314 m_bp_site_sp.reset();
315 return true;
316 }
317 return false;
318}
319
320void
321BreakpointLocation::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 = ");
Greg Clayton5205f0b2010-09-03 17:10:42 +0000342 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000343 }
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 = ");
Jim Ingham7ea35232010-10-27 22:58:34 +0000357 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
Chris Lattner24943d22010-06-08 16:52:24 +0000358
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 = ");
Greg Clayton72b71582010-09-02 21:44:10 +0000370 sc.line_entry.DumpStopContext (s, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000371 }
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();
Chris Lattner24943d22010-06-08 16:52:24 +0000409 s->Printf ("hit count = %-4u\n", GetHitCount());
410
411 if (m_options_ap.get())
412 {
Jim Ingham649492b2010-06-18 01:00:58 +0000413 s->Indent();
414 m_options_ap->GetDescription (s, level);
415 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000416 }
417 s->IndentLess();
418 }
419 else
420 {
Jim Ingham649492b2010-06-18 01:00:58 +0000421 s->Printf(", %sresolved, hit count = %u ",
Chris Lattner24943d22010-06-08 16:52:24 +0000422 (IsResolved() ? "" : "un"),
Chris Lattner24943d22010-06-08 16:52:24 +0000423 GetHitCount());
Jim Ingham649492b2010-06-18 01:00:58 +0000424 if (m_options_ap.get())
425 {
426 m_options_ap->GetDescription (s, level);
427 }
Chris Lattner24943d22010-06-08 16:52:24 +0000428 }
429}
430
431void
432BreakpointLocation::Dump(Stream *s) const
433{
434 if (s == NULL)
435 return;
436
Jim Ingham649492b2010-06-18 01:00:58 +0000437 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",
Chris Lattner24943d22010-06-08 16:52:24 +0000439 GetID(),
Jim Ingham9c6898b2010-06-22 21:12:54 +0000440 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
Greg Claytoneea26402010-09-14 23:36:40 +0000441 (uint64_t) m_address.GetLoadAddress (&m_owner.GetTarget()),
Chris Lattner24943d22010-06-08 16:52:24 +0000442 (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}