blob: dc45654a77caea793876424824892ccd4385d472 [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"
21#include "lldb/Target/Process.h"
22#include "lldb/Core/StreamString.h"
23#include "lldb/lldb-private-log.h"
24#include "lldb/Target/Thread.h"
Jim Ingham3c7b5b92010-06-16 02:00:15 +000025#include "lldb/Target/ThreadSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000026
27using namespace lldb;
28using namespace lldb_private;
29
30BreakpointLocation::BreakpointLocation
31(
32 break_id_t loc_id,
33 Breakpoint &owner,
34 Address &addr,
35 lldb::tid_t tid,
36 bool hardware
37) :
Greg Claytoneea26402010-09-14 23:36:40 +000038 StoppointLocation (loc_id, addr.GetLoadAddress(&owner.GetTarget()), hardware),
Chris Lattner24943d22010-06-08 16:52:24 +000039 m_address (addr),
40 m_owner (owner),
41 m_options_ap (),
42 m_bp_site_sp ()
43{
Jim Ingham3c7b5b92010-06-16 02:00:15 +000044 SetThreadID (tid);
Chris Lattner24943d22010-06-08 16:52:24 +000045}
46
47BreakpointLocation::~BreakpointLocation()
48{
49 ClearBreakpointSite();
50}
51
52lldb::addr_t
Greg Clayton273a8e52010-06-14 04:18:27 +000053BreakpointLocation::GetLoadAddress () const
Chris Lattner24943d22010-06-08 16:52:24 +000054{
Greg Claytoneea26402010-09-14 23:36:40 +000055 return m_address.GetLoadAddress(&m_owner.GetTarget());
Chris Lattner24943d22010-06-08 16:52:24 +000056}
57
58Address &
59BreakpointLocation::GetAddress ()
60{
61 return m_address;
62}
63
64Breakpoint &
65BreakpointLocation::GetBreakpoint ()
66{
67 return m_owner;
68}
69
70bool
71BreakpointLocation::IsEnabled ()
72{
73 if (!m_owner.IsEnabled())
74 return false;
75 else if (m_options_ap.get() != NULL)
76 return m_options_ap->IsEnabled();
77 else
78 return true;
79}
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
134void
135BreakpointLocation::ClearCallback ()
136{
137 GetLocationOptions()->ClearCallback();
138}
139
Greg Clayton54e7afa2010-07-09 20:39:50 +0000140uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000141BreakpointLocation::GetIgnoreCount ()
142{
Jim Ingham9c6898b2010-06-22 21:12:54 +0000143 return GetOptionsNoCreate()->GetIgnoreCount();
Chris Lattner24943d22010-06-08 16:52:24 +0000144}
145
146void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000147BreakpointLocation::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000148{
149 GetLocationOptions()->SetIgnoreCount(n);
150}
151
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000152const BreakpointOptions *
Jim Ingham9c6898b2010-06-22 21:12:54 +0000153BreakpointLocation::GetOptionsNoCreate () const
Chris Lattner24943d22010-06-08 16:52:24 +0000154{
155 if (m_options_ap.get() != NULL)
156 return m_options_ap.get();
157 else
158 return m_owner.GetOptions ();
159}
160
161BreakpointOptions *
162BreakpointLocation::GetLocationOptions ()
163{
Jim Ingham649492b2010-06-18 01:00:58 +0000164 // If we make the copy we don't copy the callbacks because that is potentially
165 // expensive and we don't want to do that for the simple case where someone is
166 // just disabling the location.
Chris Lattner24943d22010-06-08 16:52:24 +0000167 if (m_options_ap.get() == NULL)
Jim Ingham649492b2010-06-18 01:00:58 +0000168 m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
169
Chris Lattner24943d22010-06-08 16:52:24 +0000170 return m_options_ap.get();
171}
172
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000173bool
174BreakpointLocation::ValidForThisThread (Thread *thread)
175{
Jim Ingham9c6898b2010-06-22 21:12:54 +0000176 return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000177}
178
Chris Lattner24943d22010-06-08 16:52:24 +0000179// RETURNS - true if we should stop at this breakpoint, false if we
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000180// should continue. Note, we don't check the thread spec for the breakpoint
181// here, since if the breakpoint is not for this thread, then the event won't
182// even get reported, so the check is redundant.
Chris Lattner24943d22010-06-08 16:52:24 +0000183
184bool
185BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
186{
187 bool should_stop = true;
188
189 m_hit_count++;
190
191 if (!IsEnabled())
192 return false;
193
Chris Lattner24943d22010-06-08 16:52:24 +0000194 if (m_hit_count <= GetIgnoreCount())
195 return false;
196
197 // Tell if the callback is synchronous here.
198 context->is_synchronous = true;
199 should_stop = InvokeCallback (context);
200
201 if (should_stop)
202 {
203 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
204 if (log)
205 {
206 StreamString s;
207 GetDescription (&s, lldb::eDescriptionLevelVerbose);
208 log->Printf ("Hit breakpoint location: %s\n", s.GetData());
209 }
210 }
211 return should_stop;
212}
213
214bool
215BreakpointLocation::IsResolved () const
216{
217 return m_bp_site_sp.get() != NULL;
218}
219
220bool
221BreakpointLocation::ResolveBreakpointSite ()
222{
223 if (m_bp_site_sp)
224 return true;
225
Greg Claytoneea26402010-09-14 23:36:40 +0000226 Process *process = m_owner.GetTarget().GetProcessSP().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000227 if (process == NULL)
228 return false;
229
Greg Claytoneea26402010-09-14 23:36:40 +0000230 if (m_owner.GetTarget().GetSectionLoadList().IsEmpty())
231 return false;
232
Chris Lattner24943d22010-06-08 16:52:24 +0000233 BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this));
234
Stephen Wilson3fd1f362010-07-17 00:56:13 +0000235 lldb::break_id_t new_id = process->CreateBreakpointSite (myself_sp, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000236
Stephen Wilson3fd1f362010-07-17 00:56:13 +0000237 if (new_id == LLDB_INVALID_BREAK_ID)
Chris Lattner24943d22010-06-08 16:52:24 +0000238 {
239 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
240 if (log)
241 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
Greg Claytoneea26402010-09-14 23:36:40 +0000242 m_address.GetLoadAddress(&m_owner.GetTarget()));
Chris Lattner24943d22010-06-08 16:52:24 +0000243 return false;
244 }
245
246 return true;
247}
248
249bool
250BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
251{
252 m_bp_site_sp = bp_site_sp;
253 return true;
254}
255
256bool
257BreakpointLocation::ClearBreakpointSite ()
258{
259 if (m_bp_site_sp.get())
260 {
Jim Ingham649492b2010-06-18 01:00:58 +0000261 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
262 GetID(), m_bp_site_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000263 m_bp_site_sp.reset();
264 return true;
265 }
266 return false;
267}
268
269void
270BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
271{
272 SymbolContext sc;
273 s->Indent();
274 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
275
276 if (level == lldb::eDescriptionLevelBrief)
277 return;
278
279 s->PutCString(": ");
280
281 if (level == lldb::eDescriptionLevelVerbose)
282 s->IndentMore();
283
284 if (m_address.IsSectionOffset())
285 {
286 m_address.CalculateSymbolContext(&sc);
287
288 if (level == lldb::eDescriptionLevelFull)
289 {
290 s->PutCString("where = ");
Greg Clayton5205f0b2010-09-03 17:10:42 +0000291 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000292 }
293 else
294 {
295 if (sc.module_sp)
296 {
297 s->EOL();
298 s->Indent("module = ");
299 sc.module_sp->GetFileSpec().Dump (s);
300 }
301
302 if (sc.comp_unit != NULL)
303 {
304 s->EOL();
305 s->Indent("compile unit = ");
306 dynamic_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
307
308 if (sc.function != NULL)
309 {
310 s->EOL();
311 s->Indent("function = ");
312 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
313 }
314
315 if (sc.line_entry.line > 0)
316 {
317 s->EOL();
318 s->Indent("location = ");
Greg Clayton72b71582010-09-02 21:44:10 +0000319 sc.line_entry.DumpStopContext (s, true);
Chris Lattner24943d22010-06-08 16:52:24 +0000320 }
321
322 }
323 else
324 {
325 // If we don't have a comp unit, see if we have a symbol we can print.
326 if (sc.symbol)
327 {
328 s->EOL();
329 s->Indent("symbol = ");
330 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
331 }
332 }
333 }
334 }
335
336 if (level == lldb::eDescriptionLevelVerbose)
337 {
338 s->EOL();
339 s->Indent();
340 }
341 s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : "");
342 ExecutionContextScope *exe_scope = NULL;
343 Target *target = &m_owner.GetTarget();
344 if (target)
345 exe_scope = target->GetProcessSP().get();
346 if (exe_scope == NULL)
347 exe_scope = target;
348
349 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
350
351 if (level == lldb::eDescriptionLevelVerbose)
352 {
353 s->EOL();
354 s->Indent();
355 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
356
357 s->Indent();
Chris Lattner24943d22010-06-08 16:52:24 +0000358 s->Printf ("hit count = %-4u\n", GetHitCount());
359
360 if (m_options_ap.get())
361 {
Jim Ingham649492b2010-06-18 01:00:58 +0000362 s->Indent();
363 m_options_ap->GetDescription (s, level);
364 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000365 }
366 s->IndentLess();
367 }
368 else
369 {
Jim Ingham649492b2010-06-18 01:00:58 +0000370 s->Printf(", %sresolved, hit count = %u ",
Chris Lattner24943d22010-06-08 16:52:24 +0000371 (IsResolved() ? "" : "un"),
Chris Lattner24943d22010-06-08 16:52:24 +0000372 GetHitCount());
Jim Ingham649492b2010-06-18 01:00:58 +0000373 if (m_options_ap.get())
374 {
375 m_options_ap->GetDescription (s, level);
376 }
Chris Lattner24943d22010-06-08 16:52:24 +0000377 }
378}
379
380void
381BreakpointLocation::Dump(Stream *s) const
382{
383 if (s == NULL)
384 return;
385
Jim Ingham649492b2010-06-18 01:00:58 +0000386 s->Printf("BreakpointLocation %u: tid = %4.4x load addr = 0x%8.8llx state = %s type = %s breakpoint "
387 "hw_index = %i hit_count = %-4u ignore_count = %-4u",
Chris Lattner24943d22010-06-08 16:52:24 +0000388 GetID(),
Jim Ingham9c6898b2010-06-22 21:12:54 +0000389 GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
Greg Claytoneea26402010-09-14 23:36:40 +0000390 (uint64_t) m_address.GetLoadAddress (&m_owner.GetTarget()),
Chris Lattner24943d22010-06-08 16:52:24 +0000391 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
392 IsHardware() ? "hardware" : "software",
393 GetHardwareIndex(),
394 GetHitCount(),
395 m_options_ap.get() ? m_options_ap->GetIgnoreCount() : m_owner.GetIgnoreCount());
396}