blob: 311555cdc39a9cff40b15f15d45c6f04c211f022 [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"
Jim Inghame5ed8e92011-06-02 23:58:26 +000019#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Core/Log.h"
21#include "lldb/Target/Target.h"
Jim Inghamd1686902010-10-14 23:45:03 +000022#include "lldb/Target/ThreadPlan.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Target/Process.h"
24#include "lldb/Core/StreamString.h"
25#include "lldb/lldb-private-log.h"
26#include "lldb/Target/Thread.h"
Jim Ingham3c7b5b92010-06-16 02:00:15 +000027#include "lldb/Target/ThreadSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000028
29using namespace lldb;
30using namespace lldb_private;
31
32BreakpointLocation::BreakpointLocation
33(
34 break_id_t loc_id,
35 Breakpoint &owner,
Greg Clayton19a1ab82011-02-05 00:38:04 +000036 const Address &addr,
Chris Lattner24943d22010-06-08 16:52:24 +000037 lldb::tid_t tid,
38 bool hardware
39) :
Greg Claytonc0fa5332011-05-22 22:46:53 +000040 StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware),
Chris Lattner24943d22010-06-08 16:52:24 +000041 m_address (addr),
42 m_owner (owner),
43 m_options_ap (),
44 m_bp_site_sp ()
45{
Jim Ingham3c7b5b92010-06-16 02:00:15 +000046 SetThreadID (tid);
Chris Lattner24943d22010-06-08 16:52:24 +000047}
48
49BreakpointLocation::~BreakpointLocation()
50{
51 ClearBreakpointSite();
52}
53
54lldb::addr_t
Greg Clayton273a8e52010-06-14 04:18:27 +000055BreakpointLocation::GetLoadAddress () const
Chris Lattner24943d22010-06-08 16:52:24 +000056{
Greg Claytonc0fa5332011-05-22 22:46:53 +000057 return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +000058}
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{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000100 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 }
Chris Lattner24943d22010-06-08 16:52:24 +0000109}
110
111bool
112BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
113{
Jim Ingham649492b2010-06-18 01:00:58 +0000114 if (m_options_ap.get() != NULL && m_options_ap->HasCallback())
Chris Lattner24943d22010-06-08 16:52:24 +0000115 return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
Jim Ingham649492b2010-06-18 01:00:58 +0000116 else
117 return m_owner.InvokeCallback (context, GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000118}
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
Jim Inghamd1686902010-10-14 23:45:03 +0000136
Chris Lattner24943d22010-06-08 16:52:24 +0000137void
138BreakpointLocation::ClearCallback ()
139{
140 GetLocationOptions()->ClearCallback();
141}
142
Jim Inghamd1686902010-10-14 23:45:03 +0000143void
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 ()
161{
162 return GetLocationOptions()->GetConditionText();
163}
164
Greg Clayton54e7afa2010-07-09 20:39:50 +0000165uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000166BreakpointLocation::GetIgnoreCount ()
167{
Jim Ingham9c6898b2010-06-22 21:12:54 +0000168 return GetOptionsNoCreate()->GetIgnoreCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000169}
170
171void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000172BreakpointLocation::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000173{
174 GetLocationOptions()->SetIgnoreCount(n);
175}
176
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000177const BreakpointOptions *
Jim Ingham9c6898b2010-06-22 21:12:54 +0000178BreakpointLocation::GetOptionsNoCreate () const
Chris Lattner24943d22010-06-08 16:52:24 +0000179{
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{
Jim Ingham649492b2010-06-18 01:00:58 +0000189 // 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.
Chris Lattner24943d22010-06-08 16:52:24 +0000192 if (m_options_ap.get() == NULL)
Jim Ingham649492b2010-06-18 01:00:58 +0000193 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
194
Chris Lattner24943d22010-06-08 16:52:24 +0000195 return m_options_ap.get();
196}
197
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000198bool
199BreakpointLocation::ValidForThisThread (Thread *thread)
200{
Jim Ingham9c6898b2010-06-22 21:12:54 +0000201 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000202}
203
Chris Lattner24943d22010-06-08 16:52:24 +0000204// RETURNS - true if we should stop at this breakpoint, false if we
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000205// 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.
Chris Lattner24943d22010-06-08 16:52:24 +0000208
209bool
210BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
211{
212 bool should_stop = true;
Greg Claytone005f2c2010-11-06 01:53:30 +0000213 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
Chris Lattner24943d22010-06-08 16:52:24 +0000214
215 m_hit_count++;
216
217 if (!IsEnabled())
218 return false;
219
Chris Lattner24943d22010-06-08 16:52:24 +0000220 if (m_hit_count <= GetIgnoreCount())
221 return false;
222
Jim Inghamd1686902010-10-14 23:45:03 +0000223 // We only run synchronous callbacks in ShouldStop:
Chris Lattner24943d22010-06-08 16:52:24 +0000224 context->is_synchronous = true;
225 should_stop = InvokeCallback (context);
Jim Inghamd1686902010-10-14 23:45:03 +0000226
227 // The SYNCHRONOUS callback says we should stop, next try the condition.
228
Chris Lattner24943d22010-06-08 16:52:24 +0000229 if (should_stop)
230 {
Jim Inghame5ed8e92011-06-02 23:58:26 +0000231 // 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;
Jim Inghamd1686902010-10-14 23:45:03 +0000235 ThreadPlanSP condition_plan_sp(GetThreadPlanToTestCondition(context->exe_ctx, errors));
Jim Inghame5ed8e92011-06-02 23:58:26 +0000236
237 if (condition_plan_sp == NULL)
Jim Inghamd1686902010-10-14 23:45:03 +0000238 {
Jim Inghame5ed8e92011-06-02 23:58:26 +0000239 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
Jim Inghamd1686902010-10-14 23:45:03 +0000249 }
Jim Inghame5ed8e92011-06-02 23:58:26 +0000250 else
Jim Inghamd1686902010-10-14 23:45:03 +0000251 {
Jim Inghame5ed8e92011-06-02 23:58:26 +0000252 // Queue our condition, then continue so that we can run it.
Jim Inghamd1686902010-10-14 23:45:03 +0000253 context->exe_ctx.thread->QueueThreadPlan(condition_plan_sp, false);
Jim Inghame5ed8e92011-06-02 23:58:26 +0000254 should_stop = false;
Jim Inghamd1686902010-10-14 23:45:03 +0000255 }
256 }
257
Jim Inghame5ed8e92011-06-02 23:58:26 +0000258 if (log)
Jim Inghamd1686902010-10-14 23:45:03 +0000259 {
Jim Inghame5ed8e92011-06-02 23:58:26 +0000260 StreamString s;
261 GetDescription (&s, lldb::eDescriptionLevelVerbose);
262 log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing");
Chris Lattner24943d22010-06-08 16:52:24 +0000263 }
Jim Inghame5ed8e92011-06-02 23:58:26 +0000264
Chris Lattner24943d22010-06-08 16:52:24 +0000265 return should_stop;
266}
267
268bool
269BreakpointLocation::IsResolved () const
270{
271 return m_bp_site_sp.get() != NULL;
272}
273
Jim Inghamd1686902010-10-14 23:45:03 +0000274lldb::BreakpointSiteSP
275BreakpointLocation::GetBreakpointSite() const
276{
277 return m_bp_site_sp;
278}
279
Chris Lattner24943d22010-06-08 16:52:24 +0000280bool
281BreakpointLocation::ResolveBreakpointSite ()
282{
283 if (m_bp_site_sp)
284 return true;
285
Greg Claytoneea26402010-09-14 23:36:40 +0000286 Process *process = m_owner.GetTarget().GetProcessSP().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000287 if (process == NULL)
288 return false;
289
Greg Claytoneea26402010-09-14 23:36:40 +0000290 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty())
291 return false;
292
Chris Lattner24943d22010-06-08 16:52:24 +0000293 BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this));
294
Stephen Wilson3fd1f362010-07-17 00:56:13 +0000295 lldb::break_id_t new_id = process->CreateBreakpointSite (myself_sp, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000296
Stephen Wilson3fd1f362010-07-17 00:56:13 +0000297 if (new_id == LLDB_INVALID_BREAK_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000298 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000299 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
Chris Lattner24943d22010-06-08 16:52:24 +0000300 if (log)
301 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
Greg Claytonc0fa5332011-05-22 22:46:53 +0000302 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()));
Chris Lattner24943d22010-06-08 16:52:24 +0000303 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 {
Jim Ingham649492b2010-06-18 01:00:58 +0000321 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
322 GetID(), m_bp_site_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000323 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 = ");
Greg Clayton5205f0b2010-09-03 17:10:42 +0000351 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000352 }
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 = ");
Jim Ingham7ea35232010-10-27 22:58:34 +0000366 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
Chris Lattner24943d22010-06-08 16:52:24 +0000367
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 = ");
Greg Clayton72b71582010-09-02 21:44:10 +0000379 sc.line_entry.DumpStopContext (s, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000380 }
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();
Chris Lattner24943d22010-06-08 16:52:24 +0000418 s->Printf ("hit count = %-4u\n", GetHitCount());
419
420 if (m_options_ap.get())
421 {
Jim Ingham649492b2010-06-18 01:00:58 +0000422 s->Indent();
423 m_options_ap->GetDescription (s, level);
424 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000425 }
426 s->IndentLess();
427 }
428 else
429 {
Jim Ingham649492b2010-06-18 01:00:58 +0000430 s->Printf(", %sresolved, hit count = %u ",
Chris Lattner24943d22010-06-08 16:52:24 +0000431 (IsResolved() ? "" : "un"),
Chris Lattner24943d22010-06-08 16:52:24 +0000432 GetHitCount());
Jim Ingham649492b2010-06-18 01:00:58 +0000433 if (m_options_ap.get())
434 {
435 m_options_ap->GetDescription (s, level);
436 }
Chris Lattner24943d22010-06-08 16:52:24 +0000437 }
438}
439
440void
441BreakpointLocation::Dump(Stream *s) const
442{
443 if (s == NULL)
444 return;
445
Jim Ingham649492b2010-06-18 01:00:58 +0000446 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",
Chris Lattner24943d22010-06-08 16:52:24 +0000448 GetID(),
Jim Ingham9c6898b2010-06-22 21:12:54 +0000449 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
Greg Claytonc0fa5332011-05-22 22:46:53 +0000450 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
Chris Lattner24943d22010-06-08 16:52:24 +0000451 (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}