In thread and frame format strings, it is now allowed to use Python functions to generate part or all of the output text

Specifically, the ${target ${process ${thread and ${frame specifiers have been extended to allow a subkeyword .script:<fctName> (e.g. ${frame.script:FooFunction})
The functions are prototyped as

def FooFunction(Object,unused)

where object is of the respective SB-type (SBTarget for target.script, ... and so on)

This has not been implemented for ${var because it would be akin to a Python summary which is already well-defined in LLDB

llvm-svn: 184500
This commit is contained in:
Enrico Granata 2013-06-20 23:40:21 +00:00
parent d6c62b66b5
commit aad8e48054
7 changed files with 665 additions and 4 deletions

View File

@ -248,6 +248,8 @@ public:
SBTarget (const lldb::SBTarget& rhs);
SBTarget (const lldb::TargetSP& target_sp);
const lldb::SBTarget&
operator = (const lldb::SBTarget& rhs);
@ -802,8 +804,6 @@ protected:
// create an instance of this class.
//------------------------------------------------------------------
SBTarget (const lldb::TargetSP& target_sp);
lldb::TargetSP
GetSP () const;

View File

@ -36,6 +36,8 @@ public:
SBThread ();
SBThread (const lldb::SBThread &thread);
SBThread (const lldb::ThreadSP& lldb_object_sp);
~SBThread();
@ -201,8 +203,6 @@ protected:
friend class SBDebugger;
friend class SBValue;
SBThread (const lldb::ThreadSP& lldb_object_sp);
void
SetThread (const lldb::ThreadSP& lldb_object_sp);

View File

@ -126,6 +126,27 @@ public:
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 enum
{
@ -396,6 +417,46 @@ public:
return false;
}
virtual bool
RunScriptFormatKeyword (const char* impl_function,
Process* process,
std::string& output,
Error& error)
{
error.SetErrorString("unimplemented");
return false;
}
virtual bool
RunScriptFormatKeyword (const char* impl_function,
Thread* thread,
std::string& output,
Error& error)
{
error.SetErrorString("unimplemented");
return false;
}
virtual bool
RunScriptFormatKeyword (const char* impl_function,
Target* target,
std::string& output,
Error& error)
{
error.SetErrorString("unimplemented");
return false;
}
virtual bool
RunScriptFormatKeyword (const char* impl_function,
StackFrame* frame,
std::string& output,
Error& error)
{
error.SetErrorString("unimplemented");
return false;
}
virtual bool
GetDocumentationForItem (const char* item, std::string& dest)
{

View File

@ -172,6 +172,30 @@ public:
return GetDocumentationForItem (name,temp);
}
virtual bool
RunScriptFormatKeyword (const char* impl_function,
Process* process,
std::string& output,
Error& error);
virtual bool
RunScriptFormatKeyword (const char* impl_function,
Thread* thread,
std::string& output,
Error& error);
virtual bool
RunScriptFormatKeyword (const char* impl_function,
Target* target,
std::string& output,
Error& error);
virtual bool
RunScriptFormatKeyword (const char* impl_function,
StackFrame* frame,
std::string& output,
Error& error);
virtual bool
LoadScriptingModule (const char* filename,
bool can_reload,

View File

@ -894,6 +894,350 @@ LLDBSWIGPythonCreateOSPlugin
Py_RETURN_NONE;
}
SWIGEXPORT bool
LLDBSWIGPythonRunScriptKeywordProcess
(const char* python_function_name,
const char* session_dictionary_name,
lldb::ProcessSP& process,
std::string& output)
{
bool retval = false;
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
return retval;
lldb::SBProcess process_sb(process);
PyObject *ProcessObj_PyObj = SWIG_NewPointerObj((void *) &process_sb, SWIGTYPE_p_lldb__SBProcess, 0);
if (ProcessObj_PyObj == NULL)
return retval;
PyObject *session_dict, *pfunc;
PyObject *pargs, *pvalue;
session_dict = FindSessionDictionary (session_dictionary_name);
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, ProcessObj_PyObj); // This "steals" a reference to ProcessObj_PyObj
PyTuple_SetItem (pargs, 1, session_dict); // This "steals" a reference to session_dict
pvalue = PyObject_CallObject (pfunc, pargs);
Py_XDECREF (pargs);
if (PyErr_Occurred ())
{
PyErr_Print();
PyErr_Clear();
}
else
{
if (PyString_Check(pvalue))
{
output.assign(PyString_AsString(pvalue));
retval = true;
}
else
{
output.clear();
retval = false;
}
Py_XDECREF (pvalue);
}
Py_INCREF (session_dict);
}
else if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
}
}
return retval;
}
SWIGEXPORT bool
LLDBSWIGPythonRunScriptKeywordThread
(const char* python_function_name,
const char* session_dictionary_name,
lldb::ThreadSP& thread,
std::string& output)
{
bool retval = false;
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
return retval;
lldb::SBThread thread_sb(thread);
PyObject *ThreadObj_PyObj = SWIG_NewPointerObj((void *) &thread_sb, SWIGTYPE_p_lldb__SBThread, 0);
if (ThreadObj_PyObj == NULL)
return retval;
PyObject *session_dict, *pfunc;
PyObject *pargs, *pvalue;
session_dict = FindSessionDictionary (session_dictionary_name);
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, ThreadObj_PyObj); // This "steals" a reference to ThreadObj_PyObj
PyTuple_SetItem (pargs, 1, session_dict); // This "steals" a reference to session_dict
pvalue = PyObject_CallObject (pfunc, pargs);
Py_XDECREF (pargs);
if (PyErr_Occurred ())
{
PyErr_Print();
PyErr_Clear();
}
else
{
if (PyString_Check(pvalue))
{
output.assign(PyString_AsString(pvalue));
retval = true;
}
else
{
output.clear();
retval = false;
}
Py_XDECREF (pvalue);
}
Py_INCREF (session_dict);
}
else if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
}
}
return retval;
}
SWIGEXPORT bool
LLDBSWIGPythonRunScriptKeywordTarget
(const char* python_function_name,
const char* session_dictionary_name,
lldb::TargetSP& target,
std::string& output)
{
bool retval = false;
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
return retval;
lldb::SBTarget target_sb(target);
PyObject *TargetObj_PyObj = SWIG_NewPointerObj((void *) &target_sb, SWIGTYPE_p_lldb__SBTarget, 0);
if (TargetObj_PyObj == NULL)
return retval;
PyObject *session_dict, *pfunc;
PyObject *pargs, *pvalue;
session_dict = FindSessionDictionary (session_dictionary_name);
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, TargetObj_PyObj); // This "steals" a reference to TargetObj_PyObj
PyTuple_SetItem (pargs, 1, session_dict); // This "steals" a reference to session_dict
pvalue = PyObject_CallObject (pfunc, pargs);
Py_XDECREF (pargs);
if (PyErr_Occurred ())
{
PyErr_Print();
PyErr_Clear();
}
else
{
if (PyString_Check(pvalue))
{
output.assign(PyString_AsString(pvalue));
retval = true;
}
else
{
output.clear();
retval = false;
}
Py_XDECREF (pvalue);
}
Py_INCREF (session_dict);
}
else if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
}
}
return retval;
}
SWIGEXPORT bool
LLDBSWIGPythonRunScriptKeywordFrame
(const char* python_function_name,
const char* session_dictionary_name,
lldb::StackFrameSP& frame,
std::string& output)
{
bool retval = false;
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
return retval;
lldb::SBFrame frame_sb(frame);
PyObject *FrameObj_PyObj = SWIG_NewPointerObj((void *) &frame_sb, SWIGTYPE_p_lldb__SBFrame, 0);
if (FrameObj_PyObj == NULL)
return retval;
PyObject *session_dict, *pfunc;
PyObject *pargs, *pvalue;
session_dict = FindSessionDictionary (session_dictionary_name);
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, FrameObj_PyObj); // This "steals" a reference to FrameObj_PyObj
PyTuple_SetItem (pargs, 1, session_dict); // This "steals" a reference to session_dict
pvalue = PyObject_CallObject (pfunc, pargs);
Py_XDECREF (pargs);
if (PyErr_Occurred ())
{
PyErr_Print();
PyErr_Clear();
}
else
{
if (PyString_Check(pvalue))
{
output.assign(PyString_AsString(pvalue));
retval = true;
}
else
{
output.clear();
retval = false;
}
Py_XDECREF (pvalue);
}
Py_INCREF (session_dict);
}
else if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
}
}
return retval;
}
SWIGEXPORT bool
LLDBSwigPythonCallModuleInit
(

View File

@ -1801,6 +1801,24 @@ FormatPromptRecurse
}
}
}
else if (::strncmp(var_name_begin, "script:", strlen("script:")) == 0)
{
var_name_begin += ::strlen("script:");
std::string script_name(var_name_begin,var_name_end);
ScriptInterpreter* script_interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
if (script_interpreter)
{
std::string script_output;
Error script_error;
if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), process,script_output,script_error) && script_error.Success())
{
s.Printf("%s", script_output.c_str());
var_success = true;
}
else
s.Printf("<error: %s>",script_error.AsCString());
}
}
}
}
}
@ -1870,6 +1888,24 @@ FormatPromptRecurse
}
}
}
else if (::strncmp(var_name_begin, "script:", strlen("script:")) == 0)
{
var_name_begin += ::strlen("script:");
std::string script_name(var_name_begin,var_name_end);
ScriptInterpreter* script_interpreter = thread->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
if (script_interpreter)
{
std::string script_output;
Error script_error;
if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), thread,script_output,script_error) && script_error.Success())
{
s.Printf("%s", script_output.c_str());
var_success = true;
}
else
s.Printf("<error: %s>",script_error.AsCString());
}
}
}
}
}
@ -1911,6 +1947,24 @@ FormatPromptRecurse
var_success = true;
}
}
else if (::strncmp(var_name_begin, "script:", strlen("script:")) == 0)
{
var_name_begin += ::strlen("script:");
std::string script_name(var_name_begin,var_name_end);
ScriptInterpreter* script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
if (script_interpreter)
{
std::string script_output;
Error script_error;
if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), target,script_output,script_error) && script_error.Success())
{
s.Printf("%s", script_output.c_str());
var_success = true;
}
else
s.Printf("<error: %s>",script_error.AsCString());
}
}
}
}
break;
@ -2018,6 +2072,24 @@ FormatPromptRecurse
}
}
}
else if (::strncmp(var_name_begin, "script:", strlen("script:")) == 0)
{
var_name_begin += ::strlen("script:");
std::string script_name(var_name_begin,var_name_end);
ScriptInterpreter* script_interpreter = frame->GetThread()->GetProcess()->GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
if (script_interpreter)
{
std::string script_output;
Error script_error;
if (script_interpreter->RunScriptFormatKeyword(script_name.c_str(), frame,script_output,script_error) && script_error.Success())
{
s.Printf("%s", script_output.c_str());
var_success = true;
}
else
s.Printf("<error: %s>",script_error.AsCString());
}
}
}
}
}

