1 //===-- SBBreakpointLocation.cpp ------------------------------------------===// 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 #include "lldb/API/SBStructuredData.h" 16 #include "lldb/Utility/Instrumentation.h" 17 18 #include "lldb/Breakpoint/Breakpoint.h" 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Core/Debugger.h" 21 #include "lldb/Core/StreamFile.h" 22 #include "lldb/Core/StructuredDataImpl.h" 23 #include "lldb/Interpreter/CommandInterpreter.h" 24 #include "lldb/Interpreter/ScriptInterpreter.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/ThreadSpec.h" 27 #include "lldb/Utility/Stream.h" 28 #include "lldb/lldb-defines.h" 29 #include "lldb/lldb-types.h" 30 31 #include "SBBreakpointOptionCommon.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 SBBreakpointLocation::SBBreakpointLocation() { LLDB_INSTRUMENT_VA(this); } 37 38 SBBreakpointLocation::SBBreakpointLocation( 39 const lldb::BreakpointLocationSP &break_loc_sp) 40 : m_opaque_wp(break_loc_sp) { 41 LLDB_INSTRUMENT_VA(this, break_loc_sp); 42 } 43 44 SBBreakpointLocation::SBBreakpointLocation(const SBBreakpointLocation &rhs) 45 : m_opaque_wp(rhs.m_opaque_wp) { 46 LLDB_INSTRUMENT_VA(this, rhs); 47 } 48 49 const SBBreakpointLocation &SBBreakpointLocation:: 50 operator=(const SBBreakpointLocation &rhs) { 51 LLDB_INSTRUMENT_VA(this, rhs); 52 53 m_opaque_wp = rhs.m_opaque_wp; 54 return *this; 55 } 56 57 SBBreakpointLocation::~SBBreakpointLocation() = default; 58 59 BreakpointLocationSP SBBreakpointLocation::GetSP() const { 60 return m_opaque_wp.lock(); 61 } 62 63 bool SBBreakpointLocation::IsValid() const { 64 LLDB_INSTRUMENT_VA(this); 65 return this->operator bool(); 66 } 67 SBBreakpointLocation::operator bool() const { 68 LLDB_INSTRUMENT_VA(this); 69 70 return bool(GetSP()); 71 } 72 73 SBAddress SBBreakpointLocation::GetAddress() { 74 LLDB_INSTRUMENT_VA(this); 75 76 BreakpointLocationSP loc_sp = GetSP(); 77 if (loc_sp) { 78 return SBAddress(loc_sp->GetAddress()); 79 } 80 81 return SBAddress(); 82 } 83 84 addr_t SBBreakpointLocation::GetLoadAddress() { 85 LLDB_INSTRUMENT_VA(this); 86 87 addr_t ret_addr = LLDB_INVALID_ADDRESS; 88 BreakpointLocationSP loc_sp = GetSP(); 89 90 if (loc_sp) { 91 std::lock_guard<std::recursive_mutex> guard( 92 loc_sp->GetTarget().GetAPIMutex()); 93 ret_addr = loc_sp->GetLoadAddress(); 94 } 95 96 return ret_addr; 97 } 98 99 void SBBreakpointLocation::SetEnabled(bool enabled) { 100 LLDB_INSTRUMENT_VA(this, enabled); 101 102 BreakpointLocationSP loc_sp = GetSP(); 103 if (loc_sp) { 104 std::lock_guard<std::recursive_mutex> guard( 105 loc_sp->GetTarget().GetAPIMutex()); 106 loc_sp->SetEnabled(enabled); 107 } 108 } 109 110 bool SBBreakpointLocation::IsEnabled() { 111 LLDB_INSTRUMENT_VA(this); 112 113 BreakpointLocationSP loc_sp = GetSP(); 114 if (loc_sp) { 115 std::lock_guard<std::recursive_mutex> guard( 116 loc_sp->GetTarget().GetAPIMutex()); 117 return loc_sp->IsEnabled(); 118 } else 119 return false; 120 } 121 122 uint32_t SBBreakpointLocation::GetHitCount() { 123 LLDB_INSTRUMENT_VA(this); 124 125 BreakpointLocationSP loc_sp = GetSP(); 126 if (loc_sp) { 127 std::lock_guard<std::recursive_mutex> guard( 128 loc_sp->GetTarget().GetAPIMutex()); 129 return loc_sp->GetHitCount(); 130 } else 131 return 0; 132 } 133 134 uint32_t SBBreakpointLocation::GetIgnoreCount() { 135 LLDB_INSTRUMENT_VA(this); 136 137 BreakpointLocationSP loc_sp = GetSP(); 138 if (loc_sp) { 139 std::lock_guard<std::recursive_mutex> guard( 140 loc_sp->GetTarget().GetAPIMutex()); 141 return loc_sp->GetIgnoreCount(); 142 } else 143 return 0; 144 } 145 146 void SBBreakpointLocation::SetIgnoreCount(uint32_t n) { 147 LLDB_INSTRUMENT_VA(this, n); 148 149 BreakpointLocationSP loc_sp = GetSP(); 150 if (loc_sp) { 151 std::lock_guard<std::recursive_mutex> guard( 152 loc_sp->GetTarget().GetAPIMutex()); 153 loc_sp->SetIgnoreCount(n); 154 } 155 } 156 157 void SBBreakpointLocation::SetCondition(const char *condition) { 158 LLDB_INSTRUMENT_VA(this, condition); 159 160 BreakpointLocationSP loc_sp = GetSP(); 161 if (loc_sp) { 162 std::lock_guard<std::recursive_mutex> guard( 163 loc_sp->GetTarget().GetAPIMutex()); 164 loc_sp->SetCondition(condition); 165 } 166 } 167 168 const char *SBBreakpointLocation::GetCondition() { 169 LLDB_INSTRUMENT_VA(this); 170 171 BreakpointLocationSP loc_sp = GetSP(); 172 if (loc_sp) { 173 std::lock_guard<std::recursive_mutex> guard( 174 loc_sp->GetTarget().GetAPIMutex()); 175 return loc_sp->GetConditionText(); 176 } 177 return nullptr; 178 } 179 180 void SBBreakpointLocation::SetAutoContinue(bool auto_continue) { 181 LLDB_INSTRUMENT_VA(this, auto_continue); 182 183 BreakpointLocationSP loc_sp = GetSP(); 184 if (loc_sp) { 185 std::lock_guard<std::recursive_mutex> guard( 186 loc_sp->GetTarget().GetAPIMutex()); 187 loc_sp->SetAutoContinue(auto_continue); 188 } 189 } 190 191 bool SBBreakpointLocation::GetAutoContinue() { 192 LLDB_INSTRUMENT_VA(this); 193 194 BreakpointLocationSP loc_sp = GetSP(); 195 if (loc_sp) { 196 std::lock_guard<std::recursive_mutex> guard( 197 loc_sp->GetTarget().GetAPIMutex()); 198 return loc_sp->IsAutoContinue(); 199 } 200 return false; 201 } 202 203 void SBBreakpointLocation::SetCallback(SBBreakpointHitCallback callback, 204 void *baton) { 205 LLDB_INSTRUMENT_VA(this, callback, baton); 206 207 BreakpointLocationSP loc_sp = GetSP(); 208 209 if (loc_sp) { 210 std::lock_guard<std::recursive_mutex> guard( 211 loc_sp->GetTarget().GetAPIMutex()); 212 BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton)); 213 loc_sp->SetCallback(SBBreakpointCallbackBaton::PrivateBreakpointHitCallback, 214 baton_sp, false); 215 } 216 } 217 218 void SBBreakpointLocation::SetScriptCallbackFunction( 219 const char *callback_function_name) { 220 LLDB_INSTRUMENT_VA(this, callback_function_name); 221 } 222 223 SBError SBBreakpointLocation::SetScriptCallbackFunction( 224 const char *callback_function_name, 225 SBStructuredData &extra_args) { 226 LLDB_INSTRUMENT_VA(this, callback_function_name, extra_args); 227 SBError sb_error; 228 BreakpointLocationSP loc_sp = GetSP(); 229 230 if (loc_sp) { 231 Status error; 232 std::lock_guard<std::recursive_mutex> guard( 233 loc_sp->GetTarget().GetAPIMutex()); 234 BreakpointOptions &bp_options = loc_sp->GetLocationOptions(); 235 error = loc_sp->GetBreakpoint() 236 .GetTarget() 237 .GetDebugger() 238 .GetScriptInterpreter() 239 ->SetBreakpointCommandCallbackFunction(bp_options, 240 callback_function_name, 241 extra_args.m_impl_up 242 ->GetObjectSP()); 243 sb_error.SetError(error); 244 } else 245 sb_error.SetErrorString("invalid breakpoint"); 246 247 return sb_error; 248 } 249 250 SBError 251 SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) { 252 LLDB_INSTRUMENT_VA(this, callback_body_text); 253 254 BreakpointLocationSP loc_sp = GetSP(); 255 256 SBError sb_error; 257 if (loc_sp) { 258 std::lock_guard<std::recursive_mutex> guard( 259 loc_sp->GetTarget().GetAPIMutex()); 260 BreakpointOptions &bp_options = loc_sp->GetLocationOptions(); 261 Status error = 262 loc_sp->GetBreakpoint() 263 .GetTarget() 264 .GetDebugger() 265 .GetScriptInterpreter() 266 ->SetBreakpointCommandCallback(bp_options, callback_body_text); 267 sb_error.SetError(error); 268 } else 269 sb_error.SetErrorString("invalid breakpoint"); 270 271 return sb_error; 272 } 273 274 void SBBreakpointLocation::SetCommandLineCommands(SBStringList &commands) { 275 LLDB_INSTRUMENT_VA(this, commands); 276 277 BreakpointLocationSP loc_sp = GetSP(); 278 if (!loc_sp) 279 return; 280 if (commands.GetSize() == 0) 281 return; 282 283 std::lock_guard<std::recursive_mutex> guard( 284 loc_sp->GetTarget().GetAPIMutex()); 285 std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up( 286 new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); 287 288 loc_sp->GetLocationOptions().SetCommandDataCallback(cmd_data_up); 289 } 290 291 bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) { 292 LLDB_INSTRUMENT_VA(this, commands); 293 294 BreakpointLocationSP loc_sp = GetSP(); 295 if (!loc_sp) 296 return false; 297 StringList command_list; 298 bool has_commands = 299 loc_sp->GetLocationOptions().GetCommandLineCallbacks(command_list); 300 if (has_commands) 301 commands.AppendList(command_list); 302 return has_commands; 303 } 304 305 void SBBreakpointLocation::SetThreadID(tid_t thread_id) { 306 LLDB_INSTRUMENT_VA(this, thread_id); 307 308 BreakpointLocationSP loc_sp = GetSP(); 309 if (loc_sp) { 310 std::lock_guard<std::recursive_mutex> guard( 311 loc_sp->GetTarget().GetAPIMutex()); 312 loc_sp->SetThreadID(thread_id); 313 } 314 } 315 316 tid_t SBBreakpointLocation::GetThreadID() { 317 LLDB_INSTRUMENT_VA(this); 318 319 tid_t tid = LLDB_INVALID_THREAD_ID; 320 BreakpointLocationSP loc_sp = GetSP(); 321 if (loc_sp) { 322 std::lock_guard<std::recursive_mutex> guard( 323 loc_sp->GetTarget().GetAPIMutex()); 324 return loc_sp->GetThreadID(); 325 } 326 return tid; 327 } 328 329 void SBBreakpointLocation::SetThreadIndex(uint32_t index) { 330 LLDB_INSTRUMENT_VA(this, index); 331 332 BreakpointLocationSP loc_sp = GetSP(); 333 if (loc_sp) { 334 std::lock_guard<std::recursive_mutex> guard( 335 loc_sp->GetTarget().GetAPIMutex()); 336 loc_sp->SetThreadIndex(index); 337 } 338 } 339 340 uint32_t SBBreakpointLocation::GetThreadIndex() const { 341 LLDB_INSTRUMENT_VA(this); 342 343 uint32_t thread_idx = UINT32_MAX; 344 BreakpointLocationSP loc_sp = GetSP(); 345 if (loc_sp) { 346 std::lock_guard<std::recursive_mutex> guard( 347 loc_sp->GetTarget().GetAPIMutex()); 348 return loc_sp->GetThreadIndex(); 349 } 350 return thread_idx; 351 } 352 353 void SBBreakpointLocation::SetThreadName(const char *thread_name) { 354 LLDB_INSTRUMENT_VA(this, thread_name); 355 356 BreakpointLocationSP loc_sp = GetSP(); 357 if (loc_sp) { 358 std::lock_guard<std::recursive_mutex> guard( 359 loc_sp->GetTarget().GetAPIMutex()); 360 loc_sp->SetThreadName(thread_name); 361 } 362 } 363 364 const char *SBBreakpointLocation::GetThreadName() const { 365 LLDB_INSTRUMENT_VA(this); 366 367 BreakpointLocationSP loc_sp = GetSP(); 368 if (loc_sp) { 369 std::lock_guard<std::recursive_mutex> guard( 370 loc_sp->GetTarget().GetAPIMutex()); 371 return loc_sp->GetThreadName(); 372 } 373 return nullptr; 374 } 375 376 void SBBreakpointLocation::SetQueueName(const char *queue_name) { 377 LLDB_INSTRUMENT_VA(this, queue_name); 378 379 BreakpointLocationSP loc_sp = GetSP(); 380 if (loc_sp) { 381 std::lock_guard<std::recursive_mutex> guard( 382 loc_sp->GetTarget().GetAPIMutex()); 383 loc_sp->SetQueueName(queue_name); 384 } 385 } 386 387 const char *SBBreakpointLocation::GetQueueName() const { 388 LLDB_INSTRUMENT_VA(this); 389 390 BreakpointLocationSP loc_sp = GetSP(); 391 if (loc_sp) { 392 std::lock_guard<std::recursive_mutex> guard( 393 loc_sp->GetTarget().GetAPIMutex()); 394 return loc_sp->GetQueueName(); 395 } 396 return nullptr; 397 } 398 399 bool SBBreakpointLocation::IsResolved() { 400 LLDB_INSTRUMENT_VA(this); 401 402 BreakpointLocationSP loc_sp = GetSP(); 403 if (loc_sp) { 404 std::lock_guard<std::recursive_mutex> guard( 405 loc_sp->GetTarget().GetAPIMutex()); 406 return loc_sp->IsResolved(); 407 } 408 return false; 409 } 410 411 void SBBreakpointLocation::SetLocation( 412 const lldb::BreakpointLocationSP &break_loc_sp) { 413 // Uninstall the callbacks? 414 m_opaque_wp = break_loc_sp; 415 } 416 417 bool SBBreakpointLocation::GetDescription(SBStream &description, 418 DescriptionLevel level) { 419 LLDB_INSTRUMENT_VA(this, description, level); 420 421 Stream &strm = description.ref(); 422 BreakpointLocationSP loc_sp = GetSP(); 423 424 if (loc_sp) { 425 std::lock_guard<std::recursive_mutex> guard( 426 loc_sp->GetTarget().GetAPIMutex()); 427 loc_sp->GetDescription(&strm, level); 428 strm.EOL(); 429 } else 430 strm.PutCString("No value"); 431 432 return true; 433 } 434 435 break_id_t SBBreakpointLocation::GetID() { 436 LLDB_INSTRUMENT_VA(this); 437 438 BreakpointLocationSP loc_sp = GetSP(); 439 if (loc_sp) { 440 std::lock_guard<std::recursive_mutex> guard( 441 loc_sp->GetTarget().GetAPIMutex()); 442 return loc_sp->GetID(); 443 } else 444 return LLDB_INVALID_BREAK_ID; 445 } 446 447 SBBreakpoint SBBreakpointLocation::GetBreakpoint() { 448 LLDB_INSTRUMENT_VA(this); 449 450 BreakpointLocationSP loc_sp = GetSP(); 451 452 SBBreakpoint sb_bp; 453 if (loc_sp) { 454 std::lock_guard<std::recursive_mutex> guard( 455 loc_sp->GetTarget().GetAPIMutex()); 456 sb_bp = loc_sp->GetBreakpoint().shared_from_this(); 457 } 458 459 return sb_bp; 460 } 461