Coverage Report

Created: 2022-01-18 06:27

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h
Line
Count
Source (jump to first uncovered line)
1
//===-- ScriptedPythonInterface.h -------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H
10
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H
11
12
#include "lldb/Host/Config.h"
13
14
#if LLDB_ENABLE_PYTHON
15
16
#include "lldb/Interpreter/ScriptedInterface.h"
17
#include "lldb/Utility/DataBufferHeap.h"
18
19
#include "PythonDataObjects.h"
20
#include "SWIGPythonBridge.h"
21
#include "ScriptInterpreterPythonImpl.h"
22
23
namespace lldb_private {
24
class ScriptInterpreterPythonImpl;
25
class ScriptedPythonInterface : virtual public ScriptedInterface {
26
public:
27
  ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter);
28
1.43k
  virtual ~ScriptedPythonInterface() = default;
29
30
protected:
31
  template <typename T = StructuredData::ObjectSP>
32
111
  T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) {
33
111
    return p.CreateStructuredObject();
34
111
  }
35
36
  template <typename T = StructuredData::ObjectSP, typename... Args>
37
177
  T Dispatch(llvm::StringRef method_name, Status &error, Args... args) {
38
177
    using namespace python;
39
177
    using Locker = ScriptInterpreterPythonImpl::Locker;
40
41
177
    std::string caller_signature =
42
177
        llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
43
177
                    llvm::Twine(method_name) + llvm::Twine(")"))
44
177
            .str();
45
177
    if (!m_object_instance_sp)
46
0
      return ErrorWithMessage<T>(caller_signature, "Python object ill-formed",
47
0
                                 error);
48
49
177
    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
50
177
                   Locker::FreeLock);
51
52
177
    PythonObject implementor(PyRefType::Borrowed,
53
177
                             (PyObject *)m_object_instance_sp->GetValue());
54
55
177
    if (!implementor.IsAllocated())
56
0
      return ErrorWithMessage<T>(caller_signature,
57
0
                                 "Python implementor not allocated.", error);
58
59
177
    PythonObject pmeth(
60
177
        PyRefType::Owned,
61
177
        PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
62
63
177
    if (PyErr_Occurred())
64
0
      PyErr_Clear();
65
66
177
    if (!pmeth.IsAllocated())
67
0
      return ErrorWithMessage<T>(caller_signature,
68
0
                                 "Python method not allocated.", error);
69
70
177
    if (PyCallable_Check(pmeth.get()) == 0) {
71
0
      if (PyErr_Occurred())
72
0
        PyErr_Clear();
73
0
      return ErrorWithMessage<T>(caller_signature,
74
0
                                 "Python method not callable.", error);
75
0
    }
76
77
177
    if (PyErr_Occurred())
78
0
      PyErr_Clear();
79
80
    // TODO: make `const char *` when removing support for Python 2.
81
177
    char *format = nullptr;
82
177
    std::string format_buffer;
83
84
177
    if (sizeof...(Args) > 0) {
85
6
      FormatArgs(format_buffer, args...);
86
      // TODO: make `const char *` when removing support for Python 2.
87
6
      format = const_cast<char *>(format_buffer.c_str());
88
6
    }
89
90
    // TODO: make `const char *` when removing support for Python 2.
91
177
    PythonObject py_return(
92
177
        PyRefType::Owned,
93
177
        PyObject_CallMethod(implementor.get(),
94
177
                            const_cast<char *>(method_name.data()), format,
95
177
                            args...));
96
97
177
    if (PyErr_Occurred()) {
98
0
      PyErr_Print();
99
0
      PyErr_Clear();
100
0
      return ErrorWithMessage<T>(caller_signature,
101
0
                                 "Python method could not be called.", error);
102
0
    }
103
104
177
    if (!py_return.IsAllocated())
105
39
      return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
106
39
                                 error);
107
108
138
    return ExtractValueFromPythonObject<T>(py_return, error);
109
177
  }
lldb_private::Status lldb_private::ScriptedPythonInterface::Dispatch<lldb_private::Status>(llvm::StringRef, lldb_private::Status&)
Line
Count
Source
37
12
  T Dispatch(llvm::StringRef method_name, Status &error, Args... args) {
38
12
    using namespace python;
39
12
    using Locker = ScriptInterpreterPythonImpl::Locker;
40
41
12
    std::string caller_signature =
42
12
        llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
43
12
                    llvm::Twine(method_name) + llvm::Twine(")"))
