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 return nullptr; 174 175 std::lock_guard<std::recursive_mutex> guard( 176 loc_sp->GetTarget().GetAPIMutex()); 177 return ConstString(loc_sp->GetConditionText()).GetCString(); 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 /*is_callback=*/false); 268 sb_error.SetError(error); 269 } else 270 sb_error.SetErrorString("invalid breakpoint"); 271 272 return sb_error; 273 } 274 275 void SBBreakpointLocation::SetCommandLineCommands(SBStringList &commands) { 276 LLDB_INSTRUMENT_VA(this, commands); 277 278 BreakpointLocationSP loc_sp = GetSP(); 279 if (!loc_sp) 280 return; 281 if (commands.GetSize() == 0) 282 return; 283 284 std::lock_guard<std::recursive_mutex> guard( 285 loc_sp->GetTarget().GetAPIMutex()); 286 std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up( 287 new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); 288 289 loc_sp->GetLocationOptions().SetCommandDataCallback(cmd_data_up); 290 } 291 292 bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) { 293 LLDB_INSTRUMENT_VA(this, commands); 294 295 BreakpointLocationSP loc_sp = GetSP(); 296 if (!loc_sp) 297 return false; 298 StringList command_list; 299 bool has_commands = 300 loc_sp->GetLocationOptions().GetCommandLineCallbacks(command_list); 301 if (has_commands) 302 commands.AppendList(command_list); 303 return has_commands; 304 } 305 306 void SBBreakpointLocation::SetThreadID(tid_t thread_id) { 307 LLDB_INSTRUMENT_VA(this, thread_id); 308 309 BreakpointLocationSP loc_sp = GetSP(); 310 if (loc_sp) { 311 std::lock_guard<std::recursive_mutex> guard( 312 loc_sp->GetTarget().GetAPIMutex()); 313 loc_sp->SetThreadID(thread_id); 314 } 315 } 316 317 tid_t SBBreakpointLocation::GetThreadID() { 318 LLDB_INSTRUMENT_VA(this); 319 320 tid_t tid = LLDB_INVALID_THREAD_ID; 321 BreakpointLocationSP loc_sp = GetSP(); 322 if (loc_sp) { 323 std::lock_guard<std::recursive_mutex> guard( 324 loc_sp->GetTarget().GetAPIMutex()); 325 return loc_sp->GetThreadID(); 326 } 327 return tid; 328 } 329 330 void SBBreakpointLocation::SetThreadIndex(uint32_t index) { 331 LLDB_INSTRUMENT_VA(this, 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_INSTRUMENT_VA(this); 343 344 uint32_t thread_idx = UINT32_MAX; 345 BreakpointLocationSP loc_sp = GetSP(); 346 if (loc_sp) { 347 std::lock_guard<std::recursive_mutex> guard( 348 loc_sp->GetTarget().GetAPIMutex()); 349 return loc_sp->GetThreadIndex(); 350 } 351 return thread_idx; 352 } 353 354 void SBBreakpointLocation::SetThreadName(const char *thread_name) { 355 LLDB_INSTRUMENT_VA(this, thread_name); 356 357 BreakpointLocationSP loc_sp = GetSP(); 358 if (loc_sp) { 359 std::lock_guard<std::recursive_mutex> guard( 360 loc_sp->GetTarget().GetAPIMutex()); 361 loc_sp->SetThreadName(thread_name); 362 } 363 } 364 365 const char *SBBreakpointLocation::GetThreadName() const { 366 LLDB_INSTRUMENT_VA(this); 367 368 BreakpointLocationSP loc_sp = GetSP(); 369 if (!loc_sp) 370 return nullptr; 371 372 std::lock_guard<std::recursive_mutex> guard( 373 loc_sp->GetTarget().GetAPIMutex()); 374 return ConstString(loc_sp->GetThreadName()).GetCString(); 375 } 376 377 void SBBreakpointLocation::SetQueueName(const char *queue_name) { 378 LLDB_INSTRUMENT_VA(this, 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_INSTRUMENT_VA(this); 390 391 BreakpointLocationSP loc_sp = GetSP(); 392 if (!loc_sp) 393 return nullptr; 394 395 std::lock_guard<std::recursive_mutex> guard( 396 loc_sp->GetTarget().GetAPIMutex()); 397 return ConstString(loc_sp->GetQueueName()).GetCString(); 398 } 399 400 bool SBBreakpointLocation::IsResolved() { 401 LLDB_INSTRUMENT_VA(this); 402 403 BreakpointLocationSP loc_sp = GetSP(); 404 if (loc_sp) { 405 std::lock_guard<std::recursive_mutex> guard( 406 loc_sp->GetTarget().GetAPIMutex()); 407 return loc_sp->IsResolved(); 408 } 409 return false; 410 } 411 412 void SBBreakpointLocation::SetLocation( 413 const lldb::BreakpointLocationSP &break_loc_sp) { 414 // Uninstall the callbacks? 415 m_opaque_wp = break_loc_sp; 416 } 417 418 bool SBBreakpointLocation::GetDescription(SBStream &description, 419 DescriptionLevel level) { 420 LLDB_INSTRUMENT_VA(this, description, level); 421 422 Stream &strm = description.ref(); 423 BreakpointLocationSP loc_sp = GetSP(); 424 425 if (loc_sp) { 426 std::lock_guard<std::recursive_mutex> guard( 427 loc_sp->GetTarget().GetAPIMutex()); 428 loc_sp->GetDescription(&strm, level); 429 strm.EOL(); 430 } else 431 strm.PutCString("No value"); 432 433 return true; 434 } 435 436 break_id_t SBBreakpointLocation::GetID() { 437 LLDB_INSTRUMENT_VA(this); 438 439 BreakpointLocationSP loc_sp = GetSP(); 440 if (loc_sp) { 441 std::lock_guard<std::recursive_mutex> guard( 442 loc_sp->GetTarget().GetAPIMutex()); 443 return loc_sp->GetID(); 444 } else 445 return LLDB_INVALID_BREAK_ID; 446 } 447 448 SBBreakpoint SBBreakpointLocation::GetBreakpoint() { 449 LLDB_INSTRUMENT_VA(this); 450 451 BreakpointLocationSP loc_sp = GetSP(); 452 453 SBBreakpoint sb_bp; 454 if (loc_sp) { 455 std::lock_guard<std::recursive_mutex> guard( 456 loc_sp->GetTarget().GetAPIMutex()); 457 sb_bp = loc_sp->GetBreakpoint().shared_from_this(); 458 } 459 460 return sb_bp; 461 } 462