View File

@ -57,6 +57,10 @@ static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swi
static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = NULL;
static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = NULL;
static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = NULL;
static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = NULL;
static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = NULL;
static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = NULL;
static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = NULL;
// these are the Pythonic implementations of the required callbacks
// these are scripting-language specific, which is why they belong here
@ -124,6 +128,30 @@ LLDBSWIGPythonCreateOSPlugin (const char *python_class_name,
const char *session_dictionary_name,
const lldb::ProcessSP& process_sp);
extern "C" bool
LLDBSWIGPythonRunScriptKeywordProcess (const char* python_function_name,
const char* session_dictionary_name,
lldb::ProcessSP& process,
std::string& output);
extern "C" bool
LLDBSWIGPythonRunScriptKeywordThread (const char* python_function_name,
const char* session_dictionary_name,
lldb::ThreadSP& thread,
std::string& output);
extern "C" bool
LLDBSWIGPythonRunScriptKeywordTarget (const char* python_function_name,
const char* session_dictionary_name,
lldb::TargetSP& target,
std::string& output);
extern "C" bool
LLDBSWIGPythonRunScriptKeywordFrame (const char* python_function_name,
const char* session_dictionary_name,
lldb::StackFrameSP& frame,
std::string& output);
static int
_check_and_flush (FILE *stream)
{
@ -2577,6 +2605,134 @@ ReadPythonBacktrace (PyObject* py_backtrace)
return retval;
}
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
Process* process,
std::string& output,
Error& error)
{
bool ret_val;
if (!process)
{
error.SetErrorString("no process");
return false;
}
if (!impl_function || !impl_function[0])
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_run_script_keyword_process)
{
error.SetErrorString("internal helper function missing");
return false;
}
{
ProcessSP process_sp(process->shared_from_this());
Locker py_lock(this);
ret_val = g_swig_run_script_keyword_process (impl_function, m_dictionary_name.c_str(), process_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
}
return ret_val;
}
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
Thread* thread,
std::string& output,
Error& error)
{
bool ret_val;
if (!thread)
{
error.SetErrorString("no thread");
return false;
}
if (!impl_function || !impl_function[0])
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_run_script_keyword_thread)
{
error.SetErrorString("internal helper function missing");
return false;
}
{
ThreadSP thread_sp(thread->shared_from_this());
Locker py_lock(this);
ret_val = g_swig_run_script_keyword_thread (impl_function, m_dictionary_name.c_str(), thread_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
}
return ret_val;
}
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
Target* target,
std::string& output,
Error& error)
{
bool ret_val;
if (!target)
{
error.SetErrorString("no thread");
return false;
}
if (!impl_function || !impl_function[0])
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_run_script_keyword_thread)
{
error.SetErrorString("internal helper function missing");
return false;
}
{
TargetSP target_sp(target->shared_from_this());
Locker py_lock(this);
ret_val = g_swig_run_script_keyword_target (impl_function, m_dictionary_name.c_str(), target_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
}
return ret_val;
}
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
StackFrame* frame,
std::string& output,
Error& error)
{
bool ret_val;
if (!frame)
{
error.SetErrorString("no frame");
return false;
}
if (!impl_function || !impl_function[0])
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_run_script_keyword_thread)
{
error.SetErrorString("internal helper function missing");
return false;
}
{
StackFrameSP frame_sp(frame->shared_from_this());
Locker py_lock(this);
ret_val = g_swig_run_script_keyword_frame (impl_function, m_dictionary_name.c_str(), frame_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
}
return ret_val;
}
uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr)
{
size_t pos = 0;
@ -2909,6 +3065,10 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_ini
g_swig_call_command = LLDBSwigPythonCallCommand;
g_swig_call_module_init = LLDBSwigPythonCallModuleInit;
g_swig_create_os_plugin = LLDBSWIGPythonCreateOSPlugin;
g_swig_run_script_keyword_process = LLDBSWIGPythonRunScriptKeywordProcess;
g_swig_run_script_keyword_thread = LLDBSWIGPythonRunScriptKeywordThread;
g_swig_run_script_keyword_target = LLDBSWIGPythonRunScriptKeywordTarget;
g_swig_run_script_keyword_frame = LLDBSWIGPythonRunScriptKeywordFrame;
}
void