1 //===-- Breakpoint.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 11 // C Includes 12 // C++ Includes 13 // Other libraries and framework includes 14 // Project includes 15 16 #include "lldb/Core/Address.h" 17 #include "lldb/Breakpoint/Breakpoint.h" 18 #include "lldb/Breakpoint/BreakpointLocation.h" 19 #include "lldb/Breakpoint/BreakpointLocationCollection.h" 20 #include "lldb/Breakpoint/BreakpointResolver.h" 21 #include "lldb/Breakpoint/BreakpointResolverFileLine.h" 22 #include "lldb/Core/Log.h" 23 #include "lldb/Core/ModuleList.h" 24 #include "lldb/Core/SearchFilter.h" 25 #include "lldb/Core/Stream.h" 26 #include "lldb/Core/StreamString.h" 27 #include "lldb/Symbol/SymbolContext.h" 28 #include "lldb/Target/Target.h" 29 #include "lldb/Target/ThreadSpec.h" 30 #include "lldb/lldb-private-log.h" 31 #include "llvm/Support/Casting.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 using namespace llvm; 36 37 const ConstString & 38 Breakpoint::GetEventIdentifier () 39 { 40 static ConstString g_identifier("event-identifier.breakpoint.changed"); 41 return g_identifier; 42 } 43 44 //---------------------------------------------------------------------- 45 // Breakpoint constructor 46 //---------------------------------------------------------------------- 47 Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) : 48 m_target (target), 49 m_filter_sp (filter_sp), 50 m_resolver_sp (resolver_sp), 51 m_options (), 52 m_locations () 53 { 54 } 55 56 //---------------------------------------------------------------------- 57 // Destructor 58 //---------------------------------------------------------------------- 59 Breakpoint::~Breakpoint() 60 { 61 } 62 63 bool 64 Breakpoint::IsInternal () const 65 { 66 return LLDB_BREAK_ID_IS_INTERNAL(m_bid); 67 } 68 69 70 71 Target& 72 Breakpoint::GetTarget () 73 { 74 return m_target; 75 } 76 77 const Target& 78 Breakpoint::GetTarget () const 79 { 80 return m_target; 81 } 82 83 BreakpointLocationSP 84 Breakpoint::AddLocation (const Address &addr, bool *new_location) 85 { 86 if (new_location) 87 *new_location = false; 88 BreakpointLocationSP bp_loc_sp (m_locations.FindByAddress(addr)); 89 if (!bp_loc_sp) 90 { 91 bp_loc_sp = m_locations.Create (*this, addr); 92 if (bp_loc_sp) 93 { 94 bp_loc_sp->ResolveBreakpointSite(); 95 96 if (new_location) 97 *new_location = true; 98 } 99 } 100 return bp_loc_sp; 101 } 102 103 BreakpointLocationSP 104 Breakpoint::FindLocationByAddress (const Address &addr) 105 { 106 return m_locations.FindByAddress(addr); 107 } 108 109 break_id_t 110 Breakpoint::FindLocationIDByAddress (const Address &addr) 111 { 112 return m_locations.FindIDByAddress(addr); 113 } 114 115 BreakpointLocationSP 116 Breakpoint::FindLocationByID (break_id_t bp_loc_id) 117 { 118 return m_locations.FindByID(bp_loc_id); 119 } 120 121 BreakpointLocationSP 122 Breakpoint::GetLocationAtIndex (uint32_t index) 123 { 124 return m_locations.GetByIndex(index); 125 } 126 127 // For each of the overall options we need to decide how they propagate to 128 // the location options. This will determine the precedence of options on 129 // the breakpoint vrs. its locations. 130 131 // Disable at the breakpoint level should override the location settings. 132 // That way you can conveniently turn off a whole breakpoint without messing 133 // up the individual settings. 134 135 void 136 Breakpoint::SetEnabled (bool enable) 137 { 138 m_options.SetEnabled(enable); 139 if (enable) 140 m_locations.ResolveAllBreakpointSites(); 141 else 142 m_locations.ClearAllBreakpointSites(); 143 } 144 145 bool 146 Breakpoint::IsEnabled () 147 { 148 return m_options.IsEnabled(); 149 } 150 151 void 152 Breakpoint::SetIgnoreCount (uint32_t n) 153 { 154 m_options.SetIgnoreCount(n); 155 } 156 157 uint32_t 158 Breakpoint::GetIgnoreCount () const 159 { 160 return m_options.GetIgnoreCount(); 161 } 162 163 uint32_t 164 Breakpoint::GetHitCount () const 165 { 166 return m_locations.GetHitCount(); 167 } 168 169 void 170 Breakpoint::SetThreadID (lldb::tid_t thread_id) 171 { 172 m_options.GetThreadSpec()->SetTID(thread_id); 173 } 174 175 lldb::tid_t 176 Breakpoint::GetThreadID () 177 { 178 if (m_options.GetThreadSpec() == NULL) 179 return LLDB_INVALID_THREAD_ID; 180 else 181 return m_options.GetThreadSpec()->GetTID(); 182 } 183 184 void 185 Breakpoint::SetCondition (const char *condition) 186 { 187 m_options.SetCondition (condition); 188 } 189 190 ThreadPlan * 191 Breakpoint::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, lldb::BreakpointLocationSP loc_sp, Stream &error) 192 { 193 return m_options.GetThreadPlanToTestCondition (exe_ctx, loc_sp, error); 194 } 195 196 const char * 197 Breakpoint::GetConditionText () const 198 { 199 return m_options.GetConditionText(); 200 } 201 202 // This function is used when "baton" doesn't need to be freed 203 void 204 Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous) 205 { 206 // The default "Baton" class will keep a copy of "baton" and won't free 207 // or delete it when it goes goes out of scope. 208 m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous); 209 } 210 211 // This function is used when a baton needs to be freed and therefore is 212 // contained in a "Baton" subclass. 213 void 214 Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous) 215 { 216 m_options.SetCallback(callback, callback_baton_sp, is_synchronous); 217 } 218 219 void 220 Breakpoint::ClearCallback () 221 { 222 m_options.ClearCallback (); 223 } 224 225 bool 226 Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id) 227 { 228 return m_options.InvokeCallback (context, GetID(), bp_loc_id); 229 } 230 231 BreakpointOptions * 232 Breakpoint::GetOptions () 233 { 234 return &m_options; 235 } 236 237 void 238 Breakpoint::ResolveBreakpoint () 239 { 240 if (m_resolver_sp) 241 m_resolver_sp->ResolveBreakpoint(*m_filter_sp); 242 } 243 244 void 245 Breakpoint::ResolveBreakpointInModules (ModuleList &module_list) 246 { 247 if (m_resolver_sp) 248 m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list); 249 } 250 251 void 252 Breakpoint::ClearAllBreakpointSites () 253 { 254 m_locations.ClearAllBreakpointSites(); 255 } 256 257 //---------------------------------------------------------------------- 258 // ModulesChanged: Pass in a list of new modules, and 259 //---------------------------------------------------------------------- 260 261 void 262 Breakpoint::ModulesChanged (ModuleList &module_list, bool load) 263 { 264 if (load) 265 { 266 // The logic for handling new modules is: 267 // 1) If the filter rejects this module, then skip it. 268 // 2) Run through the current location list and if there are any locations 269 // for that module, we mark the module as "seen" and we don't try to re-resolve 270 // breakpoint locations for that module. 271 // However, we do add breakpoint sites to these locations if needed. 272 // 3) If we don't see this module in our breakpoint location list, call ResolveInModules. 273 274 ModuleList new_modules; // We'll stuff the "unseen" modules in this list, and then resolve 275 // them after the locations pass. Have to do it this way because 276 // resolving breakpoints will add new locations potentially. 277 278 const size_t num_locs = m_locations.GetSize(); 279 280 for (size_t i = 0; i < module_list.GetSize(); i++) 281 { 282 bool seen = false; 283 ModuleSP module_sp (module_list.GetModuleAtIndex (i)); 284 if (!m_filter_sp->ModulePasses (module_sp)) 285 continue; 286 287 for (size_t loc_idx = 0; loc_idx < num_locs; loc_idx++) 288 { 289 BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx); 290 if (!break_loc->IsEnabled()) 291 continue; 292 const Section *section = break_loc->GetAddress().GetSection(); 293 if (section == NULL || section->GetModule() == module_sp.get()) 294 { 295 if (!seen) 296 seen = true; 297 298 if (!break_loc->ResolveBreakpointSite()) 299 { 300 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); 301 if (log) 302 log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n", 303 break_loc->GetID(), GetID()); 304 } 305 } 306 } 307 308 if (!seen) 309 new_modules.AppendIfNeeded (module_sp); 310 311 } 312 if (new_modules.GetSize() > 0) 313 { 314 ResolveBreakpointInModules(new_modules); 315 } 316 } 317 else 318 { 319 // Go through the currently set locations and if any have breakpoints in 320 // the module list, then remove their breakpoint sites. 321 // FIXME: Think about this... Maybe it's better to delete the locations? 322 // Are we sure that on load-unload-reload the module pointer will remain 323 // the same? Or do we need to do an equality on modules that is an 324 // "equivalence"??? 325 326 for (size_t i = 0; i < module_list.GetSize(); i++) 327 { 328 ModuleSP module_sp (module_list.GetModuleAtIndex (i)); 329 if (m_filter_sp->ModulePasses (module_sp)) 330 { 331 const size_t num_locs = m_locations.GetSize(); 332 for (size_t loc_idx = 0; loc_idx < num_locs; ++loc_idx) 333 { 334 BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx); 335 const Section *section = break_loc->GetAddress().GetSection(); 336 if (section && section->GetModule() == module_sp.get()) 337 { 338 // Remove this breakpoint since the shared library is 339 // unloaded, but keep the breakpoint location around 340 // so we always get complete hit count and breakpoint 341 // lifetime info 342 break_loc->ClearBreakpointSite(); 343 } 344 } 345 } 346 } 347 } 348 } 349 350 void 351 Breakpoint::Dump (Stream *) 352 { 353 } 354 355 size_t 356 Breakpoint::GetNumResolvedLocations() const 357 { 358 // Return the number of breakpoints that are actually resolved and set 359 // down in the inferior process. 360 return m_locations.GetNumResolvedLocations(); 361 } 362 363 size_t 364 Breakpoint::GetNumLocations() const 365 { 366 return m_locations.GetSize(); 367 } 368 369 void 370 Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations) 371 { 372 assert (s != NULL); 373 s->Printf("%i: ", GetID()); 374 GetResolverDescription (s); 375 GetFilterDescription (s); 376 377 const size_t num_locations = GetNumLocations (); 378 const size_t num_resolved_locations = GetNumResolvedLocations (); 379 380 switch (level) 381 { 382 case lldb::eDescriptionLevelBrief: 383 case lldb::eDescriptionLevelFull: 384 if (num_locations > 0) 385 { 386 s->Printf(", locations = %zu", num_locations); 387 if (num_resolved_locations > 0) 388 s->Printf(", resolved = %zu", num_resolved_locations); 389 } 390 else 391 { 392 s->Printf(", locations = 0 (pending)"); 393 } 394 395 GetOptions()->GetDescription(s, level); 396 397 if (level == lldb::eDescriptionLevelFull) 398 { 399 s->IndentLess(); 400 s->EOL(); 401 } 402 break; 403 404 case lldb::eDescriptionLevelVerbose: 405 // Verbose mode does a debug dump of the breakpoint 406 Dump (s); 407 s->EOL (); 408 //s->Indent(); 409 GetOptions()->GetDescription(s, level); 410 break; 411 412 default: 413 break; 414 } 415 416 // The brief description is just the location name (1.2 or whatever). That's pointless to 417 // show in the breakpoint's description, so suppress it. 418 if (show_locations && level != lldb::eDescriptionLevelBrief) 419 { 420 s->IndentMore(); 421 for (size_t i = 0; i < num_locations; ++i) 422 { 423 BreakpointLocation *loc = GetLocationAtIndex(i).get(); 424 loc->GetDescription(s, level); 425 s->EOL(); 426 } 427 s->IndentLess(); 428 } 429 } 430 431 Breakpoint::BreakpointEventData::BreakpointEventData (BreakpointEventType sub_type, 432 BreakpointSP &new_breakpoint_sp) : 433 EventData (), 434 m_breakpoint_event (sub_type), 435 m_new_breakpoint_sp (new_breakpoint_sp) 436 { 437 } 438 439 Breakpoint::BreakpointEventData::~BreakpointEventData () 440 { 441 } 442 443 const ConstString & 444 Breakpoint::BreakpointEventData::GetFlavorString () 445 { 446 static ConstString g_flavor ("Breakpoint::BreakpointEventData"); 447 return g_flavor; 448 } 449 450 const ConstString & 451 Breakpoint::BreakpointEventData::GetFlavor () const 452 { 453 return BreakpointEventData::GetFlavorString (); 454 } 455 456 457 BreakpointSP & 458 Breakpoint::BreakpointEventData::GetBreakpoint () 459 { 460 return m_new_breakpoint_sp; 461 } 462 463 BreakpointEventType 464 Breakpoint::BreakpointEventData::GetBreakpointEventType () const 465 { 466 return m_breakpoint_event; 467 } 468 469 void 470 Breakpoint::BreakpointEventData::Dump (Stream *s) const 471 { 472 } 473 474 Breakpoint::BreakpointEventData * 475 Breakpoint::BreakpointEventData::GetEventDataFromEvent (const EventSP &event_sp) 476 { 477 if (event_sp) 478 { 479 EventData *event_data = event_sp->GetData(); 480 if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString()) 481 return static_cast <BreakpointEventData *> (event_sp->GetData()); 482 } 483 return NULL; 484 } 485 486 BreakpointEventType 487 Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (const EventSP &event_sp) 488 { 489 BreakpointEventData *data = GetEventDataFromEvent (event_sp); 490 491 if (data == NULL) 492 return eBreakpointEventTypeInvalidType; 493 else 494 return data->GetBreakpointEventType(); 495 } 496 497 BreakpointSP 498 Breakpoint::BreakpointEventData::GetBreakpointFromEvent (const EventSP &event_sp) 499 { 500 BreakpointSP bp_sp; 501 502 BreakpointEventData *data = GetEventDataFromEvent (event_sp); 503 if (data) 504 bp_sp = data->GetBreakpoint(); 505 506 return bp_sp; 507 } 508 509 lldb::BreakpointLocationSP 510 Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (const lldb::EventSP &event_sp, uint32_t bp_loc_idx) 511 { 512 lldb::BreakpointLocationSP bp_loc_sp; 513 514 BreakpointEventData *data = GetEventDataFromEvent (event_sp); 515 if (data) 516 { 517 Breakpoint *bp = data->GetBreakpoint().get(); 518 if (bp) 519 bp_loc_sp = bp->GetLocationAtIndex(bp_loc_idx); 520 } 521 522 return bp_loc_sp; 523 } 524 525 526 void 527 Breakpoint::GetResolverDescription (Stream *s) 528 { 529 if (m_resolver_sp) 530 m_resolver_sp->GetDescription (s); 531 } 532 533 534 bool 535 Breakpoint::GetMatchingFileLine (const ConstString &filename, uint32_t line_number, BreakpointLocationCollection &loc_coll) 536 { 537 // TODO: To be correct, this method needs to fill the breakpoint location collection 538 // with the location IDs which match the filename and line_number. 539 // 540 541 if (m_resolver_sp) 542 { 543 BreakpointResolverFileLine *resolverFileLine = dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get()); 544 if (resolverFileLine && 545 resolverFileLine->m_file_spec.GetFilename() == filename && 546 resolverFileLine->m_line_number == line_number) 547 { 548 return true; 549 } 550 } 551 return false; 552 } 553 554 void 555 Breakpoint::GetFilterDescription (Stream *s) 556 { 557 m_filter_sp->GetDescription (s); 558 } 559 560 const BreakpointSP 561 Breakpoint::GetSP () 562 { 563 // This object contains an instrusive ref count base class so we can 564 // easily make a shared pointer to this object 565 return BreakpointSP (this); 566 } 567