1%header %{
2
3template <typename T>
4PyObject *
5SBTypeToSWIGWrapper (T* item);
6
7class PyErr_Cleaner
8{
9public:
10    PyErr_Cleaner(bool print=false) :
11    m_print(print)
12    {
13    }
14
15    ~PyErr_Cleaner()
16    {
17        if (PyErr_Occurred())
18        {
19            if(m_print && !PyErr_ExceptionMatches(PyExc_SystemExit))
20                PyErr_Print();
21            PyErr_Clear();
22        }
23    }
24
25private:
26    bool m_print;
27};
28
29%}
30
31%wrapper %{
32
33// resolve a dotted Python name in the form
34// foo.bar.baz.Foobar to an actual Python object
35// if pmodule is NULL, the __main__ module will be used
36// as the starting point for the search
37
38
39// This function is called by lldb_private::ScriptInterpreterPython::BreakpointCallbackFunction(...)
40// and is used when a script command is attached to a breakpoint for execution.
41
42#pragma clang diagnostic push
43#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
44
45// Disable warning C4190: 'LLDBSwigPythonBreakpointCallbackFunction' has
46// C-linkage specified, but returns UDT 'llvm::Expected<bool>' which is
47// incompatible with C
48#if _MSC_VER
49#pragma warning (push)
50#pragma warning (disable : 4190)
51#endif
52
53SWIGEXPORT llvm::Expected<bool>
54LLDBSwigPythonBreakpointCallbackFunction
55(
56    const char *python_function_name,
57    const char *session_dictionary_name,
58    const lldb::StackFrameSP& frame_sp,
59    const lldb::BreakpointLocationSP& bp_loc_sp,
60    lldb_private::StructuredDataImpl *args_impl
61)
62{
63    using namespace llvm;
64
65    lldb::SBFrame sb_frame (frame_sp);
66    lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp);
67
68    PyErr_Cleaner py_err_cleaner(true);
69    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
70    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
71
72    unsigned max_positional_args;
73    if (auto arg_info = pfunc.GetArgInfo())
74        max_positional_args = arg_info.get().max_positional_args;
75    else
76        return arg_info.takeError();
77
78    PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame));
79    PythonObject bp_loc_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_bp_loc));
80
81    auto result = [&] () -> Expected<PythonObject> {
82        // If the called function doesn't take extra_args, drop them here:
83        if (max_positional_args < 4) {
84            return pfunc.Call(frame_arg, bp_loc_arg, dict);
85        } else {
86            lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
87            PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
88            return pfunc.Call(frame_arg, bp_loc_arg, args_arg, dict);
89        }
90    } ();
91
92    if (!result)
93        return result.takeError();
94
95    // Only False counts as false!
96    return result.get().get() != Py_False;
97}
98
99#if _MSC_VER
100#pragma warning (pop)
101#endif
102
103#pragma clang diagnostic pop
104
105// This function is called by lldb_private::ScriptInterpreterPython::WatchpointCallbackFunction(...)
106// and is used when a script command is attached to a watchpoint for execution.
107
108SWIGEXPORT bool
109LLDBSwigPythonWatchpointCallbackFunction
110(
111    const char *python_function_name,
112    const char *session_dictionary_name,
113    const lldb::StackFrameSP& frame_sp,
114    const lldb::WatchpointSP& wp_sp
115)
116{
117    lldb::SBFrame sb_frame (frame_sp);
118    lldb::SBWatchpoint sb_wp(wp_sp);
119
120    bool stop_at_watchpoint = true;
121
122    PyErr_Cleaner py_err_cleaner(true);
123
124    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
125    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
126
127    if (!pfunc.IsAllocated())
128        return stop_at_watchpoint;
129
130    PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_frame));
131    PythonObject wp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_wp));
132    PythonObject result = pfunc(frame_arg, wp_arg, dict);
133
134    if (result.get() == Py_False)
135        stop_at_watchpoint = false;
136
137    return stop_at_watchpoint;
138}
139
140SWIGEXPORT bool
141LLDBSwigPythonCallTypeScript
142(
143    const char *python_function_name,
144    const void *session_dictionary,
145    const lldb::ValueObjectSP& valobj_sp,
146    void** pyfunct_wrapper,
147    const lldb::TypeSummaryOptionsSP& options_sp,
148    std::string& retval
149)
150{
151    lldb::SBValue sb_value (valobj_sp);
152    lldb::SBTypeSummaryOptions sb_options(options_sp.get());
153
154    retval.clear();
155
156    if (!python_function_name || !session_dictionary)
157        return false;
158
159    PyObject *pfunc_impl = nullptr;
160
161    if (pyfunct_wrapper && *pyfunct_wrapper && PyFunction_Check (*pyfunct_wrapper))
162    {
163        pfunc_impl = (PyObject*)(*pyfunct_wrapper);
164        if (pfunc_impl->ob_refcnt == 1)
165        {
166            Py_XDECREF(pfunc_impl);
167            pfunc_impl = NULL;
168        }
169    }
170
171    PyObject *py_dict = (PyObject*)session_dictionary;
172    if (!PythonDictionary::Check(py_dict))
173        return true;
174
175    PythonDictionary dict(PyRefType::Borrowed, py_dict);
176
177    PyErr_Cleaner pyerr_cleanup(true);  // show Python errors
178
179    PythonCallable pfunc(PyRefType::Borrowed, pfunc_impl);
180
181    if (!pfunc.IsAllocated())
182    {
183        pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
184        if (!pfunc.IsAllocated())
185            return false;
186
187        if (pyfunct_wrapper)
188        {
189            *pyfunct_wrapper = pfunc.get();
190            Py_XINCREF(pfunc.get());
191        }
192    }
193
194    PythonObject result;
195    auto argc = pfunc.GetArgInfo();
196    if (!argc) {
197        llvm::consumeError(argc.takeError());
198        return false;
199    }
200
201    PythonObject value_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_value));
202    PythonObject options_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_options));
203
204    if (argc.get().max_positional_args < 3)
205        result = pfunc(value_arg,dict);
206    else
207        result = pfunc(value_arg,dict,options_arg);
208
209    retval = result.Str().GetString().str();
210
211    return true;
212}
213
214SWIGEXPORT void*
215LLDBSwigPythonCreateSyntheticProvider
216(
217    const char *python_class_name,
218    const char *session_dictionary_name,
219    const lldb::ValueObjectSP& valobj_sp
220)
221{
222    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
223        Py_RETURN_NONE;
224
225    PyErr_Cleaner py_err_cleaner(true);
226
227    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
228    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name,dict);
229
230    if (!pfunc.IsAllocated())
231        Py_RETURN_NONE;
232
233    // I do not want the SBValue to be deallocated when going out of scope because python
234    // has ownership of it and will manage memory for this object by itself
235    lldb::SBValue *sb_value = new lldb::SBValue(valobj_sp);
236    sb_value->SetPreferSyntheticValue(false);
237
238    PythonObject val_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_value));
239    if (!val_arg.IsAllocated())
240        Py_RETURN_NONE;
241
242    PythonObject result = pfunc(val_arg, dict);
243
244    if (result.IsAllocated())
245        return result.release();
246
247    Py_RETURN_NONE;
248}
249
250SWIGEXPORT void*
251LLDBSwigPythonCreateCommandObject
252(
253    const char *python_class_name,
254    const char *session_dictionary_name,
255    const lldb::DebuggerSP debugger_sp
256)
257{
258    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
259        Py_RETURN_NONE;
260
261    PyErr_Cleaner py_err_cleaner(true);
262    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
263    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
264
265    if (!pfunc.IsAllocated())
266        return nullptr;
267
268    lldb::SBDebugger debugger_sb(debugger_sp);
269    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
270    PythonObject result = pfunc(debugger_arg, dict);
271
272    if (result.IsAllocated())
273        return result.release();
274
275    Py_RETURN_NONE;
276}
277
278SWIGEXPORT void*
279LLDBSwigPythonCreateScriptedProcess
280(
281    const char *python_class_name,
282    const char *session_dictionary_name,
283    const lldb::TargetSP& target_sp,
284    lldb_private::StructuredDataImpl *args_impl,
285    std::string &error_string
286)
287{
288    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
289        Py_RETURN_NONE;
290
291    PyErr_Cleaner py_err_cleaner(true);
292
293    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
294    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
295
296    if (!pfunc.IsAllocated()) {
297        error_string.append("could not find script class: ");
298        error_string.append(python_class_name);
299        return nullptr;
300    }
301
302    // I do not want the SBTarget to be deallocated when going out of scope
303    // because python has ownership of it and will manage memory for this
304    // object by itself
305    PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBTarget(target_sp)));
306
307    if (!target_arg.IsAllocated())
308        Py_RETURN_NONE;
309
310    llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
311    if (!arg_info) {
312        llvm::handleAllErrors(
313            arg_info.takeError(),
314            [&](PythonException &E) {
315                error_string.append(E.ReadBacktrace());
316            },
317            [&](const llvm::ErrorInfoBase &E) {
318                error_string.append(E.message());
319            });
320        Py_RETURN_NONE;
321    }
322
323    PythonObject result = {};
324    if (arg_info.get().max_positional_args == 2) {
325        if (args_impl != nullptr) {
326           error_string.assign("args passed, but __init__ does not take an args dictionary");
327           Py_RETURN_NONE;
328        }
329        result = pfunc(target_arg, dict);
330    } else if (arg_info.get().max_positional_args >= 3) {
331        PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBStructuredData(args_impl)));
332        result = pfunc(target_arg, args_arg, dict);
333    } else {
334        error_string.assign("wrong number of arguments in __init__, should be 2 or 3 (not including self)");
335        Py_RETURN_NONE;
336    }
337
338    if (result.IsAllocated())
339        return result.release();
340    Py_RETURN_NONE;
341}
342
343SWIGEXPORT void*
344LLDBSwigPythonCreateScriptedThread
345(
346    const char *python_class_name,
347    const char *session_dictionary_name,
348    const lldb::TargetSP& target_sp,
349    std::string &error_string
350)
351{
352    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
353        Py_RETURN_NONE;
354
355    PyErr_Cleaner py_err_cleaner(true);
356
357    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
358    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
359
360    if (!pfunc.IsAllocated()) {
361        error_string.append("could not find script class: ");
362        error_string.append(python_class_name);
363        return nullptr;
364    }
365
366    // I do not want the SBTarget to be deallocated when going out of scope
367    // because python has ownership of it and will manage memory for this
368    // object by itself
369    PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBTarget(target_sp)));
370
371    if (!target_arg.IsAllocated())
372        Py_RETURN_NONE;
373
374    llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
375    if (!arg_info) {
376        llvm::handleAllErrors(
377            arg_info.takeError(),
378            [&](PythonException &E) {
379                error_string.append(E.ReadBacktrace());
380            },
381            [&](const llvm::ErrorInfoBase &E) {
382                error_string.append(E.message());
383            });
384        Py_RETURN_NONE;
385    }
386
387    PythonObject result = {};
388    if (arg_info.get().max_positional_args == 1) {
389        result = pfunc(target_arg);
390    } else {
391        error_string.assign("wrong number of arguments in __init__, should be 2 or 3 (not including self)");
392        Py_RETURN_NONE;
393    }
394
395    if (result.IsAllocated())
396        return result.release();
397    Py_RETURN_NONE;
398}
399
400SWIGEXPORT void*
401LLDBSwigPythonCreateScriptedThreadPlan
402(
403    const char *python_class_name,
404    const char *session_dictionary_name,
405    lldb_private::StructuredDataImpl *args_impl,
406    std::string &error_string,
407    const lldb::ThreadPlanSP& thread_plan_sp
408)
409{
410    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
411        Py_RETURN_NONE;
412
413
414    PyErr_Cleaner py_err_cleaner(true);
415
416    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
417    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
418
419    if (!pfunc.IsAllocated()) {
420        error_string.append("could not find script class: ");
421        error_string.append(python_class_name);
422        return nullptr;
423    }
424
425    // I do not want the SBThreadPlan to be deallocated when going out of scope
426    // because python has ownership of it and will manage memory for this
427    // object by itself
428    PythonObject tp_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBThreadPlan(thread_plan_sp)));
429
430    if (!tp_arg.IsAllocated())
431        Py_RETURN_NONE;
432
433    llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
434    if (!arg_info) {
435        llvm::handleAllErrors(
436            arg_info.takeError(),
437            [&](PythonException &E) {
438                error_string.append(E.ReadBacktrace());
439            },
440            [&](const llvm::ErrorInfoBase &E) {
441                error_string.append(E.message());
442            });
443        Py_RETURN_NONE;
444    }
445
446    PythonObject result = {};
447    if (arg_info.get().max_positional_args == 2) {
448        if (args_impl != nullptr) {
449           error_string.assign("args passed, but __init__ does not take an args dictionary");
450           Py_RETURN_NONE;
451        }
452        result = pfunc(tp_arg, dict);
453    } else if (arg_info.get().max_positional_args >= 3) {
454        PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(new lldb::SBStructuredData(args_impl)));
455        result = pfunc(tp_arg, args_arg, dict);
456    } else {
457        error_string.assign("wrong number of arguments in __init__, should be 2 or 3 (not including self)");
458        Py_RETURN_NONE;
459    }
460
461    // FIXME: At this point we should check that the class we found supports all the methods
462    // that we need.
463
464    if (result.IsAllocated())
465        return result.release();
466    Py_RETURN_NONE;
467}
468
469SWIGEXPORT bool
470LLDBSWIGPythonCallThreadPlan
471(
472    void *implementor,
473    const char *method_name,
474    lldb_private::Event *event,
475    bool &got_error
476)
477{
478    got_error = false;
479
480    PyErr_Cleaner py_err_cleaner(false);
481    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
482    auto pfunc = self.ResolveName<PythonCallable>(method_name);
483
484    if (!pfunc.IsAllocated())
485        return false;
486
487    PythonObject result;
488    if (event != nullptr)
489    {
490        lldb::SBEvent sb_event(event);
491        PythonObject event_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_event));
492        result = pfunc(event_arg);
493    }
494    else
495        result = pfunc();
496
497    if (PyErr_Occurred())
498    {
499        got_error = true;
500        printf ("Return value was neither false nor true for call to %s.\n", method_name);
501        PyErr_Print();
502        return false;
503    }
504
505    if (result.get() == Py_True)
506        return true;
507    else if (result.get() == Py_False)
508        return false;
509
510    // Somebody returned the wrong thing...
511    got_error = true;
512    printf ("Wrong return value type for call to %s.\n", method_name);
513    return false;
514}
515
516SWIGEXPORT void *
517LLDBSwigPythonCreateScriptedBreakpointResolver
518(
519    const char *python_class_name,
520    const char *session_dictionary_name,
521    lldb_private::StructuredDataImpl *args_impl,
522    lldb::BreakpointSP &breakpoint_sp
523)
524{
525    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
526        Py_RETURN_NONE;
527
528    PyErr_Cleaner py_err_cleaner(true);
529
530    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
531    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
532
533    if (!pfunc.IsAllocated())
534        return nullptr;
535
536    lldb::SBBreakpoint *bkpt_value = new lldb::SBBreakpoint(breakpoint_sp);
537
538    PythonObject bkpt_arg(PyRefType::Owned, SBTypeToSWIGWrapper(bkpt_value));
539
540    lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
541    PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
542
543    PythonObject result = pfunc(bkpt_arg, args_arg, dict);
544    // FIXME: At this point we should check that the class we found supports all the methods
545    // that we need.
546
547    if (result.IsAllocated())
548    {
549        // Check that __callback__ is defined:
550        auto callback_func = result.ResolveName<PythonCallable>("__callback__");
551        if (callback_func.IsAllocated())
552            return result.release();
553        else
554            result.release();
555    }
556    Py_RETURN_NONE;
557}
558
559SWIGEXPORT unsigned int
560LLDBSwigPythonCallBreakpointResolver
561(
562    void *implementor,
563    const char *method_name,
564    lldb_private::SymbolContext *sym_ctx
565)
566{
567    PyErr_Cleaner py_err_cleaner(false);
568    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
569    auto pfunc = self.ResolveName<PythonCallable>(method_name);
570
571    if (!pfunc.IsAllocated())
572        return 0;
573
574    PythonObject result;
575    if (sym_ctx != nullptr) {
576      lldb::SBSymbolContext sb_sym_ctx(sym_ctx);
577      PythonObject sym_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_sym_ctx));
578      result = pfunc(sym_ctx_arg);
579    } else
580      result = pfunc();
581
582    if (PyErr_Occurred())
583    {
584        PyErr_Print();
585        PyErr_Clear();
586        return 0;
587    }
588
589    // The callback will return a bool, but we're need to also return ints
590    // so we're squirrelling the bool through as an int...  And if you return
591    // nothing, we'll continue.
592    if (strcmp(method_name, "__callback__") == 0) {
593        if (result.get() == Py_False)
594          return 0;
595        else
596          return 1;
597    }
598
599    long long ret_val = unwrapOrSetPythonException(As<long long>(result));
600
601    if (PyErr_Occurred()) {
602        PyErr_Print();
603        PyErr_Clear();
604        return 0;
605    }
606
607    return ret_val;
608}
609
610SWIGEXPORT void *
611LLDBSwigPythonCreateScriptedStopHook
612(
613    lldb::TargetSP target_sp,
614    const char *python_class_name,
615    const char *session_dictionary_name,
616    lldb_private::StructuredDataImpl *args_impl,
617    Status &error
618)
619{
620    if (python_class_name == NULL || python_class_name[0] == '\0') {
621        error.SetErrorString("Empty class name.");
622        Py_RETURN_NONE;
623    }
624    if (!session_dictionary_name) {
625      error.SetErrorString("No session dictionary");
626      Py_RETURN_NONE;
627    }
628
629    PyErr_Cleaner py_err_cleaner(true);
630
631    auto dict =
632        PythonModule::MainModule().ResolveName<PythonDictionary>(
633            session_dictionary_name);
634    auto pfunc =
635        PythonObject::ResolveNameWithDictionary<PythonCallable>(
636            python_class_name, dict);
637
638    if (!pfunc.IsAllocated()) {
639        error.SetErrorStringWithFormat("Could not find class: %s.",
640                                       python_class_name);
641        return nullptr;
642    }
643
644    lldb::SBTarget *target_val
645        = new lldb::SBTarget(target_sp);
646
647    PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(target_val));
648
649    lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
650    PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
651
652    PythonObject result = pfunc(target_arg, args_arg, dict);
653
654    if (result.IsAllocated())
655    {
656        // Check that the handle_stop callback is defined:
657        auto callback_func = result.ResolveName<PythonCallable>("handle_stop");
658        if (callback_func.IsAllocated()) {
659          if (auto args_info = callback_func.GetArgInfo()) {
660            size_t num_args = (*args_info).max_positional_args;
661            if (num_args != 2) {
662              error.SetErrorStringWithFormat("Wrong number of args for "
663              "handle_stop callback, should be 2 (excluding self), got: %zu",
664              num_args);
665              Py_RETURN_NONE;
666            } else
667              return result.release();
668          } else {
669            error.SetErrorString("Couldn't get num arguments for handle_stop "
670                                 "callback.");
671            Py_RETURN_NONE;
672          }
673          return result.release();
674        }
675        else {
676          error.SetErrorStringWithFormat("Class \"%s\" is missing the required "
677                                         "handle_stop callback.",
678                                         python_class_name);
679          result.release();
680        }
681    }
682    Py_RETURN_NONE;
683}
684
685SWIGEXPORT bool
686LLDBSwigPythonStopHookCallHandleStop
687(
688    void *implementor,
689    lldb::ExecutionContextRefSP exc_ctx_sp,
690    lldb::StreamSP stream
691)
692{
693    // handle_stop will return a bool with the meaning "should_stop"...
694    // If you return nothing we'll assume we are going to stop.
695    // Also any errors should return true, since we should stop on error.
696
697    PyErr_Cleaner py_err_cleaner(false);
698    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
699    auto pfunc = self.ResolveName<PythonCallable>("handle_stop");
700
701    if (!pfunc.IsAllocated())
702        return true;
703
704    PythonObject result;
705    lldb::SBExecutionContext sb_exc_ctx(exc_ctx_sp);
706    PythonObject exc_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_exc_ctx));
707    lldb::SBStream sb_stream;
708    PythonObject sb_stream_arg(PyRefType::Owned,
709                               SBTypeToSWIGWrapper(sb_stream));
710    result = pfunc(exc_ctx_arg, sb_stream_arg);
711
712    if (PyErr_Occurred())
713    {
714        stream->PutCString("Python error occurred handling stop-hook.");
715        PyErr_Print();
716        PyErr_Clear();
717        return true;
718    }
719
720    // Now add the result to the output stream.  SBStream only
721    // makes an internally help StreamString which I can't interpose, so I
722    // have to copy it over here.
723    stream->PutCString(sb_stream.GetData());
724
725    if (result.get() == Py_False)
726      return false;
727    else
728      return true;
729}
730
731// wrapper that calls an optional instance member of an object taking no arguments
732static PyObject*
733LLDBSwigPython_CallOptionalMember
734(
735    PyObject* implementor,
736    char* callee_name,
737    PyObject* ret_if_not_found = Py_None,
738    bool* was_found = NULL
739)
740{
741    PyErr_Cleaner py_err_cleaner(false);
742
743    PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
744    auto pfunc = self.ResolveName<PythonCallable>(callee_name);
745
746    if (!pfunc.IsAllocated())
747    {
748        if (was_found)
749            *was_found = false;
750        Py_XINCREF(ret_if_not_found);
751        return ret_if_not_found;
752    }
753
754    if (was_found)
755        *was_found = true;
756
757    PythonObject result = pfunc();
758    return result.release();
759}
760
761SWIGEXPORT size_t
762LLDBSwigPython_CalculateNumChildren
763(
764    PyObject *implementor,
765    uint32_t max
766)
767{
768    PythonObject self(PyRefType::Borrowed, implementor);
769    auto pfunc = self.ResolveName<PythonCallable>("num_children");
770
771    if (!pfunc.IsAllocated())
772        return 0;
773
774    auto arg_info = pfunc.GetArgInfo();
775    if (!arg_info) {
776        llvm::consumeError(arg_info.takeError());
777        return 0;
778    }
779
780    size_t ret_val;
781    if (arg_info.get().max_positional_args < 1)
782        ret_val = unwrapOrSetPythonException(As<long long>(pfunc.Call()));
783    else
784        ret_val = unwrapOrSetPythonException(As<long long>(pfunc.Call(PythonInteger(max))));
785
786    if (PyErr_Occurred())
787    {
788        PyErr_Print();
789        PyErr_Clear();
790        return 0;
791    }
792
793    if (arg_info.get().max_positional_args < 1)
794        ret_val = std::min(ret_val, static_cast<size_t>(max));
795
796    return ret_val;
797}
798
799SWIGEXPORT PyObject*
800LLDBSwigPython_GetChildAtIndex
801(
802    PyObject *implementor,
803    uint32_t idx
804)
805{
806    PyErr_Cleaner py_err_cleaner(true);
807
808    PythonObject self(PyRefType::Borrowed, implementor);
809    auto pfunc = self.ResolveName<PythonCallable>("get_child_at_index");
810
811    if (!pfunc.IsAllocated())
812        return nullptr;
813
814    PythonObject result = pfunc(PythonInteger(idx));
815
816    if (!result.IsAllocated())
817        return nullptr;
818
819    lldb::SBValue* sbvalue_ptr = nullptr;
820    if (SWIG_ConvertPtr(result.get(), (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)
821        return nullptr;
822
823    if (sbvalue_ptr == nullptr)
824        return nullptr;
825
826    return result.release();
827}
828
829SWIGEXPORT int
830LLDBSwigPython_GetIndexOfChildWithName
831(
832    PyObject *implementor,
833    const char* child_name
834)
835{
836    PyErr_Cleaner py_err_cleaner(true);
837
838    PythonObject self(PyRefType::Borrowed, implementor);
839    auto pfunc = self.ResolveName<PythonCallable>("get_child_index");
840
841    if (!pfunc.IsAllocated())
842        return UINT32_MAX;
843
844    llvm::Expected<PythonObject> result = pfunc.Call(PythonString(child_name));
845
846    long long retval = unwrapOrSetPythonException(As<long long>(std::move(result)));
847
848    if (PyErr_Occurred()) {
849        PyErr_Clear(); // FIXME print this? do something else
850        return UINT32_MAX;
851    }
852
853    if (retval >= 0)
854        return (uint32_t)retval;
855
856    return UINT32_MAX;
857}
858
859SWIGEXPORT bool
860LLDBSwigPython_UpdateSynthProviderInstance
861(
862    PyObject *implementor
863)
864{
865    bool ret_val = false;
866
867    static char callee_name[] = "update";
868
869    PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name);
870
871    if (py_return == Py_True)
872        ret_val = true;
873
874    Py_XDECREF(py_return);
875
876    return ret_val;
877}
878
879SWIGEXPORT bool
880LLDBSwigPython_MightHaveChildrenSynthProviderInstance
881(
882    PyObject *implementor
883)
884{
885    bool ret_val = false;
886
887    static char callee_name[] = "has_children";
888
889    PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_True);
890
891    if (py_return == Py_True)
892        ret_val = true;
893
894    Py_XDECREF(py_return);
895
896    return ret_val;
897}
898
899SWIGEXPORT PyObject*
900LLDBSwigPython_GetValueSynthProviderInstance
901(
902    PyObject *implementor
903)
904{
905    PyObject* ret_val = nullptr;
906
907    static char callee_name[] = "get_value";
908
909    PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_None);
910
911    if (py_return == Py_None || py_return == nullptr)
912        ret_val = nullptr;
913
914    lldb::SBValue* sbvalue_ptr = NULL;
915
916    if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)
917        ret_val = nullptr;
918    else if (sbvalue_ptr == NULL)
919        ret_val = nullptr;
920    else
921        ret_val = py_return;
922
923    Py_XDECREF(py_return);
924    return ret_val;
925}
926
927SWIGEXPORT void*
928LLDBSWIGPython_CastPyObjectToSBData
929(
930    PyObject* data
931)
932{
933    lldb::SBData* sb_ptr = nullptr;
934
935    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBData, 0);
936
937    if (valid_cast == -1)
938        return NULL;
939
940    return sb_ptr;
941}
942
943
944SWIGEXPORT void*
945LLDBSWIGPython_CastPyObjectToSBError
946(
947    PyObject* data
948)
949{
950    lldb::SBError* sb_ptr = nullptr;
951
952    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBError, 0);
953
954    if (valid_cast == -1)
955        return NULL;
956
957    return sb_ptr;
958}
959
960
961SWIGEXPORT void*
962LLDBSWIGPython_CastPyObjectToSBValue
963(
964    PyObject* data
965)
966{
967    lldb::SBValue* sb_ptr = NULL;
968
969    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBValue, 0);
970
971    if (valid_cast == -1)
972        return NULL;
973
974    return sb_ptr;
975}
976
977SWIGEXPORT void*
978LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo
979(
980    PyObject* data
981)
982{
983    lldb::SBMemoryRegionInfo* sb_ptr = NULL;
984
985    int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBMemoryRegionInfo, 0);
986
987    if (valid_cast == -1)
988        return NULL;
989
990    return sb_ptr;
991}
992
993SWIGEXPORT bool
994LLDBSwigPythonCallCommand
995(
996    const char *python_function_name,
997    const char *session_dictionary_name,
998    lldb::DebuggerSP& debugger,
999    const char* args,
1000    lldb_private::CommandReturnObject& cmd_retobj,
1001    lldb::ExecutionContextRefSP exe_ctx_ref_sp
1002)
1003{
1004    lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj);
1005    lldb::SBDebugger debugger_sb(debugger);
1006    lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp);
1007
1008    PyErr_Cleaner py_err_cleaner(true);
1009    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
1010    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
1011
1012    if (!pfunc.IsAllocated())
1013        return false;
1014
1015    // pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you
1016    // see comment above for SBCommandReturnObjectReleaser for further details
1017    auto argc = pfunc.GetArgInfo();
1018    if (!argc) {
1019        llvm::consumeError(argc.takeError());
1020        return false;
1021    }
1022    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
1023    PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb));
1024    PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(&cmd_retobj_sb));
1025
1026    if (argc.get().max_positional_args < 5u)
1027        pfunc(debugger_arg, PythonString(args), cmd_retobj_arg, dict);
1028    else
1029        pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg, dict);
1030
1031    return true;
1032}
1033
1034SWIGEXPORT bool
1035LLDBSwigPythonCallCommandObject
1036(
1037    PyObject *implementor,
1038    lldb::DebuggerSP& debugger,
1039    const char* args,
1040    lldb_private::CommandReturnObject& cmd_retobj,
1041    lldb::ExecutionContextRefSP exe_ctx_ref_sp
1042)
1043{
1044    lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj);
1045    lldb::SBDebugger debugger_sb(debugger);
1046    lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp);
1047
1048    PyErr_Cleaner py_err_cleaner(true);
1049
1050    PythonObject self(PyRefType::Borrowed, implementor);
1051    auto pfunc = self.ResolveName<PythonCallable>("__call__");
1052
1053    if (!pfunc.IsAllocated())
1054        return false;
1055
1056    // pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you
1057    // see comment above for SBCommandReturnObjectReleaser for further details
1058    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
1059    PythonObject exe_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(exe_ctx_sb));
1060    PythonObject cmd_retobj_arg(PyRefType::Owned, SBTypeToSWIGWrapper(&cmd_retobj_sb));
1061
1062    pfunc(debugger_arg, PythonString(args), exe_ctx_arg, cmd_retobj_arg);
1063
1064    return true;
1065}
1066
1067SWIGEXPORT void*
1068LLDBSWIGPythonCreateOSPlugin
1069(
1070    const char *python_class_name,
1071    const char *session_dictionary_name,
1072    const lldb::ProcessSP& process_sp
1073)
1074{
1075    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
1076        Py_RETURN_NONE;
1077
1078    PyErr_Cleaner py_err_cleaner(true);
1079
1080    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
1081    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
1082
1083    if (!pfunc.IsAllocated())
1084        Py_RETURN_NONE;
1085
1086    // I do not want the SBProcess to be deallocated when going out of scope because python
1087    // has ownership of it and will manage memory for this object by itself
1088    lldb::SBProcess *process_sb = new lldb::SBProcess(process_sp);
1089    PythonObject process_arg(PyRefType::Owned, SBTypeToSWIGWrapper(process_sb));
1090    if (!process_arg.IsAllocated())
1091        Py_RETURN_NONE;
1092
1093    auto result = pfunc(process_arg);
1094
1095    if (result.IsAllocated())
1096        return result.release();
1097
1098    Py_RETURN_NONE;
1099}
1100
1101SWIGEXPORT void*
1102LLDBSWIGPython_CreateFrameRecognizer
1103(
1104    const char *python_class_name,
1105    const char *session_dictionary_name
1106)
1107{
1108    if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
1109        Py_RETURN_NONE;
1110
1111    PyErr_Cleaner py_err_cleaner(true);
1112
1113    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
1114    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
1115
1116    if (!pfunc.IsAllocated())
1117        Py_RETURN_NONE;
1118
1119    auto result = pfunc();
1120
1121    if (result.IsAllocated())
1122        return result.release();
1123
1124    Py_RETURN_NONE;
1125}
1126
1127SWIGEXPORT PyObject*
1128LLDBSwigPython_GetRecognizedArguments
1129(
1130    PyObject *implementor,
1131    const lldb::StackFrameSP& frame_sp
1132)
1133{
1134    static char callee_name[] = "get_recognized_arguments";
1135
1136    lldb::SBFrame frame_sb(frame_sp);
1137    PyObject *arg = SBTypeToSWIGWrapper(frame_sb);
1138
1139    PythonString str(callee_name);
1140    PyObject* result = PyObject_CallMethodObjArgs(implementor, str.get(), arg,
1141                                                  NULL);
1142    return result;
1143}
1144
1145SWIGEXPORT void*
1146LLDBSWIGPython_GetDynamicSetting (void* module, const char* setting, const lldb::TargetSP& target_sp)
1147{
1148    if (!module || !setting)
1149        Py_RETURN_NONE;
1150
1151    PyErr_Cleaner py_err_cleaner(true);
1152    PythonObject py_module(PyRefType::Borrowed, (PyObject *)module);
1153    auto pfunc = py_module.ResolveName<PythonCallable>("get_dynamic_setting");
1154
1155    if (!pfunc.IsAllocated())
1156        Py_RETURN_NONE;
1157
1158    lldb::SBTarget target_sb(target_sp);
1159    PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(target_sb));
1160    auto result = pfunc(target_arg, PythonString(setting));
1161
1162    return result.release();
1163}
1164
1165SWIGEXPORT bool
1166LLDBSWIGPythonRunScriptKeywordProcess
1167(const char* python_function_name,
1168const char* session_dictionary_name,
1169lldb::ProcessSP& process,
1170std::string& output)
1171
1172{
1173    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
1174        return false;
1175
1176    PyErr_Cleaner py_err_cleaner(true);
1177
1178    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
1179    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
1180
1181    if (!pfunc.IsAllocated())
1182        return false;
1183
1184    lldb::SBProcess process_sb(process);
1185    PythonObject process_arg(PyRefType::Owned, SBTypeToSWIGWrapper(process_sb));
1186    auto result = pfunc(process_arg, dict);
1187
1188    output = result.Str().GetString().str();
1189
1190    return true;
1191}
1192
1193SWIGEXPORT bool
1194LLDBSWIGPythonRunScriptKeywordThread
1195(const char* python_function_name,
1196const char* session_dictionary_name,
1197lldb::ThreadSP& thread,
1198std::string& output)
1199
1200{
1201    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
1202        return false;
1203
1204    PyErr_Cleaner py_err_cleaner(true);
1205
1206    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
1207    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
1208
1209    if (!pfunc.IsAllocated())
1210        return false;
1211
1212    lldb::SBThread thread_sb(thread);
1213    PythonObject thread_arg(PyRefType::Owned, SBTypeToSWIGWrapper(thread_sb));
1214    auto result = pfunc(thread_arg, dict);
1215
1216    output = result.Str().GetString().str();
1217
1218    return true;
1219}
1220
1221SWIGEXPORT bool
1222LLDBSWIGPythonRunScriptKeywordTarget
1223(const char* python_function_name,
1224const char* session_dictionary_name,
1225lldb::TargetSP& target,
1226std::string& output)
1227
1228{
1229    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
1230        return false;
1231
1232    PyErr_Cleaner py_err_cleaner(true);
1233
1234    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
1235    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name,dict);
1236
1237    if (!pfunc.IsAllocated())
1238        return false;
1239
1240    lldb::SBTarget target_sb(target);
1241    PythonObject target_arg(PyRefType::Owned, SBTypeToSWIGWrapper(target_sb));
1242    auto result = pfunc(target_arg, dict);
1243
1244    output = result.Str().GetString().str();
1245
1246    return true;
1247}
1248
1249SWIGEXPORT bool
1250LLDBSWIGPythonRunScriptKeywordFrame
1251(const char* python_function_name,
1252const char* session_dictionary_name,
1253lldb::StackFrameSP& frame,
1254std::string& output)
1255
1256{
1257    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
1258        return false;
1259
1260    PyErr_Cleaner py_err_cleaner(true);
1261
1262    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
1263    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name,dict);
1264
1265    if (!pfunc.IsAllocated())
1266        return false;
1267
1268    lldb::SBFrame frame_sb(frame);
1269    PythonObject frame_arg(PyRefType::Owned, SBTypeToSWIGWrapper(frame_sb));
1270    auto result = pfunc(frame_arg, dict);
1271
1272    output = result.Str().GetString().str();
1273
1274    return true;
1275}
1276
1277SWIGEXPORT bool
1278LLDBSWIGPythonRunScriptKeywordValue
1279(const char* python_function_name,
1280const char* session_dictionary_name,
1281lldb::ValueObjectSP& value,
1282std::string& output)
1283
1284{
1285    if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name)
1286        return false;
1287
1288    PyErr_Cleaner py_err_cleaner(true);
1289
1290    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
1291    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
1292
1293    if (!pfunc.IsAllocated())
1294        return false;
1295
1296    lldb::SBValue value_sb(value);
1297    PythonObject value_arg(PyRefType::Owned, SBTypeToSWIGWrapper(value_sb));
1298    auto result = pfunc(value_arg, dict);
1299
1300    output = result.Str().GetString().str();
1301
1302    return true;
1303}
1304
1305SWIGEXPORT bool
1306LLDBSwigPythonCallModuleInit
1307(
1308    const char *python_module_name,
1309    const char *session_dictionary_name,
1310    lldb::DebuggerSP& debugger
1311)
1312{
1313    std::string python_function_name_string = python_module_name;
1314    python_function_name_string += ".__lldb_init_module";
1315    const char* python_function_name = python_function_name_string.c_str();
1316
1317    PyErr_Cleaner py_err_cleaner(true);
1318
1319    auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
1320    auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_function_name, dict);
1321
1322    // This method is optional and need not exist.  So if we don't find it,
1323    // it's actually a success, not a failure.
1324    if (!pfunc.IsAllocated())
1325        return true;
1326
1327    lldb::SBDebugger debugger_sb(debugger);
1328    PythonObject debugger_arg(PyRefType::Owned, SBTypeToSWIGWrapper(debugger_sb));
1329    pfunc(debugger_arg, dict);
1330
1331    return true;
1332}
1333%}
1334
1335
1336%runtime %{
1337// Forward declaration to be inserted at the start of LLDBWrapPython.h
1338#include "lldb/API/SBDebugger.h"
1339#include "lldb/API/SBValue.h"
1340
1341SWIGEXPORT lldb::ValueObjectSP
1342LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data)
1343{
1344    lldb::ValueObjectSP valobj_sp;
1345    if (data)
1346    {
1347        lldb::SBValue* sb_ptr = (lldb::SBValue *)data;
1348        valobj_sp = sb_ptr->GetSP();
1349    }
1350    return valobj_sp;
1351}
1352
1353#ifdef __cplusplus
1354extern "C" {
1355#endif
1356
1357void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton);
1358
1359#ifdef __cplusplus
1360}
1361#endif
1362%}
1363
1364%wrapper %{
1365
1366
1367// For the LogOutputCallback functions
1368void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton) {
1369    if (baton != Py_None) {
1370      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
1371      PyObject *result = PyObject_CallFunction(reinterpret_cast<PyObject*>(baton), const_cast<char*>("s"), str);
1372	  Py_XDECREF(result);
1373      SWIG_PYTHON_THREAD_END_BLOCK;
1374    }
1375}
1376%}
1377