Home | History | Annotate | Download | only in Breakpoint
      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 #include "lldb/lldb-python.h"
     11 
     12 // C Includes
     13 // C++ Includes
     14 #include <string>
     15 
     16 // Other libraries and framework includes
     17 // Project includes
     18 #include "lldb/lldb-private-log.h"
     19 #include "lldb/Breakpoint/BreakpointLocation.h"
     20 #include "lldb/Breakpoint/BreakpointID.h"
     21 #include "lldb/Breakpoint/StoppointCallbackContext.h"
     22 #include "lldb/Core/Debugger.h"
     23 #include "lldb/Core/Log.h"
     24 #include "lldb/Core/Module.h"
     25 #include "lldb/Core/StreamString.h"
     26 #include "lldb/Symbol/CompileUnit.h"
     27 #include "lldb/Symbol/Symbol.h"
     28 #include "lldb/Target/Target.h"
     29 #include "lldb/Target/Process.h"
     30 #include "lldb/Target/Thread.h"
     31 #include "lldb/Target/ThreadSpec.h"
     32 
     33 using namespace lldb;
     34 using namespace lldb_private;
     35 
     36 BreakpointLocation::BreakpointLocation
     37 (
     38     break_id_t loc_id,
     39     Breakpoint &owner,
     40     const Address &addr,
     41     lldb::tid_t tid,
     42     bool hardware
     43 ) :
     44     StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware),
     45     m_being_created(true),
     46     m_address (addr),
     47     m_owner (owner),
     48     m_options_ap (),
     49     m_bp_site_sp (),
     50     m_condition_mutex ()
     51 {
     52     SetThreadID (tid);
     53     m_being_created = false;
     54 }
     55 
     56 BreakpointLocation::~BreakpointLocation()
     57 {
     58     ClearBreakpointSite();
     59 }
     60 
     61 lldb::addr_t
     62 BreakpointLocation::GetLoadAddress () const
     63 {
     64     return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget());
     65 }
     66 
     67 Address &
     68 BreakpointLocation::GetAddress ()
     69 {
     70     return m_address;
     71 }
     72 
     73 Breakpoint &
     74 BreakpointLocation::GetBreakpoint ()
     75 {
     76     return m_owner;
     77 }
     78 
     79 bool
     80 BreakpointLocation::IsEnabled () const
     81 {
     82     if (!m_owner.IsEnabled())
     83         return false;
     84     else if (m_options_ap.get() != NULL)
     85         return m_options_ap->IsEnabled();
     86     else
     87         return true;
     88 }
     89 
     90 void
     91 BreakpointLocation::SetEnabled (bool enabled)
     92 {
     93     GetLocationOptions()->SetEnabled(enabled);
     94     if (enabled)
     95     {
     96         ResolveBreakpointSite();
     97     }
     98     else
     99     {
    100         ClearBreakpointSite();
    101     }
    102     SendBreakpointLocationChangedEvent (enabled ? eBreakpointEventTypeEnabled : eBreakpointEventTypeDisabled);
    103 }
    104 
    105 void
    106 BreakpointLocation::SetThreadID (lldb::tid_t thread_id)
    107 {
    108     if (thread_id != LLDB_INVALID_THREAD_ID)
    109         GetLocationOptions()->SetThreadID(thread_id);
    110     else
    111     {
    112         // If we're resetting this to an invalid thread id, then
    113         // don't make an options pointer just to do that.
    114         if (m_options_ap.get() != NULL)
    115             m_options_ap->SetThreadID (thread_id);
    116     }
    117     SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
    118 }
    119 
    120 lldb::tid_t
    121 BreakpointLocation::GetThreadID ()
    122 {
    123     if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
    124         return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID();
    125     else
    126         return LLDB_INVALID_THREAD_ID;
    127 }
    128 
    129 void
    130 BreakpointLocation::SetThreadIndex (uint32_t index)
    131 {
    132     if (index != 0)
    133         GetLocationOptions()->GetThreadSpec()->SetIndex(index);
    134     else
    135     {
    136         // If we're resetting this to an invalid thread id, then
    137         // don't make an options pointer just to do that.
    138         if (m_options_ap.get() != NULL)
    139             m_options_ap->GetThreadSpec()->SetIndex(index);
    140     }
    141     SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
    142 
    143 }
    144 
    145 uint32_t
    146 BreakpointLocation::GetThreadIndex() const
    147 {
    148     if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
    149         return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetIndex();
    150     else
    151         return 0;
    152 }
    153 
    154 void
    155 BreakpointLocation::SetThreadName (const char *thread_name)
    156 {
    157     if (thread_name != NULL)
    158         GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
    159     else
    160     {
    161         // If we're resetting this to an invalid thread id, then
    162         // don't make an options pointer just to do that.
    163         if (m_options_ap.get() != NULL)
    164             m_options_ap->GetThreadSpec()->SetName(thread_name);
    165     }
    166     SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
    167 }
    168 
    169 const char *
    170 BreakpointLocation::GetThreadName () const
    171 {
    172     if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
    173         return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetName();
    174     else
    175         return NULL;
    176 }
    177 
    178 void
    179 BreakpointLocation::SetQueueName (const char *queue_name)
    180 {
    181     if (queue_name != NULL)
    182         GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
    183     else
    184     {
    185         // If we're resetting this to an invalid thread id, then
    186         // don't make an options pointer just to do that.
    187         if (m_options_ap.get() != NULL)
    188             m_options_ap->GetThreadSpec()->SetQueueName(queue_name);
    189     }
    190     SendBreakpointLocationChangedEvent (eBreakpointEventTypeThreadChanged);
    191 }
    192 
    193 const char *
    194 BreakpointLocation::GetQueueName () const
    195 {
    196     if (GetOptionsNoCreate()->GetThreadSpecNoCreate())
    197         return GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetQueueName();
    198     else
    199         return NULL;
    200 }
    201 
    202 bool
    203 BreakpointLocation::InvokeCallback (StoppointCallbackContext *context)
    204 {
    205     if (m_options_ap.get() != NULL && m_options_ap->HasCallback())
    206         return m_options_ap->InvokeCallback (context, m_owner.GetID(), GetID());
    207     else
    208         return m_owner.InvokeCallback (context, GetID());
    209 }
    210 
    211 void
    212 BreakpointLocation::SetCallback (BreakpointHitCallback callback, void *baton,
    213                  bool is_synchronous)
    214 {
    215     // The default "Baton" class will keep a copy of "baton" and won't free
    216     // or delete it when it goes goes out of scope.
    217     GetLocationOptions()->SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
    218     SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged);
    219 }
    220 
    221 void
    222 BreakpointLocation::SetCallback (BreakpointHitCallback callback, const BatonSP &baton_sp,
    223                  bool is_synchronous)
    224 {
    225     GetLocationOptions()->SetCallback (callback, baton_sp, is_synchronous);
    226     SendBreakpointLocationChangedEvent (eBreakpointEventTypeCommandChanged);
    227 }
    228 
    229 
    230 void
    231 BreakpointLocation::ClearCallback ()
    232 {
    233     GetLocationOptions()->ClearCallback();
    234 }
    235 
    236 void
    237 BreakpointLocation::SetCondition (const char *condition)
    238 {
    239     GetLocationOptions()->SetCondition (condition);
    240     SendBreakpointLocationChangedEvent (eBreakpointEventTypeConditionChanged);
    241 }
    242 
    243 const char *
    244 BreakpointLocation::GetConditionText (size_t *hash) const
    245 {
    246     return GetOptionsNoCreate()->GetConditionText(hash);
    247 }
    248 
    249 bool
    250 BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
    251 {
    252     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
    253 
    254     Mutex::Locker evaluation_locker(m_condition_mutex);
    255 
    256     size_t condition_hash;
    257     const char *condition_text = GetConditionText(&condition_hash);
    258 
    259     if (!condition_text)
    260     {
    261         m_user_expression_sp.reset();
    262         return false;
    263     }
    264 
    265     if (condition_hash != m_condition_hash ||
    266         !m_user_expression_sp ||
    267         !m_user_expression_sp->MatchesContext(exe_ctx))
    268     {
    269         m_user_expression_sp.reset(new ClangUserExpression(condition_text,
    270                                                            NULL,
    271                                                            lldb::eLanguageTypeUnknown,
    272                                                            ClangUserExpression::eResultTypeAny));
    273 
    274         StreamString errors;
    275 
    276         if (!m_user_expression_sp->Parse(errors,
    277                                          exe_ctx,
    278                                          eExecutionPolicyOnlyWhenNeeded,
    279                                          true))
    280         {
    281             error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s",
    282                                            errors.GetData());
    283             m_user_expression_sp.reset();
    284             return false;
    285         }
    286 
    287         m_condition_hash = condition_hash;
    288     }
    289 
    290     // We need to make sure the user sees any parse errors in their condition, so we'll hook the
    291     // constructor errors up to the debugger's Async I/O.
    292 
    293     ValueObjectSP result_value_sp;
    294     const bool unwind_on_error = true;
    295     const bool ignore_breakpoints = true;
    296     const bool try_all_threads = true;
    297 
    298     Error expr_error;
    299 
    300     StreamString execution_errors;
    301 
    302     ClangExpressionVariableSP result_variable_sp;
    303 
    304     ExecutionResults result_code =
    305     m_user_expression_sp->Execute(execution_errors,
    306                                   exe_ctx,
    307                                   unwind_on_error,
    308                                   ignore_breakpoints,
    309                                   m_user_expression_sp,
    310                                   result_variable_sp,
    311                                   try_all_threads,
    312                                   ClangUserExpression::kDefaultTimeout);
    313 
    314     bool ret;
    315 
    316     if (result_code == eExecutionCompleted)
    317     {
    318         if (!result_variable_sp)
    319         {
    320             ret = false;
    321             error.SetErrorString("Expression did not return a result");
    322             return false;
    323         }
    324 
    325         result_value_sp = result_variable_sp->GetValueObject();
    326 
    327         if (result_value_sp)
    328         {
    329             Scalar scalar_value;
    330             if (result_value_sp->ResolveValue (scalar_value))
    331             {
    332                 if (scalar_value.ULongLong(1) == 0)
    333                     ret = false;
    334                 else
    335                     ret = true;
    336                 if (log)
    337                     log->Printf("Condition successfully evaluated, result is %s.\n",
    338                                 ret ? "true" : "false");
    339             }
    340             else
    341             {
    342                 ret = false;
    343                 error.SetErrorString("Failed to get an integer result from the expression");
    344             }
    345         }
    346         else
    347         {
    348             ret = false;
    349             error.SetErrorString("Failed to get any result from the expression");
    350         }
    351     }
    352     else
    353     {
    354         ret = false;
    355         error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", execution_errors.GetData());
    356     }
    357 
    358     return ret;
    359 }
    360 
    361 uint32_t
    362 BreakpointLocation::GetIgnoreCount ()
    363 {
    364     return GetOptionsNoCreate()->GetIgnoreCount();
    365 }
    366 
    367 void
    368 BreakpointLocation::SetIgnoreCount (uint32_t n)
    369 {
    370     GetLocationOptions()->SetIgnoreCount(n);
    371     SendBreakpointLocationChangedEvent (eBreakpointEventTypeIgnoreChanged);
    372 }
    373 
    374 void
    375 BreakpointLocation::DecrementIgnoreCount()
    376 {
    377     if (m_options_ap.get() != NULL)
    378     {
    379         uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
    380         if (loc_ignore != 0)
    381             m_options_ap->SetIgnoreCount(loc_ignore - 1);
    382     }
    383 }
    384 
    385 bool
    386 BreakpointLocation::IgnoreCountShouldStop()
    387 {
    388     if (m_options_ap.get() != NULL)
    389     {
    390         uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
    391         if (loc_ignore != 0)
    392         {
    393             m_owner.DecrementIgnoreCount();
    394             DecrementIgnoreCount();          // Have to decrement our owners' ignore count, since it won't get a
    395                                              // chance to.
    396             return false;
    397         }
    398     }
    399     return true;
    400 }
    401 
    402 const BreakpointOptions *
    403 BreakpointLocation::GetOptionsNoCreate () const
    404 {
    405     if (m_options_ap.get() != NULL)
    406         return m_options_ap.get();
    407     else
    408         return m_owner.GetOptions ();
    409 }
    410 
    411 BreakpointOptions *
    412 BreakpointLocation::GetLocationOptions ()
    413 {
    414     // If we make the copy we don't copy the callbacks because that is potentially
    415     // expensive and we don't want to do that for the simple case where someone is
    416     // just disabling the location.
    417     if (m_options_ap.get() == NULL)
    418         m_options_ap.reset(BreakpointOptions::CopyOptionsNoCallback(*m_owner.GetOptions ()));
    419 
    420     return m_options_ap.get();
    421 }
    422 
    423 bool
    424 BreakpointLocation::ValidForThisThread (Thread *thread)
    425 {
    426     return thread->MatchesSpec(GetOptionsNoCreate()->GetThreadSpecNoCreate());
    427 }
    428 
    429 // RETURNS - true if we should stop at this breakpoint, false if we
    430 // should continue.  Note, we don't check the thread spec for the breakpoint
    431 // here, since if the breakpoint is not for this thread, then the event won't
    432 // even get reported, so the check is redundant.
    433 
    434 bool
    435 BreakpointLocation::ShouldStop (StoppointCallbackContext *context)
    436 {
    437     bool should_stop = true;
    438     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
    439 
    440     IncrementHitCount();
    441 
    442     if (!IsEnabled())
    443         return false;
    444 
    445     if (!IgnoreCountShouldStop())
    446         return false;
    447 
    448     if (!m_owner.IgnoreCountShouldStop())
    449         return false;
    450 
    451     // We only run synchronous callbacks in ShouldStop:
    452     context->is_synchronous = true;
    453     should_stop = InvokeCallback (context);
    454 
    455     if (log)
    456     {
    457         StreamString s;
    458         GetDescription (&s, lldb::eDescriptionLevelVerbose);
    459         log->Printf ("Hit breakpoint location: %s, %s.\n", s.GetData(), should_stop ? "stopping" : "continuing");
    460     }
    461 
    462     return should_stop;
    463 }
    464 
    465 bool
    466 BreakpointLocation::IsResolved () const
    467 {
    468     return m_bp_site_sp.get() != NULL;
    469 }
    470 
    471 lldb::BreakpointSiteSP
    472 BreakpointLocation::GetBreakpointSite() const
    473 {
    474     return m_bp_site_sp;
    475 }
    476 
    477 bool
    478 BreakpointLocation::ResolveBreakpointSite ()
    479 {
    480     if (m_bp_site_sp)
    481         return true;
    482 
    483     Process *process = m_owner.GetTarget().GetProcessSP().get();
    484     if (process == NULL)
    485         return false;
    486 
    487     lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false);
    488 
    489     if (new_id == LLDB_INVALID_BREAK_ID)
    490     {
    491         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
    492         if (log)
    493             log->Warning ("Tried to add breakpoint site at 0x%" PRIx64 " but it was already present.\n",
    494                           m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()));
    495         return false;
    496     }
    497 
    498     return true;
    499 }
    500 
    501 bool
    502 BreakpointLocation::SetBreakpointSite (BreakpointSiteSP& bp_site_sp)
    503 {
    504     m_bp_site_sp = bp_site_sp;
    505     return true;
    506 }
    507 
    508 bool
    509 BreakpointLocation::ClearBreakpointSite ()
    510 {
    511     if (m_bp_site_sp.get())
    512     {
    513         m_owner.GetTarget().GetProcessSP()->RemoveOwnerFromBreakpointSite (GetBreakpoint().GetID(),
    514                                                                            GetID(), m_bp_site_sp);
    515         m_bp_site_sp.reset();
    516         return true;
    517     }
    518     return false;
    519 }
    520 
    521 void
    522 BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
    523 {
    524     SymbolContext sc;
    525 
    526     // If the description level is "initial" then the breakpoint is printing out our initial state,
    527     // and we should let it decide how it wants to print our label.
    528     if (level != eDescriptionLevelInitial)
    529     {
    530         s->Indent();
    531         BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
    532     }
    533 
    534     if (level == lldb::eDescriptionLevelBrief)
    535         return;
    536 
    537     if (level != eDescriptionLevelInitial)
    538         s->PutCString(": ");
    539 
    540     if (level == lldb::eDescriptionLevelVerbose)
    541         s->IndentMore();
    542 
    543     if (m_address.IsSectionOffset())
    544     {
    545         m_address.CalculateSymbolContext(&sc);
    546 
    547         if (level == lldb::eDescriptionLevelFull || level == eDescriptionLevelInitial)
    548         {
    549             s->PutCString("where = ");
    550             sc.DumpStopContext (s, m_owner.GetTarget().GetProcessSP().get(), m_address, false, true, false);
    551         }
    552         else
    553         {
    554             if (sc.module_sp)
    555             {
    556                 s->EOL();
    557                 s->Indent("module = ");
    558                 sc.module_sp->GetFileSpec().Dump (s);
    559             }
    560 
    561             if (sc.comp_unit != NULL)
    562             {
    563                 s->EOL();
    564                 s->Indent("compile unit = ");
    565                 static_cast<FileSpec*>(sc.comp_unit)->GetFilename().Dump (s);
    566 
    567                 if (sc.function != NULL)
    568                 {
    569                     s->EOL();
    570                     s->Indent("function = ");
    571                     s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
    572                 }
    573 
    574                 if (sc.line_entry.line > 0)
    575                 {
    576                     s->EOL();
    577                     s->Indent("location = ");
    578                     sc.line_entry.DumpStopContext (s, true);
    579                 }
    580 
    581             }
    582             else
    583             {
    584                 // If we don't have a comp unit, see if we have a symbol we can print.
    585                 if (sc.symbol)
    586                 {
    587                     s->EOL();
    588                     s->Indent("symbol = ");
    589                     s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
    590                 }
    591             }
    592         }
    593     }
    594 
    595     if (level == lldb::eDescriptionLevelVerbose)
    596     {
    597         s->EOL();
    598         s->Indent();
    599     }
    600 
    601     if (m_address.IsSectionOffset() && (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
    602         s->Printf (", ");
    603     s->Printf ("address = ");
    604 
    605     ExecutionContextScope *exe_scope = NULL;
    606     Target *target = &m_owner.GetTarget();
    607     if (target)
    608         exe_scope = target->GetProcessSP().get();
    609     if (exe_scope == NULL)
    610         exe_scope = target;
    611 
    612     if (eDescriptionLevelInitial)
    613         m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
    614     else
    615         m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
    616 
    617     if (level == lldb::eDescriptionLevelVerbose)
    618     {
    619         s->EOL();
    620         s->Indent();
    621         s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
    622 
    623         s->Indent();
    624         s->Printf ("hit count = %-4u\n", GetHitCount());
    625 
    626         if (m_options_ap.get())
    627         {
    628             s->Indent();
    629             m_options_ap->GetDescription (s, level);
    630             s->EOL();
    631         }
    632         s->IndentLess();
    633     }
    634     else if (level != eDescriptionLevelInitial)
    635     {
    636         s->Printf(", %sresolved, hit count = %u ",
    637                   (IsResolved() ? "" : "un"),
    638                   GetHitCount());
    639         if (m_options_ap.get())
    640         {
    641             m_options_ap->GetDescription (s, level);
    642         }
    643     }
    644 }
    645 
    646 void
    647 BreakpointLocation::Dump(Stream *s) const
    648 {
    649     if (s == NULL)
    650         return;
    651 
    652     s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 "  load addr = 0x%8.8" PRIx64 "  state = %s  type = %s breakpoint  "
    653               "hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
    654               GetID(),
    655               GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
    656               (uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
    657               (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
    658               IsHardware() ? "hardware" : "software",
    659               GetHardwareIndex(),
    660               GetHitCount(),
    661               GetOptionsNoCreate()->GetIgnoreCount());
    662 }
    663 
    664 void
    665 BreakpointLocation::SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind)
    666 {
    667     if (!m_being_created
    668         && !m_owner.IsInternal()
    669         && m_owner.GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
    670     {
    671         Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData (eventKind,
    672                                                                                      m_owner.shared_from_this());
    673         data->GetBreakpointLocationCollection().Add (shared_from_this());
    674         m_owner.GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged, data);
    675     }
    676 }
    677 
    678