mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 02:38:07 +08:00
Switch the ScriptedBreakpointResolver over to the ScriptedInterface form (#150720)
This is NFC, I'm modernizing the interface before I add to it in a subsequent commit.
This commit is contained in:
@@ -229,78 +229,6 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject
|
||||
return pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger_sp)), dict);
|
||||
}
|
||||
|
||||
PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver(
|
||||
const char *python_class_name, const char *session_dictionary_name,
|
||||
const StructuredDataImpl &args_impl,
|
||||
const lldb::BreakpointSP &breakpoint_sp) {
|
||||
|
||||
if (python_class_name == NULL || python_class_name[0] == '\0' ||
|
||||
!session_dictionary_name)
|
||||
return PythonObject();
|
||||
|
||||
PyErr_Cleaner py_err_cleaner(true);
|
||||
|
||||
auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
|
||||
session_dictionary_name);
|
||||
auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
|
||||
python_class_name, dict);
|
||||
|
||||
if (!pfunc.IsAllocated())
|
||||
return PythonObject();
|
||||
|
||||
PythonObject result =
|
||||
pfunc(SWIGBridge::ToSWIGWrapper(breakpoint_sp), SWIGBridge::ToSWIGWrapper(args_impl), dict);
|
||||
// FIXME: At this point we should check that the class we found supports all
|
||||
// the methods that we need.
|
||||
|
||||
if (result.IsAllocated()) {
|
||||
// Check that __callback__ is defined:
|
||||
auto callback_func = result.ResolveName<PythonCallable>("__callback__");
|
||||
if (callback_func.IsAllocated())
|
||||
return result;
|
||||
}
|
||||
return PythonObject();
|
||||
}
|
||||
|
||||
unsigned int lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResolver(
|
||||
void *implementor, const char *method_name,
|
||||
lldb_private::SymbolContext *sym_ctx) {
|
||||
PyErr_Cleaner py_err_cleaner(false);
|
||||
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
|
||||
auto pfunc = self.ResolveName<PythonCallable>(method_name);
|
||||
|
||||
if (!pfunc.IsAllocated())
|
||||
return 0;
|
||||
|
||||
PythonObject result = sym_ctx ? pfunc(SWIGBridge::ToSWIGWrapper(*sym_ctx)) : pfunc();
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The callback will return a bool, but we're need to also return ints
|
||||
// so we're squirrelling the bool through as an int... And if you return
|
||||
// nothing, we'll continue.
|
||||
if (strcmp(method_name, "__callback__") == 0) {
|
||||
if (result.get() == Py_False)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
long long ret_val = unwrapOrSetPythonException(As<long long>(result));
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
// wrapper that calls an optional instance member of an object taking no
|
||||
// arguments
|
||||
static PyObject *LLDBSwigPython_CallOptionalMember(
|
||||
@@ -554,6 +482,18 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject * dat
|
||||
return sb_ptr;
|
||||
}
|
||||
|
||||
void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObject * data) {
|
||||
lldb::SBSymbolContext *sb_ptr = nullptr;
|
||||
|
||||
int valid_cast =
|
||||
SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBSymbolContext, 0);
|
||||
|
||||
if (valid_cast == -1)
|
||||
return NULL;
|
||||
|
||||
return sb_ptr;
|
||||
}
|
||||
|
||||
void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject * data) {
|
||||
lldb::SBValue *sb_ptr = NULL;
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@ protected:
|
||||
|
||||
lldb_private::SymbolContext *get() const;
|
||||
|
||||
friend class lldb_private::ScriptInterpreter;
|
||||
|
||||
private:
|
||||
std::unique_ptr<lldb_private::SymbolContext> m_opaque_up;
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "lldb/Breakpoint/BreakpointResolver.h"
|
||||
#include "lldb/Core/ModuleSpec.h"
|
||||
#include "lldb/Core/StructuredDataImpl.h"
|
||||
#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h"
|
||||
#include "lldb/lldb-forward.h"
|
||||
|
||||
namespace lldb_private {
|
||||
@@ -64,7 +65,8 @@ private:
|
||||
std::string m_class_name;
|
||||
lldb::SearchDepth m_depth;
|
||||
StructuredDataImpl m_args;
|
||||
StructuredData::GenericSP m_implementation_sp;
|
||||
Status m_error;
|
||||
lldb::ScriptedBreakpointInterfaceSP m_interface_sp;
|
||||
|
||||
BreakpointResolverScripted(const BreakpointResolverScripted &) = delete;
|
||||
const BreakpointResolverScripted &
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 LLDB_INTERPRETER_INTERFACES_SCRIPTEDBREAKPOINTINTERFACE_H
|
||||
#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDBREAKPOINTINTERFACE_H
|
||||
|
||||
#include "ScriptedInterface.h"
|
||||
#include "lldb/Symbol/SymbolContext.h"
|
||||
#include "lldb/lldb-private.h"
|
||||
|
||||
namespace lldb_private {
|
||||
class ScriptedBreakpointInterface : public ScriptedInterface {
|
||||
public:
|
||||
virtual llvm::Expected<StructuredData::GenericSP>
|
||||
CreatePluginObject(llvm::StringRef class_name, lldb::BreakpointSP break_sp,
|
||||
const StructuredDataImpl &args_sp) = 0;
|
||||
|
||||
/// "ResolverCallback" will get called when a new module is loaded. The
|
||||
/// new module information is passed in sym_ctx. The Resolver will add
|
||||
/// any breakpoint locations it found in that module.
|
||||
virtual bool ResolverCallback(SymbolContext sym_ctx) { return true; }
|
||||
virtual lldb::SearchDepth GetDepth() { return lldb::eSearchDepthModule; }
|
||||
virtual std::optional<std::string> GetShortHelp() { return nullptr; }
|
||||
};
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "lldb/API/SBLaunchInfo.h"
|
||||
#include "lldb/API/SBMemoryRegionInfo.h"
|
||||
#include "lldb/API/SBStream.h"
|
||||
#include "lldb/API/SBSymbolContext.h"
|
||||
#include "lldb/Breakpoint/BreakpointOptions.h"
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
#include "lldb/Core/SearchFilter.h"
|
||||
@@ -29,6 +30,7 @@
|
||||
#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
|
||||
#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
|
||||
#include "lldb/Interpreter/ScriptObject.h"
|
||||
#include "lldb/Symbol/SymbolContext.h"
|
||||
#include "lldb/Utility/Broadcaster.h"
|
||||
#include "lldb/Utility/Status.h"
|
||||
#include "lldb/Utility/StructuredData.h"
|
||||
@@ -257,26 +259,6 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual StructuredData::GenericSP
|
||||
CreateScriptedBreakpointResolver(const char *class_name,
|
||||
const StructuredDataImpl &args_data,
|
||||
lldb::BreakpointSP &bkpt_sp) {
|
||||
return StructuredData::GenericSP();
|
||||
}
|
||||
|
||||
virtual bool
|
||||
ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp,
|
||||
SymbolContext *sym_ctx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual lldb::SearchDepth
|
||||
ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp)
|
||||
{
|
||||
return lldb::eSearchDepthModule;
|
||||
}
|
||||
|
||||
virtual StructuredData::ObjectSP
|
||||
LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) {
|
||||
return StructuredData::ObjectSP();
|
||||
@@ -566,6 +548,11 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual lldb::ScriptedBreakpointInterfaceSP
|
||||
CreateScriptedBreakpointInterface() {
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual StructuredData::ObjectSP
|
||||
CreateStructuredDataFromScriptObject(ScriptObject obj) {
|
||||
return {};
|
||||
@@ -580,6 +567,9 @@ public:
|
||||
|
||||
lldb::StreamSP GetOpaqueTypeFromSBStream(const lldb::SBStream &stream) const;
|
||||
|
||||
SymbolContext
|
||||
GetOpaqueTypeFromSBSymbolContext(const lldb::SBSymbolContext &sym_ctx) const;
|
||||
|
||||
lldb::BreakpointSP
|
||||
GetOpaqueTypeFromSBBreakpoint(const lldb::SBBreakpoint &breakpoint) const;
|
||||
|
||||
|
||||
@@ -188,6 +188,7 @@ class Scalar;
|
||||
class ScriptInterpreter;
|
||||
class ScriptInterpreterLocker;
|
||||
class ScriptedMetadata;
|
||||
class ScriptedBreakpointInterface;
|
||||
class ScriptedPlatformInterface;
|
||||
class ScriptedProcessInterface;
|
||||
class ScriptedStopHookInterface;
|
||||
@@ -418,6 +419,8 @@ typedef std::shared_ptr<lldb_private::ScriptedThreadInterface>
|
||||
ScriptedThreadInterfaceSP;
|
||||
typedef std::shared_ptr<lldb_private::ScriptedThreadPlanInterface>
|
||||
ScriptedThreadPlanInterfaceSP;
|
||||
typedef std::shared_ptr<lldb_private::ScriptedBreakpointInterface>
|
||||
ScriptedBreakpointInterfaceSP;
|
||||
typedef std::shared_ptr<lldb_private::Section> SectionSP;
|
||||
typedef std::unique_ptr<lldb_private::SectionList> SectionListUP;
|
||||
typedef std::weak_ptr<lldb_private::Section> SectionWP;
|
||||
|
||||
@@ -35,7 +35,7 @@ BreakpointResolverScripted::BreakpointResolverScripted(
|
||||
|
||||
void BreakpointResolverScripted::CreateImplementationIfNeeded(
|
||||
BreakpointSP breakpoint_sp) {
|
||||
if (m_implementation_sp)
|
||||
if (m_interface_sp)
|
||||
return;
|
||||
|
||||
if (m_class_name.empty())
|
||||
@@ -50,8 +50,27 @@ void BreakpointResolverScripted::CreateImplementationIfNeeded(
|
||||
if (!script_interp)
|
||||
return;
|
||||
|
||||
m_implementation_sp = script_interp->CreateScriptedBreakpointResolver(
|
||||
m_class_name.c_str(), m_args, breakpoint_sp);
|
||||
m_interface_sp = script_interp->CreateScriptedBreakpointInterface();
|
||||
if (!m_interface_sp) {
|
||||
m_error = Status::FromErrorStringWithFormat(
|
||||
"BreakpointResolverScripted::%s () - ERROR: %s", __FUNCTION__,
|
||||
"Script interpreter couldn't create Scripted Breakpoint Interface");
|
||||
return;
|
||||
}
|
||||
|
||||
auto obj_or_err =
|
||||
m_interface_sp->CreatePluginObject(m_class_name, breakpoint_sp, m_args);
|
||||
if (!obj_or_err) {
|
||||
m_error = Status::FromError(obj_or_err.takeError());
|
||||
return;
|
||||
}
|
||||
|
||||
StructuredData::ObjectSP object_sp = *obj_or_err;
|
||||
if (!object_sp || !object_sp->IsValid()) {
|
||||
m_error = Status::FromErrorStringWithFormat(
|
||||
"ScriptedBreakpoint::%s () - ERROR: %s", __FUNCTION__,
|
||||
"Failed to create valid script object");
|
||||
}
|
||||
}
|
||||
|
||||
void BreakpointResolverScripted::NotifyBreakpointSet() {
|
||||
@@ -104,13 +123,10 @@ ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() {
|
||||
Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback(
|
||||
SearchFilter &filter, SymbolContext &context, Address *addr) {
|
||||
bool should_continue = true;
|
||||
if (!m_implementation_sp)
|
||||
if (!m_interface_sp)
|
||||
return Searcher::eCallbackReturnStop;
|
||||
|
||||
ScriptInterpreter *interp = GetScriptInterpreter();
|
||||
should_continue = interp->ScriptedBreakpointResolverSearchCallback(
|
||||
m_implementation_sp,
|
||||
&context);
|
||||
should_continue = m_interface_sp->ResolverCallback(context);
|
||||
if (should_continue)
|
||||
return Searcher::eCallbackReturnContinue;
|
||||
|
||||
@@ -120,25 +136,21 @@ Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback(
|
||||
lldb::SearchDepth
|
||||
BreakpointResolverScripted::GetDepth() {
|
||||
lldb::SearchDepth depth = lldb::eSearchDepthModule;
|
||||
if (m_implementation_sp) {
|
||||
ScriptInterpreter *interp = GetScriptInterpreter();
|
||||
depth = interp->ScriptedBreakpointResolverSearchDepth(
|
||||
m_implementation_sp);
|
||||
}
|
||||
if (m_interface_sp)
|
||||
depth = m_interface_sp->GetDepth();
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
void BreakpointResolverScripted::GetDescription(Stream *s) {
|
||||
StructuredData::GenericSP generic_sp;
|
||||
std::string short_help;
|
||||
std::optional<std::string> short_help;
|
||||
|
||||
if (m_implementation_sp) {
|
||||
ScriptInterpreter *interp = GetScriptInterpreter();
|
||||
interp->GetShortHelpForCommandObject(m_implementation_sp,
|
||||
short_help);
|
||||
if (m_interface_sp) {
|
||||
short_help = m_interface_sp->GetShortHelp();
|
||||
}
|
||||
if (!short_help.empty())
|
||||
s->PutCString(short_help.c_str());
|
||||
if (short_help && !short_help->empty())
|
||||
s->PutCString(short_help->c_str());
|
||||
else
|
||||
s->Printf("python class = %s", m_class_name.c_str());
|
||||
}
|
||||
|
||||
@@ -116,6 +116,13 @@ lldb::StreamSP ScriptInterpreter::GetOpaqueTypeFromSBStream(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SymbolContext ScriptInterpreter::GetOpaqueTypeFromSBSymbolContext(
|
||||
const lldb::SBSymbolContext &sb_sym_ctx) const {
|
||||
if (sb_sym_ctx.m_opaque_up)
|
||||
return *sb_sym_ctx.m_opaque_up.get();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<MemoryRegionInfo>
|
||||
ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(
|
||||
const lldb::SBMemoryRegionInfo &mem_region) const {
|
||||
|
||||
@@ -26,6 +26,7 @@ add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces PLUGIN
|
||||
ScriptedProcessPythonInterface.cpp
|
||||
ScriptedPythonInterface.cpp
|
||||
ScriptedStopHookPythonInterface.cpp
|
||||
ScriptedBreakpointPythonInterface.cpp
|
||||
ScriptedThreadPlanPythonInterface.cpp
|
||||
ScriptedThreadPythonInterface.cpp
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ void ScriptInterpreterPythonInterfaces::Initialize() {
|
||||
ScriptedPlatformPythonInterface::Initialize();
|
||||
ScriptedProcessPythonInterface::Initialize();
|
||||
ScriptedStopHookPythonInterface::Initialize();
|
||||
ScriptedBreakpointPythonInterface::Initialize();
|
||||
ScriptedThreadPlanPythonInterface::Initialize();
|
||||
}
|
||||
|
||||
@@ -37,6 +38,7 @@ void ScriptInterpreterPythonInterfaces::Terminate() {
|
||||
ScriptedPlatformPythonInterface::Terminate();
|
||||
ScriptedProcessPythonInterface::Terminate();
|
||||
ScriptedStopHookPythonInterface::Terminate();
|
||||
ScriptedBreakpointPythonInterface::Terminate();
|
||||
ScriptedThreadPlanPythonInterface::Terminate();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#if LLDB_ENABLE_PYTHON
|
||||
|
||||
#include "OperatingSystemPythonInterface.h"
|
||||
#include "ScriptedBreakpointPythonInterface.h"
|
||||
#include "ScriptedPlatformPythonInterface.h"
|
||||
#include "ScriptedProcessPythonInterface.h"
|
||||
#include "ScriptedStopHookPythonInterface.h"
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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/Core/PluginManager.h"
|
||||
#include "lldb/Host/Config.h"
|
||||
#include "lldb/Symbol/SymbolContext.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Utility/Log.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
|
||||
#if LLDB_ENABLE_PYTHON
|
||||
|
||||
// LLDB Python header must be included first
|
||||
#include "../lldb-python.h"
|
||||
|
||||
#include "../SWIGPythonBridge.h"
|
||||
#include "../ScriptInterpreterPythonImpl.h"
|
||||
#include "ScriptedBreakpointPythonInterface.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::python;
|
||||
|
||||
ScriptedBreakpointPythonInterface::ScriptedBreakpointPythonInterface(
|
||||
ScriptInterpreterPythonImpl &interpreter)
|
||||
: ScriptedBreakpointInterface(), ScriptedPythonInterface(interpreter) {}
|
||||
|
||||
llvm::Expected<StructuredData::GenericSP>
|
||||
ScriptedBreakpointPythonInterface::CreatePluginObject(
|
||||
llvm::StringRef class_name, lldb::BreakpointSP break_sp,
|
||||
const StructuredDataImpl &args_sp) {
|
||||
return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr,
|
||||
break_sp, args_sp);
|
||||
}
|
||||
|
||||
bool ScriptedBreakpointPythonInterface::ResolverCallback(
|
||||
SymbolContext sym_ctx) {
|
||||
Status error;
|
||||
|
||||
StructuredData::ObjectSP obj = Dispatch("__callback__", error, sym_ctx);
|
||||
|
||||
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
|
||||
error)) {
|
||||
Log *log = GetLog(LLDBLog::Script);
|
||||
LLDB_LOG(log, "Error calling __callback__ method: {1}", error);
|
||||
return true;
|
||||
}
|
||||
return obj->GetBooleanValue();
|
||||
}
|
||||
|
||||
lldb::SearchDepth ScriptedBreakpointPythonInterface::GetDepth() {
|
||||
Status error;
|
||||
StructuredData::ObjectSP obj = Dispatch("__get_depth__", error);
|
||||
|
||||
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
|
||||
error)) {
|
||||
return lldb::eSearchDepthModule;
|
||||
}
|
||||
uint64_t value = obj->GetUnsignedIntegerValue();
|
||||
if (value <= lldb::kLastSearchDepthKind)
|
||||
return (lldb::SearchDepth)value;
|
||||
// This is what we were doing on error before, though I'm not sure that's
|
||||
// better than returning eSearchDepthInvalid.
|
||||
return lldb::eSearchDepthModule;
|
||||
}
|
||||
|
||||
std::optional<std::string> ScriptedBreakpointPythonInterface::GetShortHelp() {
|
||||
Status error;
|
||||
StructuredData::ObjectSP obj = Dispatch("get_short_help", error);
|
||||
|
||||
if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
|
||||
error)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return obj->GetAsString()->GetValue().str();
|
||||
}
|
||||
|
||||
void ScriptedBreakpointPythonInterface::Initialize() {
|
||||
const std::vector<llvm::StringRef> ci_usages = {
|
||||
"breakpoint set -P classname [-k key -v value ...]"};
|
||||
const std::vector<llvm::StringRef> api_usages = {
|
||||
"SBTarget.BreakpointCreateFromScript"};
|
||||
PluginManager::RegisterPlugin(
|
||||
GetPluginNameStatic(),
|
||||
llvm::StringRef("Create a breakpoint that chooses locations based on "
|
||||
"user-created callbacks"),
|
||||
CreateInstance, eScriptLanguagePython, {ci_usages, api_usages});
|
||||
}
|
||||
|
||||
void ScriptedBreakpointPythonInterface::Terminate() {
|
||||
PluginManager::UnregisterPlugin(CreateInstance);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
//===-- ScriptedBreakpointPythonInterface.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 LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDBREAKPOINTPYTHONINTERFACE_H
|
||||
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDBREAKPOINTPYTHONINTERFACE_H
|
||||
|
||||
#include "lldb/Host/Config.h"
|
||||
#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h"
|
||||
|
||||
#if LLDB_ENABLE_PYTHON
|
||||
|
||||
#include "ScriptedPythonInterface.h"
|
||||
|
||||
namespace lldb_private {
|
||||
class ScriptedBreakpointPythonInterface : public ScriptedBreakpointInterface,
|
||||
public ScriptedPythonInterface,
|
||||
public PluginInterface {
|
||||
public:
|
||||
ScriptedBreakpointPythonInterface(ScriptInterpreterPythonImpl &interpreter);
|
||||
|
||||
llvm::Expected<StructuredData::GenericSP>
|
||||
CreatePluginObject(llvm::StringRef class_name, lldb::BreakpointSP break_sp,
|
||||
const StructuredDataImpl &args_sp) override;
|
||||
|
||||
llvm::SmallVector<AbstractMethodRequirement>
|
||||
GetAbstractMethodRequirements() const override {
|
||||
return llvm::SmallVector<AbstractMethodRequirement>({{"__callback__", 2}});
|
||||
}
|
||||
|
||||
bool ResolverCallback(SymbolContext sym_ctx) override;
|
||||
lldb::SearchDepth GetDepth() override;
|
||||
std::optional<std::string> GetShortHelp() override;
|
||||
|
||||
static void Initialize();
|
||||
|
||||
static void Terminate();
|
||||
|
||||
static llvm::StringRef GetPluginNameStatic() {
|
||||
return "ScriptedBreakpointPythonInterface";
|
||||
}
|
||||
|
||||
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
|
||||
};
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // LLDB_ENABLE_PYTHON
|
||||
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDBREAKPOINTPYTHONINTERFACE_H
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "../ScriptInterpreterPythonImpl.h"
|
||||
#include "ScriptedPythonInterface.h"
|
||||
#include "lldb/Symbol/SymbolContext.h"
|
||||
#include <optional>
|
||||
|
||||
using namespace lldb;
|
||||
@@ -79,6 +80,20 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <>
|
||||
SymbolContext
|
||||
ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
|
||||
python::PythonObject &p, Status &error) {
|
||||
if (lldb::SBSymbolContext *sb_symbol_context =
|
||||
reinterpret_cast<lldb::SBSymbolContext *>(
|
||||
python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(p.get())))
|
||||
return m_interpreter.GetOpaqueTypeFromSBSymbolContext(*sb_symbol_context);
|
||||
error = Status::FromErrorString(
|
||||
"Couldn't cast lldb::SBSymbolContext to lldb_private::SymbolContext.");
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template <>
|
||||
lldb::DataExtractorSP
|
||||
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
|
||||
|
||||
@@ -432,6 +432,10 @@ protected:
|
||||
return python::SWIGBridge::ToSWIGWrapper(arg);
|
||||
}
|
||||
|
||||
python::PythonObject Transform(lldb::BreakpointSP arg) {
|
||||
return python::SWIGBridge::ToSWIGWrapper(arg);
|
||||
}
|
||||
|
||||
python::PythonObject Transform(lldb::ProcessSP arg) {
|
||||
return python::SWIGBridge::ToSWIGWrapper(arg);
|
||||
}
|
||||
@@ -452,6 +456,10 @@ protected:
|
||||
return python::SWIGBridge::ToSWIGWrapper(arg);
|
||||
}
|
||||
|
||||
python::PythonObject Transform(const SymbolContext &arg) {
|
||||
return python::SWIGBridge::ToSWIGWrapper(arg);
|
||||
}
|
||||
|
||||
python::PythonObject Transform(lldb::StreamSP arg) {
|
||||
return python::SWIGBridge::ToSWIGWrapper(arg.get());
|
||||
}
|
||||
@@ -555,6 +563,11 @@ template <>
|
||||
Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>(
|
||||
python::PythonObject &p, Status &error);
|
||||
|
||||
template <>
|
||||
SymbolContext
|
||||
ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
|
||||
python::PythonObject &p, Status &error);
|
||||
|
||||
template <>
|
||||
lldb::StreamSP
|
||||
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>(
|
||||
|
||||
@@ -151,15 +151,6 @@ public:
|
||||
const char *session_dictionary_name,
|
||||
lldb::DebuggerSP debugger_sp);
|
||||
|
||||
static python::PythonObject LLDBSwigPythonCreateScriptedBreakpointResolver(
|
||||
const char *python_class_name, const char *session_dictionary_name,
|
||||
const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp);
|
||||
|
||||
static unsigned int
|
||||
LLDBSwigPythonCallBreakpointResolver(void *implementor,
|
||||
const char *method_name,
|
||||
lldb_private::SymbolContext *sym_ctx);
|
||||
|
||||
static size_t LLDBSwigPython_CalculateNumChildren(PyObject *implementor,
|
||||
uint32_t max);
|
||||
|
||||
@@ -270,6 +261,7 @@ void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data);
|
||||
void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data);
|
||||
void *LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data);
|
||||
void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data);
|
||||
void *LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObject *data);
|
||||
void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data);
|
||||
void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data);
|
||||
void *LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject *data);
|
||||
|
||||
@@ -1550,6 +1550,11 @@ ScriptInterpreterPythonImpl::CreateScriptedStopHookInterface() {
|
||||
return std::make_shared<ScriptedStopHookPythonInterface>(*this);
|
||||
}
|
||||
|
||||
ScriptedBreakpointInterfaceSP
|
||||
ScriptInterpreterPythonImpl::CreateScriptedBreakpointInterface() {
|
||||
return std::make_shared<ScriptedBreakpointPythonInterface>(*this);
|
||||
}
|
||||
|
||||
ScriptedThreadInterfaceSP
|
||||
ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {
|
||||
return std::make_shared<ScriptedThreadPythonInterface>(*this);
|
||||
@@ -1576,75 +1581,6 @@ ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(
|
||||
return py_obj.CreateStructuredObject();
|
||||
}
|
||||
|
||||
StructuredData::GenericSP
|
||||
ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver(
|
||||
const char *class_name, const StructuredDataImpl &args_data,
|
||||
lldb::BreakpointSP &bkpt_sp) {
|
||||
|
||||
if (class_name == nullptr || class_name[0] == '\0')
|
||||
return StructuredData::GenericSP();
|
||||
|
||||
if (!bkpt_sp.get())
|
||||
return StructuredData::GenericSP();
|
||||
|
||||
Debugger &debugger = bkpt_sp->GetTarget().GetDebugger();
|
||||
ScriptInterpreterPythonImpl *python_interpreter =
|
||||
GetPythonInterpreter(debugger);
|
||||
|
||||
if (!python_interpreter)
|
||||
return StructuredData::GenericSP();
|
||||
|
||||
Locker py_lock(this,
|
||||
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
||||
|
||||
PythonObject ret_val =
|
||||
SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver(
|
||||
class_name, python_interpreter->m_dictionary_name.c_str(), args_data,
|
||||
bkpt_sp);
|
||||
|
||||
return StructuredData::GenericSP(
|
||||
new StructuredPythonObject(std::move(ret_val)));
|
||||
}
|
||||
|
||||
bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback(
|
||||
StructuredData::GenericSP implementor_sp, SymbolContext *sym_ctx) {
|
||||
bool should_continue = false;
|
||||
|
||||
if (implementor_sp) {
|
||||
Locker py_lock(this,
|
||||
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
||||
should_continue = SWIGBridge::LLDBSwigPythonCallBreakpointResolver(
|
||||
implementor_sp->GetValue(), "__callback__", sym_ctx);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
return should_continue;
|
||||
}
|
||||
|
||||
lldb::SearchDepth
|
||||
ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth(
|
||||
StructuredData::GenericSP implementor_sp) {
|
||||
int depth_as_int = lldb::eSearchDepthModule;
|
||||
if (implementor_sp) {
|
||||
Locker py_lock(this,
|
||||
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
||||
depth_as_int = SWIGBridge::LLDBSwigPythonCallBreakpointResolver(
|
||||
implementor_sp->GetValue(), "__get_depth__", nullptr);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
if (depth_as_int == lldb::eSearchDepthInvalid)
|
||||
return lldb::eSearchDepthModule;
|
||||
|
||||
if (depth_as_int <= lldb::kLastSearchDepthKind)
|
||||
return (lldb::SearchDepth)depth_as_int;
|
||||
return lldb::eSearchDepthModule;
|
||||
}
|
||||
|
||||
StructuredData::ObjectSP
|
||||
ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,
|
||||
lldb_private::Status &error) {
|
||||
|
||||
@@ -80,17 +80,6 @@ public:
|
||||
StructuredData::ObjectSP
|
||||
CreateStructuredDataFromScriptObject(ScriptObject obj) override;
|
||||
|
||||
StructuredData::GenericSP
|
||||
CreateScriptedBreakpointResolver(const char *class_name,
|
||||
const StructuredDataImpl &args_data,
|
||||
lldb::BreakpointSP &bkpt_sp) override;
|
||||
bool ScriptedBreakpointResolverSearchCallback(
|
||||
StructuredData::GenericSP implementor_sp,
|
||||
SymbolContext *sym_ctx) override;
|
||||
|
||||
lldb::SearchDepth ScriptedBreakpointResolverSearchDepth(
|
||||
StructuredData::GenericSP implementor_sp) override;
|
||||
|
||||
StructuredData::GenericSP
|
||||
CreateFrameRecognizer(const char *class_name) override;
|
||||
|
||||
@@ -105,6 +94,9 @@ public:
|
||||
|
||||
lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() override;
|
||||
|
||||
lldb::ScriptedBreakpointInterfaceSP
|
||||
CreateScriptedBreakpointInterface() override;
|
||||
|
||||
lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
|
||||
|
||||
lldb::ScriptedThreadPlanInterfaceSP
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "lldb/Host/StreamFile.h"
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
#include "lldb/Interpreter/CommandReturnObject.h"
|
||||
#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h"
|
||||
#include "lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h"
|
||||
#include "lldb/Interpreter/OptionGroupWatchpoint.h"
|
||||
#include "lldb/Interpreter/OptionValues.h"
|
||||
|
||||
@@ -235,11 +235,13 @@ class TestScriptedResolver(TestBase):
|
||||
substrs=["2"],
|
||||
msg="Was only passed modules",
|
||||
)
|
||||
|
||||
print(f"Made first breakpoint: {bkpt}")
|
||||
bkpt = None
|
||||
# Make a breakpoint that asks for modules, check that we didn't get any files:
|
||||
bkpt = target.BreakpointCreateFromScript(
|
||||
"resolver.ResolverModuleDepth", extra_args, module_list, file_list
|
||||
)
|
||||
print(f"Made Second breakpoint: {bkpt}")
|
||||
self.assertGreater(
|
||||
bkpt.GetNumLocations(), 0, "ResolverModuleDepth got no locations."
|
||||
)
|
||||
|
||||
@@ -13,6 +13,7 @@ class Resolver:
|
||||
Resolver.got_files = 0
|
||||
|
||||
def __callback__(self, sym_ctx):
|
||||
print("Resolver callback called")
|
||||
sym_name = "not_a_real_function_name"
|
||||
sym_item = self.extra_args.GetValueForKey("symbol")
|
||||
if sym_item.IsValid():
|
||||
@@ -34,9 +35,18 @@ class Resolver:
|
||||
return
|
||||
|
||||
if sym_ctx.module.IsValid():
|
||||
print(f"Looking for {sym_name}")
|
||||
sym = sym_ctx.module.FindSymbol(sym_name, lldb.eSymbolTypeCode)
|
||||
if sym.IsValid():
|
||||
print(f"Adding location at {sym.GetStartAddress()} to {self.bkpt}")
|
||||
self.bkpt.AddLocation(sym.GetStartAddress())
|
||||
print(f"After addition: {self.bkpt}")
|
||||
else:
|
||||
print("Didn't find it, however...")
|
||||
|
||||
print(f"GotFiles: {Resolver.got_files}")
|
||||
for func in Resolver.func_list:
|
||||
print(f"Function: func")
|
||||
|
||||
def get_short_help(self):
|
||||
return "I am a python breakpoint resolver"
|
||||
@@ -46,17 +56,31 @@ class ResolverModuleDepth(Resolver):
|
||||
def __get_depth__(self):
|
||||
return lldb.eSearchDepthModule
|
||||
|
||||
def __callback__(self, sym_ctx):
|
||||
print(f"About to call the Resolver callback for {self.bkpt}")
|
||||
Resolver.__callback__(self, sym_ctx)
|
||||
print("Called the callback for ResolverModuleDepth")
|
||||
|
||||
|
||||
class ResolverCUDepth(Resolver):
|
||||
def __get_depth__(self):
|
||||
return lldb.eSearchDepthCompUnit
|
||||
|
||||
def __callback__(self, sym_ctx):
|
||||
Resolver.__callback__(self, sym_ctx)
|
||||
|
||||
|
||||
class ResolverFuncDepth(Resolver):
|
||||
def __get_depth__(self):
|
||||
return lldb.eSearchDepthFunction
|
||||
|
||||
def __callback__(self, sym_ctx):
|
||||
Resolver.__callback__(self, sym_ctx)
|
||||
|
||||
|
||||
class ResolverBadDepth(Resolver):
|
||||
def __get_depth__(self):
|
||||
return lldb.kLastSearchDepthKind + 1
|
||||
|
||||
def __callback__(self, sym_ctx):
|
||||
Resolver.__callback__(self, sym_ctx)
|
||||
|
||||
@@ -80,20 +80,6 @@ lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject(
|
||||
return python::PythonObject();
|
||||
}
|
||||
|
||||
python::PythonObject lldb_private::python::SWIGBridge::
|
||||
LLDBSwigPythonCreateScriptedBreakpointResolver(
|
||||
const char *python_class_name, const char *session_dictionary_name,
|
||||
const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp) {
|
||||
return python::PythonObject();
|
||||
}
|
||||
|
||||
unsigned int
|
||||
lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResolver(
|
||||
void *implementor, const char *method_name,
|
||||
lldb_private::SymbolContext *sym_ctx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t lldb_private::python::SWIGBridge::LLDBSwigPython_CalculateNumChildren(
|
||||
PyObject *implementor, uint32_t max) {
|
||||
return 0;
|
||||
@@ -144,6 +130,11 @@ lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(
|
||||
PyObject *data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *
|
||||
lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data) {
|
||||
return nullptr;
|
||||
|
||||
Reference in New Issue
Block a user