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