1 //===-- Watchpoint.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 #include "lldb/Breakpoint/Watchpoint.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Breakpoint/StoppointCallbackContext.h" 17 #include "lldb/Core/Stream.h" 18 #include "lldb/Target/Process.h" 19 #include "lldb/Target/Target.h" 20 #include "lldb/Target/ThreadSpec.h" 21 #include "lldb/Target/ThreadPlanTestCondition.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 Watchpoint::Watchpoint (lldb::addr_t addr, size_t size, bool hardware) : 27 StoppointLocation (GetNextID(), addr, size, hardware), 28 m_target(NULL), 29 m_enabled(0), 30 m_is_hardware(hardware), 31 m_watch_read(0), 32 m_watch_write(0), 33 m_watch_was_read(0), 34 m_watch_was_written(0), 35 m_ignore_count(0), 36 m_callback(NULL), 37 m_callback_baton(NULL), 38 m_decl_str(), 39 m_error() 40 { 41 } 42 43 Watchpoint::~Watchpoint() 44 { 45 } 46 47 break_id_t 48 Watchpoint::GetNextID() 49 { 50 static break_id_t g_next_ID = 0; 51 return ++g_next_ID; 52 } 53 54 bool 55 Watchpoint::SetCallback (WatchpointHitCallback callback, void *callback_baton) 56 { 57 m_callback = callback; 58 m_callback_baton = callback_baton; 59 return true; 60 } 61 62 void 63 Watchpoint::SetDeclInfo (std::string &str) 64 { 65 m_decl_str = str; 66 return; 67 } 68 69 // Override default impl of StoppointLocation::IsHardware() since m_is_hardware 70 // member field is more accurate. 71 bool 72 Watchpoint::IsHardware () const 73 { 74 return m_is_hardware; 75 } 76 77 // RETURNS - true if we should stop at this breakpoint, false if we 78 // should continue. 79 80 bool 81 Watchpoint::ShouldStop (StoppointCallbackContext *context) 82 { 83 IncrementHitCount(); 84 85 if (!IsEnabled()) 86 return false; 87 88 if (GetHitCount() <= GetIgnoreCount()) 89 return false; 90 91 return true; 92 } 93 94 void 95 Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level) 96 { 97 DumpWithLevel(s, level); 98 return; 99 } 100 101 void 102 Watchpoint::Dump(Stream *s) const 103 { 104 DumpWithLevel(s, lldb::eDescriptionLevelBrief); 105 } 106 107 void 108 Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const 109 { 110 if (s == NULL) 111 return; 112 113 assert(description_level >= lldb::eDescriptionLevelBrief && 114 description_level <= lldb::eDescriptionLevelVerbose); 115 116 s->Printf("Watchpoint %u: addr = 0x%8.8llx size = %u state = %s type = %s%s", 117 GetID(), 118 GetLoadAddress(), 119 m_byte_size, 120 m_enabled ? "enabled" : "disabled", 121 m_watch_read ? "r" : "", 122 m_watch_write ? "w" : ""); 123 124 if (description_level >= lldb::eDescriptionLevelFull) { 125 if (!m_decl_str.empty()) 126 s->Printf("\n declare @ '%s'", m_decl_str.c_str()); 127 if (GetConditionText()) 128 s->Printf("\n condition = '%s'", GetConditionText()); 129 } 130 131 if (description_level >= lldb::eDescriptionLevelVerbose) 132 if (m_callback) 133 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u callback = %8p baton = %8p", 134 GetHardwareIndex(), 135 GetHitCount(), 136 GetIgnoreCount(), 137 m_callback, 138 m_callback_baton); 139 else 140 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u", 141 GetHardwareIndex(), 142 GetHitCount(), 143 GetIgnoreCount()); 144 } 145 146 bool 147 Watchpoint::IsEnabled() const 148 { 149 return m_enabled; 150 } 151 152 void 153 Watchpoint::SetEnabled(bool enabled) 154 { 155 if (!enabled) 156 SetHardwareIndex(LLDB_INVALID_INDEX32); 157 m_enabled = enabled; 158 } 159 160 void 161 Watchpoint::SetWatchpointType (uint32_t type) 162 { 163 m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0; 164 m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0; 165 } 166 167 bool 168 Watchpoint::WatchpointRead () const 169 { 170 return m_watch_read != 0; 171 } 172 bool 173 Watchpoint::WatchpointWrite () const 174 { 175 return m_watch_write != 0; 176 } 177 uint32_t 178 Watchpoint::GetIgnoreCount () const 179 { 180 return m_ignore_count; 181 } 182 183 void 184 Watchpoint::SetIgnoreCount (uint32_t n) 185 { 186 m_ignore_count = n; 187 } 188 189 bool 190 Watchpoint::InvokeCallback (StoppointCallbackContext *context) 191 { 192 if (m_callback && context->is_synchronous) 193 { 194 uint32_t access = 0; 195 if (m_watch_was_read) 196 access |= LLDB_WATCH_TYPE_READ; 197 if (m_watch_was_written) 198 access |= LLDB_WATCH_TYPE_WRITE; 199 return m_callback(m_callback_baton, context, GetID(), access); 200 } 201 else 202 return true; 203 } 204 205 void 206 Watchpoint::SetCondition (const char *condition) 207 { 208 if (condition == NULL || condition[0] == '\0') 209 { 210 if (m_condition_ap.get()) 211 m_condition_ap.reset(); 212 } 213 else 214 { 215 // Pass NULL for expr_prefix (no translation-unit level definitions). 216 m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny)); 217 } 218 } 219 220 const char * 221 Watchpoint::GetConditionText () const 222 { 223 if (m_condition_ap.get()) 224 return m_condition_ap->GetUserText(); 225 else 226 return NULL; 227 } 228 229