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