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