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