Skip to content

Commit

Permalink
[lldb] Make use of Scripted{Python,}Interface for ScriptedThreadPlan (l…
Browse files Browse the repository at this point in the history
…lvm#70392)

This patch makes ScriptedThreadPlan conforming to the ScriptedInterface
& ScriptedPythonInterface facilities by introducing 2
ScriptedThreadPlanInterface & ScriptedThreadPlanPythonInterface classes.

This allows us to get rid of every ScriptedThreadPlan-specific SWIG
method and re-use the same affordances as other scripting offordances,
like Scripted{Process,Thread,Platform} & OperatingSystem.

To do so, this adds new transformer methods for `ThreadPlan`, `Stream` &
`Event`, to allow the bijection between C++ objects and their python
counterparts.

Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
  • Loading branch information
medismailben committed May 23, 2024
1 parent 7aa382f commit d3f819b
Show file tree
Hide file tree
Showing 25 changed files with 468 additions and 431 deletions.
17 changes: 10 additions & 7 deletions lldb/bindings/python/python-swigsafecast.swig
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ PythonObject SWIGBridge::ToSWIGWrapper(const Status& status) {
return ToSWIGHelper(new lldb::SBError(status), SWIGTYPE_p_lldb__SBError);
}

PythonObject SWIGBridge::ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb) {
return ToSWIGHelper(stream_sb.release(), SWIGTYPE_p_lldb__SBStream);
}

PythonObject SWIGBridge::ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb) {
return ToSWIGHelper(data_sb.release(), SWIGTYPE_p_lldb__SBStructuredData);
}
Expand Down Expand Up @@ -115,9 +111,16 @@ SWIGBridge::ToSWIGWrapper(CommandReturnObject &cmd_retobj) {
SWIGTYPE_p_lldb__SBCommandReturnObject);
}

ScopedPythonObject<lldb::SBEvent> SWIGBridge::ToSWIGWrapper(Event *event) {
return ScopedPythonObject<lldb::SBEvent>(new lldb::SBEvent(event),
SWIGTYPE_p_lldb__SBEvent);
PythonObject SWIGBridge::ToSWIGWrapper(const Stream *s) {
return ToSWIGHelper(new lldb::SBStream(), SWIGTYPE_p_lldb__SBStream);
}

PythonObject SWIGBridge::ToSWIGWrapper(std::shared_ptr<lldb::SBStream> stream_sb) {
return ToSWIGHelper(stream_sb.get(), SWIGTYPE_p_lldb__SBStream);
}

PythonObject SWIGBridge::ToSWIGWrapper(Event *event) {
return ToSWIGHelper(new lldb::SBEvent(event), SWIGTYPE_p_lldb__SBEvent);
}

PythonObject SWIGBridge::ToSWIGWrapper(
Expand Down
157 changes: 27 additions & 130 deletions lldb/bindings/python/python-wrapper.swig
Original file line number Diff line number Diff line change
Expand Up @@ -229,133 +229,6 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject
return pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger_sp)), dict);
}

PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedThreadPlan(
const char *python_class_name, const char *session_dictionary_name,
const lldb_private::StructuredDataImpl &args_impl,
std::string &error_string, const lldb::ThreadPlanSP &thread_plan_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()) {
error_string.append("could not find script class: ");
error_string.append(python_class_name);
return PythonObject();
}

PythonObject tp_arg = SWIGBridge::ToSWIGWrapper(thread_plan_sp);

llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
if (!arg_info) {
llvm::handleAllErrors(
arg_info.takeError(),
[&](PythonException &E) { error_string.append(E.ReadBacktrace()); },
[&](const llvm::ErrorInfoBase &E) {
error_string.append(E.message());
});
return PythonObject();
}

PythonObject result = {};
auto args_sb = std::unique_ptr<lldb::SBStructuredData>(new lldb::SBStructuredData(args_impl));
if (arg_info.get().max_positional_args == 2) {
if (args_sb->IsValid()) {
error_string.assign(
"args passed, but __init__ does not take an args dictionary");
return PythonObject();
}
result = pfunc(tp_arg, dict);
} else if (arg_info.get().max_positional_args >= 3) {
result = pfunc(tp_arg, SWIGBridge::ToSWIGWrapper(std::move(args_sb)), dict);
} else {
error_string.assign("wrong number of arguments in __init__, should be 2 or "
"3 (not including self)");
return PythonObject();
}