44
12
            .str();
45
12
    if (!m_object_instance_sp)
46
0
      return ErrorWithMessage<T>(caller_signature, "Python object ill-formed",
47
0
                                 error);
48
49
12
    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
50
12
                   Locker::FreeLock);
51
52
12
    PythonObject implementor(PyRefType::Borrowed,
53
12
                             (PyObject *)m_object_instance_sp->GetValue());
54
55
12
    if (!implementor.IsAllocated())
56
0
      return ErrorWithMessage<T>(caller_signature,
57
0
                                 "Python implementor not allocated.", error);
58
59
12
    PythonObject pmeth(
60
12
        PyRefType::Owned,
61
12
        PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
62
63
12
    if (PyErr_Occurred())
64
0
      PyErr_Clear();
65
66
12
    if (!pmeth.IsAllocated())
67
0
      return ErrorWithMessage<T>(caller_signature,
68
0
                                 "Python method not allocated.", error);
69
70
12
    if (PyCallable_Check(pmeth.get()) == 0) {
71
0
      if (PyErr_Occurred())
72
0
        PyErr_Clear();
73
0
      return ErrorWithMessage<T>(caller_signature,
74
0
                                 "Python method not callable.", error);
75
0
    }
76
77
12
    if (PyErr_Occurred())
78
0
      PyErr_Clear();
79
80
    // TODO: make `const char *` when removing support for Python 2.
81
12
    char *format = nullptr;
82
12
    std::string format_buffer;
83
84
12
    if (sizeof...(Args) > 0) {
85
0
      FormatArgs(format_buffer, args...);
86
      // TODO: make `const char *` when removing support for Python 2.
87
0
      format = const_cast<char *>(format_buffer.c_str());
88
0
    }
89
90
    // TODO: make `const char *` when removing support for Python 2.
91
12
    PythonObject py_return(
92
12
        PyRefType::Owned,
93
12
        PyObject_CallMethod(implementor.get(),
94
12
                            const_cast<char *>(method_name.data()), format,
95
12
                            args...));
96
97
12
    if (PyErr_Occurred()) {
98
0
      PyErr_Print();
99
0
      PyErr_Clear();
100
0
      return ErrorWithMessage<T>(caller_signature,
101
0
                                 "Python method could not be called.", error);
102
0
    }
103
104
12
    if (!py_return.IsAllocated())
105
0
      return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
106
0
                                 error);
107
108
12
    return ExtractValueFromPythonObject<T>(py_return, error);
109
12
  }
std::__1::shared_ptr<lldb_private::StructuredData::Object> lldb_private::ScriptedPythonInterface::Dispatch<std::__1::shared_ptr<lldb_private::StructuredData::Object> >(llvm::StringRef, lldb_private::Status&)
Line
Count
Source
37
147
  T Dispatch(llvm::StringRef method_name, Status &error, Args... args) {
38
147
    using namespace python;
39
147
    using Locker = ScriptInterpreterPythonImpl::Locker;
40
41
147
    std::string caller_signature =
42
147
        llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
43
147
                    llvm::Twine(method_name) + llvm::Twine(")"))
44
147
            .str();
45
147
    if (!m_object_instance_sp)
46
0
      return ErrorWithMessage<T>(caller_signature, "Python object ill-formed",
47
0
                                 error);
48
49
147
    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
50
147
                   Locker::FreeLock);
51
52
147
    PythonObject implementor(PyRefType::Borrowed,
53
147
                             (PyObject *)m_object_instance_sp->GetValue());
54
55
147
    if (!implementor.IsAllocated())
56
0
      return ErrorWithMessage<T>(caller_signature,
57
0
                                 "Python implementor not allocated.", error);
