diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h --- a/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -140,19 +140,6 @@ DISALLOW_COPY_AND_ASSIGN(BreakpointEventData); }; - class BreakpointPrecondition { - public: - virtual ~BreakpointPrecondition() = default; - - virtual bool EvaluatePrecondition(StoppointCallbackContext &context); - - virtual Status ConfigurePrecondition(Args &options); - - virtual void GetDescription(Stream &stream, lldb::DescriptionLevel level); - }; - - typedef std::shared_ptr BreakpointPreconditionSP; - // Saving & restoring breakpoints: static lldb::BreakpointSP CreateFromStructuredData( Target &target, StructuredData::ObjectSP &data_object_sp, Status &error); @@ -558,14 +545,14 @@ /// The Precondition should not continue the target, it should return true /// if the condition says to stop and false otherwise. /// - void SetPrecondition(BreakpointPreconditionSP precondition_sp) { + void SetPrecondition(lldb::BreakpointPreconditionSP precondition_sp) { m_precondition_sp = precondition_sp; } bool EvaluatePrecondition(StoppointCallbackContext &context); - BreakpointPreconditionSP GetPrecondition() { return m_precondition_sp; } - + lldb::BreakpointPreconditionSP GetPrecondition() { return m_precondition_sp; } + // Produces the OR'ed values for all the names assigned to this breakpoint. const BreakpointName::Permissions &GetPermissions() const { return m_permissions; @@ -659,9 +646,9 @@ m_filter_sp; // The filter that constrains the breakpoint's domain. lldb::BreakpointResolverSP m_resolver_sp; // The resolver that defines this breakpoint. - BreakpointPreconditionSP m_precondition_sp; // The precondition is a - // breakpoint-level hit filter - // that can be used + lldb::BreakpointPreconditionSP m_precondition_sp; // The precondition is a + // breakpoint-level hit + // filter that can be used // to skip certain breakpoint hits. For instance, exception breakpoints use // this to limit the stop to certain exception classes, while leaving the // condition & callback free for user specification. diff --git a/lldb/include/lldb/Breakpoint/BreakpointPrecondition.h b/lldb/include/lldb/Breakpoint/BreakpointPrecondition.h new file mode 100644 --- /dev/null +++ b/lldb/include/lldb/Breakpoint/BreakpointPrecondition.h @@ -0,0 +1,30 @@ +//===-- BreakpointPrecondition.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_BreakpointPrecondition_h_ +#define liblldb_BreakpointPrecondition_h_ + +#include "lldb/lldb-enumerations.h" + +namespace lldb_private { + +class Args; +class Status; +class StoppointCallbackContext; +class Stream; + +class BreakpointPrecondition { +public: + virtual ~BreakpointPrecondition() = default; + virtual bool EvaluatePrecondition(StoppointCallbackContext &context); + virtual Status ConfigurePrecondition(Args &args); + virtual void GetDescription(Stream &stream, lldb::DescriptionLevel level); +}; +} // namespace lldb_private + +#endif diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h --- a/lldb/include/lldb/Core/PluginManager.h +++ b/lldb/include/lldb/Core/PluginManager.h @@ -134,10 +134,11 @@ GetLanguageCreateCallbackForPluginName(ConstString name); // LanguageRuntime - static bool - RegisterPlugin(ConstString name, const char *description, - LanguageRuntimeCreateInstance create_callback, - LanguageRuntimeGetCommandObject command_callback = nullptr); + static bool RegisterPlugin( + ConstString name, const char *description, + LanguageRuntimeCreateInstance create_callback, + LanguageRuntimeGetCommandObject command_callback = nullptr, + LanguageRuntimeGetExceptionPrecondition precondition_callback = nullptr); static bool UnregisterPlugin(LanguageRuntimeCreateInstance create_callback); @@ -147,6 +148,9 @@ static LanguageRuntimeGetCommandObject GetLanguageRuntimeGetCommandObjectAtIndex(uint32_t idx); + static LanguageRuntimeGetExceptionPrecondition + GetLanguageRuntimeGetExceptionPreconditionAtIndex(uint32_t idx); + static LanguageRuntimeCreateInstance GetLanguageRuntimeCreateCallbackForPluginName(ConstString name); diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -115,9 +115,8 @@ bool catch_bp, bool throw_bp, bool is_internal = false); - static Breakpoint::BreakpointPreconditionSP - CreateExceptionPrecondition(lldb::LanguageType language, bool catch_bp, - bool throw_bp); + static lldb::BreakpointPreconditionSP + GetExceptionPrecondition(lldb::LanguageType language, bool throw_bp); virtual lldb::ValueObjectSP GetExceptionObjectForThread( lldb::ThreadSP thread_sp) { diff --git a/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/lldb/include/lldb/Target/ObjCLanguageRuntime.h --- a/lldb/include/lldb/Target/ObjCLanguageRuntime.h +++ b/lldb/include/lldb/Target/ObjCLanguageRuntime.h @@ -16,6 +16,7 @@ #include "llvm/Support/Casting.h" +#include "lldb/Breakpoint/BreakpointPrecondition.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Symbol/CompilerType.h" @@ -154,7 +155,7 @@ std::unique_ptr m_scratch_ast_ctx_up; }; - class ObjCExceptionPrecondition : public Breakpoint::BreakpointPrecondition { + class ObjCExceptionPrecondition : public BreakpointPrecondition { public: ObjCExceptionPrecondition(); @@ -171,6 +172,10 @@ std::unordered_set m_class_names; }; + static lldb::BreakpointPreconditionSP + GetBreakpointExceptionPrecondition(lldb::LanguageType language, + bool throw_bp); + class TaggedPointerVendor { public: virtual ~TaggedPointerVendor() = default; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -37,6 +37,7 @@ class BreakpointName; class BreakpointOptionGroup; class BreakpointOptions; +class BreakpointPrecondition; class BreakpointResolver; class BreakpointSite; class BreakpointSiteList; @@ -298,6 +299,7 @@ typedef std::weak_ptr BreakpointSiteWP; typedef std::shared_ptr BreakpointLocationSP; typedef std::weak_ptr BreakpointLocationWP; +typedef std::shared_ptr BreakpointPreconditionSP; typedef std::shared_ptr BreakpointResolverSP; typedef std::shared_ptr BroadcasterSP; typedef std::shared_ptr BroadcasterManagerSP; diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -55,6 +55,9 @@ Process *process, lldb::LanguageType language); typedef lldb::CommandObjectSP (*LanguageRuntimeGetCommandObject)( CommandInterpreter &interpreter); +typedef lldb::BreakpointPreconditionSP ( + *LanguageRuntimeGetExceptionPrecondition)(lldb::LanguageType language, + bool throw_bp); typedef lldb::StructuredDataPluginSP (*StructuredDataPluginCreateInstance)( Process &process); typedef Status (*StructuredDataFilterLaunchInfo)(ProcessLaunchInfo &launch_info, diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp --- a/lldb/source/Breakpoint/Breakpoint.cpp +++ b/lldb/source/Breakpoint/Breakpoint.cpp @@ -11,6 +11,7 @@ #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointLocationCollection.h" +#include "lldb/Breakpoint/BreakpointPrecondition.h" #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Breakpoint/BreakpointResolverFileLine.h" #include "lldb/Core/Address.h" @@ -995,21 +996,6 @@ return m_precondition_sp->EvaluatePrecondition(context); } -bool Breakpoint::BreakpointPrecondition::EvaluatePrecondition( - StoppointCallbackContext &context) { - return true; -} - -void Breakpoint::BreakpointPrecondition::GetDescription( - Stream &stream, lldb::DescriptionLevel level) {} - -Status -Breakpoint::BreakpointPrecondition::ConfigurePrecondition(Args &options) { - Status error; - error.SetErrorString("Base breakpoint precondition has no options."); - return error; -} - void Breakpoint::SendBreakpointChangedEvent( lldb::BreakpointEventType eventKind) { if (!m_being_created && !IsInternal() && diff --git a/lldb/source/Breakpoint/BreakpointPrecondition.cpp b/lldb/source/Breakpoint/BreakpointPrecondition.cpp new file mode 100644 --- /dev/null +++ b/lldb/source/Breakpoint/BreakpointPrecondition.cpp @@ -0,0 +1,26 @@ +//===-- BreakpointPrecondition.cpp ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Breakpoint/BreakpointPrecondition.h" +#include "lldb/Utility/Status.h" + +using namespace lldb_private; + +bool BreakpointPrecondition::EvaluatePrecondition( + StoppointCallbackContext &context) { + return false; +} + +void BreakpointPrecondition::GetDescription(Stream &stream, + lldb::DescriptionLevel level) {} + +Status BreakpointPrecondition::ConfigurePrecondition(Args &args) { + Status error; + error.SetErrorString("Base breakpoint precondition has no options."); + return error; +} diff --git a/lldb/source/Breakpoint/CMakeLists.txt b/lldb/source/Breakpoint/CMakeLists.txt --- a/lldb/source/Breakpoint/CMakeLists.txt +++ b/lldb/source/Breakpoint/CMakeLists.txt @@ -8,6 +8,7 @@ BreakpointLocationList.cpp BreakpointName.cpp BreakpointOptions.cpp + BreakpointPrecondition.cpp BreakpointResolver.cpp BreakpointResolverAddress.cpp BreakpointResolverFileLine.cpp diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -828,6 +828,7 @@ std::string description; LanguageRuntimeCreateInstance create_callback; LanguageRuntimeGetCommandObject command_callback; + LanguageRuntimeGetExceptionPrecondition precondition_callback; }; typedef std::vector LanguageRuntimeInstances; @@ -845,7 +846,8 @@ bool PluginManager::RegisterPlugin( ConstString name, const char *description, LanguageRuntimeCreateInstance create_callback, - LanguageRuntimeGetCommandObject command_callback) { + LanguageRuntimeGetCommandObject command_callback, + LanguageRuntimeGetExceptionPrecondition precondition_callback) { if (create_callback) { LanguageRuntimeInstance instance; assert((bool)name); @@ -854,6 +856,7 @@ instance.description = description; instance.create_callback = create_callback; instance.command_callback = command_callback; + instance.precondition_callback = precondition_callback; std::lock_guard guard(GetLanguageRuntimeMutex()); GetLanguageRuntimeInstances().push_back(instance); } @@ -895,6 +898,15 @@ return nullptr; } +LanguageRuntimeGetExceptionPrecondition +PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(uint32_t idx) { + std::lock_guard guard(GetLanguageRuntimeMutex()); + LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances(); + if (idx < instances.size()) + return instances[idx].precondition_callback; + return nullptr; +} + LanguageRuntimeCreateInstance PluginManager::GetLanguageRuntimeCreateCallbackForPluginName( ConstString name) { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -85,7 +85,8 @@ void AppleObjCRuntimeV1::Initialize() { PluginManager::RegisterPlugin( GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 1", - CreateInstance); + CreateInstance, + /*command_callback = */ nullptr, GetBreakpointExceptionPrecondition); } void AppleObjCRuntimeV1::Terminate() { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -806,7 +806,8 @@ CreateInstance, [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP { return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter)); - }); + }, + GetBreakpointExceptionPrecondition); } void AppleObjCRuntimeV2::Terminate() { diff --git a/lldb/source/Target/LanguageRuntime.cpp b/lldb/source/Target/LanguageRuntime.cpp --- a/lldb/source/Target/LanguageRuntime.cpp +++ b/lldb/source/Target/LanguageRuntime.cpp @@ -11,7 +11,6 @@ #include "lldb/Core/SearchFilter.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Target/Language.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Target.h" using namespace lldb; @@ -224,19 +223,24 @@ LanguageRuntime::~LanguageRuntime() = default; -Breakpoint::BreakpointPreconditionSP -LanguageRuntime::CreateExceptionPrecondition(lldb::LanguageType language, - bool catch_bp, bool throw_bp) { - switch (language) { - case eLanguageTypeObjC: - if (throw_bp) - return Breakpoint::BreakpointPreconditionSP( - new ObjCLanguageRuntime::ObjCExceptionPrecondition()); - break; - default: - break; +BreakpointPreconditionSP +LanguageRuntime::GetExceptionPrecondition(LanguageType language, + bool throw_bp) { + LanguageRuntimeCreateInstance create_callback; + for (uint32_t idx = 0; + (create_callback = + PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(idx)) != + nullptr; + idx++) { + if (auto precondition_callback = + PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex( + idx)) { + if (BreakpointPreconditionSP precond = + precondition_callback(language, throw_bp)) + return precond; + } } - return Breakpoint::BreakpointPreconditionSP(); + return BreakpointPreconditionSP(); } BreakpointSP LanguageRuntime::CreateExceptionBreakpoint( @@ -252,10 +256,8 @@ target.CreateBreakpoint(filter_sp, resolver_sp, is_internal, hardware, resolve_indirect_functions)); if (exc_breakpt_sp) { - Breakpoint::BreakpointPreconditionSP precondition_sp = - CreateExceptionPrecondition(language, catch_bp, throw_bp); - if (precondition_sp) - exc_breakpt_sp->SetPrecondition(precondition_sp); + if (auto precond = GetExceptionPrecondition(language, throw_bp)) + exc_breakpt_sp->SetPrecondition(precond); if (is_internal) exc_breakpt_sp->SetBreakpointKind("exception"); @@ -292,4 +294,3 @@ } } } - diff --git a/lldb/source/Target/ObjCLanguageRuntime.cpp b/lldb/source/Target/ObjCLanguageRuntime.cpp --- a/lldb/source/Target/ObjCLanguageRuntime.cpp +++ b/lldb/source/Target/ObjCLanguageRuntime.cpp @@ -375,6 +375,18 @@ return found; } +lldb::BreakpointPreconditionSP +ObjCLanguageRuntime::GetBreakpointExceptionPrecondition(LanguageType language, + bool throw_bp) { + if (language != eLanguageTypeObjC) + return lldb::BreakpointPreconditionSP(); + if (!throw_bp) + return lldb::BreakpointPreconditionSP(); + BreakpointPreconditionSP precondition_sp( + new ObjCLanguageRuntime::ObjCExceptionPrecondition()); + return precondition_sp; +} + // Exception breakpoint Precondition class for ObjC: void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName( const char *class_name) { diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -11,6 +11,7 @@ #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Breakpoint/BreakpointIDList.h" +#include "lldb/Breakpoint/BreakpointPrecondition.h" #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Breakpoint/BreakpointResolverAddress.h" #include "lldb/Breakpoint/BreakpointResolverFileLine.h" @@ -573,8 +574,7 @@ BreakpointSP exc_bkpt_sp = LanguageRuntime::CreateExceptionBreakpoint( *this, language, catch_bp, throw_bp, internal); if (exc_bkpt_sp && additional_args) { - Breakpoint::BreakpointPreconditionSP precondition_sp = - exc_bkpt_sp->GetPrecondition(); + BreakpointPreconditionSP precondition_sp = exc_bkpt_sp->GetPrecondition(); if (precondition_sp && additional_args) { if (error) *error = precondition_sp->ConfigurePrecondition(*additional_args);