// FIXME: At this point we should check that the class we found supports all
// the methods that we need.

return result;
}

bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
void *implementer, const char *method_name, lldb_private::Event *event,
bool &got_error) {
got_error = false;

PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementer));
auto pfunc = self.ResolveName<PythonCallable>(method_name);

if (!pfunc.IsAllocated())
return false;

PythonObject result;
if (event != nullptr) {
ScopedPythonObject<SBEvent> event_arg = SWIGBridge::ToSWIGWrapper(event);
result = pfunc(event_arg.obj());
} else
result = pfunc();

if (PyErr_Occurred()) {
got_error = true;
printf("Return value was neither false nor true for call to %s.\n",
method_name);
PyErr_Print();
return false;
}

if (result.get() == Py_True)
return true;
else if (result.get() == Py_False)
return false;

// Somebody returned the wrong thing...
got_error = true;
printf("Wrong return value type for call to %s.\n", method_name);
return false;
}

bool lldb_private::python::SWIGBridge::LLDBSWIGPythonCallThreadPlan(
void *implementer, const char *method_name, lldb_private::Stream *stream,
bool &got_error) {
got_error = false;

PyErr_Cleaner py_err_cleaner(false);
PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementer));
auto pfunc = self.ResolveName<PythonCallable>(method_name);

if (!pfunc.IsAllocated())
return false;

auto *sb_stream = new lldb::SBStream();
PythonObject sb_stream_arg =
SWIGBridge::ToSWIGWrapper(std::unique_ptr<lldb::SBStream>(sb_stream));

PythonObject result;
result = pfunc(sb_stream_arg);

if (PyErr_Occurred()) {
printf("Error occured for call to %s.\n",
method_name);
PyErr_Print();
got_error = true;
return false;
}
if (stream)
stream->PutCString(sb_stream->GetData());
return true;

}

PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver(
const char *python_class_name, const char *session_dictionary_name,
const StructuredDataImpl &args_impl,
Expand Down Expand Up @@ -500,9 +373,8 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonStopHookCallHandleStop(
if (!pfunc.IsAllocated())
return true;

auto *sb_stream = new lldb::SBStream();
PythonObject sb_stream_arg =
SWIGBridge::ToSWIGWrapper(std::unique_ptr<lldb::SBStream>(sb_stream));
std::shared_ptr<lldb::SBStream> sb_stream = std::make_shared<lldb::SBStream>();
PythonObject sb_stream_arg = SWIGBridge::ToSWIGWrapper(sb_stream);
PythonObject result =
pfunc(SWIGBridge::ToSWIGWrapper(std::move(exc_ctx_sp)), sb_stream_arg);

Expand All @@ -517,6 +389,7 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonStopHookCallHandleStop(
// makes an internally help StreamString which I can't interpose, so I
// have to copy it over here.
stream->PutCString(sb_stream->GetData());
sb_stream_arg.release();

if (result.get() == Py_False)
return false;
Expand Down Expand Up @@ -753,6 +626,30 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBError(PyObject * data
return sb_ptr;
}

void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBEvent(PyObject * data) {
lldb::SBEvent *sb_ptr = nullptr;

int valid_cast =
SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBEvent, 0);

if (valid_cast == -1)
return NULL;

return sb_ptr;
}

void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject * data) {
lldb::SBStream *sb_ptr = nullptr;

int valid_cast =
SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBStream, 0);

if (valid_cast == -1)
return NULL;

return sb_ptr;
}