58
59
147
    PythonObject pmeth(
60
147
        PyRefType::Owned,
61
147
        PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
62
63
147
    if (PyErr_Occurred())
64
0
      PyErr_Clear();
65
66
147
    if (!pmeth.IsAllocated())
67
0
      return ErrorWithMessage<T>(caller_signature,
68
0
                                 "Python method not allocated.", error);
69
70
147
    if (PyCallable_Check(pmeth.get()) == 0) {
71
0
      if (PyErr_Occurred())
72
0
        PyErr_Clear();
73
0
      return ErrorWithMessage<T>(caller_signature,
74
0
                                 "Python method not callable.", error);
75
0
    }
76
77
147
    if (PyErr_Occurred())
78
0
      PyErr_Clear();
79
80
    // TODO: make `const char *` when removing support for Python 2.
81
147
    char *format = nullptr;
82
147
    std::string format_buffer;
83
84
147
    if (sizeof...(Args) > 0) {
85
0
      FormatArgs(format_buffer, args...);
86
      // TODO: make `const char *` when removing support for Python 2.
87
0
      format = const_cast<char *>(format_buffer.c_str());
88
0
    }
89
90
    // TODO: make `const char *` when removing support for Python 2.
91
147
    PythonObject py_return(
92
147
        PyRefType::Owned,
93
147
        PyObject_CallMethod(implementor.get(),
94
147
                            const_cast<char *>(method_name.data()), format,
95
147
                            args...));
96
97
147
    if (PyErr_Occurred()) {
98
0
      PyErr_Print();
99
0
      PyErr_Clear();
100
0
      return ErrorWithMessage<T>(caller_signature,
101
0
                                 "Python method could not be called.", error);
102
0
    }
103
104
147
    if (!py_return.IsAllocated())
105
36
      return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
106
36
                                 error);
107
108
111
    return ExtractValueFromPythonObject<T>(py_return, error);
109
147
  }
llvm::Optional<lldb_private::MemoryRegionInfo> lldb_private::ScriptedPythonInterface::Dispatch<llvm::Optional<lldb_private::MemoryRegionInfo>, unsigned long long>(llvm::StringRef, lldb_private::Status&, unsigned long long)
Line
Count
Source
37
3
  T Dispatch(llvm::StringRef method_name, Status &error, Args... args) {
38
3
    using namespace python;
39
3
    using Locker = ScriptInterpreterPythonImpl::Locker;
40
41
3
    std::string caller_signature =
42
3
        llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
43
3
                    llvm::Twine(method_name) + llvm::Twine(")"))
44
3
            .str();
45
3
    if (!m_object_instance_sp)
46
0
      return ErrorWithMessage<T>(caller_signature, "Python object ill-formed",
47
0
                                 error);
48
49
3
    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
50
3
                   Locker::FreeLock);
51
52
3
    PythonObject implementor(PyRefType::Borrowed,
53
3
                             (PyObject *)m_object_instance_sp->GetValue());
54
55
3
    if (!implementor.IsAllocated())
56
0
      return ErrorWithMessage<T>(caller_signature,
57
0
                                 "Python implementor not allocated.", error);
58
59
3
    PythonObject pmeth(
60
3
        PyRefType::Owned,
61
3
        PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
62
63
3
    if (PyErr_Occurred())
64
0
      PyErr_Clear();
65
66
3
    if (!pmeth.IsAllocated())
67
0
      return ErrorWithMessage<T>(caller_signature,
68
0
                                 "Python method not allocated.", error);
69
70
3
    if (PyCallable_Check(pmeth.get()) == 0) {
71
0
      if (PyErr_Occurred())
72
0
        PyErr_Clear();
73
0
      return ErrorWithMessage<T>(caller_signature,
74
0
                                 "Python method not callable.", error);
75
0
    }
76
77
3
    if (PyErr_Occurred())
78
0
      PyErr_Clear();
79
80
    // TODO: make `const char *` when removing support for Python 2.
81
3
    char *format = nullptr;
82
3
    std::string format_buffer;
83
84
3
    if (sizeof...(Args) > 0) {
85
3
      FormatArgs(format_buffer, args...);
86
      // TODO: make `const char *` when removing support for Python 2.
87
3
      format = const_cast<char *>(format_buffer.c_str());
88
3
    }
89
90
    // TODO: make `const char *` when removing support for Python 2.
91
3
    PythonObject py_return(
92
3
        PyRefType::Owned,
93
3
        PyObject_CallMethod(implementor.get(),
94
3
                            const_cast<char *>(method_name.data()), format,
95
3
                            args...));
96
97
3
    if (PyErr_Occurred()) {
98
0
      PyErr_Print();
99
0
      PyErr_Clear();
100
0
      return ErrorWithMessage<T>(caller_signature,
101
0
                                 "Python method could not be called.", error);
102
0
    }
103
104
3
    if (!py_return.IsAllocated())
105
3
      return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
106
3
                                 error);
