468 lines · cpp
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-exception6//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 32using namespace lldb;33using namespace lldb_private;34 35SBBreakpointLocation::SBBreakpointLocation() { LLDB_INSTRUMENT_VA(this); }36 37SBBreakpointLocation::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 43SBBreakpointLocation::SBBreakpointLocation(const SBBreakpointLocation &rhs)44 : m_opaque_wp(rhs.m_opaque_wp) {45 LLDB_INSTRUMENT_VA(this, rhs);46}47 48const SBBreakpointLocation &SBBreakpointLocation::49operator=(const SBBreakpointLocation &rhs) {50 LLDB_INSTRUMENT_VA(this, rhs);51 52 m_opaque_wp = rhs.m_opaque_wp;53 return *this;54}55 56SBBreakpointLocation::~SBBreakpointLocation() = default;57 58BreakpointLocationSP SBBreakpointLocation::GetSP() const {59 return m_opaque_wp.lock();60}61 62bool SBBreakpointLocation::IsValid() const {63 LLDB_INSTRUMENT_VA(this);64 return this->operator bool();65}66SBBreakpointLocation::operator bool() const {67 LLDB_INSTRUMENT_VA(this);68 69 return bool(GetSP());70}71 72SBAddress 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 83addr_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 98void 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 llvm::consumeError(loc_sp->SetEnabled(enabled));106 }107}108 109bool 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 } else118 return false;119}120 121uint32_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 } else130 return 0;131}132 133uint32_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 } else142 return 0;143}144 145void 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 156void 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 // Treat a nullptr as clearing the condition164 if (!condition)165 loc_sp->SetCondition(StopCondition());166 else167 loc_sp->SetCondition(StopCondition(condition));168 }169}170 171const char *SBBreakpointLocation::GetCondition() {172 LLDB_INSTRUMENT_VA(this);173 174 BreakpointLocationSP loc_sp = GetSP();175 if (!loc_sp)176 return nullptr;177 178 std::lock_guard<std::recursive_mutex> guard(179 loc_sp->GetTarget().GetAPIMutex());180 StopCondition cond = loc_sp->GetCondition();181 if (!cond)182 return nullptr;183 return ConstString(cond.GetText()).GetCString();184}185 186void SBBreakpointLocation::SetAutoContinue(bool auto_continue) {187 LLDB_INSTRUMENT_VA(this, auto_continue);188 189 BreakpointLocationSP loc_sp = GetSP();190 if (loc_sp) {191 std::lock_guard<std::recursive_mutex> guard(192 loc_sp->GetTarget().GetAPIMutex());193 loc_sp->SetAutoContinue(auto_continue);194 }195}196 197bool SBBreakpointLocation::GetAutoContinue() {198 LLDB_INSTRUMENT_VA(this);199 200 BreakpointLocationSP loc_sp = GetSP();201 if (loc_sp) {202 std::lock_guard<std::recursive_mutex> guard(203 loc_sp->GetTarget().GetAPIMutex());204 return loc_sp->IsAutoContinue();205 }206 return false;207}208 209void SBBreakpointLocation::SetCallback(SBBreakpointHitCallback callback,210 void *baton) {211 LLDB_INSTRUMENT_VA(this, callback, baton);212 213 BreakpointLocationSP loc_sp = GetSP();214 215 if (loc_sp) {216 std::lock_guard<std::recursive_mutex> guard(217 loc_sp->GetTarget().GetAPIMutex());218 BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton));219 loc_sp->SetCallback(SBBreakpointCallbackBaton::PrivateBreakpointHitCallback,220 baton_sp, false);221 }222}223 224void SBBreakpointLocation::SetScriptCallbackFunction(225 const char *callback_function_name) {226 LLDB_INSTRUMENT_VA(this, callback_function_name);227}228 229SBError SBBreakpointLocation::SetScriptCallbackFunction(230 const char *callback_function_name,231 SBStructuredData &extra_args) {232 LLDB_INSTRUMENT_VA(this, callback_function_name, extra_args);233 SBError sb_error;234 BreakpointLocationSP loc_sp = GetSP();235 236 if (loc_sp) {237 Status error;238 std::lock_guard<std::recursive_mutex> guard(239 loc_sp->GetTarget().GetAPIMutex());240 BreakpointOptions &bp_options = loc_sp->GetLocationOptions();241 error = loc_sp->GetBreakpoint()242 .GetTarget()243 .GetDebugger()244 .GetScriptInterpreter()245 ->SetBreakpointCommandCallbackFunction(bp_options,246 callback_function_name,247 extra_args.m_impl_up248 ->GetObjectSP());249 sb_error.SetError(std::move(error));250 } else251 sb_error = Status::FromErrorString("invalid breakpoint");252 253 return sb_error;254}255 256SBError257SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) {258 LLDB_INSTRUMENT_VA(this, callback_body_text);259 260 BreakpointLocationSP loc_sp = GetSP();261 262 SBError sb_error;263 if (loc_sp) {264 std::lock_guard<std::recursive_mutex> guard(265 loc_sp->GetTarget().GetAPIMutex());266 BreakpointOptions &bp_options = loc_sp->GetLocationOptions();267 Status error =268 loc_sp->GetBreakpoint()269 .GetTarget()270 .GetDebugger()271 .GetScriptInterpreter()272 ->SetBreakpointCommandCallback(bp_options, callback_body_text,273 /*is_callback=*/false);274 sb_error.SetError(std::move(error));275 } else276 sb_error = Status::FromErrorString("invalid breakpoint");277 278 return sb_error;279}280 281void SBBreakpointLocation::SetCommandLineCommands(SBStringList &commands) {282 LLDB_INSTRUMENT_VA(this, commands);283 284 BreakpointLocationSP loc_sp = GetSP();285 if (!loc_sp)286 return;287 if (commands.GetSize() == 0)288 return;289 290 std::lock_guard<std::recursive_mutex> guard(291 loc_sp->GetTarget().GetAPIMutex());292 std::unique_ptr<BreakpointOptions::CommandData> cmd_data_up(293 new BreakpointOptions::CommandData(*commands, eScriptLanguageNone));294 295 loc_sp->GetLocationOptions().SetCommandDataCallback(cmd_data_up);296}297 298bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) {299 LLDB_INSTRUMENT_VA(this, commands);300 301 BreakpointLocationSP loc_sp = GetSP();302 if (!loc_sp)303 return false;304 StringList command_list;305 bool has_commands =306 loc_sp->GetLocationOptions().GetCommandLineCallbacks(command_list);307 if (has_commands)308 commands.AppendList(command_list);309 return has_commands;310}311 312void SBBreakpointLocation::SetThreadID(lldb::tid_t thread_id) {313 LLDB_INSTRUMENT_VA(this, thread_id);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->SetThreadID(thread_id);320 }321}322 323lldb::tid_t SBBreakpointLocation::GetThreadID() {324 LLDB_INSTRUMENT_VA(this);325 326 lldb::tid_t tid = LLDB_INVALID_THREAD_ID;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->GetThreadID();332 }333 return tid;334}335 336void SBBreakpointLocation::SetThreadIndex(uint32_t index) {337 LLDB_INSTRUMENT_VA(this, index);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->SetThreadIndex(index);344 }345}346 347uint32_t SBBreakpointLocation::GetThreadIndex() const {348 LLDB_INSTRUMENT_VA(this);349 350 uint32_t thread_idx = UINT32_MAX;351 BreakpointLocationSP loc_sp = GetSP();352 if (loc_sp) {353 std::lock_guard<std::recursive_mutex> guard(354 loc_sp->GetTarget().GetAPIMutex());355 return loc_sp->GetThreadIndex();356 }357 return thread_idx;358}359 360void SBBreakpointLocation::SetThreadName(const char *thread_name) {361 LLDB_INSTRUMENT_VA(this, thread_name);362 363 BreakpointLocationSP loc_sp = GetSP();364 if (loc_sp) {365 std::lock_guard<std::recursive_mutex> guard(366 loc_sp->GetTarget().GetAPIMutex());367 loc_sp->SetThreadName(thread_name);368 }369}370 371const char *SBBreakpointLocation::GetThreadName() const {372 LLDB_INSTRUMENT_VA(this);373 374 BreakpointLocationSP loc_sp = GetSP();375 if (!loc_sp)376 return nullptr;377 378 std::lock_guard<std::recursive_mutex> guard(379 loc_sp->GetTarget().GetAPIMutex());380 return ConstString(loc_sp->GetThreadName()).GetCString();381}382 383void SBBreakpointLocation::SetQueueName(const char *queue_name) {384 LLDB_INSTRUMENT_VA(this, queue_name);385 386 BreakpointLocationSP loc_sp = GetSP();387 if (loc_sp) {388 std::lock_guard<std::recursive_mutex> guard(389 loc_sp->GetTarget().GetAPIMutex());390 loc_sp->SetQueueName(queue_name);391 }392}393 394const char *SBBreakpointLocation::GetQueueName() const {395 LLDB_INSTRUMENT_VA(this);396 397 BreakpointLocationSP loc_sp = GetSP();398 if (!loc_sp)399 return nullptr;400 401 std::lock_guard<std::recursive_mutex> guard(402 loc_sp->GetTarget().GetAPIMutex());403 return ConstString(loc_sp->GetQueueName()).GetCString();404}405 406bool SBBreakpointLocation::IsResolved() {407 LLDB_INSTRUMENT_VA(this);408 409 BreakpointLocationSP loc_sp = GetSP();410 if (loc_sp) {411 std::lock_guard<std::recursive_mutex> guard(412 loc_sp->GetTarget().GetAPIMutex());413 return loc_sp->IsResolved();414 }415 return false;416}417 418void SBBreakpointLocation::SetLocation(419 const lldb::BreakpointLocationSP &break_loc_sp) {420 // Uninstall the callbacks?421 m_opaque_wp = break_loc_sp;422}423 424bool SBBreakpointLocation::GetDescription(SBStream &description,425 DescriptionLevel level) {426 LLDB_INSTRUMENT_VA(this, description, level);427 428 Stream &strm = description.ref();429 BreakpointLocationSP loc_sp = GetSP();430 431 if (loc_sp) {432 std::lock_guard<std::recursive_mutex> guard(433 loc_sp->GetTarget().GetAPIMutex());434 loc_sp->GetDescription(&strm, level);435 strm.EOL();436 } else437 strm.PutCString("No value");438 439 return true;440}441 442break_id_t SBBreakpointLocation::GetID() {443 LLDB_INSTRUMENT_VA(this);444 445 BreakpointLocationSP loc_sp = GetSP();446 if (loc_sp) {447 std::lock_guard<std::recursive_mutex> guard(448 loc_sp->GetTarget().GetAPIMutex());449 return loc_sp->GetID();450 } else451 return LLDB_INVALID_BREAK_ID;452}453 454SBBreakpoint SBBreakpointLocation::GetBreakpoint() {455 LLDB_INSTRUMENT_VA(this);456 457 BreakpointLocationSP loc_sp = GetSP();458 459 SBBreakpoint sb_bp;460 if (loc_sp) {461 std::lock_guard<std::recursive_mutex> guard(462 loc_sp->GetTarget().GetAPIMutex());463 sb_bp = loc_sp->GetBreakpoint().shared_from_this();464 }465 466 return sb_bp;467}468