blob: ef29a9628be4fdb594c74840337da8354c3ac7ff [file] [log] [blame]
//===-- ScriptInterpreterPython.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
#ifdef LLDB_DISABLE_PYTHON
// Python is disabled in this build
#else
// C Includes
// C++ Includes
#include <memory>
#include <string>
#include <vector>
// Other libraries and framework includes
// Project includes
#include "PythonDataObjects.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/lldb-private.h"
class IOHandlerPythonInterpreter;
namespace lldb_private {
class ScriptInterpreterPython : public ScriptInterpreter,
public IOHandlerDelegateMultiline {
public:
class CommandDataPython : public BreakpointOptions::CommandData {
public:
CommandDataPython() : BreakpointOptions::CommandData() {
interpreter = lldb::eScriptLanguagePython;
}
};
#if PY_MAJOR_VERSION >= 3
typedef PyObject *(*SWIGInitCallback)(void);
#else
typedef void (*SWIGInitCallback)(void);
#endif
typedef bool (*SWIGBreakpointCallbackFunction)(
const char *python_function_name, const char *session_dictionary_name,
const lldb::StackFrameSP &frame_sp,
const lldb::BreakpointLocationSP &bp_loc_sp);
typedef bool (*SWIGWatchpointCallbackFunction)(
const char *python_function_name, const char *session_dictionary_name,
const lldb::StackFrameSP &frame_sp, const lldb::WatchpointSP &wp_sp);
typedef bool (*SWIGPythonTypeScriptCallbackFunction)(
const char *python_function_name, void *session_dictionary,
const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper,
const lldb::TypeSummaryOptionsSP &options, std::string &retval);
typedef void *(*SWIGPythonCreateSyntheticProvider)(
const char *python_class_name, const char *session_dictionary_name,
const lldb::ValueObjectSP &valobj_sp);
typedef void *(*SWIGPythonCreateCommandObject)(
const char *python_class_name, const char *session_dictionary_name,
const lldb::DebuggerSP debugger_sp);
typedef void *(*SWIGPythonCreateScriptedThreadPlan)(
const char *python_class_name, const char *session_dictionary_name,
const lldb::ThreadPlanSP &thread_plan_sp);
typedef bool (*SWIGPythonCallThreadPlan)(void *implementor,
const char *method_name,
Event *event_sp, bool &got_error);
typedef void *(*SWIGPythonCreateScriptedBreakpointResolver)(
const char *python_class_name, const char *session_dictionary_name,
lldb_private::StructuredDataImpl *args_impl,
lldb::BreakpointSP &bkpt_sp);
typedef unsigned int (*SWIGPythonCallBreakpointResolver)(void *implementor,
const char *method_name,
lldb_private::SymbolContext *sym_ctx);
typedef void *(*SWIGPythonCreateOSPlugin)(const char *python_class_name,
const char *session_dictionary_name,
const lldb::ProcessSP &process_sp);
typedef size_t (*SWIGPythonCalculateNumChildren)(void *implementor,
uint32_t max);
typedef void *(*SWIGPythonGetChildAtIndex)(void *implementor, uint32_t idx);
typedef int (*SWIGPythonGetIndexOfChildWithName)(void *implementor,
const char *child_name);
typedef void *(*SWIGPythonCastPyObjectToSBValue)(void *data);
typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue)(
void *data);
typedef bool (*SWIGPythonUpdateSynthProviderInstance)(void *data);
typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance)(void *data);
typedef void *(*SWIGPythonGetValueSynthProviderInstance)(void *implementor);
typedef bool (*SWIGPythonCallCommand)(
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);
typedef bool (*SWIGPythonCallCommandObject)(
void *implementor, lldb::DebuggerSP &debugger, const char *args,
lldb_private::CommandReturnObject &cmd_retobj,
lldb::ExecutionContextRefSP exe_ctx_ref_sp);
typedef bool (*SWIGPythonCallModuleInit)(const char *python_module_name,
const char *session_dictionary_name,
lldb::DebuggerSP &debugger);
typedef bool (*SWIGPythonScriptKeyword_Process)(
const char *python_function_name, const char *session_dictionary_name,
lldb::ProcessSP &process, std::string &output);
typedef bool (*SWIGPythonScriptKeyword_Thread)(
const char *python_function_name, const char *session_dictionary_name,
lldb::ThreadSP &thread, std::string &output);
typedef bool (*SWIGPythonScriptKeyword_Target)(
const char *python_function_name, const char *session_dictionary_name,
lldb::TargetSP &target, std::string &output);
typedef bool (*SWIGPythonScriptKeyword_Frame)(
const char *python_function_name, const char *session_dictionary_name,
lldb::StackFrameSP &frame, std::string &output);
typedef bool (*SWIGPythonScriptKeyword_Value)(
const char *python_function_name, const char *session_dictionary_name,
lldb::ValueObjectSP &value, std::string &output);
typedef void *(*SWIGPython_GetDynamicSetting)(
void *module, const char *setting, const lldb::TargetSP &target_sp);
friend class ::IOHandlerPythonInterpreter;
ScriptInterpreterPython(CommandInterpreter &interpreter);
~ScriptInterpreterPython() override;
bool Interrupt() override;
bool ExecuteOneLine(
llvm::StringRef command, CommandReturnObject *result,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
void ExecuteInterpreterLoop() override;
bool ExecuteOneLineWithReturn(
llvm::StringRef in_string,
ScriptInterpreter::ScriptReturnType return_type, void *ret_value,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
lldb_private::Status ExecuteMultipleLines(
const char *in_string,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
Status
ExportFunctionDefinitionToInterpreter(StringList &function_def) override;
bool GenerateTypeScriptFunction(StringList &input, std::string &output,
const void *name_token = nullptr) override;
bool GenerateTypeSynthClass(StringList &input, std::string &output,
const void *name_token = nullptr) override;
bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
const void *name_token = nullptr) override;
// use this if the function code is just a one-liner script
bool GenerateTypeScriptFunction(const char *oneliner, std::string &output,
const void *name_token = nullptr) override;
bool GenerateScriptAliasFunction(StringList &input,
std::string &output) override;
StructuredData::ObjectSP
CreateSyntheticScriptedProvider(const char *class_name,
lldb::ValueObjectSP valobj) override;
StructuredData::GenericSP
CreateScriptCommandObject(const char *class_name) override;
StructuredData::ObjectSP
CreateScriptedThreadPlan(const char *class_name,
lldb::ThreadPlanSP thread_plan) override;
bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
Event *event,
bool &script_error) override;
bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
Event *event, bool &script_error) override;
bool ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
bool &script_error) override;
lldb::StateType
ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
bool &script_error) override;
StructuredData::GenericSP
CreateScriptedBreakpointResolver(const char *class_name,
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
OSPlugin_CreatePluginObject(const char *class_name,
lldb::ProcessSP process_sp) override;
StructuredData::DictionarySP
OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
StructuredData::ArraySP
OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
StructuredData::StringSP
OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
lldb::tid_t thread_id) override;
StructuredData::DictionarySP
OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
lldb::tid_t tid, lldb::addr_t context) override;
StructuredData::ObjectSP
LoadPluginModule(const FileSpec &file_spec,
lldb_private::Status &error) override;
StructuredData::DictionarySP
GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
const char *setting_name,
lldb_private::Status &error) override;
size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor,
uint32_t max) override;
lldb::ValueObjectSP
GetChildAtIndex(const StructuredData::ObjectSP &implementor,
uint32_t idx) override;
int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
const char *child_name) override;
bool UpdateSynthProviderInstance(
const StructuredData::ObjectSP &implementor) override;
bool MightHaveChildrenSynthProviderInstance(
const StructuredData::ObjectSP &implementor) override;
lldb::ValueObjectSP
GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
ConstString
GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
bool
RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj,
Status &error,
const lldb_private::ExecutionContext &exe_ctx) override;
bool RunScriptBasedCommand(
StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj, Status &error,
const lldb_private::ExecutionContext &exe_ctx) override;
Status GenerateFunction(const char *signature,
const StringList &input) override;
Status GenerateBreakpointCommandCallbackData(StringList &input,
std::string &output) override;
bool GenerateWatchpointCommandCallbackData(StringList &input,
std::string &output) override;
// static size_t
// GenerateBreakpointOptionsCommandCallback (void *baton,
// InputReader &reader,
// lldb::InputReaderAction
// notification,
// const char *bytes,
// size_t bytes_len);
//
// static size_t
// GenerateWatchpointOptionsCommandCallback (void *baton,
// InputReader &reader,
// lldb::InputReaderAction
// notification,
// const char *bytes,
// size_t bytes_len);
static bool BreakpointCallbackFunction(void *baton,
StoppointCallbackContext *context,
lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
static bool WatchpointCallbackFunction(void *baton,
StoppointCallbackContext *context,
lldb::user_id_t watch_id);
bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj,
StructuredData::ObjectSP &callee_wrapper_sp,
const TypeSummaryOptions &options,
std::string &retval) override;
void Clear() override;
bool GetDocumentationForItem(const char *item, std::string &dest) override;
bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
std::string &dest) override;
uint32_t
GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
std::string &dest) override;
bool CheckObjectExists(const char *name) override {
if (!name || !name[0])
return false;
std::string temp;
return GetDocumentationForItem(name, temp);
}
bool RunScriptFormatKeyword(const char *impl_function, Process *process,
std::string &output, Status &error) override;
bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
std::string &output, Status &error) override;
bool RunScriptFormatKeyword(const char *impl_function, Target *target,
std::string &output, Status &error) override;
bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame,
std::string &output, Status &error) override;
bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
std::string &output, Status &error) override;
bool
LoadScriptingModule(const char *filename, bool can_reload, bool init_session,
lldb_private::Status &error,
StructuredData::ObjectSP *module_sp = nullptr) override;
bool IsReservedWord(const char *word) override;
std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
void CollectDataForBreakpointCommandCallback(
std::vector<BreakpointOptions *> &bp_options_vec,
CommandReturnObject &result) override;
void
CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
CommandReturnObject &result) override;
/// Set the callback body text into the callback for the breakpoint.
Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
const char *callback_body) override;
void SetBreakpointCommandCallbackFunction(BreakpointOptions *bp_options,
const char *function_name) override;
/// This one is for deserialization:
Status SetBreakpointCommandCallback(
BreakpointOptions *bp_options,
std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
/// Set a one-liner as the callback for the watchpoint.
void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
const char *oneliner) override;
StringList ReadCommandInputFromUser(FILE *in_file);
void ResetOutputFileHandle(FILE *new_fh) override;
static void InitializePrivate();
static void InitializeInterpreter(
SWIGInitCallback python_swig_init_callback,
SWIGBreakpointCallbackFunction swig_breakpoint_callback,
SWIGWatchpointCallbackFunction swig_watchpoint_callback,
SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
SWIGPythonCreateSyntheticProvider swig_synthetic_script,
SWIGPythonCreateCommandObject swig_create_cmd,
SWIGPythonCalculateNumChildren swig_calc_children,
SWIGPythonGetChildAtIndex swig_get_child_index,
SWIGPythonGetIndexOfChildWithName swig_get_index_child,
SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue,
SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
SWIGPythonUpdateSynthProviderInstance swig_update_provider,
SWIGPythonMightHaveChildrenSynthProviderInstance
swig_mighthavechildren_provider,
SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
SWIGPythonCallCommand swig_call_command,
SWIGPythonCallCommandObject swig_call_command_object,
SWIGPythonCallModuleInit swig_call_module_init,
SWIGPythonCreateOSPlugin swig_create_os_plugin,
SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
SWIGPython_GetDynamicSetting swig_plugin_get,
SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
SWIGPythonCallThreadPlan swig_call_thread_plan,
SWIGPythonCreateScriptedBreakpointResolver swig_bkpt_resolver_script,
SWIGPythonCallBreakpointResolver swig_call_breakpoint_resolver);
const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
PyThreadState *GetThreadState() { return m_command_thread_state; }
void SetThreadState(PyThreadState *s) {
if (s)
m_command_thread_state = s;
}
//----------------------------------------------------------------------
// IOHandlerDelegate
//----------------------------------------------------------------------
void IOHandlerActivated(IOHandler &io_handler) override;
void IOHandlerInputComplete(IOHandler &io_handler,
std::string &data) override;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
static void Initialize();
static void Terminate();
static lldb::ScriptInterpreterSP
CreateInstance(CommandInterpreter &interpreter);
static lldb_private::ConstString GetPluginNameStatic();
static const char *GetPluginDescriptionStatic();
static FileSpec GetPythonDir();
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
lldb_private::ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
class Locker : public ScriptInterpreterLocker {
public:
enum OnEntry {
AcquireLock = 0x0001,
InitSession = 0x0002,
InitGlobals = 0x0004,
NoSTDIN = 0x0008
};
enum OnLeave {
FreeLock = 0x0001,
FreeAcquiredLock = 0x0002, // do not free the lock if we already held it
// when calling constructor
TearDownSession = 0x0004
};
Locker(ScriptInterpreterPython *py_interpreter = nullptr,
uint16_t on_entry = AcquireLock | InitSession,
uint16_t on_leave = FreeLock | TearDownSession, FILE *in = nullptr,
FILE *out = nullptr, FILE *err = nullptr);
~Locker() override;
private:
bool DoAcquireLock();
bool DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
bool DoFreeLock();
bool DoTearDownSession();
static void ReleasePythonLock();
bool m_teardown_session;
ScriptInterpreterPython *m_python_interpreter;
// FILE* m_tmp_fh;
PyGILState_STATE m_GILState;
};
protected:
class SynchronicityHandler {
private:
lldb::DebuggerSP m_debugger_sp;
ScriptedCommandSynchronicity m_synch_wanted;
bool m_old_asynch;
public:
SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity);
~SynchronicityHandler();
};
enum class AddLocation { Beginning, End };
static void AddToSysPath(AddLocation location, std::string path);
static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path);
static void ComputePythonDirForPosix(llvm::SmallVectorImpl<char> &path);
static void ComputePythonDirForWindows(llvm::SmallVectorImpl<char> &path);
bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
void LeaveSession();
void SaveTerminalState(int fd);
void RestoreTerminalState();
uint32_t IsExecutingPython() const { return m_lock_count > 0; }
uint32_t IncrementLockCount() { return ++m_lock_count; }
uint32_t DecrementLockCount() {
if (m_lock_count > 0)
--m_lock_count;
return m_lock_count;
}
enum ActiveIOHandler {
eIOHandlerNone,
eIOHandlerBreakpoint,
eIOHandlerWatchpoint
};
PythonObject &GetMainModule();
PythonDictionary &GetSessionDictionary();
PythonDictionary &GetSysModuleDictionary();
bool GetEmbeddedInterpreterModuleObjects();
bool SetStdHandle(File &file, const char *py_name, PythonFile &save_file,
const char *mode);
PythonFile m_saved_stdin;
PythonFile m_saved_stdout;
PythonFile m_saved_stderr;
PythonObject m_main_module;
PythonObject m_lldb_module;
PythonDictionary m_session_dict;
PythonDictionary m_sys_module_dict;
PythonObject m_run_one_line_function;
PythonObject m_run_one_line_str_global;
std::string m_dictionary_name;
TerminalState m_terminal_state;
ActiveIOHandler m_active_io_handler;
bool m_session_is_active;
bool m_pty_slave_is_open;
bool m_valid_session;
uint32_t m_lock_count;
PyThreadState *m_command_thread_state;
};
} // namespace lldb_private
#endif // LLDB_DISABLE_PYTHON
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H