1 //===-- 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 26 using namespace lldb; 27 using namespace lldb_private; 28 29 BreakpointLocation::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 45 BreakpointLocation::~BreakpointLocation() 46 { 47 ClearBreakpointSite(); 48 } 49 50 lldb::addr_t 51 BreakpointLocation::GetLoadAddress () 52 { 53 return m_address.GetLoadAddress(m_owner.GetTarget().GetProcessSP().get()); 54 } 55 56 Address & 57 BreakpointLocation::GetAddress () 58 { 59 return m_address; 60 } 61 62 Breakpoint & 63 BreakpointLocation::GetBreakpoint () 64 { 65 return m_owner; 66 } 67 68 bool 69 BreakpointLocation::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 79 void 80 BreakpointLocation::SetEnabled (bool enabled) 81 { 82 GetLocationOptions()->SetEnabled(enabled); 83 if (enabled) 84 { 85 ResolveBreakpointSite(); 86 } 87 else 88 { 89 ClearBreakpointSite(); 90 } 91 } 92 93 void 94 BreakpointLocation::SetThreadID (lldb::tid_t thread_id) 95 { 96 GetLocationOptions()->SetThreadID(thread_id); 97 } 98 99 lldb::tid_t 100 BreakpointLocation::GetThreadID () 101 { 102 return GetOptionsNoCopy()->GetThreadID(); 103 } 104 105 bool 106 BreakpointLocation::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 119 void 120 BreakpointLocation::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 128 void 129 BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp, 130 bool is_synchronous) 131 { 132 GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous); 133 } 134 135 void 136 BreakpointLocation::ClearCallback () 137 { 138 GetLocationOptions()->ClearCallback(); 139 } 140 141 int32_t 142 BreakpointLocation::GetIgnoreCount () 143 { 144 return GetOptionsNoCopy()->GetIgnoreCount(); 145 } 146 147 void 148 BreakpointLocation::SetIgnoreCount (int32_t n) 149 { 150 GetLocationOptions()->SetIgnoreCount(n); 151 } 152 153 BreakpointOptions * 154 BreakpointLocation::GetOptionsNoCopy () 155 { 156 if (m_options_ap.get() != NULL) 157 return m_options_ap.get(); 158 else 159 return m_owner.GetOptions (); 160 } 161 162 BreakpointOptions * 163 BreakpointLocation::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 174 bool 175 BreakpointLocation::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 208 bool 209 BreakpointLocation::IsResolved () const 210 { 211 return m_bp_site_sp.get() != NULL; 212 } 213 214 bool 215 BreakpointLocation::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 240 bool 241 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp) 242 { 243 m_bp_site_sp = bp_site_sp; 244 return true; 245 } 246 247 bool 248 BreakpointLocation::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 259 void 260 BreakpointLocation::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 374 void 375 BreakpointLocation::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 } 390