blob: a898c332b16fbd7273e0461ab277fc3157393a1a [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
Johnny Chenfb0026b2012-01-30 21:16:22 +000073BreakpointLocation::IsEnabled () const
Chris Lattner24943d22010-06-08 16:52:24 +000074{
Johnny Chenfb0026b2012-01-30 21:16:22 +000075 if (m_options_ap.get() != NULL)
Chris Lattner24943d22010-06-08 16:52:24 +000076 return m_options_ap->IsEnabled();
77 else
Johnny Chenfb0026b2012-01-30 21:16:22 +000078 return m_owner.IsEnabled();
Chris Lattner24943d22010-06-08 16:52:24 +000079}
80
81void
82BreakpointLocation::SetEnabled (bool enabled)
83{
84 GetLocationOptions()->SetEnabled(enabled);
85 if (enabled)
86 {
87 ResolveBreakpointSite();
88 }
89 else
90 {
91 ClearBreakpointSite();
92 }
93}
94
95void
96BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
97{
Jim Ingham3c7b5b92010-06-16 02:00:15 +000098 if (thread_id != LLDB_INVALID_THREAD_ID)
99 GetLocationOptions()->SetThreadID(thread_id);
100 else
101 {
102 // If we're resetting this to an invalid thread id, then
103 // don't make an options pointer just to do that.
104 if (m_options_ap.get() != NULL)
105 m_options_ap->SetThreadID (thread_id);
106 }
Chris Lattner24943d22010-06-08 16:52:24 +0000107}
108
109bool
110BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
111{
Jim Ingham649492b2010-06-18 01:00:58 +0000112 if (m_options_ap.get() != NULL && m_options_ap->HasCallback())
Chris Lattner24943d22010-06-08 16:52:24 +0000113 return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
Jim Ingham649492b2010-06-18 01:00:58 +0000114 else
115 return m_owner.InvokeCallback (context, GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000116}
117
118void
119BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton,
120 bool is_synchronous)
121{
122 // The default "Baton" class will keep a copy of "baton" and won't free
123 // or delete it when it goes goes out of scope.
124 GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
125}
126
127void
128BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp,
129 bool is_synchronous)
130{
131 GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
132}
133
Jim Inghamd1686902010-10-14 23:45:03 +0000134
Chris Lattner24943d22010-06-08 16:52:24 +0000135void
136BreakpointLocation::ClearCallback ()
137{
138 GetLocationOptions()->ClearCallback();
139}
140
Jim Inghamd1686902010-10-14 23:45:03 +0000141void
142BreakpointLocation::SetCondition (const char *condition)
143{
144 GetLocationOptions()->SetCondition (condition);
145}
146
147ThreadPlan *
148BreakpointLocation::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, Stream &error)
149{
Jim Inghamd1686902010-10-14 23:45:03 +0000150 if (m_options_ap.get())
Greg Clayton13d24fb2012-01-29 20:56:30 +0000151 return m_options_ap->GetThreadPlanToTestCondition (exe_ctx, shared_from_this(), error);
Jim Inghamd1686902010-10-14 23:45:03 +0000152 else
Greg Clayton13d24fb2012-01-29 20:56:30 +0000153 return m_owner.GetThreadPlanToTestCondition (exe_ctx, shared_from_this(), error);
Jim Inghamd1686902010-10-14 23:45:03 +0000154}
155
156const char *
Jim Inghamac354422011-06-15 21:16:00 +0000157BreakpointLocation::GetConditionText () const
Jim Inghamd1686902010-10-14 23:45:03 +0000158{
Jim Inghamac354422011-06-15 21:16:00 +0000159 return GetOptionsNoCreate()->GetConditionText();
Jim Inghamd1686902010-10-14 23:45:03 +0000160}
161
Greg Clayton54e7afa2010-07-09 20:39:50 +0000162uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000163BreakpointLocation::GetIgnoreCount ()
164{
Jim Ingham9c6898b2010-06-22 21:12:54 +0000165 return GetOptionsNoCreate()->GetIgnoreCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000166}
167
168void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000169BreakpointLocation::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000170{
171 GetLocationOptions()->SetIgnoreCount(n);
172}
173
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000174const BreakpointOptions *
Jim Ingham9c6898b2010-06-22 21:12:54 +0000175BreakpointLocation::GetOptionsNoCreate () const
Chris Lattner24943d22010-06-08 16:52:24 +0000176{
177 if (m_options_ap.get() != NULL)
178 return m_options_ap.get();
179 else
180 return m_owner.GetOptions ();
181}
182
183BreakpointOptions *
184BreakpointLocation::GetLocationOptions ()
185{
Jim Ingham649492b2010-06-18 01:00:58 +0000186 // If we make the copy we don't copy the callbacks because that is potentially
187 // expensive and we don't want to do that for the simple case where someone is
188 // just disabling the location.
Chris Lattner24943d22010-06-08 16:52:24 +0000189 if (m_options_ap.get() == NULL)
Jim Ingham649492b2010-06-18 01:00:58 +0000190 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
191
Chris Lattner24943d22010-06-08 16:52:24 +0000192 return m_options_ap.get();
193}
194
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000195bool
196BreakpointLocation::ValidForThisThread (Thread *thread)
197{
Jim Ingham9c6898b2010-06-22 21:12:54 +0000198 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000199}
200
Chris Lattner24943d22010-06-08 16:52:24 +0000201// RETURNS - true if we should stop at this breakpoint, false if we
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000202// should continue. Note, we don't check the thread spec for the breakpoint
203// here, since if the breakpoint is not for this thread, then the event won't
204// even get reported, so the check is redundant.
Chris Lattner24943d22010-06-08 16:52:24 +0000205
206bool
207BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
208{
209 bool should_stop = true;
Greg Claytone005f2c2010-11-06 01:53:30 +0000210 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
Chris Lattner24943d22010-06-08 16:52:24 +0000211
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000212 IncrementHitCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000213
214 if (!IsEnabled())
215 return false;
216
Johnny Chen51b7c5f2012-01-23 23:03:59 +0000217 if (GetHitCount() <= GetIgnoreCount())
Chris Lattner24943d22010-06-08 16:52:24 +0000218 return false;
219
Jim Inghamd1686902010-10-14 23:45:03 +0000220 // We only run synchronous callbacks in ShouldStop:
Chris Lattner24943d22010-06-08 16:52:24 +0000221 context->is_synchronous = true;
222 should_stop = InvokeCallback (context);
Jim Inghamd1686902010-10-14 23:45:03 +0000223
Jim Inghame5ed8e92011-06-02 23:58:26 +0000224 if (log)
Jim Inghamd1686902010-10-14 23:45:03 +0000225 {
Jim Inghame5ed8e92011-06-02 23:58:26 +0000226 StreamString s;
227 GetDescription (&s, lldb::eDescriptionLevelVerbose);
228 log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing");
Chris Lattner24943d22010-06-08 16:52:24 +0000229 }
Jim Inghame5ed8e92011-06-02 23:58:26 +0000230
Chris Lattner24943d22010-06-08 16:52:24 +0000231 return should_stop;
232}
233
234bool
235BreakpointLocation::IsResolved () const
236{
237 return m_bp_site_sp.get() != NULL;
238}
239
Jim Inghamd1686902010-10-14 23:45:03 +0000240lldb::BreakpointSiteSP
241BreakpointLocation::GetBreakpointSite() const
242{
243 return m_bp_site_sp;
244}
245
Chris Lattner24943d22010-06-08 16:52:24 +0000246bool
247BreakpointLocation::ResolveBreakpointSite ()
248{
249 if (m_bp_site_sp)
250 return true;
251
Greg Claytoneea26402010-09-14 23:36:40 +0000252 Process *process = m_owner.GetTarget().GetProcessSP().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000253 if (process == NULL)
254 return false;
255
Greg Claytoneea26402010-09-14 23:36:40 +0000256 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty())
257 return false;
258
Greg Clayton13d24fb2012-01-29 20:56:30 +0000259 lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false);
Chris Lattner24943d22010-06-08 16:52:24 +0000260
Stephen Wilson3fd1f362010-07-17 00:56:13 +0000261 if (new_id == LLDB_INVALID_BREAK_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000262 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000263 LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
Chris Lattner24943d22010-06-08 16:52:24 +0000264 if (log)
265 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
Greg Claytonc0fa5332011-05-22 22:46:53 +0000266 m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()));
Chris Lattner24943d22010-06-08 16:52:24 +0000267 return false;
268 }
269
270 return true;
271}
272
273bool
274BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
275{
276 m_bp_site_sp = bp_site_sp;
277 return true;
278}
279
280bool
281BreakpointLocation::ClearBreakpointSite ()
282{
283 if (m_bp_site_sp.get())
284 {
Jim Ingham649492b2010-06-18 01:00:58 +0000285 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
286 GetID(), m_bp_site_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000287 m_bp_site_sp.reset();
288 return true;
289 }
290 return false;
291}
292
293void
294BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
295{
296 SymbolContext sc;
297 s->Indent();
298 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
299
300 if (level == lldb::eDescriptionLevelBrief)
301 return;
302
303 s->PutCString(": ");
304
305 if (level == lldb::eDescriptionLevelVerbose)
306 s->IndentMore();
307
308 if (m_address.IsSectionOffset())
309 {
310 m_address.CalculateSymbolContext(&sc);
311
312 if (level == lldb::eDescriptionLevelFull)
313 {
314 s->PutCString("where = ");
Greg Clayton5205f0b2010-09-03 17:10:42 +0000315 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000316 }
317 else
318 {
319 if (sc.module_sp)
320 {
321 s->EOL();
322 s->Indent("module = ");
323 sc.module_sp->GetFileSpec().Dump (s);
324 }
325
326 if (sc.comp_unit != NULL)
327 {
328 s->EOL();
329 s->Indent("compile unit = ");
Jim Ingham7ea35232010-10-27 22:58:34 +0000330 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
Chris Lattner24943d22010-06-08 16:52:24 +0000331
332 if (sc.function != NULL)
333 {
334 s->EOL();
335 s->Indent("function = ");
336 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
337 }
338
339 if (sc.line_entry.line > 0)
340 {
341 s->EOL();
342 s->Indent("location = ");
Greg Clayton72b71582010-09-02 21:44:10 +0000343 sc.line_entry.DumpStopContext (s, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000344 }
345
346 }
347 else
348 {
349 // If we don't have a comp unit, see if we have a symbol we can print.
350 if (sc.symbol)
351 {
352 s->EOL();
353 s->Indent("symbol = ");
354 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
355 }
356 }
357 }
358 }
359
360 if (level == lldb::eDescriptionLevelVerbose)
361 {
362 s->EOL();
363 s->Indent();
364 }
365 s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : "");
366 ExecutionContextScope *exe_scope = NULL;
367 Target *target = &m_owner.GetTarget();
368 if (target)
369 exe_scope = target->GetProcessSP().get();
370 if (exe_scope == NULL)
371 exe_scope = target;
372
373 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
374
375 if (level == lldb::eDescriptionLevelVerbose)
376 {
377 s->EOL();
378 s->Indent();
379 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
380
381 s->Indent();
Chris Lattner24943d22010-06-08 16:52:24 +0000382 s->Printf ("hit count = %-4u\n", GetHitCount());
383
384 if (m_options_ap.get())
385 {
Jim Ingham649492b2010-06-18 01:00:58 +0000386 s->Indent();
387 m_options_ap->GetDescription (s, level);
388 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000389 }
390 s->IndentLess();
391 }
392 else
393 {
Jim Ingham649492b2010-06-18 01:00:58 +0000394 s->Printf(", %sresolved, hit count = %u ",
Chris Lattner24943d22010-06-08 16:52:24 +0000395 (IsResolved() ? "" : "un"),
Chris Lattner24943d22010-06-08 16:52:24 +0000396 GetHitCount());
Jim Ingham649492b2010-06-18 01:00:58 +0000397 if (m_options_ap.get())
398 {
399 m_options_ap->GetDescription (s, level);
400 }
Chris Lattner24943d22010-06-08 16:52:24 +0000401 }
402}
403
404void
405BreakpointLocation::Dump(Stream *s) const
406{
407 if (s == NULL)
408 return;
409
Greg Claytond9919d32011-12-01 23:28:38 +0000410 s->Printf("BreakpointLocation %u: tid = %4.4llx load addr = 0x%8.8llx state = %s type = %s breakpoint "
Jim Ingham649492b2010-06-18 01:00:58 +0000411 "hw_index = %i hit_count = %-4u ignore_count = %-4u",
Johnny Chenf8c0fc52012-01-26 00:08:14 +0000412 GetID(),
413 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
414 (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
Johnny Chenfb0026b2012-01-30 21:16:22 +0000415 IsEnabled() ? "enabled " : "disabled",
Johnny Chenf8c0fc52012-01-26 00:08:14 +0000416 IsHardware() ? "hardware" : "software",
417 GetHardwareIndex(),
418 GetHitCount(),
419 GetOptionsNoCreate()->GetIgnoreCount());
Chris Lattner24943d22010-06-08 16:52:24 +0000420}