mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-25 06:18:56 -04:00

Summary: Along with this, support for an optional argument to the "num_children" method of a Python synthetic child provider has also been added. These have been added with the following use case in mind: Synthetic child providers currently have a method "has_children" and "num_children". While the former is good enough to know if there are children, it does not give any insight into how many children there are. Though the latter serves this purpose, calculating the number for children of a data structure could be an O(N) operation if the data structure has N children. The new method added in this change provide a middle ground. One can call GetNumChildren(K) to know if a child exists at an index K which can be as large as the callers tolerance can be. If the caller wants to know about children beyond K, it can make an other call with 2K. If the synthetic child provider maintains state about it counting till K previosly, then the next call is only an O(K) operation. Infact, all calls made progressively with steps of K will be O(K) operations. Reviewers: vharron, clayborg, granata.enrico Subscribers: labath, lldb-commits Differential Revision: http://reviews.llvm.org/D13778 llvm-svn: 250930
1300 lines
31 KiB
Plaintext
1300 lines
31 KiB
Plaintext
%header %{
|
|
|
|
template <typename T>
|
|
PyObject *
|
|
SBTypeToSWIGWrapper (T* item);
|
|
|
|
class PyErr_Cleaner
|
|
{
|
|
public:
|
|
PyErr_Cleaner(bool print=false) :
|
|
m_print(print)
|
|
{
|
|
}
|
|
|
|
~PyErr_Cleaner()
|
|
{
|
|
if (PyErr_Occurred())
|
|
{
|
|
if(m_print && !PyErr_ExceptionMatches(PyExc_SystemExit))
|
|
PyErr_Print();
|
|
PyErr_Clear();
|
|
}
|
|
}
|
|
|
|
private:
|
|
bool m_print;
|
|
};
|
|
|
|
static PyObject*
|
|
ResolvePythonName(const char* name,
|
|
PyObject* pmodule)
|
|
{
|
|
if (!name)
|
|
return pmodule;
|
|
|
|
PyErr_Cleaner pyerr_cleanup(true); // show Python errors
|
|
|
|
PyObject* main_dict;
|
|
|
|
if (!pmodule)
|
|
{
|
|
pmodule = PyImport_AddModule ("__main__");
|
|
if (!pmodule)
|
|
return NULL;
|
|
}
|
|
|
|
if (PyType_Check(pmodule))
|
|
{
|
|
main_dict = ((PyTypeObject*)pmodule)->tp_dict;
|
|
if (!main_dict)
|
|
return NULL;
|
|
}
|
|
else if (!PyDict_Check(pmodule))
|
|
{
|
|
main_dict = PyModule_GetDict (pmodule);
|
|
if (!main_dict)
|
|
return NULL;
|
|
}
|
|
else
|
|
main_dict = pmodule;
|
|
|
|
const char* dot_pos = ::strchr(name, '.');
|
|
|
|
PyObject *dest_object;
|
|
PyObject *key, *value;
|
|
Py_ssize_t pos = 0;
|
|
|
|
if (!dot_pos)
|
|
{
|
|
dest_object = NULL;
|
|
while (PyDict_Next (main_dict, &pos, &key, &value))
|
|
{
|
|
// We have stolen references to the key and value objects in the dictionary; we need to increment
|
|
// them now so that Python's garbage collector doesn't collect them out from under us.
|
|
Py_INCREF (key);
|
|
Py_INCREF (value);
|
|
if (strcmp (PyString_AsString (key), name) == 0)
|
|
{
|
|
dest_object = value;
|
|
break;
|
|
}
|
|
}
|
|
if (!dest_object || dest_object == Py_None)
|
|
return NULL;
|
|
return dest_object;
|
|
}
|
|
else
|
|
{
|
|
size_t len = dot_pos - name;
|
|
std::string piece(name,len);
|
|
pmodule = ResolvePythonName(piece.c_str(), main_dict);
|
|
if (!pmodule)
|
|
return NULL;
|
|
return ResolvePythonName(dot_pos+1,pmodule); // tail recursion.. should be optimized by the compiler
|
|
}
|
|
}
|
|
|
|
static PyObject*
|
|
FindSessionDictionary(const char *session_dictionary_name)
|
|
{
|
|
return ResolvePythonName(session_dictionary_name, NULL);
|
|
}
|
|
|
|
class PyCallable
|
|
{
|
|
public:
|
|
struct argc {
|
|
size_t num_args;
|
|
bool varargs : 1;
|
|
bool kwargs : 1;
|
|
};
|
|
|
|
argc
|
|
GetNumArguments ()
|
|
{
|
|
PyObject *py_func_obj = NULL;
|
|
if (m_callable)
|
|
{
|
|
if (PyMethod_Check(m_callable))
|
|
py_func_obj = PyMethod_GET_FUNCTION(m_callable);
|
|
else
|
|
py_func_obj = m_callable;
|
|
}
|
|
|
|
if (py_func_obj)
|
|
{
|
|
PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj);
|
|
if (code)
|
|
{
|
|
size_t args = code->co_argcount;
|
|
bool va=false,kw=false;
|
|
if ((code->co_flags & 4) == 4)
|
|
va = true;
|
|
if ((code->co_flags & 8) == 8)
|
|
kw = true;
|
|
return {args,va,kw};
|
|
}
|
|
}
|
|
return {SIZE_MAX,false,false};
|
|
}
|
|
|
|
operator
|
|
bool ()
|
|
{
|
|
return m_callable != NULL;
|
|
}
|
|
|
|
template<typename ...Args>
|
|
PyObject*
|
|
operator () (Args... args)
|
|
{
|
|
return (*this)({SBTypeToSWIGWrapper(args)...});
|
|
}
|
|
|
|
PyObject*
|
|
operator () (std::initializer_list<PyObject*> args)
|
|
{
|
|
PyObject* retval = NULL;
|
|
PyObject* pargs = PyTuple_New (args.size());
|
|
if (pargs == NULL)
|
|
{
|
|
if (PyErr_Occurred())
|
|
PyErr_Clear();
|
|
return retval;
|
|
}
|
|
size_t idx = 0;
|
|
for (auto arg : args)
|
|
{
|
|
if (!arg)
|
|
return retval;
|
|
Py_INCREF(arg); // _SetItem steals a reference
|
|
PyTuple_SetItem(pargs,idx,arg);
|
|
idx++;
|
|
}
|
|
retval = PyObject_CallObject (m_callable, pargs);
|
|
Py_XDECREF (pargs);
|
|
return retval;
|
|
}
|
|
|
|
static PyCallable
|
|
FindWithPythonObject (PyObject* pfunc)
|
|
{
|
|
return PyCallable(pfunc);
|
|
}
|
|
|
|
static PyCallable
|
|
FindWithFunctionName (const char *python_function_name,
|
|
const char *session_dictionary_name)
|
|
{
|
|
if (!python_function_name || !session_dictionary_name)
|
|
return PyCallable();
|
|
if ( (python_function_name[0] == 0) || (session_dictionary_name[0] == 0) )
|
|
return PyCallable();
|
|
return FindWithFunctionName(python_function_name,FindSessionDictionary (session_dictionary_name));
|
|
}
|
|
|
|
static PyCallable
|
|
FindWithFunctionName (const char *python_function_name,
|
|
PyObject *session_dict)
|
|
{
|
|
if (!python_function_name || !session_dict)
|
|
return PyCallable();
|
|
if ( (python_function_name[0] == 0))
|
|
return PyCallable();
|
|
return PyCallable(ResolvePythonName (python_function_name, session_dict));
|
|
}
|
|
|
|
static PyCallable
|
|
FindWithMemberFunction (PyObject *self,
|
|
const char *python_function_name)
|
|
{
|
|
if (self == NULL || self == Py_None)
|
|
return PyCallable();
|
|
if (!python_function_name || (python_function_name[0] == 0))
|
|
return PyCallable();
|
|
return PyCallable(PyObject_GetAttrString(self, python_function_name));
|
|
}
|
|
|
|
private:
|
|
PyObject* m_callable;
|
|
|
|
PyCallable (PyObject *callable = NULL) :
|
|
m_callable(callable)
|
|
{
|
|
if (m_callable && PyCallable_Check(m_callable) == false)
|
|
m_callable = NULL;
|
|
}
|
|
};
|
|
|
|
%}
|
|
|
|
%wrapper %{
|
|
|
|
// resolve a dotted Python name in the form
|
|
// foo.bar.baz.Foobar to an actual Python object
|
|
// if pmodule is NULL, the __main__ module will be used
|
|
// as the starting point for the search
|
|
|
|
|
|
// This function is called by lldb_private::ScriptInterpreterPython::BreakpointCallbackFunction(...)
|
|
// and is used when a script command is attached to a breakpoint for execution.
|
|
|
|
SWIGEXPORT bool
|
|
LLDBSwigPythonBreakpointCallbackFunction
|
|
(
|
|
const char *python_function_name,
|
|
const char *session_dictionary_name,
|
|
const lldb::StackFrameSP& frame_sp,
|
|
const lldb::BreakpointLocationSP& bp_loc_sp
|
|
)
|
|
{
|
|
lldb::SBFrame sb_frame (frame_sp);
|
|
lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp);
|
|
|
|
bool stop_at_breakpoint = true;
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return stop_at_breakpoint;
|
|
|
|
PyObject* session_dict = NULL;
|
|
PyObject* pvalue = NULL;
|
|
pvalue = pfunc(sb_frame, sb_bp_loc, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
if (pvalue == Py_False)
|
|
stop_at_breakpoint = false;
|
|
|
|
Py_XDECREF (pvalue);
|
|
}
|
|
|
|
return stop_at_breakpoint;
|
|
}
|
|
|
|
// This function is called by lldb_private::ScriptInterpreterPython::WatchpointCallbackFunction(...)
|
|
// and is used when a script command is attached to a watchpoint for execution.
|
|
|
|
SWIGEXPORT bool
|
|
LLDBSwigPythonWatchpointCallbackFunction
|
|
(
|
|
const char *python_function_name,
|
|
const char *session_dictionary_name,
|
|
const lldb::StackFrameSP& frame_sp,
|
|
const lldb::WatchpointSP& wp_sp
|
|
)
|
|
{
|
|
lldb::SBFrame sb_frame (frame_sp);
|
|
lldb::SBWatchpoint sb_wp(wp_sp);
|
|
|
|
bool stop_at_watchpoint = true;
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return stop_at_watchpoint;
|
|
|
|
PyObject* session_dict = NULL;
|
|
PyObject* pvalue = NULL;
|
|
pvalue = pfunc(sb_frame, sb_wp, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
if (pvalue == Py_False)
|
|
stop_at_watchpoint = false;
|
|
|
|
Py_XDECREF (pvalue);
|
|
}
|
|
|
|
return stop_at_watchpoint;
|
|
}
|
|
|
|
bool
|
|
PyObjectToString (PyObject* object,
|
|
std::string& retval)
|
|
{
|
|
retval.clear();
|
|
bool was_ok = false;
|
|
if (object != NULL && object != Py_None)
|
|
{
|
|
if (PyString_Check(object))
|
|
{
|
|
retval.assign(PyString_AsString(object));
|
|
was_ok = true;
|
|
}
|
|
else
|
|
{
|
|
PyObject* value_as_string = PyObject_Str(object);
|
|
if (value_as_string && value_as_string != Py_None && PyString_Check(value_as_string))
|
|
{
|
|
retval.assign(PyString_AsString(value_as_string));
|
|
was_ok = true;
|
|
}
|
|
Py_XDECREF(value_as_string);
|
|
}
|
|
}
|
|
return was_ok;
|
|
}
|
|
|
|
SWIGEXPORT 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
|
|
)
|
|
{
|
|
lldb::SBValue sb_value (valobj_sp);
|
|
lldb::SBTypeSummaryOptions sb_options(options_sp.get());
|
|
|
|
retval.clear();
|
|
|
|
if (!python_function_name || !session_dictionary)
|
|
return false;
|
|
|
|
PyObject *session_dict = (PyObject*)session_dictionary, *pfunc_impl = NULL, *pvalue = NULL;
|
|
|
|
if (pyfunct_wrapper && *pyfunct_wrapper && PyFunction_Check (*pyfunct_wrapper))
|
|
{
|
|
pfunc_impl = (PyObject*)(*pyfunct_wrapper);
|
|
if (pfunc_impl->ob_refcnt == 1)
|
|
{
|
|
Py_XDECREF(pfunc_impl);
|
|
pfunc_impl = NULL;
|
|
}
|
|
}
|
|
|
|
if (PyDict_Check(session_dict))
|
|
{
|
|
PyErr_Cleaner pyerr_cleanup(true); // show Python errors
|
|
|
|
if (!pfunc_impl)
|
|
{
|
|
pfunc_impl = ResolvePythonName (python_function_name, session_dict);
|
|
if (!pfunc_impl || !PyCallable_Check (pfunc_impl))
|
|
return false;
|
|
else
|
|
{
|
|
if (pyfunct_wrapper)
|
|
*pyfunct_wrapper = pfunc_impl;
|
|
}
|
|
}
|
|
|
|
PyCallable pfunc = PyCallable::FindWithPythonObject(pfunc_impl);
|
|
|
|
if (!pfunc)
|
|
return false;
|
|
|
|
// if the third argument is supported, or varargs are allowed
|
|
PyCallable::argc argc = pfunc.GetNumArguments();
|
|
if (argc.num_args == 3 || argc.varargs == true)
|
|
pvalue = pfunc(sb_value,session_dict,sb_options);
|
|
else
|
|
pvalue = pfunc(sb_value,session_dict);
|
|
|
|
Py_INCREF (session_dict);
|
|
|
|
PyObjectToString(pvalue,retval);
|
|
|
|
Py_XDECREF (pvalue);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
SWIGEXPORT void*
|
|
LLDBSwigPythonCreateSyntheticProvider
|
|
(
|
|
const char *python_class_name,
|
|
const char *session_dictionary_name,
|
|
const lldb::ValueObjectSP& valobj_sp
|
|
)
|
|
{
|
|
PyObject* retval = NULL;
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
|
|
Py_RETURN_NONE;
|
|
|
|
// I do not want the SBValue to be deallocated when going out of scope because python
|
|
// has ownership of it and will manage memory for this object by itself
|
|
lldb::SBValue *sb_value = new lldb::SBValue(valobj_sp);
|
|
sb_value->SetPreferSyntheticValue(false);
|
|
PyObject *ValObj_PyObj = SBTypeToSWIGWrapper(sb_value);
|
|
|
|
if (ValObj_PyObj == NULL)
|
|
Py_RETURN_NONE;
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
Py_INCREF(ValObj_PyObj);
|
|
|
|
PyObject* session_dict = NULL;
|
|
session_dict = FindSessionDictionary(session_dictionary_name);
|
|
retval = pfunc(sb_value, session_dict);
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
Py_XINCREF(retval);
|
|
}
|
|
|
|
if (retval)
|
|
return retval;
|
|
else
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
SWIGEXPORT void*
|
|
LLDBSwigPythonCreateCommandObject
|
|
(
|
|
const char *python_class_name,
|
|
const char *session_dictionary_name,
|
|
const lldb::DebuggerSP debugger_sp
|
|
)
|
|
{
|
|
PyObject* retval = NULL;
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
|
|
Py_RETURN_NONE;
|
|
|
|
lldb::SBDebugger debugger_sb(debugger_sp);
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
PyObject* session_dict = NULL;
|
|
session_dict = FindSessionDictionary(session_dictionary_name);
|
|
retval = pfunc(debugger_sb, session_dict);
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
Py_XINCREF(retval);
|
|
}
|
|
|
|
if (retval)
|
|
return retval;
|
|
else
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
SWIGEXPORT void*
|
|
LLDBSwigPythonCreateScriptedThreadPlan
|
|
(
|
|
const char *python_class_name,
|
|
const char *session_dictionary_name,
|
|
const lldb::ThreadPlanSP& thread_plan_sp
|
|
)
|
|
{
|
|
PyObject* retval = NULL;
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
|
|
Py_RETURN_NONE;
|
|
|
|
// I do not want the SBThreadPlan to be deallocated when going out of scope because python
|
|
// has ownership of it and will manage memory for this object by itself
|
|
lldb::SBThreadPlan *tp_value = new lldb::SBThreadPlan(thread_plan_sp);
|
|
|
|
PyObject *ThreadPlan_PyObj = SBTypeToSWIGWrapper(tp_value);
|
|
|
|
if (ThreadPlan_PyObj == NULL)
|
|
Py_RETURN_NONE;
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name, session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
Py_INCREF(ThreadPlan_PyObj);
|
|
|
|
PyObject* session_dict = NULL;
|
|
session_dict = FindSessionDictionary(session_dictionary_name);
|
|
retval = pfunc(tp_value, session_dict);
|
|
|
|
// FIXME: At this point we should check that the class we found supports all the methods
|
|
// that we need.
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
Py_XINCREF(retval);
|
|
}
|
|
|
|
if (retval)
|
|
return retval;
|
|
else
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
SWIGEXPORT bool
|
|
LLDBSWIGPythonCallThreadPlan
|
|
(
|
|
void *implementor,
|
|
const char *method_name,
|
|
lldb_private::Event *event,
|
|
bool &got_error
|
|
)
|
|
{
|
|
bool ret_val = false;
|
|
got_error = false;
|
|
|
|
|
|
PyErr_Cleaner py_err_cleaner(false);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithMemberFunction((PyObject *) implementor, method_name);
|
|
|
|
if (!pfunc)
|
|
{
|
|
return ret_val;
|
|
}
|
|
|
|
PyObject* py_return = Py_None;
|
|
|
|
if (event != NULL)
|
|
{
|
|
lldb::SBEvent sb_event(event);
|
|
|
|
PyObject *py_obj_event = SBTypeToSWIGWrapper(sb_event);
|
|
|
|
py_return = pfunc(py_obj_event);
|
|
}
|
|
else
|
|
{
|
|
py_return = pfunc();
|
|
}
|
|
|
|
if (PyErr_Occurred())
|
|
{
|
|
got_error = true;
|
|
printf ("Return value was neither false nor true for call to %s.\n", method_name);
|
|
PyErr_Print();
|
|
}
|
|
else
|
|
{
|
|
if (py_return == Py_True)
|
|
ret_val = true;
|
|
else if (py_return == Py_False)
|
|
ret_val = false;
|
|
else
|
|
{
|
|
// Somebody returned the wrong thing...
|
|
got_error = true;
|
|
printf ("Wrong return value type for call to %s.\n", method_name);
|
|
}
|
|
}
|
|
|
|
Py_XDECREF(py_return);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
// wrapper that calls an optional instance member of an object taking no arguments
|
|
static PyObject*
|
|
LLDBSwigPython_CallOptionalMember
|
|
(
|
|
PyObject* self,
|
|
char* callee_name,
|
|
PyObject* ret_if_not_found = Py_None,
|
|
bool* was_found = NULL
|
|
)
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(false);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithMemberFunction(self,callee_name);
|
|
|
|
if (!pfunc)
|
|
{
|
|
if (was_found)
|
|
*was_found = false;
|
|
Py_XINCREF(ret_if_not_found);
|
|
return ret_if_not_found;
|
|
}
|
|
|
|
if (was_found)
|
|
*was_found = true;
|
|
|
|
PyObject* py_return = pfunc();
|
|
return py_return;
|
|
}
|
|
|
|
SWIGEXPORT size_t
|
|
LLDBSwigPython_CalculateNumChildren
|
|
(
|
|
PyObject *implementor,
|
|
uint32_t max
|
|
)
|
|
{
|
|
size_t ret_val = 0;
|
|
bool int_match = false;
|
|
|
|
PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor, "num_children");
|
|
|
|
if (!pfunc)
|
|
return ret_val;
|
|
|
|
PyObject* py_return = NULL;
|
|
auto argc = pfunc.GetNumArguments();
|
|
if (argc.num_args == 1)
|
|
py_return = pfunc();
|
|
else if (argc.num_args == 2)
|
|
py_return = pfunc(max);
|
|
|
|
if (!py_return)
|
|
return ret_val;
|
|
|
|
// PyInt_* are not available for Python 3 and above.
|
|
#if PY_MAJOR_VERSION < 3
|
|
if (PyInt_Check (py_return))
|
|
{
|
|
int_match = true;
|
|
ret_val = static_cast<size_t> (PyInt_AsLong (py_return));
|
|
}
|
|
#endif
|
|
|
|
// We want to check for PyLong only if the return value did not
|
|
// match PyInt. This is because we do not want to call PyLong_Check if
|
|
// PyInt_Check returns true but PyInt_AsLong generates an error.
|
|
if (!int_match && PyLong_Check (py_return))
|
|
{
|
|
#if PY_MAJOR_VERSION < 3
|
|
ret_val = static_cast<size_t> (PyLong_AsUnsignedLong (py_return));
|
|
#else
|
|
// PyLong_AsSize_t is available only for Python 3 and above.
|
|
ret_val = PyLong_AsSize_t (py_return);
|
|
#endif
|
|
}
|
|
|
|
Py_XDECREF(py_return);
|
|
|
|
if (PyErr_Occurred())
|
|
{
|
|
PyErr_Print();
|
|
PyErr_Clear();
|
|
}
|
|
|
|
if (argc.num_args == 1 && ret_val > max)
|
|
ret_val = max;
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
SWIGEXPORT PyObject*
|
|
LLDBSwigPython_GetChildAtIndex
|
|
(
|
|
PyObject *implementor,
|
|
uint32_t idx
|
|
)
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"get_child_at_index");
|
|
|
|
if (!pfunc)
|
|
return NULL;
|
|
|
|
PyObject *py_return = NULL;
|
|
py_return = pfunc(idx);
|
|
|
|
if (py_return == NULL || py_return == Py_None)
|
|
{
|
|
Py_XDECREF(py_return);
|
|
return NULL;
|
|
}
|
|
|
|
lldb::SBValue* sbvalue_ptr = NULL;
|
|
|
|
if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)
|
|
{
|
|
Py_XDECREF(py_return);
|
|
return NULL;
|
|
}
|
|
|
|
if (sbvalue_ptr == NULL)
|
|
return NULL;
|
|
|
|
return py_return;
|
|
}
|
|
|
|
SWIGEXPORT int
|
|
LLDBSwigPython_GetIndexOfChildWithName
|
|
(
|
|
PyObject *implementor,
|
|
const char* child_name
|
|
)
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"get_child_index");
|
|
|
|
if (!pfunc)
|
|
return UINT32_MAX;
|
|
|
|
PyObject *py_return = NULL;
|
|
py_return = pfunc(child_name);
|
|
|
|
if (py_return == NULL || py_return == Py_None)
|
|
{
|
|
Py_XDECREF(py_return);
|
|
return UINT32_MAX;
|
|
}
|
|
|
|
long retval = PyInt_AsLong(py_return);
|
|
Py_XDECREF(py_return);
|
|
|
|
if (retval >= 0)
|
|
return (uint32_t)retval;
|
|
|
|
return UINT32_MAX;
|
|
}
|
|
|
|
SWIGEXPORT bool
|
|
LLDBSwigPython_UpdateSynthProviderInstance
|
|
(
|
|
PyObject *implementor
|
|
)
|
|
{
|
|
bool ret_val = false;
|
|
|
|
static char callee_name[] = "update";
|
|
|
|
PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name);
|
|
|
|
if (py_return == Py_True)
|
|
ret_val = true;
|
|
|
|
Py_XDECREF(py_return);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
SWIGEXPORT bool
|
|
LLDBSwigPython_MightHaveChildrenSynthProviderInstance
|
|
(
|
|
PyObject *implementor
|
|
)
|
|
{
|
|
bool ret_val = false;
|
|
|
|
static char callee_name[] = "has_children";
|
|
|
|
PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_True);
|
|
|
|
if (py_return == Py_True)
|
|
ret_val = true;
|
|
|
|
Py_XDECREF(py_return);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
SWIGEXPORT PyObject*
|
|
LLDBSwigPython_GetValueSynthProviderInstance
|
|
(
|
|
PyObject *implementor
|
|
)
|
|
{
|
|
PyObject* ret_val = nullptr;
|
|
|
|
static char callee_name[] = "get_value";
|
|
|
|
PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_None);
|
|
|
|
if (py_return == Py_None || py_return == nullptr)
|
|
ret_val = nullptr;
|
|
|
|
lldb::SBValue* sbvalue_ptr = NULL;
|
|
|
|
if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)
|
|
ret_val = nullptr;
|
|
else if (sbvalue_ptr == NULL)
|
|
ret_val = nullptr;
|
|
else
|
|
ret_val = py_return;
|
|
|
|
Py_XDECREF(py_return);
|
|
return ret_val;
|
|
}
|
|
|
|
SWIGEXPORT void*
|
|
LLDBSWIGPython_CastPyObjectToSBValue
|
|
(
|
|
PyObject* data
|
|
)
|
|
{
|
|
lldb::SBValue* sb_ptr = NULL;
|
|
|
|
int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBValue, 0);
|
|
|
|
if (valid_cast == -1)
|
|
return NULL;
|
|
|
|
return sb_ptr;
|
|
}
|
|
|
|
// Currently, SBCommandReturnObjectReleaser wraps a unique pointer to an
|
|
// lldb_private::CommandReturnObject. This means that the destructor for the
|
|
// SB object will deallocate its contained CommandReturnObject. Because that
|
|
// object is used as the real return object for Python-based commands, we want
|
|
// it to stay around. Thus, we release the unique pointer before returning from
|
|
// LLDBSwigPythonCallCommand, and to guarantee that the release will occur no
|
|
// matter how we exit from the function, we have a releaser object whose
|
|
// destructor does the right thing for us
|
|
class SBCommandReturnObjectReleaser
|
|
{
|
|
public:
|
|
SBCommandReturnObjectReleaser (lldb::SBCommandReturnObject &obj) :
|
|
m_command_return_object_ref (obj)
|
|
{
|
|
}
|
|
|
|
~SBCommandReturnObjectReleaser ()
|
|
{
|
|
m_command_return_object_ref.Release();
|
|
}
|
|
private:
|
|
lldb::SBCommandReturnObject &m_command_return_object_ref;
|
|
};
|
|
|
|
SWIGEXPORT 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
|
|
)
|
|
{
|
|
|
|
lldb::SBCommandReturnObject cmd_retobj_sb(&cmd_retobj);
|
|
SBCommandReturnObjectReleaser cmd_retobj_sb_releaser(cmd_retobj_sb);
|
|
lldb::SBDebugger debugger_sb(debugger);
|
|
lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp);
|
|
|
|
bool retval = false;
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
PyObject* session_dict = NULL;
|
|
// pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you
|
|
// see comment above for SBCommandReturnObjectReleaser for further details
|
|
PyObject* pvalue = NULL;
|
|
|
|
PyCallable::argc argc = pfunc.GetNumArguments();
|
|
if (argc.num_args == 5 || argc.varargs == true)
|
|
pvalue = pfunc(debugger_sb, args, exe_ctx_sb, &cmd_retobj_sb, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
else
|
|
pvalue = pfunc(debugger_sb, args, &cmd_retobj_sb, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
|
|
Py_XINCREF (session_dict);
|
|
Py_XDECREF (pvalue);
|
|
|
|
retval = true;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
SWIGEXPORT bool
|
|
LLDBSwigPythonCallCommandObject
|
|
(
|
|
PyObject *implementor,
|
|
lldb::DebuggerSP& debugger,
|
|
const char* args,
|
|
lldb_private::CommandReturnObject& cmd_retobj,
|
|
lldb::ExecutionContextRefSP exe_ctx_ref_sp
|
|
)
|
|
{
|
|
|
|
lldb::SBCommandReturnObject cmd_retobj_sb(&cmd_retobj);
|
|
SBCommandReturnObjectReleaser cmd_retobj_sb_releaser(cmd_retobj_sb);
|
|
lldb::SBDebugger debugger_sb(debugger);
|
|
lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp);
|
|
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"__call__");
|
|
|
|
if (!pfunc)
|
|
return false;
|
|
|
|
// pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you
|
|
// see comment above for SBCommandReturnObjectReleaser for further details
|
|
PyObject* pvalue = NULL;
|
|
|
|
pvalue = pfunc(debugger_sb, args, exe_ctx_sb, &cmd_retobj_sb);
|
|
|
|
Py_XDECREF (pvalue);
|
|
|
|
return true;
|
|
}
|
|
|
|
SWIGEXPORT void*
|
|
LLDBSWIGPythonCreateOSPlugin
|
|
(
|
|
const char *python_class_name,
|
|
const char *session_dictionary_name,
|
|
const lldb::ProcessSP& process_sp
|
|
)
|
|
{
|
|
PyObject* retval = NULL;
|
|
|
|
if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
|
|
Py_RETURN_NONE;
|
|
|
|
// I do not want the SBProcess to be deallocated when going out of scope because python
|
|
// has ownership of it and will manage memory for this object by itself
|
|
lldb::SBProcess *process_sb = new lldb::SBProcess(process_sp);
|
|
|
|
PyObject *SBProc_PyObj = SBTypeToSWIGWrapper(process_sb);
|
|
|
|
if (SBProc_PyObj == NULL)
|
|
Py_RETURN_NONE;
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
Py_INCREF(SBProc_PyObj);
|
|
|
|
PyObject* session_dict = NULL;
|
|
session_dict = session_dict = FindSessionDictionary(session_dictionary_name);
|
|
retval = pfunc(SBProc_PyObj);
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
Py_XINCREF(retval);
|
|
}
|
|
|
|
if (retval)
|
|
return retval;
|
|
else
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
SWIGEXPORT void*
|
|
LLDBSWIGPython_GetDynamicSetting (void* module, const char* setting, const lldb::TargetSP& target_sp)
|
|
{
|
|
|
|
if (!module || !setting)
|
|
Py_RETURN_NONE;
|
|
|
|
lldb::SBTarget target_sb(target_sp);
|
|
|
|
PyObject *pvalue = NULL;
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName("get_dynamic_setting",(PyObject *)module);
|
|
|
|
if (!pfunc)
|
|
Py_RETURN_NONE;
|
|
|
|
pvalue = pfunc(target_sb, setting);
|
|
}
|
|
|
|
return pvalue;
|
|
}
|
|
|
|
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);
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
PyObject* session_dict = NULL;
|
|
PyObject* pvalue = NULL;
|
|
pvalue = pfunc(process_sb, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
if (PyObjectToString(pvalue,output))
|
|
retval = true;
|
|
|
|
Py_XDECREF(pvalue);
|
|
}
|
|
|
|
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);
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
PyObject* session_dict = NULL;
|
|
PyObject* pvalue = NULL;
|
|
pvalue = pfunc(thread_sb, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
if (PyObjectToString(pvalue,output))
|
|
retval = true;
|
|
|
|
Py_XDECREF(pvalue);
|
|
}
|
|
|
|
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);
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
PyObject* session_dict = NULL;
|
|
PyObject* pvalue = NULL;
|
|
pvalue = pfunc(target_sb, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
if (PyObjectToString(pvalue,output))
|
|
retval = true;
|
|
|
|
Py_XDECREF(pvalue);
|
|
}
|
|
|
|
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);
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
PyObject* session_dict = NULL;
|
|
PyObject* pvalue = NULL;
|
|
pvalue = pfunc(frame_sb, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
if (PyObjectToString(pvalue,output))
|
|
retval = true;
|
|
|
|
Py_XDECREF(pvalue);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
SWIGEXPORT bool
|
|
LLDBSWIGPythonRunScriptKeywordValue
|
|
(const char* python_function_name,
|
|
const char* session_dictionary_name,
|
|
lldb::ValueObjectSP& value,
|
|
std::string& output)
|
|
|
|
{
|
|
bool retval = false;
|
|
|
|
if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
|
|
return retval;
|
|
|
|
lldb::SBValue value_sb(value);
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return retval;
|
|
|
|
PyObject* session_dict = NULL;
|
|
PyObject* pvalue = NULL;
|
|
pvalue = pfunc(value_sb, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
if (PyObjectToString(pvalue,output))
|
|
retval = true;
|
|
|
|
Py_XDECREF(pvalue);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
SWIGEXPORT bool
|
|
LLDBSwigPythonCallModuleInit
|
|
(
|
|
const char *python_module_name,
|
|
const char *session_dictionary_name,
|
|
lldb::DebuggerSP& debugger
|
|
)
|
|
{
|
|
bool retval = false;
|
|
|
|
lldb::SBDebugger debugger_sb(debugger);
|
|
|
|
std::string python_function_name_string = python_module_name;
|
|
python_function_name_string += ".__lldb_init_module";
|
|
const char* python_function_name = python_function_name_string.c_str();
|
|
|
|
{
|
|
PyErr_Cleaner py_err_cleaner(true);
|
|
|
|
PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name);
|
|
|
|
if (!pfunc)
|
|
return true;
|
|
|
|
PyObject* session_dict = NULL;
|
|
PyObject* pvalue = NULL;
|
|
pvalue = pfunc(debugger_sb, session_dict = FindSessionDictionary(session_dictionary_name));
|
|
|
|
Py_XINCREF (session_dict);
|
|
|
|
retval = true;
|
|
|
|
Py_XDECREF(pvalue);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
%}
|
|
|
|
|
|
%runtime %{
|
|
// Forward declaration to be inserted at the start of LLDBWrapPython.h
|
|
#include "lldb/API/SBDebugger.h"
|
|
#include "lldb/API/SBValue.h"
|
|
|
|
SWIGEXPORT lldb::ValueObjectSP
|
|
LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data)
|
|
{
|
|
lldb::ValueObjectSP valobj_sp;
|
|
if (data)
|
|
{
|
|
lldb::SBValue* sb_ptr = (lldb::SBValue *)data;
|
|
valobj_sp = sb_ptr->GetSP();
|
|
}
|
|
return valobj_sp;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
%}
|
|
|
|
%wrapper %{
|
|
|
|
|
|
// For the LogOutputCallback functions
|
|
void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton) {
|
|
if (baton != Py_None) {
|
|
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
|
PyObject_CallFunction(reinterpret_cast<PyObject*>(baton), const_cast<char*>("s"), str);
|
|
SWIG_PYTHON_THREAD_END_BLOCK;
|
|
}
|
|
}
|
|
%}
|