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 "SBReproducerPrivate.h" 11 #include "lldb/API/SBAddress.h" 12 #include "lldb/API/SBDebugger.h" 13 #include "lldb/API/SBDefines.h" 14 #include "lldb/API/SBStream.h" 15 #include "lldb/API/SBStructuredData.h" 16 #include "lldb/API/SBStringList.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 using namespace lldb; 32 using namespace lldb_private; 33 34 SBBreakpointLocation::SBBreakpointLocation() { 35 LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBreakpointLocation); 36 } 37 38 SBBreakpointLocation::SBBreakpointLocation( 39 const lldb::BreakpointLocationSP &break_loc_sp) 40 : m_opaque_wp(break_loc_sp) { 41 LLDB_RECORD_CONSTRUCTOR(SBBreakpointLocation, 42 (const lldb::BreakpointLocationSP &), break_loc_sp); 43 } 44 45 SBBreakpointLocation::SBBreakpointLocation(const SBBreakpointLocation &rhs) 46 : m_opaque_wp(rhs.m_opaque_wp) { 47 LLDB_RECORD_CONSTRUCTOR(SBBreakpointLocation, 48 (const lldb::SBBreakpointLocation &), rhs); 49 } 50 51 const SBBreakpointLocation &SBBreakpointLocation:: 52 operator=(const SBBreakpointLocation &rhs) { 53 LLDB_RECORD_METHOD( 54 const lldb::SBBreakpointLocation &, 55 SBBreakpointLocation, operator=,(const lldb::SBBreakpointLocation &), 56 rhs); 57 58 m_opaque_wp = rhs.m_opaque_wp; 59 return LLDB_RECORD_RESULT(*this); 60 } 61 62 SBBreakpointLocation::~SBBreakpointLocation() = default; 63 64 BreakpointLocationSP SBBreakpointLocation::GetSP() const { 65 return m_opaque_wp.lock(); 66 } 67 68 bool SBBreakpointLocation::IsValid() const { 69 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpointLocation, IsValid); 70 return this->operator bool(); 71 } 72 SBBreakpointLocation::operator bool() const { 73 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpointLocation, operator bool); 74 75 return bool(GetSP()); 76 } 77 78 SBAddress SBBreakpointLocation::GetAddress() { 79 LLDB_RECORD_METHOD_NO_ARGS(lldb::SBAddress, SBBreakpointLocation, GetAddress); 80 81 BreakpointLocationSP loc_sp = GetSP(); 82 if (loc_sp) { 83 return LLDB_RECORD_RESULT(SBAddress(&loc_sp->GetAddress())); 84 } 85 86 return LLDB_RECORD_RESULT(SBAddress()); 87 } 88 89 addr_t SBBreakpointLocation::GetLoadAddress() { 90 LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBBreakpointLocation, 91 GetLoadAddress); 92 93 addr_t ret_addr = LLDB_INVALID_ADDRESS; 94 BreakpointLocationSP loc_sp = GetSP(); 95 96 if (loc_sp) { 97 std::lock_guard<std::recursive_mutex> guard( 98 loc_sp->GetTarget().GetAPIMutex()); 99 ret_addr = loc_sp->GetLoadAddress(); 100 } 101 102 return ret_addr; 103 } 104 105 void SBBreakpointLocation::SetEnabled(bool enabled) { 106 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetEnabled, (bool), enabled); 107 108 BreakpointLocationSP loc_sp = GetSP(); 109 if (loc_sp) { 110 std::lock_guard<std::recursive_mutex> guard( 111 loc_sp->GetTarget().GetAPIMutex()); 112 loc_sp->SetEnabled(enabled); 113 } 114 } 115 116 bool SBBreakpointLocation::IsEnabled() { 117 LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpointLocation, IsEnabled); 118 119 BreakpointLocationSP loc_sp = GetSP(); 120 if (loc_sp) { 121 std::lock_guard<std::recursive_mutex> guard( 122 loc_sp->GetTarget().GetAPIMutex()); 123 return loc_sp->IsEnabled(); 124 } else 125 return false; 126 } 127 128 uint32_t SBBreakpointLocation::GetHitCount() { 129 LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBBreakpointLocation, GetHitCount); 130 131 BreakpointLocationSP loc_sp = GetSP(); 132 if (loc_sp) { 133 std::lock_guard<std::recursive_mutex> guard( 134 loc_sp->GetTarget().GetAPIMutex()); 135 return loc_sp->GetHitCount(); 136 } else 137 return 0; 138 } 139 140 uint32_t SBBreakpointLocation::GetIgnoreCount() { 141 LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBBreakpointLocation, GetIgnoreCount); 142 143 BreakpointLocationSP loc_sp = GetSP(); 144 if (loc_sp) { 145 std::lock_guard<std::recursive_mutex> guard( 146 loc_sp->GetTarget().GetAPIMutex()); 147 return loc_sp->GetIgnoreCount(); 148 } else 149 return 0; 150 } 151 152 void SBBreakpointLocation::SetIgnoreCount(uint32_t n) { 153 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetIgnoreCount, (uint32_t), n); 154 155 BreakpointLocationSP loc_sp = GetSP(); 156 if (loc_sp) { 157 std::lock_guard<std::recursive_mutex> guard( 158 loc_sp->GetTarget().GetAPIMutex()); 159 loc_sp->SetIgnoreCount(n); 160 } 161 } 162 163 void SBBreakpointLocation::SetCondition(const char *condition) { 164 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetCondition, (const char *), 165 condition); 166 167 BreakpointLocationSP loc_sp = GetSP(); 168 if (loc_sp) { 169 std::lock_guard<std::recursive_mutex> guard( 170 loc_sp->GetTarget().GetAPIMutex()); 171 loc_sp->SetCondition(condition); 172 } 173 } 174 175 const char *SBBreakpointLocation::GetCondition() { 176 LLDB_RECORD_METHOD_NO_ARGS(const char *, SBBreakpointLocation, GetCondition); 177 178 BreakpointLocationSP loc_sp = GetSP(); 179 if (loc_sp) { 180 std::lock_guard<std::recursive_mutex> guard( 181 loc_sp->GetTarget().GetAPIMutex()); 182 return loc_sp->GetConditionText(); 183 } 184 return nullptr; 185 } 186 187 void SBBreakpointLocation::SetAutoContinue(bool auto_continue) { 188 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetAutoContinue, (bool), 189 auto_continue); 190 191 BreakpointLocationSP loc_sp = GetSP(); 192 if (loc_sp) { 193 std::lock_guard<std::recursive_mutex> guard( 194 loc_sp->GetTarget().GetAPIMutex()); 195 loc_sp->SetAutoContinue(auto_continue); 196 } 197 } 198 199 bool SBBreakpointLocation::GetAutoContinue() { 200 LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpointLocation, GetAutoContinue); 201 202 BreakpointLocationSP loc_sp = GetSP(); 203 if (loc_sp) { 204 std::lock_guard<std::recursive_mutex> guard( 205 loc_sp->GetTarget().GetAPIMutex()); 206 return loc_sp->IsAutoContinue(); 207 } 208 return false; 209 } 210 211 void SBBreakpointLocation::SetScriptCallbackFunction( 212 const char *callback_function_name) { 213 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetScriptCallbackFunction, 214 (const char *), callback_function_name); 215 } 216 217 SBError SBBreakpointLocation::SetScriptCallbackFunction( 218 const char *callback_function_name, 219 SBStructuredData &extra_args) { 220 LLDB_RECORD_METHOD(SBError, SBBreakpointLocation, SetScriptCallbackFunction, 221 (const char *, SBStructuredData &), 222 callback_function_name, extra_args); 223 SBError sb_error; 224 BreakpointLocationSP loc_sp = GetSP(); 225 226 if (loc_sp) { 227 Status error; 228 std::lock_guard<std::recursive_mutex> guard( 229 loc_sp->GetTarget().GetAPIMutex()); 230 BreakpointOptions *bp_options = loc_sp->GetLocationOptions(); 231 error = loc_sp->GetBreakpoint() 232 .GetTarget() 233 .GetDebugger() 234 .GetScriptInterpreter() 235 ->SetBreakpointCommandCallbackFunction(bp_options, 236 callback_function_name, 237 extra_args.m_impl_up 238 ->GetObjectSP()); 239 sb_error.SetError(error); 240 } else 241 sb_error.SetErrorString("invalid breakpoint"); 242 243 return LLDB_RECORD_RESULT(sb_error); 244 } 245 246 SBError 247 SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) { 248 LLDB_RECORD_METHOD(lldb::SBError, SBBreakpointLocation, SetScriptCallbackBody, 249 (const char *), callback_body_text); 250 251 BreakpointLocationSP loc_sp = GetSP(); 252 253 SBError sb_error; 254 if (loc_sp) { 255 std::lock_guard<std::recursive_mutex> guard( 256 loc_sp->GetTarget().GetAPIMutex()); 257 BreakpointOptions *bp_options = loc_sp->GetLocationOptions(); 258 Status error = 259 loc_sp->GetBreakpoint() 260 .GetTarget() 261 .GetDebugger() 262 .GetScriptInterpreter() 263 ->SetBreakpointCommandCallback(bp_options, callback_body_text); 264 sb_error.SetError(error); 265 } else 266 sb_error.SetErrorString("invalid breakpoint"); 267 268 return LLDB_RECORD_RESULT(sb_error); 269 } 270 271 void SBBreakpointLocation::SetCommandLineCommands(SBStringList &commands) { 272 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetCommandLineCommands, 273 (lldb::SBStringList &), commands); 274 275 BreakpointLocationSP loc_sp = GetSP(); 276 if (!loc_sp) 277 return; 278 if (commands.GetSize() == 0) 279 return; 280 281 std::lock_guard<std::recursive_mutex> guard( 282 loc_sp->GetTarget().GetAPIMutex()); 283 std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up( 284 new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); 285 286 loc_sp->GetLocationOptions()->SetCommandDataCallback(cmd_data_up); 287 } 288 289 bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) { 290 LLDB_RECORD_METHOD(bool, SBBreakpointLocation, GetCommandLineCommands, 291 (lldb::SBStringList &), commands); 292 293 BreakpointLocationSP loc_sp = GetSP(); 294 if (!loc_sp) 295 return false; 296 StringList command_list; 297 bool has_commands = 298 loc_sp->GetLocationOptions()->GetCommandLineCallbacks(command_list); 299 if (has_commands) 300 commands.AppendList(command_list); 301 return has_commands; 302 } 303 304 void SBBreakpointLocation::SetThreadID(tid_t thread_id) { 305 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetThreadID, (lldb::tid_t), 306 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_RECORD_METHOD_NO_ARGS(lldb::tid_t, SBBreakpointLocation, GetThreadID); 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_RECORD_METHOD(void, SBBreakpointLocation, SetThreadIndex, (uint32_t), 331 index); 332 333 BreakpointLocationSP loc_sp = GetSP(); 334 if (loc_sp) { 335 std::lock_guard<std::recursive_mutex> guard( 336 loc_sp->GetTarget().GetAPIMutex()); 337 loc_sp->SetThreadIndex(index); 338 } 339 } 340 341 uint32_t SBBreakpointLocation::GetThreadIndex() const { 342 LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBBreakpointLocation, 343 GetThreadIndex); 344 345 uint32_t thread_idx = UINT32_MAX; 346 BreakpointLocationSP loc_sp = GetSP(); 347 if (loc_sp) { 348 std::lock_guard<std::recursive_mutex> guard( 349 loc_sp->GetTarget().GetAPIMutex()); 350 return loc_sp->GetThreadIndex(); 351 } 352 return thread_idx; 353 } 354 355 void SBBreakpointLocation::SetThreadName(const char *thread_name) { 356 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetThreadName, (const char *), 357 thread_name); 358 359 BreakpointLocationSP loc_sp = GetSP(); 360 if (loc_sp) { 361 std::lock_guard<std::recursive_mutex> guard( 362 loc_sp->GetTarget().GetAPIMutex()); 363 loc_sp->SetThreadName(thread_name); 364 } 365 } 366 367 const char *SBBreakpointLocation::GetThreadName() const { 368 LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBBreakpointLocation, 369 GetThreadName); 370 371 BreakpointLocationSP loc_sp = GetSP(); 372 if (loc_sp) { 373 std::lock_guard<std::recursive_mutex> guard( 374 loc_sp->GetTarget().GetAPIMutex()); 375 return loc_sp->GetThreadName(); 376 } 377 return nullptr; 378 } 379 380 void SBBreakpointLocation::SetQueueName(const char *queue_name) { 381 LLDB_RECORD_METHOD(void, SBBreakpointLocation, SetQueueName, (const char *), 382 queue_name); 383 384 BreakpointLocationSP loc_sp = GetSP(); 385 if (loc_sp) { 386 std::lock_guard<std::recursive_mutex> guard( 387 loc_sp->GetTarget().GetAPIMutex()); 388 loc_sp->SetQueueName(queue_name); 389 } 390 } 391 392 const char *SBBreakpointLocation::GetQueueName() const { 393 LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBBreakpointLocation, 394 GetQueueName); 395 396 BreakpointLocationSP loc_sp = GetSP(); 397 if (loc_sp) { 398 std::lock_guard<std::recursive_mutex> guard( 399 loc_sp->GetTarget().GetAPIMutex()); 400 loc_sp->GetQueueName(); 401 } 402 return nullptr; 403 } 404 405 bool SBBreakpointLocation::IsResolved() { 406 LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpointLocation, IsResolved); 407 408 BreakpointLocationSP loc_sp = GetSP(); 409 if (loc_sp) { 410 std::lock_guard<std::recursive_mutex> guard( 411 loc_sp->GetTarget().GetAPIMutex()); 412 return loc_sp->IsResolved(); 413 } 414 return false; 415 } 416 417 void SBBreakpointLocation::SetLocation( 418 const lldb::BreakpointLocationSP &break_loc_sp) { 419 // Uninstall the callbacks? 420 m_opaque_wp = break_loc_sp; 421 } 422 423 bool SBBreakpointLocation::GetDescription(SBStream &description, 424 DescriptionLevel level) { 425 LLDB_RECORD_METHOD(bool, SBBreakpointLocation, GetDescription, 426 (lldb::SBStream &, lldb::DescriptionLevel), description, 427 level); 428 429 Stream &strm = description.ref(); 430 BreakpointLocationSP loc_sp = GetSP(); 431 432 if (loc_sp) { 433 std::lock_guard<std::recursive_mutex> guard( 434 loc_sp->GetTarget().GetAPIMutex()); 435 loc_sp->GetDescription(&strm, level); 436 strm.EOL(); 437 } else 438 strm.PutCString("No value"); 439 440 return true; 441 } 442 443 break_id_t SBBreakpointLocation::GetID() { 444 LLDB_RECORD_METHOD_NO_ARGS(lldb::break_id_t, SBBreakpointLocation, GetID); 445 446 BreakpointLocationSP loc_sp = GetSP(); 447 if (loc_sp) { 448 std::lock_guard<std::recursive_mutex> guard( 449 loc_sp->GetTarget().GetAPIMutex()); 450 return loc_sp->GetID(); 451 } else 452 return LLDB_INVALID_BREAK_ID; 453 } 454 455 SBBreakpoint SBBreakpointLocation::GetBreakpoint() { 456 LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBreakpoint, SBBreakpointLocation, 457 GetBreakpoint); 458 459 BreakpointLocationSP loc_sp = GetSP(); 460 461 SBBreakpoint sb_bp; 462 if (loc_sp) { 463 std::lock_guard<std::recursive_mutex> guard( 464 loc_sp->GetTarget().GetAPIMutex()); 465 sb_bp = loc_sp->GetBreakpoint().shared_from_this(); 466 } 467 468 return LLDB_RECORD_RESULT(sb_bp); 469 } 470 471 namespace lldb_private { 472 namespace repro { 473 474 template <> 475 void RegisterMethods<SBBreakpointLocation>(Registry &R) { 476 LLDB_REGISTER_CONSTRUCTOR(SBBreakpointLocation, ()); 477 LLDB_REGISTER_CONSTRUCTOR(SBBreakpointLocation, 478 (const lldb::BreakpointLocationSP &)); 479 LLDB_REGISTER_CONSTRUCTOR(SBBreakpointLocation, 480 (const lldb::SBBreakpointLocation &)); 481 LLDB_REGISTER_METHOD( 482 const lldb::SBBreakpointLocation &, 483 SBBreakpointLocation, operator=,(const lldb::SBBreakpointLocation &)); 484 LLDB_REGISTER_METHOD_CONST(bool, SBBreakpointLocation, IsValid, ()); 485 LLDB_REGISTER_METHOD_CONST(bool, SBBreakpointLocation, operator bool, ()); 486 LLDB_REGISTER_METHOD(lldb::SBAddress, SBBreakpointLocation, GetAddress, ()); 487 LLDB_REGISTER_METHOD(lldb::addr_t, SBBreakpointLocation, GetLoadAddress, 488 ()); 489 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetEnabled, (bool)); 490 LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, IsEnabled, ()); 491 LLDB_REGISTER_METHOD(uint32_t, SBBreakpointLocation, GetHitCount, ()); 492 LLDB_REGISTER_METHOD(uint32_t, SBBreakpointLocation, GetIgnoreCount, ()); 493 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetIgnoreCount, 494 (uint32_t)); 495 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetCondition, 496 (const char *)); 497 LLDB_REGISTER_METHOD(const char *, SBBreakpointLocation, GetCondition, ()); 498 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetAutoContinue, (bool)); 499 LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, GetAutoContinue, ()); 500 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetScriptCallbackFunction, 501 (const char *)); 502 LLDB_REGISTER_METHOD(SBError, SBBreakpointLocation, SetScriptCallbackFunction, 503 (const char *, SBStructuredData &)); 504 LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpointLocation, 505 SetScriptCallbackBody, (const char *)); 506 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetCommandLineCommands, 507 (lldb::SBStringList &)); 508 LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, GetCommandLineCommands, 509 (lldb::SBStringList &)); 510 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetThreadID, 511 (lldb::tid_t)); 512 LLDB_REGISTER_METHOD(lldb::tid_t, SBBreakpointLocation, GetThreadID, ()); 513 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetThreadIndex, 514 (uint32_t)); 515 LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpointLocation, GetThreadIndex, 516 ()); 517 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetThreadName, 518 (const char *)); 519 LLDB_REGISTER_METHOD_CONST(const char *, SBBreakpointLocation, 520 GetThreadName, ()); 521 LLDB_REGISTER_METHOD(void, SBBreakpointLocation, SetQueueName, 522 (const char *)); 523 LLDB_REGISTER_METHOD_CONST(const char *, SBBreakpointLocation, GetQueueName, 524 ()); 525 LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, IsResolved, ()); 526 LLDB_REGISTER_METHOD(bool, SBBreakpointLocation, GetDescription, 527 (lldb::SBStream &, lldb::DescriptionLevel)); 528 LLDB_REGISTER_METHOD(lldb::break_id_t, SBBreakpointLocation, GetID, ()); 529 LLDB_REGISTER_METHOD(lldb::SBBreakpoint, SBBreakpointLocation, 530 GetBreakpoint, ()); 531 } 532 533 } 534 } 535