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