void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject * data) {
lldb::SBValue *sb_ptr = NULL;

Expand Down
4 changes: 3 additions & 1 deletion lldb/include/lldb/API/SBEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <vector>

namespace lldb_private {
class ScriptInterpreter;
namespace python {
class SWIGBridge;
}
Expand Down Expand Up @@ -73,11 +74,12 @@ class LLDB_API SBEvent {
friend class SBThread;
friend class SBWatchpoint;

friend class lldb_private::ScriptInterpreter;
friend class lldb_private::python::SWIGBridge;

SBEvent(lldb::EventSP &event_sp);

SBEvent(lldb_private::Event *event_sp);
SBEvent(lldb_private::Event *event);

lldb::EventSP &GetSP() const;

Expand Down
6 changes: 6 additions & 0 deletions lldb/include/lldb/API/SBStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

#include "lldb/API/SBDefines.h"

namespace lldb_private {
class ScriptInterpreter;
} // namespace lldb_private

namespace lldb {

class LLDB_API SBStream {
Expand Down Expand Up @@ -101,6 +105,8 @@ class LLDB_API SBStream {
friend class SBValue;
friend class SBWatchpoint;

friend class lldb_private::ScriptInterpreter;

lldb_private::Stream *operator->();

lldb_private::Stream *get();
Expand Down
4 changes: 2 additions & 2 deletions lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDINTERFACE_H

#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/UnimplementedError.h"
Expand Down Expand Up @@ -52,7 +51,8 @@ class ScriptedInterface {
}

template <typename T = StructuredData::ObjectSP>
bool CheckStructuredDataObject(llvm::StringRef caller, T obj, Status &error) {
static bool CheckStructuredDataObject(llvm::StringRef caller, T obj,
Status &error) {
if (!obj)
return ErrorWithMessage<bool>(caller, "Null Structured Data object",
error);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//===-- ScriptedThreadPlanInterface.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_INTERPRETER_INTERFACES_SCRIPTEDTHREADPLANINTERFACE_H
#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDTHREADPLANINTERFACE_H

#include "lldb/lldb-private.h"

#include "ScriptedInterface.h"

namespace lldb_private {
class ScriptedThreadPlanInterface : public ScriptedInterface {
public:
virtual llvm::Expected<StructuredData::GenericSP>
CreatePluginObject(llvm::StringRef class_name,
lldb::ThreadPlanSP thread_plan_sp,
const StructuredDataImpl &args_sp) = 0;

virtual llvm::Expected<bool> ExplainsStop(Event *event) { return true; }

virtual llvm::Expected<bool> ShouldStop(Event *event) { return true; }

virtual llvm::Expected<bool> IsStale() { return true; };

virtual lldb::StateType GetRunState() { return lldb::eStateStepping; }

virtual llvm::Expected<bool> GetStopDescription(lldb_private::Stream *s) {
return true;
}
};
} // namespace lldb_private

#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDTHREADPLANINTERFACE_H
55 changes: 11 additions & 44 deletions lldb/include/lldb/Interpreter/ScriptInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBData.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/API/SBStream.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/SearchFilter.h"
Expand Down Expand Up @@ -250,50 +252,6 @@ class ScriptInterpreter : public PluginInterface {
return lldb::ValueObjectListSP();
}

virtual StructuredData::ObjectSP
CreateScriptedThreadPlan(const char *class_name,
const StructuredDataImpl &args_data,
std::string &error_str,
lldb::ThreadPlanSP thread_plan_sp) {
return StructuredData::ObjectSP();
}

virtual bool
ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
Event *event, bool &script_error) {
script_error = true;
return true;
}

virtual bool
ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
Event *event, bool &script_error) {
script_error = true;
return true;
}

virtual bool
ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
bool &script_error) {
script_error = true;
return true;
}

virtual lldb::StateType
ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
bool &script_error) {
script_error = true;
return lldb::eStateStepping;
}

virtual bool
ScriptedThreadPlanGetStopDescription(StructuredData::ObjectSP implementor_sp,
lldb_private::Stream *stream,
bool &script_error) {
script_error = true;
return false;
}

virtual StructuredData::GenericSP
CreateScriptedBreakpointResolver(const char *class_name,
const StructuredDataImpl &args_data,
Expand Down Expand Up @@ -592,6 +550,11 @@ class ScriptInterpreter : public PluginInterface {
return {};
}

virtual lldb::ScriptedThreadPlanInterfaceSP
CreateScriptedThreadPlanInterface() {
return {};
}

virtual lldb::OperatingSystemInterfaceSP CreateOperatingSystemInterface() {
return {};
}
Expand All @@ -610,6 +573,10 @@ class ScriptInterpreter : public PluginInterface {

Status GetStatusFromSBError(const lldb::SBError &error) const;

Event *GetOpaqueTypeFromSBEvent(const lldb::SBEvent &event) const;

Stream *GetOpaqueTypeFromSBStream(const lldb::SBStream &stream) const;

lldb::BreakpointSP
GetOpaqueTypeFromSBBreakpoint(const lldb::SBBreakpoint &breakpoint) const;

Expand Down
Loading

0 comments on commit d3f819b

Please sign in to comment.