mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 10:58:11 +08:00
this patch introduces a new command script import command which takes as input a filename for a Python script and imports the module contained in that file. the containing directory is added to the Python path such that dependencies are honored. also, the module may contain an __lldb_init_module(debugger,dict) function, which gets called after importing, and which can somehow initialize the module's interaction with lldb
llvm-svn: 142283
This commit is contained in:
@@ -357,6 +357,34 @@ public:
|
||||
size_t
|
||||
GetPath (char *path, size_t max_path_length) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Extract the extension of the file.
|
||||
///
|
||||
/// Returns a ConstString that represents the extension of the filename
|
||||
/// for this FileSpec object. If this object does not represent a file,
|
||||
/// or the filename has no extension, ConstString(NULL) is returned.
|
||||
/// The dot ('.') character is not returned as part of the extension
|
||||
///
|
||||
/// @return
|
||||
/// Returns the extension of the file as a ConstString object.
|
||||
//------------------------------------------------------------------
|
||||
ConstString
|
||||
GetFileNameExtension () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the filename without the extension part
|
||||
///
|
||||
/// Returns a ConstString that represents the filename of this object
|
||||
/// without the extension part (e.g. for a file named "foo.bar", "foo"
|
||||
/// is returned)
|
||||
///
|
||||
/// @return
|
||||
/// Returns the filename without extension
|
||||
/// as a ConstString object.
|
||||
//------------------------------------------------------------------
|
||||
ConstString
|
||||
GetFileNameStrippingExtension () const;
|
||||
|
||||
FileType
|
||||
GetFileType () const;
|
||||
|
||||
|
||||
@@ -11,7 +11,10 @@
|
||||
#define liblldb_ScriptInterpreter_h_
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
|
||||
#include "lldb/Core/Broadcaster.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
|
||||
#include "lldb/Utility/PseudoTerminal.h"
|
||||
|
||||
|
||||
@@ -48,24 +51,28 @@ public:
|
||||
const char* args,
|
||||
std::string& err_msg,
|
||||
lldb_private::CommandReturnObject& cmd_retobj);
|
||||
|
||||
typedef bool (*SWIGPythonCallModuleInit) (const std::string python_module_name,
|
||||
const char *session_dictionary_name,
|
||||
lldb::DebuggerSP& debugger);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
eCharPtr,
|
||||
eBool,
|
||||
eShortInt,
|
||||
eShortIntUnsigned,
|
||||
eInt,
|
||||
eIntUnsigned,
|
||||
eLongInt,
|
||||
eLongIntUnsigned,
|
||||
eLongLong,
|
||||
eLongLongUnsigned,
|
||||
eFloat,
|
||||
eDouble,
|
||||
eChar,
|
||||
eCharStrOrNone
|
||||
} ReturnType;
|
||||
eScriptReturnTypeCharPtr,
|
||||
eScriptReturnTypeBool,
|
||||
eScriptReturnTypeShortInt,
|
||||
eScriptReturnTypeShortIntUnsigned,
|
||||
eScriptReturnTypeInt,
|
||||
eScriptReturnTypeIntUnsigned,
|
||||
eScriptReturnTypeLongInt,
|
||||
eScriptReturnTypeLongIntUnsigned,
|
||||
eScriptReturnTypeLongLong,
|
||||
eScriptReturnTypeLongLongUnsigned,
|
||||
eScriptReturnTypeFloat,
|
||||
eScriptReturnTypeDouble,
|
||||
eScriptReturnTypeChar,
|
||||
eScriptReturnTypeCharStrOrNone
|
||||
} ScriptReturnType;
|
||||
|
||||
|
||||
ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang);
|
||||
@@ -79,7 +86,7 @@ public:
|
||||
ExecuteInterpreterLoop () = 0;
|
||||
|
||||
virtual bool
|
||||
ExecuteOneLineWithReturn (const char *in_string, ReturnType return_type, void *ret_value)
|
||||
ExecuteOneLineWithReturn (const char *in_string, ScriptReturnType return_type, void *ret_value)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -176,20 +183,28 @@ public:
|
||||
}
|
||||
|
||||
virtual bool
|
||||
RunScriptBasedCommand(const char* impl_function,
|
||||
const char* args,
|
||||
lldb_private::CommandReturnObject& cmd_retobj,
|
||||
Error& error)
|
||||
RunScriptBasedCommand (const char* impl_function,
|
||||
const char* args,
|
||||
lldb_private::CommandReturnObject& cmd_retobj,
|
||||
Error& error)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::string
|
||||
GetDocumentationForItem(const char* item)
|
||||
GetDocumentationForItem (const char* item)
|
||||
{
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
virtual bool
|
||||
LoadScriptingModule (const char* filename,
|
||||
lldb_private::Error& error)
|
||||
{
|
||||
error.SetErrorString("loading unimplemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *
|
||||
GetScriptInterpreterPtyName ();
|
||||
|
||||
@@ -212,7 +227,8 @@ public:
|
||||
SWIGPythonGetIndexOfChildWithName python_swig_get_index_child,
|
||||
SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue,
|
||||
SWIGPythonUpdateSynthProviderInstance python_swig_update_provider,
|
||||
SWIGPythonCallCommand python_swig_call_command);
|
||||
SWIGPythonCallCommand python_swig_call_command,
|
||||
SWIGPythonCallModuleInit python_swig_call_mod_init);
|
||||
|
||||
static void
|
||||
TerminateInterpreter ();
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
|
||||
bool
|
||||
ExecuteOneLineWithReturn (const char *in_string,
|
||||
ScriptInterpreter::ReturnType return_type,
|
||||
ScriptInterpreter::ScriptReturnType return_type,
|
||||
void *ret_value);
|
||||
|
||||
bool
|
||||
@@ -108,7 +108,11 @@ public:
|
||||
lldb::ValueObjectSP valobj);
|
||||
|
||||
virtual std::string
|
||||
GetDocumentationForItem(const char* item);
|
||||
GetDocumentationForItem (const char* item);
|
||||
|
||||
virtual bool
|
||||
LoadScriptingModule (const char* filename,
|
||||
lldb_private::Error& error);
|
||||
|
||||
void
|
||||
CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
|
||||
@@ -141,7 +145,8 @@ public:
|
||||
SWIGPythonGetIndexOfChildWithName python_swig_get_index_child,
|
||||
SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue,
|
||||
SWIGPythonUpdateSynthProviderInstance python_swig_update_provider,
|
||||
SWIGPythonCallCommand python_swig_call_command);
|
||||
SWIGPythonCallCommand python_swig_call_command,
|
||||
SWIGPythonCallModuleInit python_swig_call_mod_init);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -676,7 +676,89 @@ LLDBSwigPythonCallCommand
|
||||
PyErr_Print();
|
||||
PyErr_Clear ();
|
||||
}
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
SWIGEXPORT bool
|
||||
LLDBSwigPythonCallModuleInit
|
||||
(
|
||||
const std::string python_module_name,
|
||||
const char *session_dictionary_name,
|
||||
lldb::DebuggerSP& debugger
|
||||
)
|
||||
{
|
||||
|
||||
lldb::SBDebugger debugger_sb(debugger);
|
||||
|
||||
bool retval = false;
|
||||
|
||||
PyObject *DebuggerObj_PyObj = SWIG_NewPointerObj((void *) &debugger_sb, SWIGTYPE_p_lldb__SBDebugger, 0);
|
||||
|
||||
if (DebuggerObj_PyObj == NULL)
|
||||
return retval;
|
||||
|
||||
if (!(python_module_name.length()) || !session_dictionary_name)
|
||||
return retval;
|
||||
|
||||
PyObject *session_dict, *pfunc;
|
||||
PyObject *pargs, *pvalue;
|
||||
|
||||
session_dict = FindSessionDictionary (session_dictionary_name);
|
||||
|
||||
std::string python_function_name_string = python_module_name + (".__lldb_init_module");
|
||||
const char* python_function_name = python_function_name_string.c_str();
|
||||
|
||||
if (session_dict != NULL)
|
||||
{
|
||||
pfunc = ResolvePythonName (python_function_name, session_dict);
|
||||
|
||||
if (PyErr_Occurred()) // this might not exist.. let's make sure we handle that
|
||||
{
|
||||
PyErr_Clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pfunc == NULL)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
// Set up the arguments and call the function.
|
||||
|
||||
if (PyCallable_Check (pfunc))
|
||||
{
|
||||
pargs = PyTuple_New (2);
|
||||
if (pargs == NULL)
|
||||
{
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Clear();
|
||||
return retval;
|
||||
}
|
||||
|
||||
PyTuple_SetItem (pargs, 0, DebuggerObj_PyObj); // This "steals" a reference to DebuggerObj_PyObj
|
||||
PyTuple_SetItem (pargs, 1, session_dict); // This "steals" a reference to session_dict
|
||||
pvalue = PyObject_CallObject (pfunc, pargs);
|
||||
Py_DECREF (pargs);
|
||||
|
||||
if (PyErr_Occurred ())
|
||||
{
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = true;
|
||||
Py_XDECREF (pvalue);
|
||||
}
|
||||
Py_INCREF (session_dict);
|
||||
}
|
||||
else if (PyErr_Occurred())
|
||||
{
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
@@ -358,6 +358,13 @@ extern "C" bool LLDBSwigPythonCallCommand
|
||||
lldb_private::CommandReturnObject& cmd_retobj
|
||||
);
|
||||
|
||||
extern "C" bool LLDBSwigPythonCallModuleInit
|
||||
(
|
||||
const std::string python_module_name,
|
||||
const char *session_dictionary_name,
|
||||
lldb::DebuggerSP& debugger
|
||||
);
|
||||
|
||||
|
||||
extern "C" void init_lldb(void);
|
||||
|
||||
@@ -377,6 +384,7 @@ SBCommandInterpreter::InitializeSWIG ()
|
||||
LLDBSwigPython_GetIndexOfChildWithName,
|
||||
LLDBSWIGPython_CastPyObjectToSBValue,
|
||||
LLDBSwigPython_UpdateSynthProviderInstance,
|
||||
LLDBSwigPythonCallCommand);
|
||||
LLDBSwigPythonCallCommand,
|
||||
LLDBSwigPythonCallModuleInit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1220,6 +1220,78 @@ public:
|
||||
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectCommandsScriptImport
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class CommandObjectCommandsScriptImport : public CommandObject
|
||||
{
|
||||
public:
|
||||
CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) :
|
||||
CommandObject (interpreter,
|
||||
"command script import",
|
||||
"Import a scripting module in LLDB.",
|
||||
NULL)
|
||||
{
|
||||
CommandArgumentEntry arg1;
|
||||
CommandArgumentData cmd_arg;
|
||||
|
||||
// Define the first (and only) variant of this arg.
|
||||
cmd_arg.arg_type = eArgTypePath;
|
||||
cmd_arg.arg_repetition = eArgRepeatPlain;
|
||||
|
||||
// There is only one variant this argument could be; put it into the argument entry.
|
||||
arg1.push_back (cmd_arg);
|
||||
|
||||
// Push the data for the first argument into the m_arguments vector.
|
||||
m_arguments.push_back (arg1);
|
||||
}
|
||||
|
||||
~CommandObjectCommandsScriptImport ()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Execute
|
||||
(
|
||||
Args& args,
|
||||
CommandReturnObject &result
|
||||
)
|
||||
{
|
||||
|
||||
if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
|
||||
{
|
||||
result.AppendError ("only scripting language supported for module importing is currently Python");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t argc = args.GetArgumentCount();
|
||||
|
||||
if (argc != 1)
|
||||
{
|
||||
result.AppendError ("'command script import' requires one argument");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string path = args.GetArgumentAtIndex(0);
|
||||
Error error;
|
||||
|
||||
if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
|
||||
error))
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat("module importing failed: %s", error.AsCString());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
|
||||
return result.Succeeded();
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectCommandsScriptAdd
|
||||
@@ -1684,6 +1756,7 @@ public:
|
||||
LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
|
||||
LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
|
||||
LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
|
||||
LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
|
||||
}
|
||||
|
||||
~CommandObjectMultiwordCommandsScript ()
|
||||
|
||||
@@ -699,10 +699,39 @@ FileSpec::GetPath(char *path, size_t path_max_len) const
|
||||
return ::snprintf (path, path_max_len, "%s", filename);
|
||||
}
|
||||
}
|
||||
path[0] = '\0';
|
||||
if (path)
|
||||
path[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
ConstString
|
||||
FileSpec::GetFileNameExtension () const
|
||||
{
|
||||
const char *filename = m_filename.GetCString();
|
||||
if (filename == NULL)
|
||||
return ConstString();
|
||||
|
||||
char* dot_pos = strrchr(filename, '.');
|
||||
if (dot_pos == NULL)
|
||||
return ConstString();
|
||||
|
||||
return ConstString(dot_pos+1);
|
||||
}
|
||||
|
||||
ConstString
|
||||
FileSpec::GetFileNameStrippingExtension () const
|
||||
{
|
||||
const char *filename = m_filename.GetCString();
|
||||
if (filename == NULL)
|
||||
return ConstString();
|
||||
|
||||
char* dot_pos = strrchr(filename, '.');
|
||||
if (dot_pos == NULL)
|
||||
return m_filename;
|
||||
|
||||
return ConstString(filename, dot_pos-filename);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Returns a shared pointer to a data buffer that contains all or
|
||||
// part of the contents of a file. The data is memory mapped and
|
||||
|
||||
@@ -100,7 +100,8 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call
|
||||
SWIGPythonGetIndexOfChildWithName python_swig_get_index_child,
|
||||
SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue,
|
||||
SWIGPythonUpdateSynthProviderInstance python_swig_update_provider,
|
||||
SWIGPythonCallCommand python_swig_call_command)
|
||||
SWIGPythonCallCommand python_swig_call_command,
|
||||
SWIGPythonCallModuleInit python_swig_call_mod_init)
|
||||
{
|
||||
ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback,
|
||||
python_swig_breakpoint_callback,
|
||||
@@ -111,7 +112,8 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call
|
||||
python_swig_get_index_child,
|
||||
python_swig_cast_to_sbvalue,
|
||||
python_swig_update_provider,
|
||||
python_swig_call_command);
|
||||
python_swig_call_command,
|
||||
python_swig_call_mod_init);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -42,6 +42,7 @@ static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_chi
|
||||
static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL;
|
||||
static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL;
|
||||
static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = NULL;
|
||||
static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = NULL;
|
||||
|
||||
static int
|
||||
_check_and_flush (FILE *stream)
|
||||
@@ -198,6 +199,10 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete
|
||||
run_string.Printf ("run_one_line (%s, 'import copy')", m_dictionary_name.c_str());
|
||||
PyRun_SimpleString (run_string.GetData());
|
||||
|
||||
run_string.Clear();
|
||||
run_string.Printf ("run_one_line (%s, 'import os')", m_dictionary_name.c_str());
|
||||
PyRun_SimpleString (run_string.GetData());
|
||||
|
||||
run_string.Clear();
|
||||
run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %d')", m_dictionary_name.c_str(),
|
||||
interpreter.GetDebugger().GetID());
|
||||
@@ -702,7 +707,7 @@ ScriptInterpreterPython::ExecuteInterpreterLoop ()
|
||||
|
||||
bool
|
||||
ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
|
||||
ScriptInterpreter::ReturnType return_type,
|
||||
ScriptInterpreter::ScriptReturnType return_type,
|
||||
void *ret_value)
|
||||
{
|
||||
|
||||
@@ -783,85 +788,85 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
|
||||
{
|
||||
switch (return_type)
|
||||
{
|
||||
case eCharPtr: // "char *"
|
||||
case eScriptReturnTypeCharPtr: // "char *"
|
||||
{
|
||||
const char format[3] = "s#";
|
||||
success = PyArg_Parse (py_return, format, (char **) ret_value);
|
||||
break;
|
||||
}
|
||||
case eCharStrOrNone: // char* or NULL if py_return == Py_None
|
||||
case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None
|
||||
{
|
||||
const char format[3] = "z";
|
||||
success = PyArg_Parse (py_return, format, (char **) ret_value);
|
||||
break;
|
||||
}
|
||||
case eBool:
|
||||
case eScriptReturnTypeBool:
|
||||
{
|
||||
const char format[2] = "b";
|
||||
success = PyArg_Parse (py_return, format, (bool *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eShortInt:
|
||||
case eScriptReturnTypeShortInt:
|
||||
{
|
||||
const char format[2] = "h";
|
||||
success = PyArg_Parse (py_return, format, (short *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eShortIntUnsigned:
|
||||
case eScriptReturnTypeShortIntUnsigned:
|
||||
{
|
||||
const char format[2] = "H";
|
||||
success = PyArg_Parse (py_return, format, (unsigned short *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eInt:
|
||||
case eScriptReturnTypeInt:
|
||||
{
|
||||
const char format[2] = "i";
|
||||
success = PyArg_Parse (py_return, format, (int *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eIntUnsigned:
|
||||
case eScriptReturnTypeIntUnsigned:
|
||||
{
|
||||
const char format[2] = "I";
|
||||
success = PyArg_Parse (py_return, format, (unsigned int *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eLongInt:
|
||||
case eScriptReturnTypeLongInt:
|
||||
{
|
||||
const char format[2] = "l";
|
||||
success = PyArg_Parse (py_return, format, (long *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eLongIntUnsigned:
|
||||
case eScriptReturnTypeLongIntUnsigned:
|
||||
{
|
||||
const char format[2] = "k";
|
||||
success = PyArg_Parse (py_return, format, (unsigned long *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eLongLong:
|
||||
case eScriptReturnTypeLongLong:
|
||||
{
|
||||
const char format[2] = "L";
|
||||
success = PyArg_Parse (py_return, format, (long long *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eLongLongUnsigned:
|
||||
case eScriptReturnTypeLongLongUnsigned:
|
||||
{
|
||||
const char format[2] = "K";
|
||||
success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eFloat:
|
||||
case eScriptReturnTypeFloat:
|
||||
{
|
||||
const char format[2] = "f";
|
||||
success = PyArg_Parse (py_return, format, (float *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eDouble:
|
||||
case eScriptReturnTypeDouble:
|
||||
{
|
||||
const char format[2] = "d";
|
||||
success = PyArg_Parse (py_return, format, (double *) ret_value);
|
||||
break;
|
||||
}
|
||||
case eChar:
|
||||
case eScriptReturnTypeChar:
|
||||
{
|
||||
const char format[2] = "c";
|
||||
success = PyArg_Parse (py_return, format, (char *) ret_value);
|
||||
@@ -1824,6 +1829,98 @@ ScriptInterpreterPython::UpdateSynthProviderInstance (void* implementor)
|
||||
return;
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
|
||||
lldb_private::Error& error)
|
||||
{
|
||||
if (!pathname || !pathname[0])
|
||||
{
|
||||
error.SetErrorString("invalid pathname");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!g_swig_call_module_init)
|
||||
{
|
||||
error.SetErrorString("internal helper function missing");
|
||||
return false;
|
||||
}
|
||||
|
||||
ScriptInterpreterPython *python_interpreter = this;
|
||||
|
||||
lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().GetSP();
|
||||
|
||||
FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
|
||||
|
||||
{
|
||||
Locker py_lock(python_interpreter, tmp_fh);
|
||||
|
||||
FileSpec target_file(pathname, true);
|
||||
|
||||
// TODO: would we want to reject any other value?
|
||||
if (target_file.GetFileType() == FileSpec::eFileTypeInvalid ||
|
||||
target_file.GetFileType() == FileSpec::eFileTypeUnknown)
|
||||
{
|
||||
error.SetErrorString("invalid pathname");
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* directory = target_file.GetDirectory().GetCString();
|
||||
std::string basename(target_file.GetFilename().GetCString());
|
||||
|
||||
// now make sure that Python has "directory" in the search path
|
||||
StreamString command_stream;
|
||||
command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.append('%s');\n\n",
|
||||
directory,
|
||||
directory);
|
||||
bool syspath_retval = python_interpreter->ExecuteMultipleLines(command_stream.GetData());
|
||||
if (!syspath_retval)
|
||||
{
|
||||
error.SetErrorString("Python sys.path handling failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// strip .py or .pyc extension
|
||||
ConstString extension = target_file.GetFileNameExtension();
|
||||
if (::strcmp(extension.GetCString(), "py") == 0)
|
||||
basename.resize(basename.length()-3);
|
||||
else if(::strcmp(extension.GetCString(), "pyc") == 0)
|
||||
basename.resize(basename.length()-4);
|
||||
|
||||
// check if the module is already import-ed
|
||||
command_stream.Clear();
|
||||
command_stream.Printf("sys.getrefcount(%s)",basename.c_str());
|
||||
int refcount = 0;
|
||||
// this call will fail if the module does not exist (because the parameter to it is not a string
|
||||
// but an actual Python module object, which is non-existant if the module was not imported before)
|
||||
if (python_interpreter->ExecuteOneLineWithReturn(command_stream.GetData(),
|
||||
ScriptInterpreterPython::eScriptReturnTypeInt, &refcount) && refcount > 0)
|
||||
{
|
||||
error.SetErrorString("module already imported");
|
||||
return false;
|
||||
}
|
||||
|
||||
// now actually do the import
|
||||
command_stream.Clear();
|
||||
command_stream.Printf("import %s",basename.c_str());
|
||||
bool import_retval = python_interpreter->ExecuteOneLine(command_stream.GetData(), NULL);
|
||||
if (!import_retval)
|
||||
{
|
||||
error.SetErrorString("Python import statement failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// call __lldb_module_init(debugger,dict)
|
||||
if (!g_swig_call_module_init (basename,
|
||||
python_interpreter->m_dictionary_name.c_str(),
|
||||
debugger_sp))
|
||||
{
|
||||
error.SetErrorString("calling __lldb_module_init failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function,
|
||||
const char* args,
|
||||
@@ -1886,7 +1983,7 @@ ScriptInterpreterPython::GetDocumentationForItem(const char* item)
|
||||
char* result_ptr = NULL; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully
|
||||
|
||||
if (ExecuteOneLineWithReturn (command.c_str(),
|
||||
ScriptInterpreter::eCharStrOrNone,
|
||||
ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
|
||||
&result_ptr) && result_ptr)
|
||||
{
|
||||
return std::string(result_ptr);
|
||||
@@ -1905,7 +2002,8 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini
|
||||
SWIGPythonGetIndexOfChildWithName python_swig_get_index_child,
|
||||
SWIGPythonCastPyObjectToSBValue python_swig_cast_to_sbvalue,
|
||||
SWIGPythonUpdateSynthProviderInstance python_swig_update_provider,
|
||||
SWIGPythonCallCommand python_swig_call_command)
|
||||
SWIGPythonCallCommand python_swig_call_command,
|
||||
SWIGPythonCallModuleInit python_swig_call_mod_init)
|
||||
{
|
||||
g_swig_init_callback = python_swig_init_callback;
|
||||
g_swig_breakpoint_callback = python_swig_breakpoint_callback;
|
||||
@@ -1917,6 +2015,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini
|
||||
g_swig_cast_to_sbvalue = python_swig_cast_to_sbvalue;
|
||||
g_swig_update_provider = python_swig_update_provider;
|
||||
g_swig_call_command = python_swig_call_command;
|
||||
g_swig_call_module_init = python_swig_call_mod_init;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
6
lldb/test/functionalities/command_script/import/Makefile
Normal file
6
lldb/test/functionalities/command_script/import/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
LEVEL = ../../../make
|
||||
|
||||
C_SOURCES := main.c
|
||||
EXE := hello_world
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
||||
@@ -0,0 +1,71 @@
|
||||
"""Test custom import command to import files by path."""
|
||||
|
||||
import os, sys, time
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbtest import *
|
||||
|
||||
class ImportTestCase(TestBase):
|
||||
|
||||
mydir = os.path.join("functionalities", "command_script", "import")
|
||||
|
||||
@python_api_test
|
||||
def test_import_command(self):
|
||||
"""Import some Python scripts by path and test them"""
|
||||
self.run_test()
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
|
||||
def run_test(self):
|
||||
"""Import some Python scripts by path and test them."""
|
||||
|
||||
# This is the function to remove the custom commands in order to have a
|
||||
# clean slate for the next test case.
|
||||
def cleanup():
|
||||
self.runCmd('command script delete foo2cmd', check=False)
|
||||
self.runCmd('command script delete foocmd', check=False)
|
||||
self.runCmd('command script delete foobarcmd', check=False)
|
||||
self.runCmd('command script delete barcmd', check=False)
|
||||
self.runCmd('command script delete barothercmd', check=False)
|
||||
|
||||
# Execute the cleanup function during test case tear down.
|
||||
self.addTearDownHook(cleanup)
|
||||
|
||||
self.runCmd("command script import ./foo/foo.py")
|
||||
self.runCmd("command script import ./foo/foo2.py")
|
||||
self.runCmd("command script import ./foo/bar/foobar.py")
|
||||
self.runCmd("command script import ./bar/bar.py")
|
||||
|
||||
self.expect("command script import ./nosuchfile.py",
|
||||
error=True, startstr='error: module importing failed')
|
||||
self.expect("command script import ./nosuchfolder/",
|
||||
error=True, startstr='error: module importing failed')
|
||||
self.expect("command script import ./foo/foo.py",
|
||||
error=True, startstr='error: module importing failed')
|
||||
|
||||
self.runCmd("script import dummymodule")
|
||||
self.expect("command script import ./dummymodule.py",
|
||||
error=True, startstr='error: module importing failed')
|
||||
|
||||
self.runCmd("command script add -f foo.foo_function foocmd")
|
||||
self.runCmd("command script add -f foobar.foo_function foobarcmd")
|
||||
self.runCmd("command script add -f bar.bar_function barcmd")
|
||||
self.expect("foocmd hello",
|
||||
substrs = ['foo says', 'hello'])
|
||||
self.expect("foo2cmd hello",
|
||||
substrs = ['foo2 says', 'hello'])
|
||||
self.expect("barcmd hello",
|
||||
substrs = ['barutil says', 'bar told me', 'hello'])
|
||||
self.expect("barothercmd hello",
|
||||
substrs = ['barutil says', 'bar told me', 'hello'])
|
||||
self.expect("foobarcmd hello",
|
||||
substrs = ['foobar says', 'hello'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
||||
10
lldb/test/functionalities/command_script/import/bar/bar.py
Normal file
10
lldb/test/functionalities/command_script/import/bar/bar.py
Normal file
@@ -0,0 +1,10 @@
|
||||
def bar_function(debugger, args, result, dict):
|
||||
global UtilityModule
|
||||
result.Printf(UtilityModule.barutil_function("bar told me " + args))
|
||||
return None
|
||||
|
||||
def __lldb_init_module(debugger, session_dict):
|
||||
global UtilityModule
|
||||
UtilityModule = __import__("barutil")
|
||||
debugger.HandleCommand("command script add -f bar.bar_function barothercmd")
|
||||
return None
|
||||
@@ -0,0 +1,2 @@
|
||||
def barutil_function(x):
|
||||
return "barutil says: " + x
|
||||
@@ -0,0 +1,2 @@
|
||||
def no_useful_code(foo):
|
||||
return foo
|
||||
@@ -0,0 +1,3 @@
|
||||
def foo_function(debugger, args, result, dict):
|
||||
result.Printf("foobar says " + args)
|
||||
return None
|
||||
@@ -0,0 +1,3 @@
|
||||
def foo_function(debugger, args, result, dict):
|
||||
result.Printf("foo says " + args)
|
||||
return None
|
||||
@@ -0,0 +1,7 @@
|
||||
def foo2_function(debugger, args, result, dict):
|
||||
result.Printf("foo2 says " + args)
|
||||
return None
|
||||
|
||||
def __lldb_init_module(debugger, session_dict):
|
||||
debugger.HandleCommand("command script add -f foo2.foo2_function foo2cmd")
|
||||
return None
|
||||
15
lldb/test/functionalities/command_script/import/main.c
Normal file
15
lldb/test/functionalities/command_script/import/main.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char const *argv[]) {
|
||||
printf("Hello world.\n"); // Set break point at this line.
|
||||
if (argc == 1)
|
||||
return 0;
|
||||
|
||||
// Waiting to be attached by the debugger, otherwise.
|
||||
char line[100];
|
||||
while (fgets(line, sizeof(line), stdin)) { // Waiting to be attached...
|
||||
printf("input line=>%s\n", line);
|
||||
}
|
||||
|
||||
printf("Exiting now\n");
|
||||
}
|
||||
Reference in New Issue
Block a user