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 (NULL), 45 m_condition_ap() 46 { 47 } 48 49 //---------------------------------------------------------------------- 50 // BreakpointOptions copy constructor 51 //---------------------------------------------------------------------- 52 BreakpointOptions::BreakpointOptions(const BreakpointOptions& rhs) : 53 m_callback (rhs.m_callback), 54 m_callback_baton_sp (rhs.m_callback_baton_sp), 55 m_callback_is_synchronous (rhs.m_callback_is_synchronous), 56 m_enabled (rhs.m_enabled), 57 m_one_shot (rhs.m_one_shot), 58 m_ignore_count (rhs.m_ignore_count), 59 m_thread_spec_ap (NULL), 60 m_condition_ap (NULL) 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 if (rhs.m_condition_ap.get()) 65 m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny)); 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 if (rhs.m_condition_ap.get()) 83 m_condition_ap.reset (new ClangUserExpression (rhs.m_condition_ap->GetUserText(), NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny)); 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 == NULL || condition[0] == '\0') 166 { 167 if (m_condition_ap.get()) 168 m_condition_ap.reset(); 169 } 170 else 171 { 172 m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny)); 173 } 174 } 175 176 const char * 177 BreakpointOptions::GetConditionText () const 178 { 179 if (m_condition_ap.get()) 180 return m_condition_ap->GetUserText(); 181 else 182 return NULL; 183 } 184 185 const ThreadSpec * 186 BreakpointOptions::GetThreadSpecNoCreate () const 187 { 188 return m_thread_spec_ap.get(); 189 } 190 191 ThreadSpec * 192 BreakpointOptions::GetThreadSpec () 193 { 194 if (m_thread_spec_ap.get() == NULL) 195 m_thread_spec_ap.reset (new ThreadSpec()); 196 197 return m_thread_spec_ap.get(); 198 } 199 200 void 201 BreakpointOptions::SetThreadID (lldb::tid_t thread_id) 202 { 203 GetThreadSpec()->SetTID(thread_id); 204 } 205 206 void 207 BreakpointOptions::GetDescription (Stream *s, lldb::DescriptionLevel level) const 208 { 209 210 // Figure out if there are any options not at their default value, and only print 211 // anything if there are: 212 213 if (m_ignore_count != 0 || !m_enabled || m_one_shot || (GetThreadSpecNoCreate() != NULL && GetThreadSpecNoCreate()->HasSpecification ())) 214 { 215 if (level == lldb::eDescriptionLevelVerbose) 216 { 217 s->EOL (); 218 s->IndentMore(); 219 s->Indent(); 220 s->PutCString("Breakpoint Options:\n"); 221 s->IndentMore(); 222 s->Indent(); 223 } 224 else 225 s->PutCString(" Options: "); 226 227 if (m_ignore_count > 0) 228 s->Printf("ignore: %d ", m_ignore_count); 229 s->Printf("%sabled ", m_enabled ? "en" : "dis"); 230 231 if (m_one_shot) 232 s->Printf ("one-shot "); 233 234 if (m_thread_spec_ap.get()) 235 m_thread_spec_ap->GetDescription (s, level); 236 else if (level == eDescriptionLevelBrief) 237 s->PutCString ("thread spec: no "); 238 if (level == lldb::eDescriptionLevelFull) 239 { 240 s->IndentLess(); 241 s->IndentMore(); 242 } 243 } 244 245 if (m_callback_baton_sp.get()) 246 { 247 if (level != eDescriptionLevelBrief) 248 { 249 s->EOL(); 250 m_callback_baton_sp->GetDescription (s, level); 251 } 252 } 253 if (m_condition_ap.get()) 254 { 255 if (level != eDescriptionLevelBrief) 256 { 257 s->EOL(); 258 s->Printf("Condition: %s\n", m_condition_ap->GetUserText()); 259 } 260 } 261 } 262 263 void 264 BreakpointOptions::CommandBaton::GetDescription (Stream *s, lldb::DescriptionLevel level) const 265 { 266 CommandData *data = (CommandData *)m_data; 267 268 if (level == eDescriptionLevelBrief) 269 { 270 s->Printf (", commands = %s", (data && data->user_source.GetSize() > 0) ? "yes" : "no"); 271 return; 272 } 273 274 s->IndentMore (); 275 s->Indent("Breakpoint commands:\n"); 276 277 s->IndentMore (); 278 if (data && data->user_source.GetSize() > 0) 279 { 280 const size_t num_strings = data->user_source.GetSize(); 281 for (size_t i = 0; i < num_strings; ++i) 282 { 283 s->Indent(data->user_source.GetStringAtIndex(i)); 284 s->EOL(); 285 } 286 } 287 else 288 { 289 s->PutCString ("No commands.\n"); 290 } 291 s->IndentLess (); 292 s->IndentLess (); 293 } 294 295