diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 | 
| commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
| tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /lldb/bindings/python | |
| parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) | |
Notes
Diffstat (limited to 'lldb/bindings/python')
| -rw-r--r-- | lldb/bindings/python/createPythonInit.py | 17 | ||||
| -rw-r--r-- | lldb/bindings/python/python-extensions.swig | 592 | ||||
| -rw-r--r-- | lldb/bindings/python/python-swigsafecast.swig | 154 | ||||
| -rw-r--r-- | lldb/bindings/python/python-typemaps.swig | 532 | ||||
| -rw-r--r-- | lldb/bindings/python/python-wrapper.swig | 1067 | 
5 files changed, 2362 insertions, 0 deletions
diff --git a/lldb/bindings/python/createPythonInit.py b/lldb/bindings/python/createPythonInit.py new file mode 100644 index 000000000000..3deb9159b702 --- /dev/null +++ b/lldb/bindings/python/createPythonInit.py @@ -0,0 +1,17 @@ +import os +import sys + +pkgRelDir = sys.argv[1] +pkgFiles = sys.argv[2:] + +getFileName = lambda f: os.path.splitext(os.path.basename(f))[0] +importNames = ', '.join('"{}"'.format(getFileName(f)) for f in pkgFiles) + +script = """__all__ = [{import_names}] +for x in __all__: +  __import__('lldb.{pkg_name}.' + x) +""".format(import_names=importNames, pkg_name=pkgRelDir.replace("/", ".")) + +pkgIniFile = os.path.normpath(os.path.join(pkgRelDir, "__init__.py")) +with open(pkgIniFile, "w") as f: +    f.write(script) diff --git a/lldb/bindings/python/python-extensions.swig b/lldb/bindings/python/python-extensions.swig new file mode 100644 index 000000000000..0b23fdd40006 --- /dev/null +++ b/lldb/bindings/python/python-extensions.swig @@ -0,0 +1,592 @@ +%extend lldb::SBBreakpoint { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBBroadcaster { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBCommandReturnObject { +        /* the write() and flush() calls are not part of the SB API proper, and are solely for Python usage +        they are meant to make an SBCommandReturnObject into a file-like object so that instructions of the sort +        print >>sb_command_return_object, "something" +        will work correctly */ + +        void lldb::SBCommandReturnObject::write (const char* str) +        { +            if (str) +                $self->Printf("%s",str); +        } +        void lldb::SBCommandReturnObject::flush () +        {} +} + +%extend lldb::SBCompileUnit { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBDeclaration { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBFunction { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBLineEntry { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBModule { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBSection { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} +%extend lldb::SBStream { +        /* the write() and flush() calls are not part of the SB API proper, and are solely for Python usage +        they are meant to make an SBStream into a file-like object so that instructions of the sort +        print >>sb_stream, "something" +        will work correctly */ + +        void lldb::SBStream::write (const char* str) +        { +            if (str) +                $self->Printf("%s",str); +        } +        void lldb::SBStream::flush () +        {} +} +%extend lldb::SBSymbol { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBTarget { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBTypeFilter { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBTypeNameSpecifier { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBTypeSummary { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBTypeSynthetic { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%extend lldb::SBThread { +    %pythoncode %{ +        def __eq__(self, rhs): +            if not isinstance(rhs, type(self)): +                return False + +            return getattr(_lldb,self.__class__.__name__+"___eq__")(self, rhs) + +        def __ne__(self, rhs): +            if not isinstance(rhs, type(self)): +                return True + +            return getattr(_lldb,self.__class__.__name__+"___ne__")(self, rhs) +    %} +} + +%pythoncode %{ + +def command(command_name=None, doc=None): +    import lldb +    """A decorator function that registers an LLDB command line +        command that is bound to the function it is attached to.""" +    def callable(function): +        """Registers an lldb command for the decorated function.""" +        command = "command script add -f %s.%s %s" % (function.__module__, function.__name__, command_name or function.__name__) +        lldb.debugger.HandleCommand(command) +        if doc: +            function.__doc__ = doc +        return function + +    return callable + +class declaration(object): +    '''A class that represents a source declaration location with file, line and column.''' +    def __init__(self, file, line, col): +        self.file = file +        self.line = line +        self.col = col + +class value_iter(object): +    def __iter__(self): +        return self + +    def __next__(self): +        if self.index >= self.length: +            raise StopIteration() +        child_sbvalue = self.sbvalue.GetChildAtIndex(self.index) +        self.index += 1 +        return value(child_sbvalue) + +    def next(self): +        return self.__next__() + +    def __init__(self,value): +        self.index = 0 +        self.sbvalue = value +        if type(self.sbvalue) is value: +            self.sbvalue = self.sbvalue.sbvalue +        self.length = self.sbvalue.GetNumChildren() + +class value(object): +    '''A class designed to wrap lldb.SBValue() objects so the resulting object +    can be used as a variable would be in code. So if you have a Point structure +    variable in your code in the current frame named "pt", you can initialize an instance +    of this class with it: + +    pt = lldb.value(lldb.frame.FindVariable("pt")) +    print pt +    print pt.x +    print pt.y + +    pt = lldb.value(lldb.frame.FindVariable("rectangle_array")) +    print rectangle_array[12] +    print rectangle_array[5].origin.x''' +    def __init__(self, sbvalue): +        self.sbvalue = sbvalue + +    def __nonzero__(self): +        return self.sbvalue.__nonzero__() + +    def __bool__(self): +        return self.sbvalue.__bool__() + +    def __str__(self): +        return self.sbvalue.__str__() + +    def __getitem__(self, key): +        # Allow array access if this value has children... +        if type(key) is value: +            key = int(key) +        if type(key) is int: +            child_sbvalue = (self.sbvalue.GetValueForExpressionPath("[%i]" % key)) +            if child_sbvalue and child_sbvalue.IsValid(): +                return value(child_sbvalue) +            raise IndexError("Index '%d' is out of range" % key) +        raise TypeError("No array item of type %s" % str(type(key))) + +    def __iter__(self): +        return value_iter(self.sbvalue) + +    def __getattr__(self, name): +        child_sbvalue = self.sbvalue.GetChildMemberWithName (name) +        if child_sbvalue and child_sbvalue.IsValid(): +            return value(child_sbvalue) +        raise AttributeError("Attribute '%s' is not defined" % name) + +    def __add__(self, other): +        return int(self) + int(other) + +    def __sub__(self, other): +        return int(self) - int(other) + +    def __mul__(self, other): +        return int(self) * int(other) + +    def __floordiv__(self, other): +        return int(self) // int(other) + +    def __mod__(self, other): +        return int(self) % int(other) + +    def __divmod__(self, other): +        return int(self) % int(other) + +    def __pow__(self, other): +        return int(self) ** int(other) + +    def __lshift__(self, other): +        return int(self) << int(other) + +    def __rshift__(self, other): +        return int(self) >> int(other) + +    def __and__(self, other): +        return int(self) & int(other) + +    def __xor__(self, other): +        return int(self) ^ int(other) + +    def __or__(self, other): +        return int(self) | int(other) + +    def __div__(self, other): +        return int(self) / int(other) + +    def __truediv__(self, other): +        return int(self) / int(other) + +    def __iadd__(self, other): +        result = self.__add__(other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __isub__(self, other): +        result = self.__sub__(other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __imul__(self, other): +        result = self.__mul__(other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __idiv__(self, other): +        result = self.__div__(other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __itruediv__(self, other): +        result = self.__truediv__(other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __ifloordiv__(self, other): +        result =  self.__floordiv__(self, other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __imod__(self, other): +        result =  self.__and__(self, other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __ipow__(self, other): +        result = self.__pow__(self, other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __ipow__(self, other, modulo): +        result = self.__pow__(self, other, modulo) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __ilshift__(self, other): +        result = self.__lshift__(other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __irshift__(self, other): +        result =  self.__rshift__(other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __iand__(self, other): +        result =  self.__and__(self, other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __ixor__(self, other): +        result =  self.__xor__(self, other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __ior__(self, other): +        result =  self.__ior__(self, other) +        self.sbvalue.SetValueFromCString (str(result)) +        return result + +    def __neg__(self): +        return -int(self) + +    def __pos__(self): +        return +int(self) + +    def __abs__(self): +        return abs(int(self)) + +    def __invert__(self): +        return ~int(self) + +    def __complex__(self): +        return complex (int(self)) + +    def __int__(self): +        is_num,is_sign = is_numeric_type(self.sbvalue.GetType().GetCanonicalType().GetBasicType()) +        if is_num and not is_sign: return self.sbvalue.GetValueAsUnsigned() +        return self.sbvalue.GetValueAsSigned() + +    def __long__(self): +        return self.__int__() + +    def __float__(self): +        return float (self.sbvalue.GetValueAsSigned()) + +    def __oct__(self): +        return '0%o' % self.sbvalue.GetValueAsUnsigned() + +    def __hex__(self): +        return '0x%x' % self.sbvalue.GetValueAsUnsigned() + +    def __len__(self): +        return self.sbvalue.GetNumChildren() + +    def __eq__(self, other): +        if type(other) is int: +                return int(self) == other +        elif type(other) is str: +                return str(self) == other +        elif type(other) is value: +                self_err = SBError() +                other_err = SBError() +                self_val = self.sbvalue.GetValueAsUnsigned(self_err) +                if self_err.fail: +                        raise ValueError("unable to extract value of self") +                other_val = other.sbvalue.GetValueAsUnsigned(other_err) +                if other_err.fail: +                        raise ValueError("unable to extract value of other") +                return self_val == other_val +        raise TypeError("Unknown type %s, No equality operation defined." % str(type(other))) + +    def __ne__(self, other): +        return not self.__eq__(other) +%} + +%pythoncode %{ + +class SBSyntheticValueProvider(object): +    def __init__(self,valobj): +        pass + +    def num_children(self): +        return 0 + +    def get_child_index(self,name): +        return None + +    def get_child_at_index(self,idx): +        return None + +    def update(self): +        pass + +    def has_children(self): +        return False + + +%} + +%pythoncode %{ + +# given an lldb.SBBasicType it returns a tuple +# (is_numeric, is_signed) +# the value of is_signed is undefined if is_numeric == false +def is_numeric_type(basic_type): +    if basic_type == eBasicTypeInvalid: return (False,False) +    if basic_type == eBasicTypeVoid: return (False,False) +    if basic_type == eBasicTypeChar: return (True,False) +    if basic_type == eBasicTypeSignedChar: return (True,True) +    if basic_type == eBasicTypeUnsignedChar: return (True,False) +    if basic_type == eBasicTypeWChar: return (True,False) +    if basic_type == eBasicTypeSignedWChar: return (True,True) +    if basic_type == eBasicTypeUnsignedWChar: return (True,False) +    if basic_type == eBasicTypeChar16: return (True,False) +    if basic_type == eBasicTypeChar32: return (True,False) +    if basic_type == eBasicTypeShort: return (True,True) +    if basic_type == eBasicTypeUnsignedShort: return (True,False) +    if basic_type == eBasicTypeInt: return (True,True) +    if basic_type == eBasicTypeUnsignedInt: return (True,False) +    if basic_type == eBasicTypeLong: return (True,True) +    if basic_type == eBasicTypeUnsignedLong: return (True,False) +    if basic_type == eBasicTypeLongLong: return (True,True) +    if basic_type == eBasicTypeUnsignedLongLong: return (True,False) +    if basic_type == eBasicTypeInt128: return (True,True) +    if basic_type == eBasicTypeUnsignedInt128: return (True,False) +    if basic_type == eBasicTypeBool: return (False,False) +    if basic_type == eBasicTypeHalf: return (True,True) +    if basic_type == eBasicTypeFloat: return (True,True) +    if basic_type == eBasicTypeDouble: return (True,True) +    if basic_type == eBasicTypeLongDouble: return (True,True) +    if basic_type == eBasicTypeFloatComplex: return (True,True) +    if basic_type == eBasicTypeDoubleComplex: return (True,True) +    if basic_type == eBasicTypeLongDoubleComplex: return (True,True) +    if basic_type == eBasicTypeObjCID: return (False,False) +    if basic_type == eBasicTypeObjCClass: return (False,False) +    if basic_type == eBasicTypeObjCSel: return (False,False) +    if basic_type == eBasicTypeNullPtr: return (False,False) +    #if basic_type == eBasicTypeOther: +    return (False,False) + +%} diff --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig new file mode 100644 index 000000000000..d5cafbfa67cb --- /dev/null +++ b/lldb/bindings/python/python-swigsafecast.swig @@ -0,0 +1,154 @@ +// leaving this undefined ensures we will get a linker error if we try to use SBTypeToSWIGWrapper() +// for a type for which we did not specialze this function +template <typename SBClass> +PyObject* +SBTypeToSWIGWrapper (SBClass* sb_object); + +template <typename SBClass> +PyObject* +SBTypeToSWIGWrapper (SBClass& sb_object) +{ +    return SBTypeToSWIGWrapper(&sb_object); +} + +template <typename SBClass> +PyObject* +SBTypeToSWIGWrapper (const SBClass& sb_object) +{ +    return SBTypeToSWIGWrapper(&sb_object); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (PyObject* py_object) +{ +    return py_object; +} + +template <> +PyObject* +SBTypeToSWIGWrapper (unsigned int* c_int) +{ +    if (!c_int) +        return NULL; +    return PyInt_FromLong(*c_int); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBEvent* event_sb) +{ +    return SWIG_NewPointerObj((void *) event_sb, SWIGTYPE_p_lldb__SBEvent, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBProcess* process_sb) +{ +    return SWIG_NewPointerObj((void *) process_sb, SWIGTYPE_p_lldb__SBProcess, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBThread* thread_sb) +{ +    return SWIG_NewPointerObj((void *) thread_sb, SWIGTYPE_p_lldb__SBThread, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBThreadPlan* thread_plan_sb) +{ +    return SWIG_NewPointerObj((void *) thread_plan_sb, SWIGTYPE_p_lldb__SBThreadPlan, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBTarget* target_sb) +{ +    return SWIG_NewPointerObj((void *) target_sb, SWIGTYPE_p_lldb__SBTarget, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBFrame* frame_sb) +{ +    return SWIG_NewPointerObj((void *) frame_sb, SWIGTYPE_p_lldb__SBFrame, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBDebugger* debugger_sb) +{ +    return SWIG_NewPointerObj((void *) debugger_sb, SWIGTYPE_p_lldb__SBDebugger, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBBreakpoint* breakpoint_sb) +{ +    return SWIG_NewPointerObj((void *) breakpoint_sb, SWIGTYPE_p_lldb__SBBreakpoint, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBWatchpoint* watchpoint_sb) +{ +    return SWIG_NewPointerObj((void *) watchpoint_sb, SWIGTYPE_p_lldb__SBWatchpoint, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBBreakpointLocation* breakpoint_location_sb) +{ +    return SWIG_NewPointerObj((void *) breakpoint_location_sb, SWIGTYPE_p_lldb__SBBreakpointLocation, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBBreakpointName* breakpoint_name_sb) +{ +    return SWIG_NewPointerObj((void *) breakpoint_name_sb, SWIGTYPE_p_lldb__SBBreakpointName, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBValue* value_sb) +{ +    return SWIG_NewPointerObj((void *) value_sb, SWIGTYPE_p_lldb__SBValue, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBCommandReturnObject* cmd_ret_obj_sb) +{ +    return SWIG_NewPointerObj((void *) cmd_ret_obj_sb, SWIGTYPE_p_lldb__SBCommandReturnObject, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBExecutionContext* ctx_sb) +{ +    return SWIG_NewPointerObj((void *) ctx_sb, SWIGTYPE_p_lldb__SBExecutionContext, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBTypeSummaryOptions* summary_options_sb) +{ +    return SWIG_NewPointerObj((void *) summary_options_sb, SWIGTYPE_p_lldb__SBTypeSummaryOptions, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBStructuredData* structured_data_sb) +{ +    return SWIG_NewPointerObj((void *) structured_data_sb, SWIGTYPE_p_lldb__SBStructuredData, 0); +} + +template <> +PyObject* +SBTypeToSWIGWrapper (lldb::SBSymbolContext* sym_ctx_sb) +{ +    return SWIG_NewPointerObj((void *) sym_ctx_sb, SWIGTYPE_p_lldb__SBSymbolContext, 0); +} diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig new file mode 100644 index 000000000000..c08aeab71f78 --- /dev/null +++ b/lldb/bindings/python/python-typemaps.swig @@ -0,0 +1,532 @@ +/* Typemap definitions, to allow SWIG to properly handle 'char**' data types. */ + +%typemap(in) char ** { +  /* Check if is a list  */ +  if (PythonList::Check($input)) { +    PythonList list(PyRefType::Borrowed, $input); +    int size = list.GetSize(); +    int i = 0; +    $1 = (char**)malloc((size+1)*sizeof(char*)); +    for (i = 0; i < size; i++) { +      PythonString py_str = list.GetItemAtIndex(i).AsType<PythonString>(); +      if (!py_str.IsAllocated()) { +        PyErr_SetString(PyExc_TypeError,"list must contain strings"); +        free($1); +        return nullptr; +      } + +      $1[i] = const_cast<char*>(py_str.GetString().data()); +    } +    $1[i] = 0; +  } else if ($input == Py_None) { +    $1 =  NULL; +  } else { +    PyErr_SetString(PyExc_TypeError,"not a list"); +    return NULL; +  } +} + +%typemap(typecheck) char ** { +  /* Check if is a list  */ +  $1 = 1; +  if (PythonList::Check($input)) { +    PythonList list(PyRefType::Borrowed, $input); +    int size = list.GetSize(); +    int i = 0; +    for (i = 0; i < size; i++) { +      PythonString s = list.GetItemAtIndex(i).AsType<PythonString>(); +      if (!s.IsAllocated()) { $1 = 0; } +    } +  } +  else +  { +    $1 = ( ($input == Py_None) ? 1 : 0); +  } +} + +%typemap(freearg) char** { +  free((char *) $1); +} + +%typemap(out) char** { +  int len; +  int i; +  len = 0; +  while ($1[len]) len++; +  PythonList list(len); +  for (i = 0; i < len; i++) +    list.SetItemAtIndex(i, PythonString($1[i])); +  $result = list.release(); +} + +%typemap(in) lldb::tid_t { +  PythonObject obj = Retain<PythonObject>($input); +  lldb::tid_t value = unwrapOrSetPythonException(As<unsigned long long>(obj));  +  if (PyErr_Occurred()) +    return nullptr; +  $1 = value; +} + +%typemap(in) lldb::StateType { +  PythonObject obj = Retain<PythonObject>($input); +  unsigned long long state_type_value = +    unwrapOrSetPythonException(As<unsigned long long>(obj)); +  if (PyErr_Occurred()) +    return nullptr; +  if (state_type_value > lldb::StateType::kLastStateType) { +    PyErr_SetString(PyExc_ValueError, "Not a valid StateType value"); +    return nullptr; +  } +  $1 = static_cast<lldb::StateType>(state_type_value); +} + +/* Typemap definitions to allow SWIG to properly handle char buffer. */ + +// typemap for a char buffer +%typemap(in) (char *dst, size_t dst_len) { +   if (!PyInt_Check($input)) { +       PyErr_SetString(PyExc_ValueError, "Expecting an integer"); +       return NULL; +   } +   $2 = PyInt_AsLong($input); +   if ($2 <= 0) { +       PyErr_SetString(PyExc_ValueError, "Positive integer expected"); +       return NULL; +   } +   $1 = (char *) malloc($2); +} +// SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated +// as char data instead of byte data. +%typemap(in) (void *char_buf, size_t size) = (char *dst, size_t dst_len); + +// Return the char buffer.  Discarding any previous return result +%typemap(argout) (char *dst, size_t dst_len) { +   Py_XDECREF($result);   /* Blow away any previous result */ +   if (result == 0) { +      PythonString string(""); +      $result = string.release(); +      Py_INCREF($result); +   } else { +      llvm::StringRef ref(static_cast<const char*>($1), result); +      PythonString string(ref); +      $result = string.release(); +   } +   free($1); +} +// SBProcess::ReadCStringFromMemory() uses a void*, but needs to be treated +// as char data instead of byte data. +%typemap(argout) (void *char_buf, size_t size) = (char *dst, size_t dst_len); + + +// typemap for handling an snprintf-like API like SBThread::GetStopDescription. +%typemap(in) (char *dst_or_null, size_t dst_len) { +   if (!PyInt_Check($input)) { +       PyErr_SetString(PyExc_ValueError, "Expecting an integer"); +       return NULL; +   } +   $2 = PyInt_AsLong($input); +   if ($2 <= 0) { +       PyErr_SetString(PyExc_ValueError, "Positive integer expected"); +       return NULL; +   } +   $1 = (char *) malloc($2); +} +%typemap(argout) (char *dst_or_null, size_t dst_len) { +   Py_XDECREF($result);   /* Blow away any previous result */ +   llvm::StringRef ref($1); +   PythonString string(ref); +   $result = string.release(); +   free($1); +} + + +// typemap for an outgoing buffer +// See also SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len). +// Ditto for SBProcess::PutSTDIN(const char *src, size_t src_len). +%typemap(in) (const char *cstr, uint32_t cstr_len), +             (const char *src, size_t src_len) { +   if (PythonString::Check($input)) { +      PythonString str(PyRefType::Borrowed, $input); +      $1 = (char*)str.GetString().data(); +      $2 = str.GetSize(); +   } +   else if(PythonByteArray::Check($input)) { +      PythonByteArray bytearray(PyRefType::Borrowed, $input); +      $1 = (char*)bytearray.GetBytes().data(); +      $2 = bytearray.GetSize(); +   } +   else if (PythonBytes::Check($input)) { +      PythonBytes bytes(PyRefType::Borrowed, $input); +      $1 = (char*)bytes.GetBytes().data(); +      $2 = bytes.GetSize(); +   } +   else { +      PyErr_SetString(PyExc_ValueError, "Expecting a string"); +      return NULL; +   } +} +// For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput. +%typemap(in) (const void *buf, size_t size), +             (const void *data, size_t data_len) { +   if (PythonString::Check($input)) { +      PythonString str(PyRefType::Borrowed, $input); +      $1 = (void*)str.GetString().data(); +      $2 = str.GetSize(); +   } +   else if(PythonByteArray::Check($input)) { +      PythonByteArray bytearray(PyRefType::Borrowed, $input); +      $1 = (void*)bytearray.GetBytes().data(); +      $2 = bytearray.GetSize(); +   } +   else if (PythonBytes::Check($input)) { +      PythonBytes bytes(PyRefType::Borrowed, $input); +      $1 = (void*)bytes.GetBytes().data(); +      $2 = bytes.GetSize(); +   } +   else { +      PyErr_SetString(PyExc_ValueError, "Expecting a buffer"); +      return NULL; +   } +} + +// typemap for an incoming buffer +// See also SBProcess::ReadMemory. +%typemap(in) (void *buf, size_t size) { +   if (PyInt_Check($input)) { +      $2 = PyInt_AsLong($input); +   } else if (PyLong_Check($input)) { +      $2 = PyLong_AsLong($input); +   } else { +      PyErr_SetString(PyExc_ValueError, "Expecting an integer or long object"); +      return NULL; +   } +   if ($2 <= 0) { +       PyErr_SetString(PyExc_ValueError, "Positive integer expected"); +       return NULL; +   } +   $1 = (void *) malloc($2); +} + +// Return the buffer.  Discarding any previous return result +// See also SBProcess::ReadMemory. +%typemap(argout) (void *buf, size_t size) { +   Py_XDECREF($result);   /* Blow away any previous result */ +   if (result == 0) { +      $result = Py_None; +      Py_INCREF($result); +   } else { +      PythonBytes bytes(static_cast<const uint8_t*>($1), result); +      $result = bytes.release(); +   } +   free($1); +} + +%{ +namespace { +template <class T> +T PyLongAsT(PyObject *obj) { +  static_assert(true, "unsupported type"); +} + +template <> uint64_t PyLongAsT<uint64_t>(PyObject *obj) { +  return static_cast<uint64_t>(PyLong_AsUnsignedLongLong(obj)); +} + +template <> uint32_t PyLongAsT<uint32_t>(PyObject *obj) { +  return static_cast<uint32_t>(PyLong_AsUnsignedLong(obj)); +} + +template <> int64_t PyLongAsT<int64_t>(PyObject *obj) { +  return static_cast<int64_t>(PyLong_AsLongLong(obj)); +} + +template <> int32_t PyLongAsT<int32_t>(PyObject *obj) { +  return static_cast<int32_t>(PyLong_AsLong(obj)); +} + +template <class T> +bool SetNumberFromPyObject(T &number, PyObject *obj) { +  if (PyInt_Check(obj)) +    number = static_cast<T>(PyInt_AsLong(obj)); +  else if (PyLong_Check(obj)) +    number = PyLongAsT<T>(obj); +  else return false; + +  return true; +} + +template <> +bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { +  if (PyFloat_Check(obj)) { +    number = PyFloat_AsDouble(obj); +    return true; +  } + +  return false; +} + +} // namespace +%} + +// these typemaps allow Python users to pass list objects +// and have them turn into C++ arrays (this is useful, for instance +// when creating SBData objects from lists of numbers) +%typemap(in) (uint64_t* array, size_t array_len), +             (uint32_t* array, size_t array_len), +             (int64_t* array, size_t array_len), +             (int32_t* array, size_t array_len), +             (double* array, size_t array_len) { +  /* Check if is a list  */ +  if (PyList_Check($input)) { +    int size = PyList_Size($input); +    int i = 0; +    $2 = size; +    $1 = ($1_type) malloc(size * sizeof($*1_type)); +    for (i = 0; i < size; i++) { +      PyObject *o = PyList_GetItem($input,i); +      if (!SetNumberFromPyObject($1[i], o)) { +        PyErr_SetString(PyExc_TypeError,"list must contain numbers"); +        free($1); +        return NULL; +      } + +      if (PyErr_Occurred()) { +        free($1); +        return NULL; +      } +    } +  } else if ($input == Py_None) { +    $1 =  NULL; +    $2 = 0; +  } else { +    PyErr_SetString(PyExc_TypeError,"not a list"); +    return NULL; +  } +} + +%typemap(freearg) (uint64_t* array, size_t array_len), +                  (uint32_t* array, size_t array_len), +                  (int64_t* array, size_t array_len), +                  (int32_t* array, size_t array_len), +                  (double* array, size_t array_len) { +  free($1); +} + +// these typemaps wrap SBModule::GetVersion() from requiring a memory buffer +// to the more Pythonic style where a list is returned and no previous allocation +// is necessary - this will break if more than 50 versions are ever returned +%typemap(typecheck) (uint32_t *versions, uint32_t num_versions) { +    $1 = ($input == Py_None ? 1 : 0); +} + +%typemap(in, numinputs=0) (uint32_t *versions) { +    $1 = (uint32_t*)malloc(sizeof(uint32_t) * 50); +} + +%typemap(in, numinputs=0) (uint32_t num_versions) { +    $1 = 50; +} + +%typemap(argout) (uint32_t *versions, uint32_t num_versions) { +    uint32_t count = result; +    if (count >= $2) +        count = $2; +    PyObject* list = PyList_New(count); +    for (uint32_t j = 0; j < count; j++) +    { +        PyObject* item = PyInt_FromLong($1[j]); +        int ok = PyList_SetItem(list,j,item); +        if (ok != 0) +        { +            $result = Py_None; +            break; +        } +    } +    $result = list; +} + +%typemap(freearg) (uint32_t *versions) { +    free($1); +} + + +// For Log::LogOutputCallback +%typemap(in) (lldb::LogOutputCallback log_callback, void *baton) { +  if (!($input == Py_None || PyCallable_Check(reinterpret_cast<PyObject*>($input)))) { +    PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); +    return NULL; +  } + +  // FIXME (filcab): We can't currently check if our callback is already +  // LLDBSwigPythonCallPythonLogOutputCallback (to DECREF the previous +  // baton) nor can we just remove all traces of a callback, if we want to +  // revert to a file logging mechanism. + +  // Don't lose the callback reference +  Py_INCREF($input); +  $1 = LLDBSwigPythonCallPythonLogOutputCallback; +  $2 = $input; +} + +%typemap(typecheck) (lldb::LogOutputCallback log_callback, void *baton) { +  $1 = $input == Py_None; +  $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject*>($input)); +} + + +%typemap(in) lldb::FileSP { +  PythonFile py_file(PyRefType::Borrowed, $input); +  if (!py_file) { +    PyErr_SetString(PyExc_TypeError, "not a file"); +    return nullptr; +  } +  auto sp = unwrapOrSetPythonException(py_file.ConvertToFile()); +  if (!sp) +    return nullptr; +  $1 = sp; +} + +%typemap(in) lldb::FileSP FORCE_IO_METHODS { +  PythonFile py_file(PyRefType::Borrowed, $input); +  if (!py_file) { +    PyErr_SetString(PyExc_TypeError, "not a file"); +    return nullptr; +  } +  auto sp = unwrapOrSetPythonException(py_file.ConvertToFileForcingUseOfScriptingIOMethods()); +  if (!sp) +    return nullptr; +  $1 = sp; +} + +%typemap(in) lldb::FileSP BORROWED { +  PythonFile py_file(PyRefType::Borrowed, $input); +  if (!py_file) { +    PyErr_SetString(PyExc_TypeError, "not a file"); +    return nullptr; +  } +  auto sp = unwrapOrSetPythonException(py_file.ConvertToFile(/*borrowed=*/true)); +  if (!sp) +    return nullptr; +  $1 = sp; +} + +%typemap(in) lldb::FileSP BORROWED_FORCE_IO_METHODS { +  PythonFile py_file(PyRefType::Borrowed, $input); +  if (!py_file) { +    PyErr_SetString(PyExc_TypeError, "not a file"); +    return nullptr; +  } +  auto sp = unwrapOrSetPythonException(py_file.ConvertToFileForcingUseOfScriptingIOMethods(/*borrowed=*/true)); +  if (!sp) +    return nullptr; +  $1 = sp; +} + +%typecheck(SWIG_TYPECHECK_POINTER) lldb::FileSP { +  if (PythonFile::Check($input)) { +    $1 = 1; +  } else { +    PyErr_Clear(); +    $1 = 0; +  } +} + +%typemap(out) lldb::FileSP { +  $result = nullptr; +  lldb::FileSP &sp = $1; +  if (sp) { +    PythonFile pyfile = unwrapOrSetPythonException(PythonFile::FromFile(*sp)); +    if (!pyfile.IsValid()) +      return nullptr; +    $result = pyfile.release(); +  } +  if (!$result) +  { +      $result = Py_None; +      Py_INCREF(Py_None); +  } +} + +%typemap(in) (const char* string, int len) { +    if ($input == Py_None) +    { +        $1 = NULL; +        $2 = 0; +    } +    else if (PythonString::Check($input)) +    { +        PythonString py_str(PyRefType::Borrowed, $input); +        llvm::StringRef str = py_str.GetString(); +        $1 = const_cast<char*>(str.data()); +        $2 = str.size(); +        // In Python 2, if $input is a PyUnicode object then this +        // will trigger a Unicode -> String conversion, in which +        // case the `PythonString` will now own the PyString.  Thus +        // if it goes out of scope, the data will be deleted.  The +        // only way to avoid this is to leak the Python object in +        // that case.  Note that if there was no conversion, then +        // releasing the string will not leak anything, since we +        // created this as a borrowed reference. +        py_str.release(); +    } +    else +    { +        PyErr_SetString(PyExc_TypeError,"not a string-like object"); +        return NULL; +    } +} + +%inline %{ + +struct Py_buffer_RAII { +  Py_buffer buffer = {}; +  Py_buffer_RAII() {}; +  Py_buffer &operator=(const Py_buffer_RAII &) = delete; +  Py_buffer_RAII(const Py_buffer_RAII &) = delete; +  ~Py_buffer_RAII() { +    if (buffer.obj) +      PyBuffer_Release(&buffer); +  } +}; + +%} + +// These two pybuffer macros are copied out of swig/Lib/python/pybuffer.i, +// and fixed so they will not crash if PyObject_GetBuffer fails. +// https://github.com/swig/swig/issues/1640 +// +// I've also moved the call to PyBuffer_Release to the end of the SWIG wrapper, +// doing it right away is not legal according to the python buffer protocol. + +%define %pybuffer_mutable_binary(TYPEMAP, SIZE) +%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { +  int res; Py_ssize_t size = 0; void *buf = 0; +  res = PyObject_GetBuffer($input, &view.buffer, PyBUF_WRITABLE); +  if (res < 0) { +    PyErr_Clear(); +    %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); +  } +  size = view.buffer.len; +  buf = view.buffer.buf; +  $1 = ($1_ltype) buf; +  $2 = ($2_ltype) (size/sizeof($*1_type)); +} +%enddef + +%define %pybuffer_binary(TYPEMAP, SIZE) +%typemap(in) (TYPEMAP, SIZE) (Py_buffer_RAII view) { +  int res; Py_ssize_t size = 0; const void *buf = 0; +  res = PyObject_GetBuffer($input, &view.buffer, PyBUF_CONTIG_RO); +  if (res < 0) { +    PyErr_Clear(); +    %argument_fail(res, "(TYPEMAP, SIZE)", $symname, $argnum); +  } +  size = view.buffer.len; +  buf = view.buffer.buf; +  $1 = ($1_ltype) buf; +  $2 = ($2_ltype) (size / sizeof($*1_type)); +} +%enddef + +%pybuffer_binary(const uint8_t *buf, size_t num_bytes); +%pybuffer_mutable_binary(uint8_t *buf, size_t num_bytes); diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig new file mode 100644 index 000000000000..f9e89373fe25 --- /dev/null +++ b/lldb/bindings/python/python-wrapper.swig @@ -0,0 +1,1067 @@ +%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; +}; + +%} + +%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 llvm::Expected<bool> +LLDBSwigPythonBreakpointCallbackFunction +( +    const char *python_function_name, +    const char *session_dictionary_name, +    const lldb::StackFrameSP& frame_sp, +    const lldb::BreakpointLocationSP& bp_loc_sp, +    lldb_private::StructuredDataImpl *args_impl +) +{ +    using namespace llvm; + +    lldb::SBFrame sb_frame (frame_sp); +    lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); + +    PyErr_Cleaner py_err_cleaner(true); +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict); + +    unsigned max_positional_args; +    if (auto arg_info = pfunc.GetArgInfo()) +        max_positional_args = arg_info.get().max_positional_args; +    else +        return arg_info.takeError(); + +    PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame)); +    PythonObject bp_loc_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_bp_loc)); + +    auto result = [&] () -> Expected<PythonObject> { +        // If the called function doesn't take extra_args, drop them here: +        if (max_positional_args < 4) { +            return pfunc.Call(frame_arg, bp_loc_arg, dict); +        } else { +            lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl); +            PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value)); +            return pfunc.Call(frame_arg, bp_loc_arg, args_arg, dict); +        } +    } (); + +    if (!result) +        return result.takeError(); + +    // Only False counts as false! +    return result.get().get() != Py_False; +} + +// 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); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict); + +    if (!pfunc.IsAllocated()) +        return stop_at_watchpoint; + +    PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame)); +    PythonObject wp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_wp)); +    PythonObject result = pfunc(frame_arg, wp_arg, dict); + +    if (result.get() == Py_False) +        stop_at_watchpoint = false; + +    return stop_at_watchpoint; +} + +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 *pfunc_impl = nullptr; + +    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; +        } +    } + +    PyObject *py_dict = (PyObject*)session_dictionary; +    if (!PythonDictionary::Check(py_dict)) +        return true; + +    PythonDictionary dict(PyRefType::Borrowed, py_dict); + +    PyErr_Cleaner pyerr_cleanup(true);  // show Python errors + +    PythonCallable pfunc(PyRefType::Borrowed, pfunc_impl); + +    if (!pfunc.IsAllocated()) +    { +        pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict); +        if (!pfunc.IsAllocated()) +            return false; + +        if (pyfunct_wrapper) +        { +            *pyfunct_wrapper = pfunc.get(); +            Py_XINCREF(pfunc.get()); +        } +    } + +    PythonObject result; +    auto argc = pfunc.GetArgInfo(); +    if (!argc) { +        llvm::consumeError(argc.takeError()); +        return false; +    } + +    PythonObject value_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_value)); +    PythonObject options_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_options)); + +    if (argc.get().max_positional_args < 3) +        result = pfunc(value_arg,dict); +    else +        result = pfunc(value_arg,dict,options_arg); + +    retval = result.Str().GetString().str(); + +    return true; +} + +SWIGEXPORT void* +LLDBSwigPythonCreateSyntheticProvider +( +    const char *python_class_name, +    const char *session_dictionary_name, +    const lldb::ValueObjectSP& valobj_sp +) +{ +    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) +        Py_RETURN_NONE; + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name,dict); + +    if (!pfunc.IsAllocated()) +        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); + +    PythonObject val_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_value)); +    if (!val_arg.IsAllocated()) +        Py_RETURN_NONE; + +    PythonObject result = pfunc(val_arg, dict); + +    if (result.IsAllocated()) +        return result.release(); + +    Py_RETURN_NONE; +} + +SWIGEXPORT void* +LLDBSwigPythonCreateCommandObject +( +    const char *python_class_name, +    const char *session_dictionary_name, +    const lldb::DebuggerSP debugger_sp +) +{ +    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) +        Py_RETURN_NONE; + +    PyErr_Cleaner py_err_cleaner(true); +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict); + +    if (!pfunc.IsAllocated()) +        return nullptr; + +    lldb::SBDebugger debugger_sb(debugger_sp); +    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb)); +    PythonObject result = pfunc(debugger_arg, dict); + +    if (result.IsAllocated()) +        return result.release(); + +    Py_RETURN_NONE; +} + +SWIGEXPORT void* +LLDBSwigPythonCreateScriptedThreadPlan +( +    const char *python_class_name, +    const char *session_dictionary_name, +    lldb_private::StructuredDataImpl *args_impl, +    std::string &error_string, +    const lldb::ThreadPlanSP& thread_plan_sp +) +{ +    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); + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict); + +    if (!pfunc.IsAllocated()) { +        error_string.append("could not find script class: "); +        error_string.append(python_class_name); +        return nullptr; +    } + +    PythonObject tp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(tp_value)); + +    if (!tp_arg.IsAllocated()) +        Py_RETURN_NONE; + +    llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo(); +    if (!arg_info) { +        llvm::handleAllErrors( +            arg_info.takeError(), +            [&](PythonException &E) { +                error_string.append(E.ReadBacktrace()); +            }, +            [&](const llvm::ErrorInfoBase &E) { +                error_string.append(E.message()); +            }); +        Py_RETURN_NONE; +    } + +    PythonObject result = {}; +    if (arg_info.get().max_positional_args == 2) { +        if (args_impl != nullptr) { +           error_string.assign("args passed, but __init__ does not take an args dictionary"); +           Py_RETURN_NONE; +        } +        result = pfunc(tp_arg, dict); +    } else if (arg_info.get().max_positional_args >= 3) { +        lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl); +        PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value)); +        result = pfunc(tp_arg, args_arg, dict); +    } else { +        error_string.assign("wrong number of arguments in __init__, should be 2 or 3 (not including self)"); +        Py_RETURN_NONE; +    } + +    // FIXME: At this point we should check that the class we found supports all the methods +    // that we need. + +    if (result.IsAllocated()) +        return result.release(); +    Py_RETURN_NONE; +} + +SWIGEXPORT bool +LLDBSWIGPythonCallThreadPlan +( +    void *implementor, +    const char *method_name, +    lldb_private::Event *event, +    bool &got_error +) +{ +    got_error = false; + +    PyErr_Cleaner py_err_cleaner(false); +    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor)); +    auto pfunc = self.ResolveName<PythonCallable>(method_name); + +    if (!pfunc.IsAllocated()) +        return false; + +    PythonObject result; +    if (event != nullptr) +    { +        lldb::SBEvent sb_event(event); +        PythonObject event_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_event)); +        result = pfunc(event_arg); +    } +    else +        result = pfunc(); + +    if (PyErr_Occurred()) +    { +        got_error = true; +        printf ("Return value was neither false nor true for call to %s.\n", method_name); +        PyErr_Print(); +        return false; +    } + +    if (result.get() == Py_True) +        return true; +    else if (result.get() == Py_False) +        return false; + +    // Somebody returned the wrong thing... +    got_error = true; +    printf ("Wrong return value type for call to %s.\n", method_name); +    return false; +} + +SWIGEXPORT void * +LLDBSwigPythonCreateScriptedBreakpointResolver +( +    const char *python_class_name, +    const char *session_dictionary_name, +    lldb_private::StructuredDataImpl *args_impl, +    lldb::BreakpointSP &breakpoint_sp +) +{ +    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) +        Py_RETURN_NONE; + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict); + +    if (!pfunc.IsAllocated()) +        return nullptr; + +    lldb::SBBreakpoint *bkpt_value = new lldb::SBBreakpoint(breakpoint_sp); + +    PythonObject bkpt_arg(PyRefType::Owned, SBTypeToSWIGWrapper(bkpt_value)); + +    lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl); +    PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value)); + +    PythonObject result = pfunc(bkpt_arg, args_arg, dict); +    // FIXME: At this point we should check that the class we found supports all the methods +    // that we need. + +    if (result.IsAllocated()) +    { +        // Check that __callback__ is defined: +        auto callback_func = result.ResolveName<PythonCallable>("__callback__"); +        if (callback_func.IsAllocated()) +            return result.release(); +        else +            result.release(); +    } +    Py_RETURN_NONE; +} + +SWIGEXPORT unsigned int +LLDBSwigPythonCallBreakpointResolver +( +    void *implementor, +    const char *method_name, +    lldb_private::SymbolContext *sym_ctx +) +{ +    PyErr_Cleaner py_err_cleaner(false); +    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor)); +    auto pfunc = self.ResolveName<PythonCallable>(method_name); + +    if (!pfunc.IsAllocated()) +        return 0; + +    PythonObject result; +    if (sym_ctx != nullptr) { +      lldb::SBSymbolContext sb_sym_ctx(sym_ctx); +      PythonObject sym_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_sym_ctx)); +      result = pfunc(sym_ctx_arg); +    } else +      result = pfunc(); + +    if (PyErr_Occurred()) +    { +        PyErr_Print(); +        PyErr_Clear(); +        return 0; +    } + +    // The callback will return a bool, but we're need to also return ints +    // so we're squirrelling the bool through as an int...  And if you return +    // nothing, we'll continue. +    if (strcmp(method_name, "__callback__") == 0) { +        if (result.get() == Py_False) +          return 0; +        else +          return 1; +    } + +    long long ret_val = unwrapOrSetPythonException(As<long long>(result)); + +    if (PyErr_Occurred()) { +        PyErr_Print(); +        PyErr_Clear(); +        return 0; +    } + +    return ret_val; +} + +// wrapper that calls an optional instance member of an object taking no arguments +static PyObject* +LLDBSwigPython_CallOptionalMember +( +    PyObject* implementor, +    char* callee_name, +    PyObject* ret_if_not_found = Py_None, +    bool* was_found = NULL +) +{ +    PyErr_Cleaner py_err_cleaner(false); + +    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor)); +    auto pfunc = self.ResolveName<PythonCallable>(callee_name); + +    if (!pfunc.IsAllocated()) +    { +        if (was_found) +            *was_found = false; +        Py_XINCREF(ret_if_not_found); +        return ret_if_not_found; +    } + +    if (was_found) +        *was_found = true; + +    PythonObject result = pfunc(); +    return result.release(); +} + +SWIGEXPORT size_t +LLDBSwigPython_CalculateNumChildren +( +    PyObject *implementor, +    uint32_t max +) +{ +    PythonObject self(PyRefType::Borrowed, implementor); +    auto pfunc = self.ResolveName<PythonCallable>("num_children"); + +    if (!pfunc.IsAllocated()) +        return 0; + +    auto arg_info = pfunc.GetArgInfo(); +    if (!arg_info) { +        llvm::consumeError(arg_info.takeError()); +        return 0; +    } + +    size_t ret_val; +    if (arg_info.get().max_positional_args < 1) +        ret_val = unwrapOrSetPythonException(As<long long>(pfunc.Call())); +    else +        ret_val = unwrapOrSetPythonException(As<long long>(pfunc.Call(PythonInteger(max)))); + +    if (PyErr_Occurred()) +    { +        PyErr_Print(); +        PyErr_Clear(); +        return 0; +    } + +    if (arg_info.get().max_positional_args < 1) +        ret_val = std::min(ret_val, static_cast<size_t>(max)); + +    return ret_val; +} + +SWIGEXPORT PyObject* +LLDBSwigPython_GetChildAtIndex +( +    PyObject *implementor, +    uint32_t idx +) +{ +    PyErr_Cleaner py_err_cleaner(true); + +    PythonObject self(PyRefType::Borrowed, implementor); +    auto pfunc = self.ResolveName<PythonCallable>("get_child_at_index"); + +    if (!pfunc.IsAllocated()) +        return nullptr; + +    PythonObject result = pfunc(PythonInteger(idx)); + +    if (!result.IsAllocated()) +        return nullptr; + +    lldb::SBValue* sbvalue_ptr = nullptr; +    if (SWIG_ConvertPtr(result.get(), (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1) +        return nullptr; + +    if (sbvalue_ptr == nullptr) +        return nullptr; + +    return result.release(); +} + +SWIGEXPORT int +LLDBSwigPython_GetIndexOfChildWithName +( +    PyObject *implementor, +    const char* child_name +) +{ +    PyErr_Cleaner py_err_cleaner(true); + +    PythonObject self(PyRefType::Borrowed, implementor); +    auto pfunc = self.ResolveName<PythonCallable>("get_child_index"); + +    if (!pfunc.IsAllocated()) +        return UINT32_MAX; + +    llvm::Expected<PythonObject> result = pfunc.Call(PythonString(child_name)); + +    long long retval = unwrapOrSetPythonException(As<long long>(std::move(result))); + +    if (PyErr_Occurred()) {  +        PyErr_Clear(); // FIXME print this? do something else +        return UINT32_MAX; +    } + +    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; +} + +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); +    lldb::SBDebugger debugger_sb(debugger); +    lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp); + +    PyErr_Cleaner py_err_cleaner(true); +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict); + +    if (!pfunc.IsAllocated()) +        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 +    auto argc = pfunc.GetArgInfo(); +    if (!argc) { +        llvm::consumeError(argc.takeError()); +        return false; +    } +    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb)); +    PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb)); +    PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(&cmd_retobj_sb)); + +    if (argc.get().max_positional_args < 5u) +        pfunc(debugger_arg, PythonString(args), cmd_retobj_arg, dict); +    else +        pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg, dict); + +    return true; +} + +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); +    lldb::SBDebugger debugger_sb(debugger); +    lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp); + +    PyErr_Cleaner py_err_cleaner(true); + +    PythonObject self(PyRefType::Borrowed, implementor); +    auto pfunc = self.ResolveName<PythonCallable>("__call__"); + +    if (!pfunc.IsAllocated()) +        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 +    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb)); +    PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb)); +    PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(&cmd_retobj_sb)); + +    pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg); + +    return true; +} + +SWIGEXPORT void* +LLDBSWIGPythonCreateOSPlugin +( +    const char *python_class_name, +    const char *session_dictionary_name, +    const lldb::ProcessSP& process_sp +) +{ +    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) +        Py_RETURN_NONE; + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict); + +    if (!pfunc.IsAllocated()) +        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); +    PythonObject process_arg(PyRefType::Owned, SBTypeToSWIGWrapper(process_sb)); +    if (!process_arg.IsAllocated()) +        Py_RETURN_NONE; + +    auto result = pfunc(process_arg); + +    if (result.IsAllocated()) +        return result.release(); + +    Py_RETURN_NONE; +} + +SWIGEXPORT void* +LLDBSWIGPython_CreateFrameRecognizer +( +    const char *python_class_name, +    const char *session_dictionary_name +) +{ +    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) +        Py_RETURN_NONE; + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict); + +    if (!pfunc.IsAllocated()) +        Py_RETURN_NONE; + +    auto result = pfunc(); + +    if (result.IsAllocated()) +        return result.release(); + +    Py_RETURN_NONE; +} + +SWIGEXPORT PyObject* +LLDBSwigPython_GetRecognizedArguments +( +    PyObject *implementor, +    const lldb::StackFrameSP& frame_sp +) +{ +    static char callee_name[] = "get_recognized_arguments"; + +    lldb::SBFrame frame_sb(frame_sp); +    PyObject *arg = SBTypeToSWIGWrapper(frame_sb); + +    PythonString str(callee_name); +    PyObject* result = PyObject_CallMethodObjArgs(implementor, str.get(), arg, +                                                  NULL); +    return result; +} + +SWIGEXPORT void* +LLDBSWIGPython_GetDynamicSetting (void* module, const char* setting, const lldb::TargetSP& target_sp) +{ +    if (!module || !setting) +        Py_RETURN_NONE; + +    PyErr_Cleaner py_err_cleaner(true); +    PythonObject py_module(PyRefType::Borrowed, (PyObject *)module); +    auto pfunc = py_module.ResolveName<PythonCallable>("get_dynamic_setting"); + +    if (!pfunc.IsAllocated()) +        Py_RETURN_NONE; + +    lldb::SBTarget target_sb(target_sp); +    PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(target_sb)); +    auto result = pfunc(target_arg, PythonString(setting)); + +    return result.release(); +} + +SWIGEXPORT bool +LLDBSWIGPythonRunScriptKeywordProcess +(const char* python_function_name, +const char* session_dictionary_name, +lldb::ProcessSP& process, +std::string& output) + +{ +    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) +        return false; + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict); + +    if (!pfunc.IsAllocated()) +        return false; + +    lldb::SBProcess process_sb(process); +    PythonObject process_arg(PyRefType::Owned, SBTypeToSWIGWrapper(process_sb)); +    auto result = pfunc(process_arg, dict); + +    output = result.Str().GetString().str(); + +    return true; +} + +SWIGEXPORT bool +LLDBSWIGPythonRunScriptKeywordThread +(const char* python_function_name, +const char* session_dictionary_name, +lldb::ThreadSP& thread, +std::string& output) + +{ +    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) +        return false; + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict); + +    if (!pfunc.IsAllocated()) +        return false; + +    lldb::SBThread thread_sb(thread); +    PythonObject thread_arg(PyRefType::Owned, SBTypeToSWIGWrapper(thread_sb)); +    auto result = pfunc(thread_arg, dict); + +    output = result.Str().GetString().str(); + +    return true; +} + +SWIGEXPORT bool +LLDBSWIGPythonRunScriptKeywordTarget +(const char* python_function_name, +const char* session_dictionary_name, +lldb::TargetSP& target, +std::string& output) + +{ +    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) +        return false; + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name,dict); + +    if (!pfunc.IsAllocated()) +        return false; + +    lldb::SBTarget target_sb(target); +    PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(target_sb)); +    auto result = pfunc(target_arg, dict); + +    output = result.Str().GetString().str(); + +    return true; +} + +SWIGEXPORT bool +LLDBSWIGPythonRunScriptKeywordFrame +(const char* python_function_name, +const char* session_dictionary_name, +lldb::StackFrameSP& frame, +std::string& output) + +{ +    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) +        return false; + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name,dict); + +    if (!pfunc.IsAllocated()) +        return false; + +    lldb::SBFrame frame_sb(frame); +    PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(frame_sb)); +    auto result = pfunc(frame_arg, dict); + +    output = result.Str().GetString().str(); + +    return true; +} + +SWIGEXPORT bool +LLDBSWIGPythonRunScriptKeywordValue +(const char* python_function_name, +const char* session_dictionary_name, +lldb::ValueObjectSP& value, +std::string& output) + +{ +    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) +        return false; + +    PyErr_Cleaner py_err_cleaner(true); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict); + +    if (!pfunc.IsAllocated()) +        return false; + +    lldb::SBValue value_sb(value); +    PythonObject value_arg(PyRefType::Owned, SBTypeToSWIGWrapper(value_sb)); +    auto result = pfunc(value_arg, dict); + +    output = result.Str().GetString().str(); + +    return true; +} + +SWIGEXPORT bool +LLDBSwigPythonCallModuleInit +( +    const char *python_module_name, +    const char *session_dictionary_name, +    lldb::DebuggerSP& 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); + +    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name); +    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict); + +    // This method is optional and need not exist.  So if we don't find it, +    // it's actually a success, not a failure. +    if (!pfunc.IsAllocated()) +        return true; + +    lldb::SBDebugger debugger_sb(debugger); +    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb)); +    pfunc(debugger_arg, dict); + +    return true; +} +%} + + +%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 *result = PyObject_CallFunction(reinterpret_cast<PyObject*>(baton), const_cast<char*>("s"), str); +	  Py_XDECREF(result); +      SWIG_PYTHON_THREAD_END_BLOCK; +    } +} +%}  | 
