1 //===-- SBBreakpointLocation.cpp --------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/API/SBBreakpointLocation.h" 10 #include "lldb/API/SBAddress.h" 11 #include "lldb/API/SBDebugger.h" 12 #include "lldb/API/SBDefines.h" 13 #include "lldb/API/SBStream.h" 14 #include "lldb/API/SBStringList.h" 15 16 #include "lldb/Breakpoint/Breakpoint.h" 17 #include "lldb/Breakpoint/BreakpointLocation.h" 18 #include "lldb/Core/Debugger.h" 19 #include "lldb/Core/StreamFile.h" 20 #include "lldb/Interpreter/CommandInterpreter.h" 21 #include "lldb/Interpreter/ScriptInterpreter.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Target/ThreadSpec.h" 24 #include "lldb/Utility/Log.h" 25 #include "lldb/Utility/Stream.h" 26 #include "lldb/lldb-defines.h" 27 #include "lldb/lldb-types.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 SBBreakpointLocation::SBBreakpointLocation() {} 33 34 SBBreakpointLocation::SBBreakpointLocation( 35 const lldb::BreakpointLocationSP &break_loc_sp) 36 : m_opaque_wp(break_loc_sp) { 37 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 38 39 if (log) { 40 SBStream sstr; 41 GetDescription(sstr, lldb::eDescriptionLevelBrief); 42 LLDB_LOG(log, "location = {0} ({1})", break_loc_sp.get(), sstr.GetData()); 43 } 44 } 45 46 SBBreakpointLocation::SBBreakpointLocation(const SBBreakpointLocation &rhs) 47 : m_opaque_wp(rhs.m_opaque_wp) {} 48 49 const SBBreakpointLocation &SBBreakpointLocation:: 50 operator=(const SBBreakpointLocation &rhs) { 51 m_opaque_wp = rhs.m_opaque_wp; 52 return *this; 53 } 54 55 SBBreakpointLocation::~SBBreakpointLocation() {} 56 57 BreakpointLocationSP SBBreakpointLocation::GetSP() const { 58 return m_opaque_wp.lock(); 59 } 60 61 bool SBBreakpointLocation::IsValid() const { return bool(GetSP()); } 62 63 SBAddress SBBreakpointLocation::GetAddress() { 64 BreakpointLocationSP loc_sp = GetSP(); 65 if (loc_sp) 66 return SBAddress(&loc_sp->GetAddress()); 67 else 68 return SBAddress(); 69 } 70 71 addr_t SBBreakpointLocation::GetLoadAddress() { 72 addr_t ret_addr = LLDB_INVALID_ADDRESS; 73 BreakpointLocationSP loc_sp = GetSP(); 74 75 if (loc_sp) { 76 std::lock_guard<std::recursive_mutex> guard( 77 loc_sp->GetTarget().GetAPIMutex()); 78 ret_addr = loc_sp->GetLoadAddress(); 79 } 80 81 return ret_addr; 82 } 83 84 void SBBreakpointLocation::SetEnabled(bool enabled) { 85 BreakpointLocationSP loc_sp = GetSP(); 86 if (loc_sp) { 87 std::lock_guard<std::recursive_mutex> guard( 88 loc_sp->GetTarget().GetAPIMutex()); 89 loc_sp->SetEnabled(enabled); 90 } 91 } 92 93 bool SBBreakpointLocation::IsEnabled() { 94 BreakpointLocationSP loc_sp = GetSP(); 95 if (loc_sp) { 96 std::lock_guard<std::recursive_mutex> guard( 97 loc_sp->GetTarget().GetAPIMutex()); 98 return loc_sp->IsEnabled(); 99 } else 100 return false; 101 } 102 103 uint32_t SBBreakpointLocation::GetHitCount() { 104 BreakpointLocationSP loc_sp = GetSP(); 105 if (loc_sp) { 106 std::lock_guard<std::recursive_mutex> guard( 107 loc_sp->GetTarget().GetAPIMutex()); 108 return loc_sp->GetHitCount(); 109 } else 110 return 0; 111 } 112 113 uint32_t SBBreakpointLocation::GetIgnoreCount() { 114 BreakpointLocationSP loc_sp = GetSP(); 115 if (loc_sp) { 116 std::lock_guard<std::recursive_mutex> guard( 117 loc_sp->GetTarget().GetAPIMutex()); 118 return loc_sp->GetIgnoreCount(); 119 } else 120 return 0; 121 } 122 123 void SBBreakpointLocation::SetIgnoreCount(uint32_t n) { 124 BreakpointLocationSP loc_sp = GetSP(); 125 if (loc_sp) { 126 std::lock_guard<std::recursive_mutex> guard( 127 loc_sp->GetTarget().GetAPIMutex()); 128 loc_sp->SetIgnoreCount(n); 129 } 130 } 131 132 void SBBreakpointLocation::SetCondition(const char *condition) { 133 BreakpointLocationSP loc_sp = GetSP(); 134 if (loc_sp) { 135 std::lock_guard<std::recursive_mutex> guard( 136 loc_sp->GetTarget().GetAPIMutex()); 137 loc_sp->SetCondition(condition); 138 } 139 } 140 141 const char *SBBreakpointLocation::GetCondition() { 142 BreakpointLocationSP loc_sp = GetSP(); 143 if (loc_sp) { 144 std::lock_guard<std::recursive_mutex> guard( 145 loc_sp->GetTarget().GetAPIMutex()); 146 return loc_sp->GetConditionText(); 147 } 148 return NULL; 149 } 150 151 void SBBreakpointLocation::SetAutoContinue(bool auto_continue) { 152 BreakpointLocationSP loc_sp = GetSP(); 153 if (loc_sp) { 154 std::lock_guard<std::recursive_mutex> guard( 155 loc_sp->GetTarget().GetAPIMutex()); 156 loc_sp->SetAutoContinue(auto_continue); 157 } 158 } 159 160 bool SBBreakpointLocation::GetAutoContinue() { 161 BreakpointLocationSP loc_sp = GetSP(); 162 if (loc_sp) { 163 std::lock_guard<std::recursive_mutex> guard( 164 loc_sp->GetTarget().GetAPIMutex()); 165 return loc_sp->IsAutoContinue(); 166 } 167 return false; 168 } 169 170 void SBBreakpointLocation::SetScriptCallbackFunction( 171 const char *callback_function_name) { 172 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 173 BreakpointLocationSP loc_sp = GetSP(); 174 LLDB_LOG(log, "location = {0}, callback = {1}", loc_sp.get(), 175 callback_function_name); 176 177 if (loc_sp) { 178 std::lock_guard<std::recursive_mutex> guard( 179 loc_sp->GetTarget().GetAPIMutex()); 180 BreakpointOptions *bp_options = loc_sp->GetLocationOptions(); 181 loc_sp->GetBreakpoint() 182 .GetTarget() 183 .GetDebugger() 184 .GetCommandInterpreter() 185 .GetScriptInterpreter() 186 ->SetBreakpointCommandCallbackFunction(bp_options, 187 callback_function_name); 188 } 189 } 190 191 SBError 192 SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) { 193 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 194 BreakpointLocationSP loc_sp = GetSP(); 195 LLDB_LOG(log, "location = {0}: callback body:\n{1}", loc_sp.get(), 196 callback_body_text); 197 198 SBError sb_error; 199 if (loc_sp) { 200 std::lock_guard<std::recursive_mutex> guard( 201 loc_sp->GetTarget().GetAPIMutex()); 202 BreakpointOptions *bp_options = loc_sp->GetLocationOptions(); 203 Status error = 204 loc_sp->GetBreakpoint() 205 .GetTarget() 206 .GetDebugger() 207 .GetCommandInterpreter() 208 .GetScriptInterpreter() 209 ->SetBreakpointCommandCallback(bp_options, callback_body_text); 210 sb_error.SetError(error); 211 } else 212 sb_error.SetErrorString("invalid breakpoint"); 213 214 return sb_error; 215 } 216 217 void SBBreakpointLocation::SetCommandLineCommands(SBStringList &commands) { 218 BreakpointLocationSP loc_sp = GetSP(); 219 if (!loc_sp) 220 return; 221 if (commands.GetSize() == 0) 222 return; 223 224 std::lock_guard<std::recursive_mutex> guard( 225 loc_sp->GetTarget().GetAPIMutex()); 226 std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up( 227 new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); 228 229 loc_sp->GetLocationOptions()->SetCommandDataCallback(cmd_data_up); 230 } 231 232 bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) { 233 BreakpointLocationSP loc_sp = GetSP(); 234 if (!loc_sp) 235 return false; 236 StringList command_list; 237 bool has_commands = 238 loc_sp->GetLocationOptions()->GetCommandLineCallbacks(command_list); 239 if (has_commands) 240 commands.AppendList(command_list); 241 return has_commands; 242 } 243 244 void SBBreakpointLocation::SetThreadID(tid_t thread_id) { 245 BreakpointLocationSP loc_sp = GetSP(); 246 if (loc_sp) { 247 std::lock_guard<std::recursive_mutex> guard( 248 loc_sp->GetTarget().GetAPIMutex()); 249 loc_sp->SetThreadID(thread_id); 250 } 251 } 252 253 tid_t SBBreakpointLocation::GetThreadID() { 254 tid_t tid = LLDB_INVALID_THREAD_ID; 255 BreakpointLocationSP loc_sp = GetSP(); 256 if (loc_sp) { 257 std::lock_guard<std::recursive_mutex> guard( 258 loc_sp->GetTarget().GetAPIMutex()); 259 return loc_sp->GetThreadID(); 260 } 261 return tid; 262 } 263 264 void SBBreakpointLocation::SetThreadIndex(uint32_t index) { 265 BreakpointLocationSP loc_sp = GetSP(); 266 if (loc_sp) { 267 std::lock_guard<std::recursive_mutex> guard( 268 loc_sp->GetTarget().GetAPIMutex()); 269 loc_sp->SetThreadIndex(index); 270 } 271 } 272 273 uint32_t SBBreakpointLocation::GetThreadIndex() const { 274 uint32_t thread_idx = UINT32_MAX; 275 BreakpointLocationSP loc_sp = GetSP(); 276 if (loc_sp) { 277 std::lock_guard<std::recursive_mutex> guard( 278 loc_sp->GetTarget().GetAPIMutex()); 279 return loc_sp->GetThreadIndex(); 280 } 281 return thread_idx; 282 } 283 284 void SBBreakpointLocation::SetThreadName(const char *thread_name) { 285 BreakpointLocationSP loc_sp = GetSP(); 286 if (loc_sp) { 287 std::lock_guard<std::recursive_mutex> guard( 288 loc_sp->GetTarget().GetAPIMutex()); 289 loc_sp->SetThreadName(thread_name); 290 } 291 } 292 293 const char *SBBreakpointLocation::GetThreadName() const { 294 BreakpointLocationSP loc_sp = GetSP(); 295 if (loc_sp) { 296 std::lock_guard<std::recursive_mutex> guard( 297 loc_sp->GetTarget().GetAPIMutex()); 298 return loc_sp->GetThreadName(); 299 } 300 return NULL; 301 } 302 303 void SBBreakpointLocation::SetQueueName(const char *queue_name) { 304 BreakpointLocationSP loc_sp = GetSP(); 305 if (loc_sp) { 306 std::lock_guard<std::recursive_mutex> guard( 307 loc_sp->GetTarget().GetAPIMutex()); 308 loc_sp->SetQueueName(queue_name); 309 } 310 } 311 312 const char *SBBreakpointLocation::GetQueueName() const { 313 BreakpointLocationSP loc_sp = GetSP(); 314 if (loc_sp) { 315 std::lock_guard<std::recursive_mutex> guard( 316 loc_sp->GetTarget().GetAPIMutex()); 317 loc_sp->GetQueueName(); 318 } 319 return NULL; 320 } 321 322 bool SBBreakpointLocation::IsResolved() { 323 BreakpointLocationSP loc_sp = GetSP(); 324 if (loc_sp) { 325 std::lock_guard<std::recursive_mutex> guard( 326 loc_sp->GetTarget().GetAPIMutex()); 327 return loc_sp->IsResolved(); 328 } 329 return false; 330 } 331 332 void SBBreakpointLocation::SetLocation( 333 const lldb::BreakpointLocationSP &break_loc_sp) { 334 // Uninstall the callbacks? 335 m_opaque_wp = break_loc_sp; 336 } 337 338 bool SBBreakpointLocation::GetDescription(SBStream &description, 339 DescriptionLevel level) { 340 Stream &strm = description.ref(); 341 BreakpointLocationSP loc_sp = GetSP(); 342 343 if (loc_sp) { 344 std::lock_guard<std::recursive_mutex> guard( 345 loc_sp->GetTarget().GetAPIMutex()); 346 loc_sp->GetDescription(&strm, level); 347 strm.EOL(); 348 } else 349 strm.PutCString("No value"); 350 351 return true; 352 } 353 354 break_id_t SBBreakpointLocation::GetID() { 355 BreakpointLocationSP loc_sp = GetSP(); 356 if (loc_sp) { 357 std::lock_guard<std::recursive_mutex> guard( 358 loc_sp->GetTarget().GetAPIMutex()); 359 return loc_sp->GetID(); 360 } else 361 return LLDB_INVALID_BREAK_ID; 362 } 363 364 SBBreakpoint SBBreakpointLocation::GetBreakpoint() { 365 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); 366 BreakpointLocationSP loc_sp = GetSP(); 367 368 SBBreakpoint sb_bp; 369 if (loc_sp) { 370 std::lock_guard<std::recursive_mutex> guard( 371 loc_sp->GetTarget().GetAPIMutex()); 372 sb_bp = loc_sp->GetBreakpoint().shared_from_this(); 373 } 374 375 if (log) { 376 SBStream sstr; 377 sb_bp.GetDescription(sstr); 378 LLDB_LOG(log, "location = {0}, breakpoint = {1} ({2})", loc_sp.get(), 379 sb_bp.GetSP().get(), sstr.GetData()); 380 } 381 return sb_bp; 382 } 383