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