blob: 5c0e81df38119bc7739c85f83337e3f20bdd425b [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"
25
26using namespace lldb;
27using namespace lldb_private;
28
29BreakpointLocation::BreakpointLocation
30(
31 break_id_t loc_id,
32 Breakpoint &owner,
33 Address &addr,
34 lldb::tid_t tid,
35 bool hardware
36) :
37 StoppointLocation (loc_id, addr.GetLoadAddress(owner.GetTarget().GetProcessSP().get()), tid, hardware),
38 m_address (addr),
39 m_owner (owner),
40 m_options_ap (),
41 m_bp_site_sp ()
42{
43}
44
45BreakpointLocation::~BreakpointLocation()
46{
47 ClearBreakpointSite();
48}
49
50lldb::addr_t
51BreakpointLocation::GetLoadAddress ()
52{
53 return m_address.GetLoadAddress(m_owner.GetTarget().GetProcessSP().get());
54}
55
56Address &
57BreakpointLocation::GetAddress ()
58{
59 return m_address;
60}
61
62Breakpoint &
63BreakpointLocation::GetBreakpoint ()
64{
65 return m_owner;
66}
67
68bool
69BreakpointLocation::IsEnabled ()
70{
71 if (!m_owner.IsEnabled())
72 return false;
73 else if (m_options_ap.get() != NULL)
74 return m_options_ap->IsEnabled();
75 else
76 return true;
77}
78
79void
80BreakpointLocation::SetEnabled (bool enabled)
81{
82 GetLocationOptions()->SetEnabled(enabled);
83 if (enabled)
84 {
85 ResolveBreakpointSite();
86 }
87 else
88 {
89 ClearBreakpointSite();
90 }
91}
92
93void
94BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
95{
96 GetLocationOptions()->SetThreadID(thread_id);
97}
98
99lldb::tid_t
100BreakpointLocation::GetThreadID ()
101{
102 return GetOptionsNoCopy()->GetThreadID();
103}
104
105bool
106BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
107{
108 bool owner_result;
109
110 owner_result = m_owner.InvokeCallback (context, GetID());
111 if (owner_result == false)
112 return false;
113 else if (m_options_ap.get() != NULL)
114 return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
115 else
116 return true;
117}
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
135void
136BreakpointLocation::ClearCallback ()
137{
138 GetLocationOptions()->ClearCallback();
139}
140
141int32_t
142BreakpointLocation::GetIgnoreCount ()
143{
144 return GetOptionsNoCopy()->GetIgnoreCount();
145}
146
147void
148BreakpointLocation::SetIgnoreCount (int32_t n)
149{
150 GetLocationOptions()->SetIgnoreCount(n);
151}
152
153BreakpointOptions *
154BreakpointLocation::GetOptionsNoCopy ()
155{
156 if (m_options_ap.get() != NULL)
157 return m_options_ap.get();
158 else
159 return m_owner.GetOptions ();
160}
161
162BreakpointOptions *
163BreakpointLocation::GetLocationOptions ()
164{
165 if (m_options_ap.get() == NULL)
166 m_options_ap.reset(new BreakpointOptions (*m_owner.GetOptions ()));
167
168 return m_options_ap.get();
169}
170
171// RETURNS - true if we should stop at this breakpoint, false if we
172// should continue.
173
174bool
175BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
176{
177 bool should_stop = true;
178
179 m_hit_count++;
180
181 if (!IsEnabled())
182 return false;
183
184 if (GetThreadID() != LLDB_INVALID_THREAD_ID
185 && context->context.thread->GetID() != GetThreadID())
186 return false;
187
188 if (m_hit_count <= GetIgnoreCount())
189 return false;
190
191 // Tell if the callback is synchronous here.
192 context->is_synchronous = true;
193 should_stop = InvokeCallback (context);
194
195 if (should_stop)
196 {
197 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
198 if (log)
199 {
200 StreamString s;
201 GetDescription (&s, lldb::eDescriptionLevelVerbose);
202 log->Printf ("Hit breakpoint location: %s\n", s.GetData());
203 }
204 }
205 return should_stop;
206}
207
208bool
209BreakpointLocation::IsResolved () const
210{
211 return m_bp_site_sp.get() != NULL;
212}
213
214bool
215BreakpointLocation::ResolveBreakpointSite ()
216{
217 if (m_bp_site_sp)
218 return true;
219
220 Process* process = m_owner.GetTarget().GetProcessSP().get();
221 if (process == NULL)
222 return false;
223
224 BreakpointLocationSP myself_sp(m_owner.GetLocationSP (this));
225
226 lldb::user_id_t new_id = process->CreateBreakpointSite (myself_sp, false);
227
228 if (new_id == LLDB_INVALID_UID)
229 {
230 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
231 if (log)
232 log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
233 m_address.GetLoadAddress(process));
234 return false;
235 }
236
237 return true;
238}
239
240bool
241BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
242{
243 m_bp_site_sp = bp_site_sp;
244 return true;
245}
246
247bool
248BreakpointLocation::ClearBreakpointSite ()
249{
250 if (m_bp_site_sp.get())
251 {
252 m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(), GetID(), m_bp_site_sp);
253 m_bp_site_sp.reset();
254 return true;
255 }
256 return false;
257}
258
259void
260BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
261{
262 SymbolContext sc;
263 s->Indent();
264 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
265
266 if (level == lldb::eDescriptionLevelBrief)
267 return;
268
269 s->PutCString(": ");
270
271 if (level == lldb::eDescriptionLevelVerbose)
272 s->IndentMore();
273
274 if (m_address.IsSectionOffset())
275 {
276 m_address.CalculateSymbolContext(&sc);
277
278 if (level == lldb::eDescriptionLevelFull)
279 {
280 s->PutCString("where = ");
281 sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address);
282 }
283 else
284 {
285 if (sc.module_sp)
286 {
287 s->EOL();
288 s->Indent("module = ");
289 sc.module_sp->GetFileSpec().Dump (s);
290 }
291
292 if (sc.comp_unit != NULL)
293 {
294 s->EOL();
295 s->Indent("compile unit = ");
296 dynamic_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
297
298 if (sc.function != NULL)
299 {
300 s->EOL();
301 s->Indent("function = ");
302 s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
303 }
304
305 if (sc.line_entry.line > 0)
306 {
307 s->EOL();
308 s->Indent("location = ");
309 sc.line_entry.DumpStopContext (s);
310 }
311
312 }
313 else
314 {
315 // If we don't have a comp unit, see if we have a symbol we can print.
316 if (sc.symbol)
317 {
318 s->EOL();
319 s->Indent("symbol = ");
320 s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
321 }
322 }
323 }
324 }
325
326 if (level == lldb::eDescriptionLevelVerbose)
327 {
328 s->EOL();
329 s->Indent();
330 }
331 s->Printf ("%saddress = ", (level == lldb::eDescriptionLevelFull && m_address.IsSectionOffset()) ? ", " : "");
332 ExecutionContextScope *exe_scope = NULL;
333 Target *target = &m_owner.GetTarget();
334 if (target)
335 exe_scope = target->GetProcessSP().get();
336 if (exe_scope == NULL)
337 exe_scope = target;
338
339 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
340
341 if (level == lldb::eDescriptionLevelVerbose)
342 {
343 s->EOL();
344 s->Indent();
345 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
346
347 s->Indent();
348 s->Printf("enabled = %s\n", IsEnabled() ? "true" : "false");
349
350 s->Indent();
351 s->Printf ("hit count = %-4u\n", GetHitCount());
352
353 if (m_options_ap.get())
354 {
355 Baton *baton = m_options_ap->GetBaton();
356 if (baton)
357 {
358 s->Indent();
359 baton->GetDescription (s, level);
360 s->EOL();
361 }
362 }
363 s->IndentLess();
364 }
365 else
366 {
367 s->Printf(", %sresolved, %s, hit count = %u",
368 (IsResolved() ? "" : "un"),
369 (IsEnabled() ? "enabled" : "disabled"),
370 GetHitCount());
371 }
372}
373
374void
375BreakpointLocation::Dump(Stream *s) const
376{
377 if (s == NULL)
378 return;
379
380 s->Printf("BreakpointLocation %u: tid = %4.4x load addr = 0x%8.8llx state = %s type = %s breakpoint hw_index = %i hit_count = %-4u ignore_count = %-4u",
381 GetID(),
382 m_tid,
383 (uint64_t) m_address.GetLoadAddress(m_owner.GetTarget().GetProcessSP().get()),
384 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
385 IsHardware() ? "hardware" : "software",
386 GetHardwareIndex(),
387 GetHitCount(),
388 m_options_ap.get() ? m_options_ap->GetIgnoreCount() : m_owner.GetIgnoreCount());
389}