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/Value.h" 18 #include "lldb/Target/Process.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Target/ThreadSpec.h" 21 #include "lldb/Utility/Stream.h" 22 #include "lldb/Utility/StringList.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 anything if there are: 147 148 if ((GetThreadSpecNoCreate() != nullptr && 149 GetThreadSpecNoCreate()->HasSpecification())) { 150 if (level == lldb::eDescriptionLevelVerbose) { 151 s->EOL(); 152 s->IndentMore(); 153 s->Indent(); 154 s->PutCString("Watchpoint Options:\n"); 155 s->IndentMore(); 156 s->Indent(); 157 } else 158 s->PutCString(" Options: "); 159 160 if (m_thread_spec_ap.get()) 161 m_thread_spec_ap->GetDescription(s, level); 162 else if (level == eDescriptionLevelBrief) 163 s->PutCString("thread spec: no "); 164 if (level == lldb::eDescriptionLevelFull) { 165 s->IndentLess(); 166 s->IndentMore(); 167 } 168 } 169 170 GetCallbackDescription(s, level); 171 } 172 173 void WatchpointOptions::CommandBaton::GetDescription( 174 Stream *s, lldb::DescriptionLevel level) const { 175 const CommandData *data = getItem(); 176 177 if (level == eDescriptionLevelBrief) { 178 s->Printf(", commands = %s", 179 (data && data->user_source.GetSize() > 0) ? "yes" : "no"); 180 return; 181 } 182 183 s->IndentMore(); 184 s->Indent("watchpoint commands:\n"); 185 186 s->IndentMore(); 187 if (data && data->user_source.GetSize() > 0) { 188 const size_t num_strings = data->user_source.GetSize(); 189 for (size_t i = 0; i < num_strings; ++i) { 190 s->Indent(data->user_source.GetStringAtIndex(i)); 191 s->EOL(); 192 } 193 } else { 194 s->PutCString("No commands.\n"); 195 } 196 s->IndentLess(); 197 s->IndentLess(); 198 } 199