107
108
0
    return ExtractValueFromPythonObject<T>(py_return, error);
109
3
  }
Unexecuted instantiation: std::__1::shared_ptr<lldb_private::StructuredData::Object> lldb_private::ScriptedPythonInterface::Dispatch<std::__1::shared_ptr<lldb_private::StructuredData::Object>, unsigned long long>(llvm::StringRef, lldb_private::Status&, unsigned long long)
std::__1::shared_ptr<lldb_private::DataExtractor> lldb_private::ScriptedPythonInterface::Dispatch<std::__1::shared_ptr<lldb_private::DataExtractor>, unsigned long long, unsigned long>(llvm::StringRef, lldb_private::Status&, unsigned long long, unsigned long)
Line
Count
Source
37
3
  T Dispatch(llvm::StringRef method_name, Status &error, Args... args) {
38
3
    using namespace python;
39
3
    using Locker = ScriptInterpreterPythonImpl::Locker;
40
41
3
    std::string caller_signature =
42
3
        llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
43
3
                    llvm::Twine(method_name) + llvm::Twine(")"))
44
3
            .str();
45
3
    if (!m_object_instance_sp)
46
0
      return ErrorWithMessage<T>(caller_signature, "Python object ill-formed",
47
0
                                 error);
48
49
3
    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
50
3
                   Locker::FreeLock);
51
52
3
    PythonObject implementor(PyRefType::Borrowed,
53
3
                             (PyObject *)m_object_instance_sp->GetValue());
54
55
3
    if (!implementor.IsAllocated())
56
0
      return ErrorWithMessage<T>(caller_signature,
57
0
                                 "Python implementor not allocated.", error);
58
59
3
    PythonObject pmeth(
60
3
        PyRefType::Owned,
61
3
        PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
62
63
3
    if (PyErr_Occurred())
64
0
      PyErr_Clear();
65
66
3
    if (!pmeth.IsAllocated())
67
0
      return ErrorWithMessage<T>(caller_signature,
68
0
                                 "Python method not allocated.", error);
69
70
3
    if (PyCallable_Check(pmeth.get()) == 0) {
71
0
      if (PyErr_Occurred())
72
0
        PyErr_Clear();
73
0
      return ErrorWithMessage<T>(caller_signature,
74
0
                                 "Python method not callable.", error);
75
0
    }
76
77
3
    if (PyErr_Occurred())
78
0
      PyErr_Clear();
79
80
    // TODO: make `const char *` when removing support for Python 2.
81
3
    char *format = nullptr;
82
3
    std::string format_buffer;
83
84
3
    if (sizeof...(Args) > 0) {
85
3
      FormatArgs(format_buffer, args...);
86
      // TODO: make `const char *` when removing support for Python 2.
87
3
      format = const_cast<char *>(format_buffer.c_str());
88
3
    }
89
90
    // TODO: make `const char *` when removing support for Python 2.
91
3
    PythonObject py_return(
92
3
        PyRefType::Owned,
93
3
        PyObject_CallMethod(implementor.get(),
94
3
                            const_cast<char *>(method_name.data()), format,
95
3
                            args...));
96
97
3
    if (PyErr_Occurred()) {
98
0
      PyErr_Print();
99
0
      PyErr_Clear();
100
0
      return ErrorWithMessage<T>(caller_signature,
101
0
                                 "Python method could not be called.", error);
102
0
    }
103
104
3
    if (!py_return.IsAllocated())
105
0
      return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
106
0
                                 error);
107
108
3
    return ExtractValueFromPythonObject<T>(py_return, error);
109
3
  }
std::__1::shared_ptr<lldb_private::StructuredData::Dictionary> lldb_private::ScriptedPythonInterface::Dispatch<std::__1::shared_ptr<lldb_private::StructuredData::Dictionary> >(llvm::StringRef, lldb_private::Status&)
Line
Count
Source
37
12
  T Dispatch(llvm::StringRef method_name, Status &error, Args... args) {
38
12
    using namespace python;
39
12
    using Locker = ScriptInterpreterPythonImpl::Locker;
40
41
12
    std::string caller_signature =
42
12
        llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") +
43
12
                    llvm::Twine(method_name) + llvm::Twine(")"))
44
12
            .str();
45
12
    if (!m_object_instance_sp)
46
0
      return ErrorWithMessage<T>(caller_signature, "Python object ill-formed",
47
0
                                 error);
48
49
12
    Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN,
