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/StructuredDataImpl.h" 22 #include "lldb/Interpreter/CommandInterpreter.h" 23 #include "lldb/Interpreter/ScriptInterpreter.h" 24 #include "lldb/Target/Target.h" 25 #include "lldb/Target/ThreadSpec.h" 26 #include "lldb/Utility/Stream.h" 27 #include "lldb/lldb-defines.h" 28 #include "lldb/lldb-types.h" 29 30 #include "SBBreakpointOptionCommon.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 SBBreakpointLocation::SBBreakpointLocation() { LLDB_INSTRUMENT_VA(this); } 36 37 SBBreakpointLocation::SBBreakpointLocation( 38 const lldb::BreakpointLocationSP &break_loc_sp) 39 : m_opaque_wp(break_loc_sp) { 40 LLDB_INSTRUMENT_VA(this, break_loc_sp); 41 } 42 43 SBBreakpointLocation::SBBreakpointLocation(const SBBreakpointLocation &rhs) 44 : m_opaque_wp(rhs.m_opaque_wp) { 45 LLDB_INSTRUMENT_VA(this, rhs); 46 } 47 48 const SBBreakpointLocation &SBBreakpointLocation:: 49 operator=(const SBBreakpointLocation &rhs) { 50 LLDB_INSTRUMENT_VA(this, rhs); 51 52 m_opaque_wp = rhs.m_opaque_wp; 53 return *this; 54 } 55 56 SBBreakpointLocation::~SBBreakpointLocation() = default; 57 58 BreakpointLocationSP SBBreakpointLocation::GetSP() const { 59 return m_opaque_wp.lock(); 60 } 61 62 bool SBBreakpointLocation::IsValid() const { 63 LLDB_INSTRUMENT_VA(this); 64 return this->operator bool(); 65 } 66 SBBreakpointLocation::operator bool() const { 67 LLDB_INSTRUMENT_VA(this); 68 69 return bool(GetSP()); 70 } 71 72 SBAddress SBBreakpointLocation::GetAddress() { 73 LLDB_INSTRUMENT_VA(this); 74 75 BreakpointLocationSP loc_sp = GetSP(); 76 if (loc_sp) { 77 return SBAddress(loc_sp->GetAddress()); 78 } 79 80 return SBAddress(); 81 } 82 83 addr_t SBBreakpointLocation::GetLoadAddress() { 84 LLDB_INSTRUMENT_VA(this); 85 86 addr_t ret_addr = LLDB_INVALID_ADDRESS; 87 BreakpointLocationSP loc_sp = GetSP(); 88 89 if (loc_sp) { 90 std::lock_guard<std::recursive_mutex> guard( 91 loc_sp->GetTarget().GetAPIMutex()); 92 ret_addr = loc_sp->GetLoadAddress(); 93 } 94 95 return ret_addr; 96 } 97 98 void SBBreakpointLocation::SetEnabled(bool enabled) { 99 LLDB_INSTRUMENT_VA(this, enabled); 100 101 BreakpointLocationSP loc_sp = GetSP(); 102 if (loc_sp) { 103 std::lock_guard<std::recursive_mutex> guard( 104 loc_sp->GetTarget().GetAPIMutex()); 105 loc_sp->SetEnabled(enabled); 106 } 107 } 108 109 bool SBBreakpointLocation::IsEnabled() { 110 LLDB_INSTRUMENT_VA(this); 111 112 BreakpointLocationSP loc_sp = GetSP(); 113 if (loc_sp) { 114 std::lock_guard<std::recursive_mutex> guard( 115 loc_sp->GetTarget().GetAPIMutex()); 116 return loc_sp->IsEnabled(); 117 } else 118 return false; 119 } 120 121 uint32_t SBBreakpointLocation::GetHitCount() { 122 LLDB_INSTRUMENT_VA(this); 123 124 BreakpointLocationSP loc_sp = GetSP(); 125 if (loc_sp) { 126 std::lock_guard<std::recursive_mutex> guard( 127 loc_sp->GetTarget().GetAPIMutex()); 128 return loc_sp->GetHitCount(); 129 } else 130 return 0; 131 } 132 133 uint32_t SBBreakpointLocation::GetIgnoreCount() { 134 LLDB_INSTRUMENT_VA(this); 135 136 BreakpointLocationSP loc_sp = GetSP(); 137 if (loc_sp) { 138 std::lock_guard<std::recursive_mutex> guard( 139 loc_sp->GetTarget().GetAPIMutex()); 140 return loc_sp->GetIgnoreCount(); 141 } else 142 return 0; 143 } 144 145 void SBBreakpointLocation::SetIgnoreCount(uint32_t n) { 146 LLDB_INSTRUMENT_VA(this, n); 147 148 BreakpointLocationSP loc_sp = GetSP(); 149 if (loc_sp) { 150 std::lock_guard<std::recursive_mutex> guard( 151 loc_sp->GetTarget().GetAPIMutex()); 152 loc_sp->SetIgnoreCount(n); 153 } 154 } 155 156 void SBBreakpointLocation::SetCondition(const char *condition) { 157 LLDB_INSTRUMENT_VA(this, condition); 158 159 BreakpointLocationSP loc_sp = GetSP(); 160 if (loc_sp) { 161 std::lock_guard<std::recursive_mutex> guard( 162 loc_sp->GetTarget().GetAPIMutex()); 163 loc_sp->SetCondition(condition); 164 } 165 } 166 167 const char *SBBreakpointLocation::GetCondition() { 168 LLDB_INSTRUMENT_VA(this); 169 170 BreakpointLocationSP loc_sp = GetSP(); 171 if (!loc_sp) 172 return nullptr; 173 174 std::lock_guard<std::recursive_mutex> guard( 175 loc_sp->GetTarget().GetAPIMutex()); 176 return ConstString(loc_sp->GetConditionText()).GetCString(); 177 } 178 179 void SBBreakpointLocation::SetAutoContinue(bool auto_continue) { 180 LLDB_INSTRUMENT_VA(this, auto_continue); 181 182 BreakpointLocationSP loc_sp = GetSP(); 183 if (loc_sp) { 184 std::lock_guard<std::recursive_mutex> guard( 185 loc_sp->GetTarget().GetAPIMutex()); 186 loc_sp->SetAutoContinue(auto_continue); 187 } 188 } 189 190 bool SBBreakpointLocation::GetAutoContinue() { 191 LLDB_INSTRUMENT_VA(this); 192 193 BreakpointLocationSP loc_sp = GetSP(); 194 if (loc_sp) { 195 std::lock_guard<std::recursive_mutex> guard( 196 loc_sp->GetTarget().GetAPIMutex()); 197 return loc_sp->IsAutoContinue(); 198 } 199 return false; 200 } 201 202 void SBBreakpointLocation::SetCallback(SBBreakpointHitCallback callback, 203 void *baton) { 204 LLDB_INSTRUMENT_VA(this, callback, baton); 205 206 BreakpointLocationSP loc_sp = GetSP(); 207 208 if (loc_sp) { 209 std::lock_guard<std::recursive_mutex> guard( 210 loc_sp->GetTarget().GetAPIMutex()); 211 BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton)); 212 loc_sp->SetCallback(SBBreakpointCallbackBaton::PrivateBreakpointHitCallback, 213 baton_sp, false); 214 } 215 } 216 217 void SBBreakpointLocation::SetScriptCallbackFunction( 218 const char *callback_function_name) { 219 LLDB_INSTRUMENT_VA(this, callback_function_name); 220 } 221 222 SBError SBBreakpointLocation::SetScriptCallbackFunction( 223 const char *callback_function_name, 224 SBStructuredData &extra_args) { 225 LLDB_INSTRUMENT_VA(this, callback_function_name, extra_args); 226 SBError sb_error; 227 BreakpointLocationSP loc_sp = GetSP(); 228 229 if (loc_sp) { 230 Status error; 231 std::lock_guard<std::recursive_mutex> guard( 232 loc_sp->GetTarget().GetAPIMutex()); 233 BreakpointOptions &bp_options = loc_sp->GetLocationOptions(); 234 error = loc_sp->GetBreakpoint() 235 .GetTarget() 236 .GetDebugger() 237 .GetScriptInterpreter() 238 ->SetBreakpointCommandCallbackFunction(bp_options, 239 callback_function_name, 240 extra_args.m_impl_up 241 ->GetObjectSP()); 242 sb_error.SetError(error); 243 } else 244 sb_error.SetErrorString("invalid breakpoint"); 245 246 return sb_error; 247 } 248 249 SBError 250 SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) { 251 LLDB_INSTRUMENT_VA(this, callback_body_text); 252 253 BreakpointLocationSP loc_sp = GetSP(); 254 255 SBError sb_error; 256 if (loc_sp) { 257 std::lock_guard<std::recursive_mutex> guard( 258 loc_sp->GetTarget().GetAPIMutex()); 259 BreakpointOptions &bp_options = loc_sp->GetLocationOptions(); 260 Status error = 261 loc_sp->GetBreakpoint() 262 .GetTarget() 263 .GetDebugger() 264 .GetScriptInterpreter() 265 ->SetBreakpointCommandCallback(bp_options, callback_body_text, 266 /*is_callback=*/false); 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 return nullptr; 370 371 std::lock_guard<std::recursive_mutex> guard( 372 loc_sp->GetTarget().GetAPIMutex()); 373 return ConstString(loc_sp->GetThreadName()).GetCString(); 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 return nullptr; 393 394 std::lock_guard<std::recursive_mutex> guard( 395 loc_sp->GetTarget().GetAPIMutex()); 396 return ConstString(loc_sp->GetQueueName()).GetCString(); 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