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