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