Home | History | Annotate | Download | only in Breakpoint
      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/Section.h"
     26 #include "lldb/Core/Stream.h"
     27 #include "lldb/Core/StreamString.h"
     28 #include "lldb/Symbol/SymbolContext.h"
     29 #include "lldb/Target/Target.h"
     30 #include "lldb/Target/ThreadSpec.h"
     31 #include "lldb/lldb-private-log.h"
     32 #include "llvm/Support/Casting.h"
     33 
     34 using namespace lldb;
     35 using namespace lldb_private;
     36 using namespace llvm;
     37 
     38 const ConstString &
     39 Breakpoint::GetEventIdentifier ()
     40 {
     41     static ConstString g_identifier("event-identifier.breakpoint.changed");
     42     return g_identifier;
     43 }
     44 
     45 //----------------------------------------------------------------------
     46 // Breakpoint constructor
     47 //----------------------------------------------------------------------
     48 Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) :
     49     m_being_created(true),
     50     m_target (target),
     51     m_filter_sp (filter_sp),
     52     m_resolver_sp (resolver_sp),
     53     m_options (),
     54     m_locations (*this)
     55 {
     56     m_being_created = false;
     57 }
     58 
     59 //----------------------------------------------------------------------
     60 // Destructor
     61 //----------------------------------------------------------------------
     62 Breakpoint::~Breakpoint()
     63 {
     64 }
     65 
     66 bool
     67 Breakpoint::IsInternal () const
     68 {
     69     return LLDB_BREAK_ID_IS_INTERNAL(m_bid);
     70 }
     71 
     72 
     73 
     74 Target&
     75 Breakpoint::GetTarget ()
     76 {
     77     return m_target;
     78 }
     79 
     80 const Target&
     81 Breakpoint::GetTarget () const
     82 {
     83     return m_target;
     84 }
     85 
     86 BreakpointLocationSP
     87 Breakpoint::AddLocation (const Address &addr, bool *new_location)
     88 {
     89     return m_locations.AddLocation (addr, new_location);
     90 }
     91 
     92 BreakpointLocationSP
     93 Breakpoint::FindLocationByAddress (const Address &addr)
     94 {
     95     return m_locations.FindByAddress(addr);
     96 }
     97 
     98 break_id_t
     99 Breakpoint::FindLocationIDByAddress (const Address &addr)
    100 {
    101     return m_locations.FindIDByAddress(addr);
    102 }
    103 
    104 BreakpointLocationSP
    105 Breakpoint::FindLocationByID (break_id_t bp_loc_id)
    106 {
    107     return m_locations.FindByID(bp_loc_id);
    108 }
    109 
    110 BreakpointLocationSP
    111 Breakpoint::GetLocationAtIndex (size_t index)
    112 {
    113     return m_locations.GetByIndex(index);
    114 }
    115 
    116 // For each of the overall options we need to decide how they propagate to
    117 // the location options.  This will determine the precedence of options on
    118 // the breakpoint vs. its locations.
    119 
    120 // Disable at the breakpoint level should override the location settings.
    121 // That way you can conveniently turn off a whole breakpoint without messing
    122 // up the individual settings.
    123 
    124 void
    125 Breakpoint::SetEnabled (bool enable)
    126 {
    127     if (enable == m_options.IsEnabled())
    128         return;
    129 
    130     m_options.SetEnabled(enable);
    131     if (enable)
    132         m_locations.ResolveAllBreakpointSites();
    133     else
    134         m_locations.ClearAllBreakpointSites();
    135 
    136     SendBreakpointChangedEvent (enable ? eBreakpointEventTypeEnabled : eBreakpointEventTypeDisabled);
    137 
    138 }
    139 
    140 bool
    141 Breakpoint::IsEnabled ()
    142 {
    143     return m_options.IsEnabled();
    144 }
    145 
    146 void
    147 Breakpoint::SetIgnoreCount (uint32_t n)
    148 {
    149     if (m_options.GetIgnoreCount() == n)
    150         return;
    151 
    152     m_options.SetIgnoreCount(n);
    153     SendBreakpointChangedEvent (eBreakpointEventTypeIgnoreChanged);
    154 }
    155 
    156 void
    157 Breakpoint::DecrementIgnoreCount ()
    158 {
    159     uint32_t ignore = m_options.GetIgnoreCount();
    160     if (ignore != 0)
    161         m_options.SetIgnoreCount(ignore - 1);
    162 }
    163 
    164 uint32_t
    165 Breakpoint::GetIgnoreCount () const
    166 {
    167     return m_options.GetIgnoreCount();
    168 }
    169 
    170 bool
    171 Breakpoint::IgnoreCountShouldStop ()
    172 {
    173     uint32_t ignore = GetIgnoreCount();
    174     if (ignore != 0)
    175     {
    176         // When we get here we know the location that caused the stop doesn't have an ignore count,
    177         // since by contract we call it first...  So we don't have to find & decrement it, we only have
    178         // to decrement our own ignore count.
    179         DecrementIgnoreCount();
    180         return false;
    181     }
    182     else
    183         return true;
    184 }
    185 
    186 uint32_t
    187 Breakpoint::GetHitCount () const
    188 {
    189     return m_locations.GetHitCount();
    190 }
    191 
    192 bool
    193 Breakpoint::IsOneShot () const
    194 {
    195     return m_options.IsOneShot();
    196 }
    197 
    198 void
    199 Breakpoint::SetOneShot (bool one_shot)
    200 {
    201     m_options.SetOneShot (one_shot);
    202 }
    203 
    204 void
    205 Breakpoint::SetThreadID (lldb::tid_t thread_id)
    206 {
    207     if (m_options.GetThreadSpec()->GetTID() == thread_id)
    208         return;
    209 
    210     m_options.GetThreadSpec()->SetTID(thread_id);
    211     SendBreakpointChangedEvent (eBreakpointEventTypeThreadChanged);
    212 }
    213 
    214 lldb::tid_t
    215 Breakpoint::GetThreadID () const
    216 {
    217     if (m_options.GetThreadSpecNoCreate() == NULL)
    218         return LLDB_INVALID_THREAD_ID;
    219     else
    220         return m_options.GetThreadSpecNoCreate()->GetTID();
    221 }
    222 
    223 void
    224 Breakpoint::SetThreadIndex (uint32_t index)
    225 {
    226     if (m_options.GetThreadSpec()->GetIndex() == index)
    227         return;
    228 
    229     m_options.GetThreadSpec()->SetIndex(index);
    230     SendBreakpointChangedEvent (eBreakpointEventTypeThreadChanged);
    231 }
    232 
    233 uint32_t
    234 Breakpoint::GetThreadIndex() const
    235 {
    236     if (m_options.GetThreadSpecNoCreate() == NULL)
    237         return 0;
    238     else
    239         return m_options.GetThreadSpecNoCreate()->GetIndex();
    240 }
    241 
    242 void
    243 Breakpoint::SetThreadName (const char *thread_name)
    244 {
    245     if (m_options.GetThreadSpec()->GetName() != NULL
    246         && ::strcmp (m_options.GetThreadSpec()->GetName(), thread_name) == 0)
    247         return;
    248 
    249     m_options.GetThreadSpec()->SetName (thread_name);
    250     SendBreakpointChangedEvent (eBreakpointEventTypeThreadChanged);
    251 }
    252 
    253 const char *
    254 Breakpoint::GetThreadName () const
    255 {
    256     if (m_options.GetThreadSpecNoCreate() == NULL)
    257         return NULL;
    258     else
    259         return m_options.GetThreadSpecNoCreate()->GetName();
    260 }
    261 
    262 void
    263 Breakpoint::SetQueueName (const char *queue_name)
    264 {
    265     if (m_options.GetThreadSpec()->GetQueueName() != NULL
    266         && ::strcmp (m_options.GetThreadSpec()->GetQueueName(), queue_name) == 0)
    267         return;
    268 
    269     m_options.GetThreadSpec()->SetQueueName (queue_name);
    270     SendBreakpointChangedEvent (eBreakpointEventTypeThreadChanged);
    271 }
    272 
    273 const char *
    274 Breakpoint::GetQueueName () const
    275 {
    276     if (m_options.GetThreadSpecNoCreate() == NULL)
    277         return NULL;
    278     else
    279         return m_options.GetThreadSpecNoCreate()->GetQueueName();
    280 }
    281 
    282 void
    283 Breakpoint::SetCondition (const char *condition)
    284 {
    285     m_options.SetCondition (condition);
    286     SendBreakpointChangedEvent (eBreakpointEventTypeConditionChanged);
    287 }
    288 
    289 const char *
    290 Breakpoint::GetConditionText () const
    291 {
    292     return m_options.GetConditionText();
    293 }
    294 
    295 // This function is used when "baton" doesn't need to be freed
    296 void
    297 Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous)
    298 {
    299     // The default "Baton" class will keep a copy of "baton" and won't free
    300     // or delete it when it goes goes out of scope.
    301     m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
    302 
    303     SendBreakpointChangedEvent (eBreakpointEventTypeCommandChanged);
    304 }
    305 
    306 // This function is used when a baton needs to be freed and therefore is
    307 // contained in a "Baton" subclass.
    308 void
    309 Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
    310 {
    311     m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
    312 }
    313 
    314 void
    315 Breakpoint::ClearCallback ()
    316 {
    317     m_options.ClearCallback ();
    318 }
    319 
    320 bool
    321 Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id)
    322 {
    323     return m_options.InvokeCallback (context, GetID(), bp_loc_id);
    324 }
    325 
    326 BreakpointOptions *
    327 Breakpoint::GetOptions ()
    328 {
    329     return &m_options;
    330 }
    331 
    332 void
    333 Breakpoint::ResolveBreakpoint ()
    334 {
    335     if (m_resolver_sp)
    336         m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
    337 }
    338 
    339 void
    340 Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
    341 {
    342     if (m_resolver_sp)
    343         m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
    344 }
    345 
    346 void
    347 Breakpoint::ClearAllBreakpointSites ()
    348 {
    349     m_locations.ClearAllBreakpointSites();
    350 }
    351 
    352 //----------------------------------------------------------------------
    353 // ModulesChanged: Pass in a list of new modules, and
    354 //----------------------------------------------------------------------
    355 
    356 void
    357 Breakpoint::ModulesChanged (ModuleList &module_list, bool load, bool delete_locations)
    358 {
    359     Mutex::Locker modules_mutex(module_list.GetMutex());
    360     if (load)
    361     {
    362         // The logic for handling new modules is:
    363         // 1) If the filter rejects this module, then skip it.
    364         // 2) Run through the current location list and if there are any locations
    365         //    for that module, we mark the module as "seen" and we don't try to re-resolve
    366         //    breakpoint locations for that module.
    367         //    However, we do add breakpoint sites to these locations if needed.
    368         // 3) If we don't see this module in our breakpoint location list, call ResolveInModules.
    369 
    370         ModuleList new_modules;  // We'll stuff the "unseen" modules in this list, and then resolve
    371                                  // them after the locations pass.  Have to do it this way because
    372                                  // resolving breakpoints will add new locations potentially.
    373 
    374         const size_t num_locs = m_locations.GetSize();
    375         size_t num_modules = module_list.GetSize();
    376         for (size_t i = 0; i < num_modules; i++)
    377         {
    378             bool seen = false;
    379             ModuleSP module_sp (module_list.GetModuleAtIndexUnlocked (i));
    380             if (!m_filter_sp->ModulePasses (module_sp))
    381                 continue;
    382 
    383             for (size_t loc_idx = 0; loc_idx < num_locs; loc_idx++)
    384             {
    385                 BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx);
    386                 if (!break_loc->IsEnabled())
    387                     continue;
    388                 SectionSP section_sp (break_loc->GetAddress().GetSection());
    389                 if (!section_sp || section_sp->GetModule() == module_sp)
    390                 {
    391                     if (!seen)
    392                         seen = true;
    393 
    394                     if (!break_loc->ResolveBreakpointSite())
    395                     {
    396                         Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
    397                         if (log)
    398                             log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n",
    399                                          break_loc->GetID(), GetID());
    400                     }
    401                 }
    402             }
    403 
    404             if (!seen)
    405                 new_modules.AppendIfNeeded (module_sp);
    406 
    407         }
    408 
    409         if (new_modules.GetSize() > 0)
    410         {
    411             // If this is not an internal breakpoint, set up to record the new locations, then dispatch
    412             // an event with the new locations.
    413             if (!IsInternal())
    414             {
    415                 BreakpointEventData *new_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsAdded,
    416                                                                                     shared_from_this());
    417 
    418                 m_locations.StartRecordingNewLocations(new_locations_event->GetBreakpointLocationCollection());
    419 
    420                 ResolveBreakpointInModules(new_modules);
    421 
    422                 m_locations.StopRecordingNewLocations();
    423                 if (new_locations_event->GetBreakpointLocationCollection().GetSize() != 0)
    424                 {
    425                     SendBreakpointChangedEvent (new_locations_event);
    426                 }
    427                 else
    428                     delete new_locations_event;
    429             }
    430             else
    431                 ResolveBreakpointInModules(new_modules);
    432 
    433         }
    434     }
    435     else
    436     {
    437         // Go through the currently set locations and if any have breakpoints in
    438         // the module list, then remove their breakpoint sites, and their locations if asked to.
    439 
    440         BreakpointEventData *removed_locations_event;
    441         if (!IsInternal())
    442             removed_locations_event = new BreakpointEventData (eBreakpointEventTypeLocationsRemoved,
    443                                                                shared_from_this());
    444         else
    445             removed_locations_event = NULL;
    446 
    447         size_t num_modules = module_list.GetSize();
    448         for (size_t i = 0; i < num_modules; i++)
    449         {
    450             ModuleSP module_sp (module_list.GetModuleAtIndexUnlocked (i));
    451             if (m_filter_sp->ModulePasses (module_sp))
    452             {
    453                 size_t loc_idx = 0;
    454                 size_t num_locations = m_locations.GetSize();
    455                 BreakpointLocationCollection locations_to_remove;
    456                 for (loc_idx = 0; loc_idx < num_locations; loc_idx++)
    457                 {
    458                     BreakpointLocationSP break_loc_sp (m_locations.GetByIndex(loc_idx));
    459                     SectionSP section_sp (break_loc_sp->GetAddress().GetSection());
    460                     if (section_sp && section_sp->GetModule() == module_sp)
    461                     {
    462                         // Remove this breakpoint since the shared library is
    463                         // unloaded, but keep the breakpoint location around
    464                         // so we always get complete hit count and breakpoint
    465                         // lifetime info
    466                         break_loc_sp->ClearBreakpointSite();
    467                         if (removed_locations_event)
    468                         {
    469                             removed_locations_event->GetBreakpointLocationCollection().Add(break_loc_sp);
    470                         }
    471                         if (delete_locations)
    472                             locations_to_remove.Add (break_loc_sp);
    473 
    474                     }
    475                 }
    476 
    477                 if (delete_locations)
    478                 {
    479                     size_t num_locations_to_remove = locations_to_remove.GetSize();
    480                     for (loc_idx = 0; loc_idx < num_locations_to_remove; loc_idx++)
    481                         m_locations.RemoveLocation  (locations_to_remove.GetByIndex(loc_idx));
    482                 }
    483             }
    484         }
    485         SendBreakpointChangedEvent (removed_locations_event);
    486     }
    487 }
    488 
    489 void
    490 Breakpoint::ModuleReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp)
    491 {
    492     ModuleList temp_list;
    493     temp_list.Append (new_module_sp);
    494     ModulesChanged (temp_list, true);
    495 
    496     // TO DO: For now I'm just adding locations for the new module and removing the
    497     // breakpoint locations that were in the old module.
    498     // We should really go find the ones that are in the new module & if we can determine that they are "equivalent"
    499     // carry over the options from the old location to the new.
    500 
    501     temp_list.Clear();
    502     temp_list.Append (old_module_sp);
    503     ModulesChanged (temp_list, false, true);
    504 }
    505 
    506 void
    507 Breakpoint::Dump (Stream *)
    508 {
    509 }
    510 
    511 size_t
    512 Breakpoint::GetNumResolvedLocations() const
    513 {
    514     // Return the number of breakpoints that are actually resolved and set
    515     // down in the inferior process.
    516     return m_locations.GetNumResolvedLocations();
    517 }
    518 
    519 size_t
    520 Breakpoint::GetNumLocations() const
    521 {
    522     return m_locations.GetSize();
    523 }
    524 
    525 void
    526 Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
    527 {
    528     assert (s != NULL);
    529 
    530     if (!m_kind_description.empty())
    531     {
    532         if (eDescriptionLevelBrief)
    533         {
    534             s->PutCString (GetBreakpointKind());
    535             return;
    536         }
    537         else
    538             s->Printf("Kind: %s\n", GetBreakpointKind ());
    539     }
    540 
    541     const size_t num_locations = GetNumLocations ();
    542     const size_t num_resolved_locations = GetNumResolvedLocations ();
    543 
    544     // They just made the breakpoint, they don't need to be told HOW they made it...
    545     // Also, we'll print the breakpoint number differently depending on whether there is 1 or more locations.
    546     if (level != eDescriptionLevelInitial)
    547     {
    548         s->Printf("%i: ", GetID());
    549         GetResolverDescription (s);
    550         GetFilterDescription (s);
    551     }
    552 
    553     switch (level)
    554     {
    555     case lldb::eDescriptionLevelBrief:
    556     case lldb::eDescriptionLevelFull:
    557         if (num_locations > 0)
    558         {
    559             s->Printf(", locations = %" PRIu64, (uint64_t)num_locations);
    560             if (num_resolved_locations > 0)
    561                 s->Printf(", resolved = %" PRIu64, (uint64_t)num_resolved_locations);
    562         }
    563         else
    564         {
    565             // Don't print the pending notification for exception resolvers since we don't generally
    566             // know how to set them until the target is run.
    567             if (m_resolver_sp->getResolverID() != BreakpointResolver::ExceptionResolver)
    568                 s->Printf(", locations = 0 (pending)");
    569         }
    570 
    571         GetOptions()->GetDescription(s, level);
    572 
    573         if (level == lldb::eDescriptionLevelFull)
    574         {
    575             s->IndentLess();
    576             s->EOL();
    577         }
    578         break;
    579 
    580     case lldb::eDescriptionLevelInitial:
    581         s->Printf ("Breakpoint %i: ", GetID());
    582         if (num_locations == 0)
    583         {
    584             s->Printf ("no locations (pending).");
    585         }
    586         else if (num_locations == 1)
    587         {
    588             // If there is one location only, we'll just print that location information.  But don't do this if
    589             // show locations is true, then that will be handled below.
    590             if (show_locations == false)
    591             {
    592                 GetLocationAtIndex(0)->GetDescription(s, level);
    593             }
    594             else
    595             {
    596                 s->Printf ("%zd locations.", num_locations);
    597             }
    598         }
    599         else
    600         {
    601             s->Printf ("%zd locations.", num_locations);
    602         }
    603         s->EOL();
    604         break;
    605     case lldb::eDescriptionLevelVerbose:
    606         // Verbose mode does a debug dump of the breakpoint
    607         Dump (s);
    608         s->EOL ();
    609             //s->Indent();
    610         GetOptions()->GetDescription(s, level);
    611         break;
    612 
    613     default:
    614         break;
    615     }
    616 
    617     // The brief description is just the location name (1.2 or whatever).  That's pointless to
    618     // show in the breakpoint's description, so suppress it.
    619     if (show_locations && level != lldb::eDescriptionLevelBrief)
    620     {
    621         s->IndentMore();
    622         for (size_t i = 0; i < num_locations; ++i)
    623         {
    624             BreakpointLocation *loc = GetLocationAtIndex(i).get();
    625             loc->GetDescription(s, level);
    626             s->EOL();
    627         }
    628         s->IndentLess();
    629     }
    630 }
    631 
    632 void
    633 Breakpoint::GetResolverDescription (Stream *s)
    634 {
    635     if (m_resolver_sp)
    636         m_resolver_sp->GetDescription (s);
    637 }
    638 
    639 
    640 bool
    641 Breakpoint::GetMatchingFileLine (const ConstString &filename, uint32_t line_number, BreakpointLocationCollection &loc_coll)
    642 {
    643     // TODO: To be correct, this method needs to fill the breakpoint location collection
    644     //       with the location IDs which match the filename and line_number.
    645     //
    646 
    647     if (m_resolver_sp)
    648     {
    649         BreakpointResolverFileLine *resolverFileLine = dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get());
    650         if (resolverFileLine &&
    651             resolverFileLine->m_file_spec.GetFilename() == filename &&
    652             resolverFileLine->m_line_number == line_number)
    653         {
    654             return true;
    655         }
    656     }
    657     return false;
    658 }
    659 
    660 void
    661 Breakpoint::GetFilterDescription (Stream *s)
    662 {
    663     m_filter_sp->GetDescription (s);
    664 }
    665 
    666 void
    667 Breakpoint::SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind)
    668 {
    669     if (!m_being_created
    670         && !IsInternal()
    671         && GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
    672     {
    673         BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind, shared_from_this());
    674 
    675         GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
    676     }
    677 }
    678 
    679 void
    680 Breakpoint::SendBreakpointChangedEvent (BreakpointEventData *data)
    681 {
    682 
    683     if (data == NULL)
    684         return;
    685 
    686     if (!m_being_created
    687         && !IsInternal()
    688         && GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
    689         GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
    690     else
    691         delete data;
    692 }
    693 
    694 Breakpoint::BreakpointEventData::BreakpointEventData (BreakpointEventType sub_type,
    695                                                       const BreakpointSP &new_breakpoint_sp) :
    696     EventData (),
    697     m_breakpoint_event (sub_type),
    698     m_new_breakpoint_sp (new_breakpoint_sp)
    699 {
    700 }
    701 
    702 Breakpoint::BreakpointEventData::~BreakpointEventData ()
    703 {
    704 }
    705 
    706 const ConstString &
    707 Breakpoint::BreakpointEventData::GetFlavorString ()
    708 {
    709     static ConstString g_flavor ("Breakpoint::BreakpointEventData");
    710     return g_flavor;
    711 }
    712 
    713 const ConstString &
    714 Breakpoint::BreakpointEventData::GetFlavor () const
    715 {
    716     return BreakpointEventData::GetFlavorString ();
    717 }
    718 
    719 
    720 BreakpointSP &
    721 Breakpoint::BreakpointEventData::GetBreakpoint ()
    722 {
    723     return m_new_breakpoint_sp;
    724 }
    725 
    726 BreakpointEventType
    727 Breakpoint::BreakpointEventData::GetBreakpointEventType () const
    728 {
    729     return m_breakpoint_event;
    730 }
    731 
    732 void
    733 Breakpoint::BreakpointEventData::Dump (Stream *s) const
    734 {
    735 }
    736 
    737 const Breakpoint::BreakpointEventData *
    738 Breakpoint::BreakpointEventData::GetEventDataFromEvent (const Event *event)
    739 {
    740     if (event)
    741     {
    742         const EventData *event_data = event->GetData();
    743         if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
    744             return static_cast <const BreakpointEventData *> (event->GetData());
    745     }
    746     return NULL;
    747 }
    748 
    749 BreakpointEventType
    750 Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (const EventSP &event_sp)
    751 {
    752     const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get());
    753 
    754     if (data == NULL)
    755         return eBreakpointEventTypeInvalidType;
    756     else
    757         return data->GetBreakpointEventType();
    758 }
    759 
    760 BreakpointSP
    761 Breakpoint::BreakpointEventData::GetBreakpointFromEvent (const EventSP &event_sp)
    762 {
    763     BreakpointSP bp_sp;
    764 
    765     const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get());
    766     if (data)
    767         bp_sp = data->m_new_breakpoint_sp;
    768 
    769     return bp_sp;
    770 }
    771 
    772 size_t
    773 Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (const EventSP &event_sp)
    774 {
    775     const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get());
    776     if (data)
    777         return data->m_locations.GetSize();
    778 
    779     return 0;
    780 }
    781 
    782 lldb::BreakpointLocationSP
    783 Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (const lldb::EventSP &event_sp, uint32_t bp_loc_idx)
    784 {
    785     lldb::BreakpointLocationSP bp_loc_sp;
    786 
    787     const BreakpointEventData *data = GetEventDataFromEvent (event_sp.get());
    788     if (data)
    789     {
    790         bp_loc_sp = data->m_locations.GetByIndex(bp_loc_idx);
    791     }
    792 
    793     return bp_loc_sp;
    794 }
    795