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 70 bool 71 Watchpoint::IsHardware () const 72 { 73 return m_is_hardware; 74 } 75 76 // RETURNS - true if we should stop at this breakpoint, false if we 77 // should continue. 78 79 bool 80 Watchpoint::ShouldStop (StoppointCallbackContext *context) 81 { 82 ++m_hit_count; 83 84 if (!IsEnabled()) 85 return false; 86 87 if (m_hit_count <= GetIgnoreCount()) 88 return false; 89 90 return true; 91 } 92 93 void 94 Watchpoint::GetDescription (Stream *s, lldb::DescriptionLevel level) 95 { 96 DumpWithLevel(s, level); 97 return; 98 } 99 100 void 101 Watchpoint::Dump(Stream *s) const 102 { 103 DumpWithLevel(s, lldb::eDescriptionLevelBrief); 104 } 105 106 void 107 Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const 108 { 109 if (s == NULL) 110 return; 111 112 assert(description_level >= lldb::eDescriptionLevelBrief && 113 description_level <= lldb::eDescriptionLevelVerbose); 114 115 s->Printf("Watchpoint %u: addr = 0x%8.8llx size = %u state = %s type = %s%s", 116 GetID(), 117 (uint64_t)m_addr, 118 m_byte_size, 119 m_enabled ? "enabled" : "disabled", 120 m_watch_read ? "r" : "", 121 m_watch_write ? "w" : ""); 122 123 if (description_level >= lldb::eDescriptionLevelFull) { 124 if (m_decl_str.c_str()) 125 s->Printf("\n declare @ '%s'", m_decl_str.c_str()); 126 if (GetConditionText()) 127 s->Printf("\n condition = '%s'", GetConditionText()); 128 } 129 130 if (description_level >= lldb::eDescriptionLevelVerbose) 131 if (m_callback) 132 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u callback = %8p baton = %8p", 133 GetHardwareIndex(), 134 GetHitCount(), 135 GetIgnoreCount(), 136 m_callback, 137 m_callback_baton); 138 else 139 s->Printf("\n hw_index = %i hit_count = %-4u ignore_count = %-4u", 140 GetHardwareIndex(), 141 GetHitCount(), 142 GetIgnoreCount()); 143 } 144 145 bool 146 Watchpoint::IsEnabled() const 147 { 148 return m_enabled; 149 } 150 151 void 152 Watchpoint::SetEnabled(bool enabled) 153 { 154 if (!enabled) 155 SetHardwareIndex(LLDB_INVALID_INDEX32); 156 m_enabled = enabled; 157 } 158 159 void 160 Watchpoint::SetWatchpointType (uint32_t type) 161 { 162 m_watch_read = (type & LLDB_WATCH_TYPE_READ) != 0; 163 m_watch_write = (type & LLDB_WATCH_TYPE_WRITE) != 0; 164 } 165 166 bool 167 Watchpoint::WatchpointRead () const 168 { 169 return m_watch_read != 0; 170 } 171 bool 172 Watchpoint::WatchpointWrite () const 173 { 174 return m_watch_write != 0; 175 } 176 uint32_t 177 Watchpoint::GetIgnoreCount () const 178 { 179 return m_ignore_count; 180 } 181 182 void 183 Watchpoint::SetIgnoreCount (uint32_t n) 184 { 185 m_ignore_count = n; 186 } 187 188 bool 189 Watchpoint::InvokeCallback (StoppointCallbackContext *context) 190 { 191 if (m_callback && context->is_synchronous) 192 { 193 uint32_t access = 0; 194 if (m_watch_was_read) 195 access |= LLDB_WATCH_TYPE_READ; 196 if (m_watch_was_written) 197 access |= LLDB_WATCH_TYPE_WRITE; 198 return m_callback(m_callback_baton, context, GetID(), access); 199 } 200 else 201 return true; 202 } 203 204 void 205 Watchpoint::SetCondition (const char *condition) 206 { 207 if (condition == NULL || condition[0] == '\0') 208 { 209 if (m_condition_ap.get()) 210 m_condition_ap.reset(); 211 } 212 else 213 { 214 // Pass NULL for expr_prefix (no translation-unit level definitions). 215 m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny)); 216 } 217 } 218 219 const char * 220 Watchpoint::GetConditionText () const 221 { 222 if (m_condition_ap.get()) 223 return m_condition_ap->GetUserText(); 224 else 225 return NULL; 226 } 227 228