xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (revision 9c40264fdadbb229ce311c9bda898981d7ac8eae)
1 //===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifdef LLDB_DISABLE_PYTHON
11 
12 // Python is disabled in this build
13 
14 #else
15 
16 #include "lldb-python.h"
17 #include "PythonDataObjects.h"
18 #include "ScriptInterpreterPython.h"
19 
20 #include "lldb/Core/Stream.h"
21 #include "lldb/Host/File.h"
22 #include "lldb/Interpreter/ScriptInterpreter.h"
23 
24 #include <stdio.h>
25 
26 using namespace lldb_private;
27 using namespace lldb;
28 
29 void
30 StructuredPythonObject::Dump(Stream &s) const
31 {
32     s << "Python Obj: 0x" << GetValue();
33 }
34 
35 //----------------------------------------------------------------------
36 // PythonObject
37 //----------------------------------------------------------------------
38 
39 void
40 PythonObject::Dump(Stream &strm) const
41 {
42     if (m_py_obj)
43     {
44         FILE *file = ::tmpfile();
45         if (file)
46         {
47             ::PyObject_Print (m_py_obj, file, 0);
48             const long length = ftell (file);
49             if (length)
50             {
51                 ::rewind(file);
52                 std::vector<char> file_contents (length,'\0');
53                 const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
54                 if (length_read > 0)
55                     strm.Write (file_contents.data(), length_read);
56             }
57             ::fclose (file);
58         }
59     }
60     else
61         strm.PutCString ("NULL");
62 }
63 
64 PyObjectType
65 PythonObject::GetObjectType() const
66 {
67     if (!IsAllocated())
68         return PyObjectType::None;
69 
70     if (PythonList::Check(m_py_obj))
71         return PyObjectType::List;
72     if (PythonDictionary::Check(m_py_obj))
73         return PyObjectType::Dictionary;
74     if (PythonString::Check(m_py_obj))
75         return PyObjectType::String;
76     if (PythonInteger::Check(m_py_obj))
77         return PyObjectType::Integer;
78     if (PythonFile::Check(m_py_obj))
79         return PyObjectType::File;
80     return PyObjectType::Unknown;
81 }
82 
83 PythonString
84 PythonObject::Repr()
85 {
86     if (!m_py_obj)
87         return PythonString();
88     PyObject *repr = PyObject_Repr(m_py_obj);
89     if (!repr)
90         return PythonString();
91     return PythonString(PyRefType::Owned, repr);
92 }
93 
94 PythonString
95 PythonObject::Str()
96 {
97     if (!m_py_obj)
98         return PythonString();
99     PyObject *str = PyObject_Str(m_py_obj);
100     if (!str)
101         return PythonString();
102     return PythonString(PyRefType::Owned, str);
103 }
104 
105 bool
106 PythonObject::HasAttribute(llvm::StringRef attr) const
107 {
108     if (!IsValid())
109         return false;
110     PythonString py_attr(attr);
111     return !!PyObject_HasAttr(m_py_obj, py_attr.get());
112 }
113 
114 bool
115 PythonObject::IsNone() const
116 {
117     return m_py_obj == Py_None;
118 }
119 
120 bool
121 PythonObject::IsValid() const
122 {
123     return m_py_obj != nullptr;
124 }
125 
126 bool
127 PythonObject::IsAllocated() const
128 {
129     return IsValid() && !IsNone();
130 }
131 
132 StructuredData::ObjectSP
133 PythonObject::CreateStructuredObject() const
134 {
135     switch (GetObjectType())
136     {
137         case PyObjectType::Dictionary:
138             return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
139         case PyObjectType::Integer:
140             return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
141         case PyObjectType::List:
142             return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
143         case PyObjectType::String:
144             return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
145         case PyObjectType::None:
146             return StructuredData::ObjectSP();
147         default:
148             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
149     }
150 }
151 
152 //----------------------------------------------------------------------
153 // PythonString
154 //----------------------------------------------------------------------
155 
156 PythonString::PythonString(PyRefType type, PyObject *py_obj)
157     : PythonObject()
158 {
159     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
160 }
161 
162 PythonString::PythonString(const PythonString &object)
163     : PythonObject(object)
164 {
165 }
166 
167 PythonString::PythonString(llvm::StringRef string)
168     : PythonObject()
169 {
170     SetString(string);
171 }
172 
173 PythonString::PythonString(const char *string)
174     : PythonObject()
175 {
176     SetString(llvm::StringRef(string));
177 }
178 
179 PythonString::PythonString()
180     : PythonObject()
181 {
182 }
183 
184 PythonString::~PythonString ()
185 {
186 }
187 
188 bool
189 PythonString::Check(PyObject *py_obj)
190 {
191     if (!py_obj)
192         return false;
193 
194 #if PY_MAJOR_VERSION >= 3
195     return PyUnicode_Check(py_obj);
196 #else
197     return PyString_Check(py_obj);
198 #endif
199 }
200 
201 void
202 PythonString::Reset(PyRefType type, PyObject *py_obj)
203 {
204     // Grab the desired reference type so that if we end up rejecting
205     // `py_obj` it still gets decremented if necessary.
206     PythonObject result(type, py_obj);
207 
208     if (!PythonString::Check(py_obj))
209     {
210         PythonObject::Reset();
211         return;
212     }
213 
214     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
215     // back into the virtual implementation.
216     PythonObject::Reset(PyRefType::Borrowed, result.get());
217 }
218 
219 llvm::StringRef
220 PythonString::GetString() const
221 {
222     if (!IsValid())
223         return llvm::StringRef();
224 
225     Py_ssize_t size;
226     char *c;
227 
228 #if PY_MAJOR_VERSION >= 3
229     c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
230 #else
231     PyString_AsStringAndSize(m_py_obj, &c, &size);
232 #endif
233     return llvm::StringRef(c, size);
234 }
235 
236 size_t
237 PythonString::GetSize() const
238 {
239     if (IsValid())
240     {
241 #if PY_MAJOR_VERSION >= 3
242         return PyUnicode_GetSize(m_py_obj);
243 #else
244         return PyString_Size(m_py_obj);
245 #endif
246     }
247     return 0;
248 }
249 
250 void
251 PythonString::SetString (llvm::StringRef string)
252 {
253 #if PY_MAJOR_VERSION >= 3
254     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
255     PythonObject::Reset(PyRefType::Owned, unicode);
256 #else
257     PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
258     PythonObject::Reset(PyRefType::Owned, str);
259 #endif
260 }
261 
262 StructuredData::StringSP
263 PythonString::CreateStructuredString() const
264 {
265     StructuredData::StringSP result(new StructuredData::String);
266     result->SetValue(GetString());
267     return result;
268 }
269 
270 //----------------------------------------------------------------------
271 // PythonInteger
272 //----------------------------------------------------------------------
273 
274 PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
275     : PythonObject()
276 {
277     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
278 }
279 
280 PythonInteger::PythonInteger(const PythonInteger &object)
281     : PythonObject(object)
282 {
283 }
284 
285 PythonInteger::PythonInteger(int64_t value)
286     : PythonObject()
287 {
288     SetInteger(value);
289 }
290 
291 
292 PythonInteger::~PythonInteger ()
293 {
294 }
295 
296 bool
297 PythonInteger::Check(PyObject *py_obj)
298 {
299     if (!py_obj)
300         return false;
301 
302 #if PY_MAJOR_VERSION >= 3
303     // Python 3 does not have PyInt_Check.  There is only one type of
304     // integral value, long.
305     return PyLong_Check(py_obj);
306 #else
307     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
308 #endif
309 }
310 
311 void
312 PythonInteger::Reset(PyRefType type, PyObject *py_obj)
313 {
314     // Grab the desired reference type so that if we end up rejecting
315     // `py_obj` it still gets decremented if necessary.
316     PythonObject result(type, py_obj);
317 
318     if (!PythonInteger::Check(py_obj))
319     {
320         PythonObject::Reset();
321         return;
322     }
323 
324 #if PY_MAJOR_VERSION < 3
325     // Always store this as a PyLong, which makes interoperability between
326     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
327     // since 3.x doesn't even have a PyInt.
328     if (PyInt_Check(py_obj))
329     {
330         // Since we converted the original object to a different type, the new
331         // object is an owned object regardless of the ownership semantics requested
332         // by the user.
333         result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
334     }
335 #endif
336 
337     assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
338 
339     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
340     // back into the virtual implementation.
341     PythonObject::Reset(PyRefType::Borrowed, result.get());
342 }
343 
344 int64_t
345 PythonInteger::GetInteger() const
346 {
347     if (m_py_obj)
348     {
349         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
350 
351         return PyLong_AsLongLong(m_py_obj);
352     }
353     return UINT64_MAX;
354 }
355 
356 void
357 PythonInteger::SetInteger(int64_t value)
358 {
359     PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
360 }
361 
362 StructuredData::IntegerSP
363 PythonInteger::CreateStructuredInteger() const
364 {
365     StructuredData::IntegerSP result(new StructuredData::Integer);
366     result->SetValue(GetInteger());
367     return result;
368 }
369 
370 //----------------------------------------------------------------------
371 // PythonList
372 //----------------------------------------------------------------------
373 
374 PythonList::PythonList(PyInitialValue value)
375     : PythonObject()
376 {
377     if (value == PyInitialValue::Empty)
378         Reset(PyRefType::Owned, PyList_New(0));
379 }
380 
381 PythonList::PythonList(int list_size)
382     : PythonObject()
383 {
384     Reset(PyRefType::Owned, PyList_New(list_size));
385 }
386 
387 PythonList::PythonList(PyRefType type, PyObject *py_obj)
388     : PythonObject()
389 {
390     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
391 }
392 
393 PythonList::PythonList(const PythonList &list)
394     : PythonObject(list)
395 {
396 }
397 
398 PythonList::~PythonList ()
399 {
400 }
401 
402 bool
403 PythonList::Check(PyObject *py_obj)
404 {
405     if (!py_obj)
406         return false;
407     return PyList_Check(py_obj);
408 }
409 
410 void
411 PythonList::Reset(PyRefType type, PyObject *py_obj)
412 {
413     // Grab the desired reference type so that if we end up rejecting
414     // `py_obj` it still gets decremented if necessary.
415     PythonObject result(type, py_obj);
416 
417     if (!PythonList::Check(py_obj))
418     {
419         PythonObject::Reset();
420         return;
421     }
422 
423     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
424     // back into the virtual implementation.
425     PythonObject::Reset(PyRefType::Borrowed, result.get());
426 }
427 
428 uint32_t
429 PythonList::GetSize() const
430 {
431     if (IsValid())
432         return PyList_GET_SIZE(m_py_obj);
433     return 0;
434 }
435 
436 PythonObject
437 PythonList::GetItemAtIndex(uint32_t index) const
438 {
439     if (IsValid())
440         return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
441     return PythonObject();
442 }
443 
444 void
445 PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
446 {
447     if (IsAllocated() && object.IsValid())
448     {
449         // PyList_SetItem is documented to "steal" a reference, so we need to
450         // convert it to an owned reference by incrementing it.
451         Py_INCREF(object.get());
452         PyList_SetItem(m_py_obj, index, object.get());
453     }
454 }
455 
456 void
457 PythonList::AppendItem(const PythonObject &object)
458 {
459     if (IsAllocated() && object.IsValid())
460     {
461         // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
462         // here like we do with `PyList_SetItem`.
463         PyList_Append(m_py_obj, object.get());
464     }
465 }
466 
467 StructuredData::ArraySP
468 PythonList::CreateStructuredArray() const
469 {
470     StructuredData::ArraySP result(new StructuredData::Array);
471     uint32_t count = GetSize();
472     for (uint32_t i = 0; i < count; ++i)
473     {
474         PythonObject obj = GetItemAtIndex(i);
475         result->AddItem(obj.CreateStructuredObject());
476     }
477     return result;
478 }
479 
480 //----------------------------------------------------------------------
481 // PythonDictionary
482 //----------------------------------------------------------------------
483 
484 PythonDictionary::PythonDictionary(PyInitialValue value)
485     : PythonObject()
486 {
487     if (value == PyInitialValue::Empty)
488         Reset(PyRefType::Owned, PyDict_New());
489 }
490 
491 PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
492     : PythonObject()
493 {
494     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
495 }
496 
497 PythonDictionary::PythonDictionary(const PythonDictionary &object)
498     : PythonObject(object)
499 {
500 }
501 
502 PythonDictionary::~PythonDictionary ()
503 {
504 }
505 
506 bool
507 PythonDictionary::Check(PyObject *py_obj)
508 {
509     if (!py_obj)
510         return false;
511 
512     return PyDict_Check(py_obj);
513 }
514 
515 void
516 PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
517 {
518     // Grab the desired reference type so that if we end up rejecting
519     // `py_obj` it still gets decremented if necessary.
520     PythonObject result(type, py_obj);
521 
522     if (!PythonDictionary::Check(py_obj))
523     {
524         PythonObject::Reset();
525         return;
526     }
527 
528     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
529     // back into the virtual implementation.
530     PythonObject::Reset(PyRefType::Borrowed, result.get());
531 }
532 
533 uint32_t
534 PythonDictionary::GetSize() const
535 {
536     if (IsValid())
537         return PyDict_Size(m_py_obj);
538     return 0;
539 }
540 
541 PythonList
542 PythonDictionary::GetKeys() const
543 {
544     if (IsValid())
545         return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
546     return PythonList(PyInitialValue::Invalid);
547 }
548 
549 PythonObject
550 PythonDictionary::GetItemForKey(const PythonObject &key) const
551 {
552     if (IsAllocated() && key.IsValid())
553         return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
554     return PythonObject();
555 }
556 
557 void
558 PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
559 {
560     if (IsAllocated() && key.IsValid() && value.IsValid())
561         PyDict_SetItem(m_py_obj, key.get(), value.get());
562 }
563 
564 StructuredData::DictionarySP
565 PythonDictionary::CreateStructuredDictionary() const
566 {
567     StructuredData::DictionarySP result(new StructuredData::Dictionary);
568     PythonList keys(GetKeys());
569     uint32_t num_keys = keys.GetSize();
570     for (uint32_t i = 0; i < num_keys; ++i)
571     {
572         PythonObject key = keys.GetItemAtIndex(i);
573         PythonObject value = GetItemForKey(key);
574         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
575         result->AddItem(key.Str().GetString(), structured_value);
576     }
577     return result;
578 }
579 
580 PythonFile::PythonFile(File &file, const char *mode)
581 {
582     Reset(file, mode);
583 }
584 
585 PythonFile::PythonFile(PyRefType type, PyObject *o)
586 {
587     Reset(type, o);
588 }
589 
590 PythonFile::~PythonFile()
591 {
592 }
593 
594 bool
595 PythonFile::Check(PyObject *py_obj)
596 {
597 #if PY_MAJOR_VERSION < 3
598     return PyFile_Check(py_obj);
599 #else
600     // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
601     // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
602     // over `io.open()`, which returns some object derived from `io.IOBase`.
603     // As a result, the only way to detect a file in Python 3 is to check whether
604     // it inherits from `io.IOBase`.  Since it is possible for non-files to also
605     // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
606     // attribute, which should guarantee that it is backed by the file system.
607     PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
608     PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
609     PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
610 
611     PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
612 
613     if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
614         return false;
615     if (!object_type.HasAttribute("fileno"))
616         return false;
617 
618     return true;
619 #endif
620 }
621 
622 void
623 PythonFile::Reset(PyRefType type, PyObject *py_obj)
624 {
625     // Grab the desired reference type so that if we end up rejecting
626     // `py_obj` it still gets decremented if necessary.
627     PythonObject result(type, py_obj);
628 
629     if (!PythonFile::Check(py_obj))
630     {
631         PythonObject::Reset();
632         return;
633     }
634 
635     // Calling PythonObject::Reset(const PythonObject&) will lead to stack
636     // overflow since it calls back into the virtual implementation.
637     PythonObject::Reset(PyRefType::Borrowed, result.get());
638 }
639 
640 void
641 PythonFile::Reset(File &file, const char *mode)
642 {
643     char *cmode = const_cast<char *>(mode);
644 #if PY_MAJOR_VERSION >= 3
645     Reset(PyRefType::Owned,
646         PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
647 #else
648     // Read through the Python source, doesn't seem to modify these strings
649     Reset(PyRefType::Owned,
650         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
651 #endif
652 }
653 
654 #endif
655