50
12
                   Locker::FreeLock);
51
52
12
    PythonObject implementor(PyRefType::Borrowed,
53
12
                             (PyObject *)m_object_instance_sp->GetValue());
54
55
12
    if (!implementor.IsAllocated())
56
0
      return ErrorWithMessage<T>(caller_signature,
57
0
                                 "Python implementor not allocated.", error);
58
59
12
    PythonObject pmeth(
60
12
        PyRefType::Owned,
61
12
        PyObject_GetAttrString(implementor.get(), method_name.str().c_str()));
62
63
12
    if (PyErr_Occurred())
64
0
      PyErr_Clear();
65
66
12
    if (!pmeth.IsAllocated())
67
0
      return ErrorWithMessage<T>(caller_signature,
68
0
                                 "Python method not allocated.", error);
69
70
12
    if (PyCallable_Check(pmeth.get()) == 0) {
71
0
      if (PyErr_Occurred())
72
0
        PyErr_Clear();
73
0
      return ErrorWithMessage<T>(caller_signature,
74
0
                                 "Python method not callable.", error);
75
0
    }
76
77
12
    if (PyErr_Occurred())
78
0
      PyErr_Clear();
79
80
    // TODO: make `const char *` when removing support for Python 2.
81
12
    char *format = nullptr;
82
12
    std::string format_buffer;
83
84
12
    if (sizeof...(Args) > 0) {
85
0
      FormatArgs(format_buffer, args...);
86
      // TODO: make `const char *` when removing support for Python 2.
87
0
      format = const_cast<char *>(format_buffer.c_str());
88
0
    }
89
90
    // TODO: make `const char *` when removing support for Python 2.
91
12
    PythonObject py_return(
92
12
        PyRefType::Owned,
93
12
        PyObject_CallMethod(implementor.get(),
94
12
                            const_cast<char *>(method_name.data()), format,
95
12
                            args...));
96
97
12
    if (PyErr_Occurred()) {
98
0
      PyErr_Print();
99
0
      PyErr_Clear();
100
0
      return ErrorWithMessage<T>(caller_signature,
101
0
                                 "Python method could not be called.", error);
102
0
    }
103
104
12
    if (!py_return.IsAllocated())
105
0
      return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
106
0
                                 error);
107
108
12
    return ExtractValueFromPythonObject<T>(py_return, error);
109
12
  }
110
111
  Status GetStatusFromMethod(llvm::StringRef method_name);
112
113
  template <typename T, typename... Args>
114
3
  void FormatArgs(std::string &fmt, T arg, Args... args) const {
115
3
    FormatArgs(fmt, arg);
116
3
    FormatArgs(fmt, args...);
117
3
  }
118
119
9
  template <typename T> void FormatArgs(std::string &fmt, T arg) const {
120
9
    fmt += GetPythonValueFormatString(arg);
121
9
  }
void lldb_private::ScriptedPythonInterface::FormatArgs<unsigned long long>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, unsigned long long) const
Line
Count
Source
119
6
  template <typename T> void FormatArgs(std::string &fmt, T arg) const {
120
6
    fmt += GetPythonValueFormatString(arg);
121
6
  }
void lldb_private::ScriptedPythonInterface::FormatArgs<unsigned long>(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&, unsigned long) const
Line
Count
Source
119
3
  template <typename T> void FormatArgs(std::string &fmt, T arg) const {
120
3
    fmt += GetPythonValueFormatString(arg);
121
3
  }
122
123
0
  void FormatArgs(std::string &fmt) const {}
124
125
  // The lifetime is managed by the ScriptInterpreter
126
  ScriptInterpreterPythonImpl &m_interpreter;
127
};
128
129
template <>
130
StructuredData::DictionarySP
131
ScriptedPythonInterface::ExtractValueFromPythonObject<
132
    StructuredData::DictionarySP>(python::PythonObject &p, Status &error);
133
134
template <>
135
Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
136
    python::PythonObject &p, Status &error);
137
138
template <>
139
lldb::DataExtractorSP
140
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
141
    python::PythonObject &p, Status &error);
142
143
template <>
144
llvm::Optional<MemoryRegionInfo>
145
ScriptedPythonInterface::ExtractValueFromPythonObject<
146
    llvm::Optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error);
147
148
} // namespace lldb_private
149
150
#endif // LLDB_ENABLE_PYTHON
151
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H