[Target] Decouple ObjCLanguageRuntime from LanguageRuntime

Summary:
ObjCLanguageRuntime was being pulled into LanguageRuntime because of
Breakpoint Preconditions. If we move BreakpointPrecondition out of Breakpoint,
we can extend the LanguageRuntime plugin interface so that LanguageRuntimes
can give us a BreakpointPrecondition for exceptions.

Differential Revision: https://reviews.llvm.org/D63181

llvm-svn: 364098
This commit is contained in:
Alex Langford 2019-06-21 19:43:07 +00:00
parent 4649a051bf
commit 7f9c9f2264
16 changed files with 135 additions and 65 deletions

View File

@ -140,19 +140,6 @@ public:
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<BreakpointPrecondition> BreakpointPreconditionSP;
// Saving & restoring breakpoints:
static lldb::BreakpointSP CreateFromStructuredData(
Target &target, StructuredData::ObjectSP &data_object_sp, Status &error);
@ -558,14 +545,14 @@ public:
/// 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 @@ private:
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.

View File

@ -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

View File

@ -134,10 +134,11 @@ public:
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 @@ public:
static LanguageRuntimeGetCommandObject
GetLanguageRuntimeGetCommandObjectAtIndex(uint32_t idx);
static LanguageRuntimeGetExceptionPrecondition
GetLanguageRuntimeGetExceptionPreconditionAtIndex(uint32_t idx);
static LanguageRuntimeCreateInstance
GetLanguageRuntimeCreateCallbackForPluginName(ConstString name);

View File

@ -115,9 +115,8 @@ public:
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) {

View File

@ -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 @@ public:
std::unique_ptr<ClangASTContext> m_scratch_ast_ctx_up;
};
class ObjCExceptionPrecondition : public Breakpoint::BreakpointPrecondition {
class ObjCExceptionPrecondition : public BreakpointPrecondition {
public:
ObjCExceptionPrecondition();
@ -171,6 +172,10 @@ public:
std::unordered_set<std::string> m_class_names;
};
static lldb::BreakpointPreconditionSP
GetBreakpointExceptionPrecondition(lldb::LanguageType language,
bool throw_bp);
class TaggedPointerVendor {
public:
virtual ~TaggedPointerVendor() = default;

View File

@ -37,6 +37,7 @@ class BreakpointLocationList;
class BreakpointName;
class BreakpointOptionGroup;
class BreakpointOptions;
class BreakpointPrecondition;
class BreakpointResolver;
class BreakpointSite;
class BreakpointSiteList;
@ -298,6 +299,7 @@ typedef std::shared_ptr<lldb_private::BreakpointSite> BreakpointSiteSP;
typedef std::weak_ptr<lldb_private::BreakpointSite> BreakpointSiteWP;
typedef std::shared_ptr<lldb_private::BreakpointLocation> BreakpointLocationSP;
typedef std::weak_ptr<lldb_private::BreakpointLocation> BreakpointLocationWP;
typedef std::shared_ptr<lldb_private::BreakpointPrecondition> BreakpointPreconditionSP;
typedef std::shared_ptr<lldb_private::BreakpointResolver> BreakpointResolverSP;
typedef std::shared_ptr<lldb_private::Broadcaster> BroadcasterSP;
typedef std::shared_ptr<lldb_private::BroadcasterManager> BroadcasterManagerSP;

View File

@ -55,6 +55,9 @@ typedef LanguageRuntime *(*LanguageRuntimeCreateInstance)(
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,

View File

@ -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 @@ bool Breakpoint::EvaluatePrecondition(StoppointCallbackContext &context) {
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() &&

View File

@ -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;
}

View File

@ -8,6 +8,7 @@ add_lldb_library(lldbBreakpoint
BreakpointLocationList.cpp
BreakpointName.cpp
BreakpointOptions.cpp
BreakpointPrecondition.cpp
BreakpointResolver.cpp
BreakpointResolverAddress.cpp
BreakpointResolverFileLine.cpp

View File

@ -828,6 +828,7 @@ struct LanguageRuntimeInstance {
std::string description;
LanguageRuntimeCreateInstance create_callback;
LanguageRuntimeGetCommandObject command_callback;
LanguageRuntimeGetExceptionPrecondition precondition_callback;
};
typedef std::vector<LanguageRuntimeInstance> LanguageRuntimeInstances;
@ -845,7 +846,8 @@ static LanguageRuntimeInstances &GetLanguageRuntimeInstances() {
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 @@ bool PluginManager::RegisterPlugin(
instance.description = description;
instance.create_callback = create_callback;
instance.command_callback = command_callback;
instance.precondition_callback = precondition_callback;
std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
GetLanguageRuntimeInstances().push_back(instance);
}
@ -895,6 +898,15 @@ PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(uint32_t idx) {
return nullptr;
}
LanguageRuntimeGetExceptionPrecondition
PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex());
LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances();
if (idx < instances.size())
return instances[idx].precondition_callback;
return nullptr;
}
LanguageRuntimeCreateInstance
PluginManager::GetLanguageRuntimeCreateCallbackForPluginName(
ConstString name) {

View File

@ -85,7 +85,8 @@ AppleObjCRuntimeV1::CreateInstance(Process *process,
void AppleObjCRuntimeV1::Initialize() {
PluginManager::RegisterPlugin(
GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 1",
CreateInstance);
CreateInstance,
/*command_callback = */ nullptr, GetBreakpointExceptionPrecondition);
}
void AppleObjCRuntimeV1::Terminate() {

View File

@ -806,7 +806,8 @@ void AppleObjCRuntimeV2::Initialize() {
CreateInstance,
[](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
});
},
GetBreakpointExceptionPrecondition);
}
void AppleObjCRuntimeV2::Terminate() {

View File

@ -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(Process *process) : m_process(process) {}
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 @@ BreakpointSP LanguageRuntime::CreateExceptionBreakpoint(
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 @@ void LanguageRuntime::InitializeCommands(CommandObject *parent) {
}
}
}

View File

@ -375,6 +375,18 @@ bool ObjCLanguageRuntime::GetTypeBitSize(const CompilerType &compiler_type,
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) {

View File

@ -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 @@ Target::CreateExceptionBreakpoint(enum lldb::LanguageType language,
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);