Home | History | Annotate | Download | only in Breakpoint
      1 //===-- BreakpointOptions.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/Breakpoint/BreakpointOptions.h"
     11 
     12 // C Includes
     13 // C++ Includes
     14 // Other libraries and framework includes
     15 // Project includes
     16 #include "lldb/Core/Stream.h"
     17 #include "lldb/Core/StringList.h"
     18 #include "lldb/Core/Value.h"
     19 #include "lldb/Breakpoint/StoppointCallbackContext.h"
     20 #include "lldb/Target/Process.h"
     21 #include "lldb/Target/Target.h"
     22 #include "lldb/Target/ThreadSpec.h"
     23 #include "lldb/Expression/ClangUserExpression.h"
     24 
     25 using namespace lldb;
     26 using namespace lldb_private;
     27 
     28 bool
     29 BreakpointOptions::NullCallback (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
     30 {
     31     return true;
     32 }
     33 
     34 //----------------------------------------------------------------------
     35 // BreakpointOptions constructor
     36 //----------------------------------------------------------------------
     37 BreakpointOptions::BreakpointOptions() :
     38     m_callback (BreakpointOptions::NullCallback),
     39     m_callback_baton_sp (),
     40     m_callback_is_synchronous (false),
     41     m_enabled (true),
     42     m_one_shot (false),
     43     m_ignore_count (0),
     44     m_thread_spec_ap (),
     45     m_condition_text (),
     46     m_condition_text_hash (0)
     47 {
     48 }
     49 
     50 //----------------------------------------------------------------------
     51 // BreakpointOptions copy constructor
     52 //----------------------------------------------------------------------
     53 BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) :
     54     m_callback (rhs.m_callback),
     55     m_callback_baton_sp (rhs.m_callback_baton_sp),
     56     m_callback_is_synchronous (rhs.m_callback_is_synchronous),
     57     m_enabled (rhs.m_enabled),
     58     m_one_shot (rhs.m_one_shot),
     59     m_ignore_count (rhs.m_ignore_count),
     60     m_thread_spec_ap ()
     61 {
     62     if (rhs.m_thread_spec_ap.get() != NULL)
     63         m_thread_spec_ap.reset (new ThreadSpec(*rhs.m_thread_spec_ap.get()));
     64     m_condition_text = rhs.m_condition_text;
     65     m_condition_text_hash = rhs.m_condition_text_hash;
     66 }
     67 
     68 //----------------------------------------------------------------------
     69 // BreakpointOptions assignment operator
     70 //----------------------------------------------------------------------
     71 const BreakpointOptions&
     72 BreakpointOptions::operator=(const BreakpointOptions& rhs)
     73 {
     74     m_callback = rhs.m_callback;
     75     m_callback_baton_sp = rhs.m_callback_baton_sp;
     76     m_callback_is_synchronous = rhs.m_callback_is_synchronous;
     77     m_enabled = rhs.m_enabled;
     78     m_one_shot = rhs.m_one_shot;
     79     m_ignore_count = rhs.m_ignore_count;
     80     if (rhs.m_thread_spec_ap.get() != NULL)
     81         m_thread_spec_ap.reset(new ThreadSpec(*rhs.m_thread_spec_ap.get()));
     82     m_condition_text = rhs.m_condition_text;
     83     m_condition_text_hash = rhs.m_condition_text_hash;
     84     return *this;
     85 }
     86 
     87 BreakpointOptions *
     88 BreakpointOptions::CopyOptionsNoCallback (BreakpointOptions &orig)
     89 {
     90     BreakpointHitCallback orig_callback = orig.m_callback;
     91     lldb::BatonSP orig_callback_baton_sp = orig.m_callback_baton_sp;
     92     bool orig_is_sync = orig.m_callback_is_synchronous;
     93 
     94     orig.ClearCallback();
     95     BreakpointOptions *ret_val = new BreakpointOptions(orig);
     96 
     97     orig.SetCallback (orig_callback, orig_callback_baton_sp, orig_is_sync);
     98 
     99     return ret_val;
    100 }
    101 
    102 //----------------------------------------------------------------------
    103 // Destructor
    104 //----------------------------------------------------------------------
    105 BreakpointOptions::~BreakpointOptions()
    106 {
    107 }
    108 
    109 //------------------------------------------------------------------
    110 // Callbacks
    111 //------------------------------------------------------------------
    112 void
    113 BreakpointOptions::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool callback_is_synchronous)
    114 {
    115     m_callback_is_synchronous = callback_is_synchronous;
    116     m_callback = callback;
    117     m_callback_baton_sp = callback_baton_sp;
    118 }
    119 
    120 void
    121 BreakpointOptions::ClearCallback ()
    122 {
    123     m_callback = BreakpointOptions::NullCallback;
    124     m_callback_is_synchronous = false;
    125     m_callback_baton_sp.reset();
    126 }
    127 
    128 Baton *
    129 BreakpointOptions::GetBaton ()
    130 {
    131     return m_callback_baton_sp.get();
    132 }
    133 
    134 const Baton *
    135 BreakpointOptions::GetBaton () const
    136 {
    137     return m_callback_baton_sp.get();
    138 }
    139 
    140 bool
    141 BreakpointOptions::InvokeCallback (StoppointCallbackContext *context,
    142                                    lldb::user_id_t break_id,
    143                                    lldb::user_id_t break_loc_id)
    144 {
    145     if (m_callback && context->is_synchronous == IsCallbackSynchronous())
    146     {
    147         return m_callback (m_callback_baton_sp ? m_callback_baton_sp->m_data : NULL,
    148                            context,
    149                            break_id,
    150                            break_loc_id);
    151     }
    152     else
    153         return true;
    154 }
    155 
    156 bool
    157 BreakpointOptions::HasCallback ()
    158 {
    159     return m_callback != BreakpointOptions::NullCallback;
    160 }
    161 
    162 void
    163 BreakpointOptions::SetCondition (const char *condition)
    164 {
    165     if (!condition)
    166         condition = "";
    167 
    168     m_condition_text.assign(condition);
    169     std::hash<std::string> hasher;
    170     m_condition_text_hash = hasher(m_condition_text);
    171 }
    172 
    173 const char *
    174 BreakpointOptions::GetConditionText (size_t *hash) const
    175 {
    176     if (!m_condition_text.empty())
    177     {
    178         if (hash)
    179             *hash = m_condition_text_hash;
    180 
    181         return m_condition_text.c_str();
    182     }
    183     else
    184     {
    185         return NULL;
    186     }
    187 }
    188 
    189 const ThreadSpec *
    190 BreakpointOptions::GetThreadSpecNoCreate () const
    191 {
    192     return m_thread_spec_ap.get();
    193 }
    194 
    195 ThreadSpec *
    196 BreakpointOptions::GetThreadSpec ()
    197 {
    198     if (m_thread_spec_ap.get() == NULL)
    199         m_thread_spec_ap.reset (new ThreadSpec());
    200 
    201     return m_thread_spec_ap.get();
    202 }
    203 
    204 void
    205 BreakpointOptions::SetThreadID (lldb::tid_t thread_id)
    206 {
    207     GetThreadSpec()->SetTID(thread_id);
    208 }
    209 
    210 void
    211 BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const
    212 {
    213 
    214     // Figure out if there are any options not at their default value, and only print
    215     // anything if there are:
    216 
    217     if (m_ignore_count != 0 || !m_enabled || m_one_shot || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ()))
    218     {
    219         if (level == lldb::eDescriptionLevelVerbose)
    220         {
    221             s->EOL ();
    222             s->IndentMore();
    223             s->Indent();
    224             s->PutCString("Breakpoint Options:\n");
    225             s->IndentMore();
    226             s->Indent();
    227         }
    228         else
    229             s->PutCString(" Options: ");
    230 
    231         if (m_ignore_count > 0)
    232             s->Printf("ignore: %d ", m_ignore_count);
    233         s->Printf("%sabled ", m_enabled ? "en" : "dis");
    234 
    235         if (m_one_shot)
    236             s->Printf ("one-shot ");
    237 
    238         if (m_thread_spec_ap.get())
    239             m_thread_spec_ap->GetDescription (s, level);
    240         else if (level == eDescriptionLevelBrief)
    241             s->PutCString ("thread spec: no ");
    242         if (level == lldb::eDescriptionLevelFull)
    243         {
    244             s->IndentLess();
    245             s->IndentMore();
    246         }
    247     }
    248 
    249     if (m_callback_baton_sp.get())
    250     {
    251         if (level != eDescriptionLevelBrief)
    252         {
    253             s->EOL();
    254             m_callback_baton_sp->GetDescription (s, level);
    255         }
    256     }
    257     if (!m_condition_text.empty())
    258     {
    259        if (level != eDescriptionLevelBrief)
    260        {
    261             s->EOL();
    262             s->Printf("Condition: %s\n", m_condition_text.c_str());
    263         }
    264     }
    265 }
    266 
    267 void
    268 BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const
    269 {
    270     CommandData *data = (CommandData *)m_data;
    271 
    272     if (level == eDescriptionLevelBrief)
    273     {
    274         s->Printf (", commands = %s", (data && data->user_source.GetSize() > 0) ? "yes" : "no");
    275         return;
    276     }
    277 
    278     s->IndentMore ();
    279     s->Indent("Breakpoint commands:\n");
    280 
    281     s->IndentMore ();
    282     if (data && data->user_source.GetSize() > 0)
    283     {
    284         const size_t num_strings = data->user_source.GetSize();
    285         for (size_t i = 0; i < num_strings; ++i)
    286         {
    287             s->Indent(data->user_source.GetStringAtIndex(i));
    288             s->EOL();
    289         }
    290     }
    291     else
    292     {
    293         s->PutCString ("No commands.\n");
    294     }
    295     s->IndentLess ();
    296     s->IndentLess ();
    297 }
    298 
    299