blob: 525efd36ea16d75b0b72cb322789ec7d45a3e810 [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;
Jim Inghamd1686902010-10-14 23:45:03 +0000212 Log *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));
234 if (log && errors.GetSize() > 0)
235 {
236 log->Printf("Error evaluating condition: \"%s\".\n", errors.GetData());
237 }
238 else if (condition_plan_sp != NULL)
239 {
240 context->exe_ctx.thread->QueueThreadPlan(condition_plan_sp, false);
241 return false;
242 }
243 }
244
245 if (should_stop)
246 {
Chris Lattner24943d22010-06-08 16:52:24 +0000247 if (log)
248 {
249 StreamString s;
250 GetDescription (&s, lldb::eDescriptionLevelVerbose);
251 log->Printf ("Hit breakpoint location: %s\n", s.GetData());
252 }
253 }
254 return should_stop;
255}
256
257bool
258BreakpointLocation::IsResolved () const
259{
260 return m_bp_site_sp.get() != NULL;
261}
262
Jim Inghamd1686902010-10-14 23:45:03 +0000263lldb::BreakpointSiteSP
264BreakpointLocation::GetBreakpointSite() const
265{
266 return m_bp_site_sp;
267}
268
Chris Lattner24943d22010-06-08 16:52:24 +0000269bool
270BreakpointLocation::ResolveBreakpointSite ()
271{
272 if (m_bp_site_sp)
273 return true;
274
Greg Claytoneea26402010-09-14 23:36:40 +0000275 Process *process = m_owner.GetTarget().GetProcessSP().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000276 if (process == NULL)
277 return false;
278
Greg Claytoneea26402010-09-14 23:36:40 +0000279 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty())
280 return false;
281
Chris Lattner24943d22010-06-08 16:52:24 +0000282 BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this));
283
Stephen Wilson3fd1f362010-07-17 00:56:13 +0000284 lldb::break_id_t new_id = process->CreateBreakpointSite (myself_sp, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000285
Stephen Wilson3fd1f362010-07-17 00:56:13 +0000286 if (new_id == LLDB_INVALID_BREAK_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000287 {
288 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
289 if (log)
290 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
Greg Claytoneea26402010-09-14 23:36:40 +0000291 m_address.GetLoadAddress(&m_owner.GetTarget()));
Chris Lattner24943d22010-06-08 16:52:24 +0000292 return false;
293 }
294
295 return true;
296}
297
298bool
299BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
300{
301 m_bp_site_sp = bp_site_sp;
302 return true;
303}
304
305bool
306BreakpointLocation::ClearBreakpointSite ()
307{
308 if (m_bp_site_sp.get())
309 {
Jim Ingham649492b2010-06-18 01:00:58 +0000310 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
311 GetID(), m_bp_site_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000312 m_bp_site_sp.reset();
313 return true;
314 }
315 return false;
316}
317
318void
319BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
320{
321 SymbolContext sc;
322 s->Indent();
323 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
324
325 if (level == lldb::eDescriptionLevelBrief)
326 return;
327
328 s->PutCString(": ");
329
330 if (level == lldb::eDescriptionLevelVerbose)
331 s->IndentMore();
332
333 if (m_address.IsSectionOffset())
334 {
335 m_address.CalculateSymbolContext(&sc);
336
337 if (level == lldb::eDescriptionLevelFull)
338 {
339 s->PutCString("where = ");
Greg Clayton5205f0b2010-09-03 17:10:42 +0000340 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000341 }
342 else
343 {
344 if (sc.module_sp)
345 {
346 s->EOL();
347 s->Indent("module = ");
348 sc.module_sp->GetFileSpec().Dump (s);
349 }
350
351 if (sc.comp_unit != NULL)
352 {
353 s->EOL();
354 s->Indent("compile unit = ");
Jim Ingham7ea35232010-10-27 22:58:34 +0000355 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
Chris Lattner24943d22010-06-08 16:52:24 +0000356
357 if (sc.function != NULL)
358 {
359 s->EOL();
360 s->Indent("function = ");
361 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
362 }
363
364 if (sc.line_entry.line > 0)
365 {
366 s->EOL();
367 s->Indent("location = ");
Greg Clayton72b71582010-09-02 21:44:10 +0000368 sc.line_entry.DumpStopContext (s, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000369 }
370
371 }
372 else
373 {
374 // If we don't have a comp unit, see if we have a symbol we can print.
375 if (sc.symbol)
376 {
377 s->EOL();
378 s->Indent("symbol = ");
379 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
380 }
381 }
382 }
383 }
384
385 if (level == lldb::eDescriptionLevelVerbose)
386 {
387 s->EOL();
388 s->Indent();
389 }
390 s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : "");
391 ExecutionContextScope *exe_scope = NULL;
392 Target *target = &m_owner.GetTarget();
393 if (target)
394 exe_scope = target->GetProcessSP().get();
395 if (exe_scope == NULL)
396 exe_scope = target;
397
398 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
399
400 if (level == lldb::eDescriptionLevelVerbose)
401 {
402 s->EOL();
403 s->Indent();
404 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
405
406 s->Indent();
Chris Lattner24943d22010-06-08 16:52:24 +0000407 s->Printf ("hit count = %-4u\n", GetHitCount());
408
409 if (m_options_ap.get())
410 {
Jim Ingham649492b2010-06-18 01:00:58 +0000411 s->Indent();
412 m_options_ap->GetDescription (s, level);
413 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000414 }
415 s->IndentLess();
416 }
417 else
418 {
Jim Ingham649492b2010-06-18 01:00:58 +0000419 s->Printf(", %sresolved, hit count = %u ",
Chris Lattner24943d22010-06-08 16:52:24 +0000420 (IsResolved() ? "" : "un"),
Chris Lattner24943d22010-06-08 16:52:24 +0000421 GetHitCount());
Jim Ingham649492b2010-06-18 01:00:58 +0000422 if (m_options_ap.get())
423 {
424 m_options_ap->GetDescription (s, level);
425 }
Chris Lattner24943d22010-06-08 16:52:24 +0000426 }
427}
428
429void
430BreakpointLocation::Dump(Stream *s) const
431{
432 if (s == NULL)
433 return;
434
Jim Ingham649492b2010-06-18 01:00:58 +0000435 s->Printf("BreakpointLocation %u: tid = %4.4x load addr = 0x%8.8llx state = %s type = %s breakpoint "
436 "hw_index = %i hit_count = %-4u ignore_count = %-4u",
Chris Lattner24943d22010-06-08 16:52:24 +0000437 GetID(),
Jim Ingham9c6898b2010-06-22 21:12:54 +0000438 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
Greg Claytoneea26402010-09-14 23:36:40 +0000439 (uint64_t) m_address.GetLoadAddress (&m_owner.GetTarget()),
Chris Lattner24943d22010-06-08 16:52:24 +0000440 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
441 IsHardware() ? "hardware" : "software",
442 GetHardwareIndex(),
443 GetHitCount(),
444 m_options_ap.get() ? m_options_ap->GetIgnoreCount() : m_owner.GetIgnoreCount());
445}