jimingham 04b443e778
Add the ability to define custom completers to the parsed_cmd template. (#109062)
If your arguments or option values are of a type that naturally uses one
of our common completion mechanisms, you will get completion for free.
But if you have your own custom values or if you want to do fancy things
like have `break set -s foo.dylib -n ba<TAB>` only complete on symbols
in foo.dylib, you can use this new mechanism to achieve that.
2024-09-24 10:00:00 -07:00

275 lines
12 KiB
C++

//===-- ScriptInterpreterPython.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_SWIGPYTHONBRIDGE_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H
#include <optional>
#include <string>
#include "lldb/Host/Config.h"
#if LLDB_ENABLE_PYTHON
// LLDB Python header must be included first
#include "lldb-python.h"
#include "Plugins/ScriptInterpreter/Python/PythonDataObjects.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-types.h"
#include "llvm/Support/Error.h"
namespace lldb {
class SBEvent;
class SBCommandReturnObject;
class SBValue;
class SBStream;
class SBStructuredData;
class SBFileSpec;
class SBModuleSpec;
class SBStringList;
} // namespace lldb
namespace lldb_private {
namespace python {
typedef struct swig_type_info swig_type_info;
python::PythonObject ToSWIGHelper(void *obj, swig_type_info *info);
/// A class that automatically clears an SB object when it goes out of scope.
/// Use for cases where the SB object points to a temporary/unowned entity.
template <typename T> class ScopedPythonObject : PythonObject {
public:
ScopedPythonObject(T *sb, swig_type_info *info)
: PythonObject(ToSWIGHelper(sb, info)), m_sb(sb) {}
~ScopedPythonObject() {
if (m_sb)
*m_sb = T();
}
ScopedPythonObject(ScopedPythonObject &&rhs)
: PythonObject(std::move(rhs)), m_sb(std::exchange(rhs.m_sb, nullptr)) {}
ScopedPythonObject(const ScopedPythonObject &) = delete;
ScopedPythonObject &operator=(const ScopedPythonObject &) = delete;
ScopedPythonObject &operator=(ScopedPythonObject &&) = delete;
const PythonObject &obj() const { return *this; }
private:
T *m_sb;
};
// TODO: We may want to support other languages in the future w/ SWIG (we
// already support Lua right now, for example). We could create a generic
// SWIGBridge class and have this one specialize it, something like this:
//
// <typename T>
// class SWIGBridge {
// static T ToSWIGWrapper(...);
// };
//
// class SWIGPythonBridge : public SWIGBridge<PythonObject> {
// template<> static PythonObject ToSWIGWrapper(...);
// };
//
// And we should be able to more easily support things like Lua
class SWIGBridge {
public:
static PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBValue> value_sb);
static PythonObject ToSWIGWrapper(lldb::ValueObjectSP value_sp);
static PythonObject ToSWIGWrapper(lldb::TargetSP target_sp);
static PythonObject ToSWIGWrapper(lldb::ProcessSP process_sp);
static PythonObject ToSWIGWrapper(lldb::ThreadPlanSP thread_plan_sp);
static PythonObject ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp);
static PythonObject ToSWIGWrapper(Status &&status);
static PythonObject ToSWIGWrapper(const StructuredDataImpl &data_impl);
static PythonObject ToSWIGWrapper(lldb::ThreadSP thread_sp);
static PythonObject ToSWIGWrapper(lldb::StackFrameSP frame_sp);
static PythonObject ToSWIGWrapper(lldb::DebuggerSP debugger_sp);
static PythonObject ToSWIGWrapper(lldb::WatchpointSP watchpoint_sp);
static PythonObject ToSWIGWrapper(lldb::BreakpointLocationSP bp_loc_sp);
static PythonObject ToSWIGWrapper(lldb::TypeImplSP type_impl_sp);
static PythonObject ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp);
static PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options);
static PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx);
static PythonObject ToSWIGWrapper(const Stream *stream);
static PythonObject ToSWIGWrapper(std::shared_ptr<lldb::SBStream> stream_sb);
static PythonObject ToSWIGWrapper(Event *event);
static PythonObject ToSWIGWrapper(lldb::ProcessAttachInfoSP attach_info_sp);
static PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp);
static PythonObject ToSWIGWrapper(lldb::DataExtractorSP data_extractor_sp);
static PythonObject
ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb);
static PythonObject
ToSWIGWrapper(std::unique_ptr<lldb::SBFileSpec> file_spec_sb);
static PythonObject
ToSWIGWrapper(std::unique_ptr<lldb::SBModuleSpec> module_spec_sb);
static python::ScopedPythonObject<lldb::SBCommandReturnObject>
ToSWIGWrapper(CommandReturnObject &cmd_retobj);
// These prototypes are the Pythonic implementations of the required
// callbacks. Although these are scripting-language specific, their definition
// depends on the public API.
static llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction(
const char *python_function_name, const char *session_dictionary_name,
const lldb::StackFrameSP &sb_frame,
const lldb::BreakpointLocationSP &sb_bp_loc,
const lldb_private::StructuredDataImpl &args_impl);
static bool LLDBSwigPythonWatchpointCallbackFunction(
const char *python_function_name, const char *session_dictionary_name,
const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp);
static bool
LLDBSwigPythonFormatterCallbackFunction(const char *python_function_name,
const char *session_dictionary_name,
lldb::TypeImplSP type_impl_sp);
static bool LLDBSwigPythonCallTypeScript(
const char *python_function_name, const void *session_dictionary,
const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper,
const lldb::TypeSummaryOptionsSP &options_sp, std::string &retval);
static python::PythonObject
LLDBSwigPythonCreateSyntheticProvider(const char *python_class_name,
const char *session_dictionary_name,
const lldb::ValueObjectSP &valobj_sp);
static python::PythonObject
LLDBSwigPythonCreateCommandObject(const char *python_class_name,
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);
static PyObject *LLDBSwigPython_GetChildAtIndex(PyObject *implementor,
uint32_t idx);
static int LLDBSwigPython_GetIndexOfChildWithName(PyObject *implementor,
const char *child_name);
static lldb::ValueObjectSP
LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data);
static bool LLDBSwigPython_UpdateSynthProviderInstance(PyObject *implementor);
static bool
LLDBSwigPython_MightHaveChildrenSynthProviderInstance(PyObject *implementor);
static PyObject *
LLDBSwigPython_GetValueSynthProviderInstance(PyObject *implementor);
static bool
LLDBSwigPythonCallCommand(const char *python_function_name,
const char *session_dictionary_name,
lldb::DebuggerSP debugger, const char *args,
lldb_private::CommandReturnObject &cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp);
static bool
LLDBSwigPythonCallCommandObject(PyObject *implementor,
lldb::DebuggerSP debugger, const char *args,
lldb_private::CommandReturnObject &cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp);
static bool
LLDBSwigPythonCallParsedCommandObject(PyObject *implementor,
lldb::DebuggerSP debugger,
StructuredDataImpl &args_impl,
lldb_private::CommandReturnObject &cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp);
static std::optional<std::string>
LLDBSwigPythonGetRepeatCommandForScriptedCommand(PyObject *implementor,
std::string &command);
static StructuredData::DictionarySP
LLDBSwigPythonHandleArgumentCompletionForScriptedCommand(
PyObject *implementor, std::vector<llvm::StringRef> &args_impl,
size_t args_pos, size_t pos_in_arg);
static StructuredData::DictionarySP
LLDBSwigPythonHandleOptionArgumentCompletionForScriptedCommand(
PyObject *implementor, llvm::StringRef &long_option, size_t pos_in_arg);
static bool LLDBSwigPythonCallModuleInit(const char *python_module_name,
const char *session_dictionary_name,
lldb::DebuggerSP debugger);
static python::PythonObject
LLDBSWIGPythonCreateOSPlugin(const char *python_class_name,
const char *session_dictionary_name,
const lldb::ProcessSP &process_sp);
static python::PythonObject
LLDBSWIGPython_CreateFrameRecognizer(const char *python_class_name,
const char *session_dictionary_name);
static PyObject *
LLDBSwigPython_GetRecognizedArguments(PyObject *implementor,
const lldb::StackFrameSP &frame_sp);
static bool LLDBSwigPython_ShouldHide(PyObject *implementor,
const lldb::StackFrameSP &frame_sp);
static bool LLDBSWIGPythonRunScriptKeywordProcess(
const char *python_function_name, const char *session_dictionary_name,
const lldb::ProcessSP &process, std::string &output);
static std::optional<std::string>
LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name,
const char *session_dictionary_name,
lldb::ThreadSP thread);
static bool LLDBSWIGPythonRunScriptKeywordTarget(
const char *python_function_name, const char *session_dictionary_name,
const lldb::TargetSP &target, std::string &output);
static std::optional<std::string>
LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name,
const char *session_dictionary_name,
lldb::StackFrameSP frame);
static bool LLDBSWIGPythonRunScriptKeywordValue(
const char *python_function_name, const char *session_dictionary_name,
const lldb::ValueObjectSP &value, std::string &output);
static void *
LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting,
const lldb::TargetSP &target_sp);
};
void *LLDBSWIGPython_CastPyObjectToSBData(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBBreakpoint(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject *data);
} // namespace python
} // namespace lldb_private
#endif // LLDB_ENABLE_PYTHON
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H