xref: /llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (revision 7d6d218e1219f7df284b83dfb3eaa5e5b70e77e8)
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 PythonObject
115 PythonObject::GetAttributeValue(llvm::StringRef attr) const
116 {
117     if (!IsValid())
118         return PythonObject();
119 
120     PythonString py_attr(attr);
121     if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
122         return PythonObject();
123 
124     return PythonObject(PyRefType::Owned,
125         PyObject_GetAttr(m_py_obj, py_attr.get()));
126 }
127 
128 bool
129 PythonObject::IsNone() const
130 {
131     return m_py_obj == Py_None;
132 }
133 
134 bool
135 PythonObject::IsValid() const
136 {
137     return m_py_obj != nullptr;
138 }
139 
140 bool
141 PythonObject::IsAllocated() const
142 {
143     return IsValid() && !IsNone();
144 }
145 
146 StructuredData::ObjectSP
147 PythonObject::CreateStructuredObject() const
148 {
149     switch (GetObjectType())
150     {
151         case PyObjectType::Dictionary:
152             return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
153         case PyObjectType::Integer:
154             return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
155         case PyObjectType::List:
156             return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
157         case PyObjectType::String:
158             return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
159         case PyObjectType::None:
160             return StructuredData::ObjectSP();
161         default:
162             return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
163     }
164 }
165 
166 //----------------------------------------------------------------------
167 // PythonString
168 //----------------------------------------------------------------------
169 
170 PythonString::PythonString(PyRefType type, PyObject *py_obj)
171     : PythonObject()
172 {
173     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
174 }
175 
176 PythonString::PythonString(const PythonString &object)
177     : PythonObject(object)
178 {
179 }
180 
181 PythonString::PythonString(llvm::StringRef string)
182     : PythonObject()
183 {
184     SetString(string);
185 }
186 
187 PythonString::PythonString(const char *string)
188     : PythonObject()
189 {
190     SetString(llvm::StringRef(string));
191 }
192 
193 PythonString::PythonString()
194     : PythonObject()
195 {
196 }
197 
198 PythonString::~PythonString ()
199 {
200 }
201 
202 bool
203 PythonString::Check(PyObject *py_obj)
204 {
205     if (!py_obj)
206         return false;
207 
208     if (PyUnicode_Check(py_obj))
209         return true;
210 #if PY_MAJOR_VERSION < 3
211     if (PyString_Check(py_obj))
212         return true;
213 #endif
214     return false;
215 }
216 
217 void
218 PythonString::Reset(PyRefType type, PyObject *py_obj)
219 {
220     // Grab the desired reference type so that if we end up rejecting
221     // `py_obj` it still gets decremented if necessary.
222     PythonObject result(type, py_obj);
223 
224     if (!PythonString::Check(py_obj))
225     {
226         PythonObject::Reset();
227         return;
228     }
229 #if PY_MAJOR_VERSION < 3
230     // In Python 2, Don't store PyUnicode objects directly, because we need
231     // access to their underlying character buffers which Python 2 doesn't
232     // provide.
233     if (PyUnicode_Check(py_obj))
234         result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
235 #endif
236     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
237     // back into the virtual implementation.
238     PythonObject::Reset(PyRefType::Borrowed, result.get());
239 }
240 
241 llvm::StringRef
242 PythonString::GetString() const
243 {
244     if (!IsValid())
245         return llvm::StringRef();
246 
247     Py_ssize_t size;
248     char *c;
249 
250 #if PY_MAJOR_VERSION >= 3
251     c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
252 #else
253     PyString_AsStringAndSize(m_py_obj, &c, &size);
254 #endif
255     return llvm::StringRef(c, size);
256 }
257 
258 size_t
259 PythonString::GetSize() const
260 {
261     if (IsValid())
262     {
263 #if PY_MAJOR_VERSION >= 3
264         return PyUnicode_GetSize(m_py_obj);
265 #else
266         return PyString_Size(m_py_obj);
267 #endif
268     }
269     return 0;
270 }
271 
272 void
273 PythonString::SetString (llvm::StringRef string)
274 {
275 #if PY_MAJOR_VERSION >= 3
276     PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
277     PythonObject::Reset(PyRefType::Owned, unicode);
278 #else
279     PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
280     PythonObject::Reset(PyRefType::Owned, str);
281 #endif
282 }
283 
284 StructuredData::StringSP
285 PythonString::CreateStructuredString() const
286 {
287     StructuredData::StringSP result(new StructuredData::String);
288     result->SetValue(GetString());
289     return result;
290 }
291 
292 //----------------------------------------------------------------------
293 // PythonInteger
294 //----------------------------------------------------------------------
295 
296 PythonInteger::PythonInteger()
297     : PythonObject()
298 {
299 
300 }
301 
302 PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
303     : PythonObject()
304 {
305     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
306 }
307 
308 PythonInteger::PythonInteger(const PythonInteger &object)
309     : PythonObject(object)
310 {
311 }
312 
313 PythonInteger::PythonInteger(int64_t value)
314     : PythonObject()
315 {
316     SetInteger(value);
317 }
318 
319 
320 PythonInteger::~PythonInteger ()
321 {
322 }
323 
324 bool
325 PythonInteger::Check(PyObject *py_obj)
326 {
327     if (!py_obj)
328         return false;
329 
330 #if PY_MAJOR_VERSION >= 3
331     // Python 3 does not have PyInt_Check.  There is only one type of
332     // integral value, long.
333     return PyLong_Check(py_obj);
334 #else
335     return PyLong_Check(py_obj) || PyInt_Check(py_obj);
336 #endif
337 }
338 
339 void
340 PythonInteger::Reset(PyRefType type, PyObject *py_obj)
341 {
342     // Grab the desired reference type so that if we end up rejecting
343     // `py_obj` it still gets decremented if necessary.
344     PythonObject result(type, py_obj);
345 
346     if (!PythonInteger::Check(py_obj))
347     {
348         PythonObject::Reset();
349         return;
350     }
351 
352 #if PY_MAJOR_VERSION < 3
353     // Always store this as a PyLong, which makes interoperability between
354     // Python 2.x and Python 3.x easier.  This is only necessary in 2.x,
355     // since 3.x doesn't even have a PyInt.
356     if (PyInt_Check(py_obj))
357     {
358         // Since we converted the original object to a different type, the new
359         // object is an owned object regardless of the ownership semantics requested
360         // by the user.
361         result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
362     }
363 #endif
364 
365     assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
366 
367     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
368     // back into the virtual implementation.
369     PythonObject::Reset(PyRefType::Borrowed, result.get());
370 }
371 
372 int64_t
373 PythonInteger::GetInteger() const
374 {
375     if (m_py_obj)
376     {
377         assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
378 
379         return PyLong_AsLongLong(m_py_obj);
380     }
381     return UINT64_MAX;
382 }
383 
384 void
385 PythonInteger::SetInteger(int64_t value)
386 {
387     PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
388 }
389 
390 StructuredData::IntegerSP
391 PythonInteger::CreateStructuredInteger() const
392 {
393     StructuredData::IntegerSP result(new StructuredData::Integer);
394     result->SetValue(GetInteger());
395     return result;
396 }
397 
398 //----------------------------------------------------------------------
399 // PythonList
400 //----------------------------------------------------------------------
401 
402 PythonList::PythonList(PyInitialValue value)
403     : PythonObject()
404 {
405     if (value == PyInitialValue::Empty)
406         Reset(PyRefType::Owned, PyList_New(0));
407 }
408 
409 PythonList::PythonList(int list_size)
410     : PythonObject()
411 {
412     Reset(PyRefType::Owned, PyList_New(list_size));
413 }
414 
415 PythonList::PythonList(PyRefType type, PyObject *py_obj)
416     : PythonObject()
417 {
418     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
419 }
420 
421 PythonList::PythonList(const PythonList &list)
422     : PythonObject(list)
423 {
424 }
425 
426 PythonList::~PythonList ()
427 {
428 }
429 
430 bool
431 PythonList::Check(PyObject *py_obj)
432 {
433     if (!py_obj)
434         return false;
435     return PyList_Check(py_obj);
436 }
437 
438 void
439 PythonList::Reset(PyRefType type, PyObject *py_obj)
440 {
441     // Grab the desired reference type so that if we end up rejecting
442     // `py_obj` it still gets decremented if necessary.
443     PythonObject result(type, py_obj);
444 
445     if (!PythonList::Check(py_obj))
446     {
447         PythonObject::Reset();
448         return;
449     }
450 
451     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
452     // back into the virtual implementation.
453     PythonObject::Reset(PyRefType::Borrowed, result.get());
454 }
455 
456 uint32_t
457 PythonList::GetSize() const
458 {
459     if (IsValid())
460         return PyList_GET_SIZE(m_py_obj);
461     return 0;
462 }
463 
464 PythonObject
465 PythonList::GetItemAtIndex(uint32_t index) const
466 {
467     if (IsValid())
468         return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
469     return PythonObject();
470 }
471 
472 void
473 PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
474 {
475     if (IsAllocated() && object.IsValid())
476     {
477         // PyList_SetItem is documented to "steal" a reference, so we need to
478         // convert it to an owned reference by incrementing it.
479         Py_INCREF(object.get());
480         PyList_SetItem(m_py_obj, index, object.get());
481     }
482 }
483 
484 void
485 PythonList::AppendItem(const PythonObject &object)
486 {
487     if (IsAllocated() && object.IsValid())
488     {
489         // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
490         // here like we do with `PyList_SetItem`.
491         PyList_Append(m_py_obj, object.get());
492     }
493 }
494 
495 StructuredData::ArraySP
496 PythonList::CreateStructuredArray() const
497 {
498     StructuredData::ArraySP result(new StructuredData::Array);
499     uint32_t count = GetSize();
500     for (uint32_t i = 0; i < count; ++i)
501     {
502         PythonObject obj = GetItemAtIndex(i);
503         result->AddItem(obj.CreateStructuredObject());
504     }
505     return result;
506 }
507 
508 //----------------------------------------------------------------------
509 // PythonDictionary
510 //----------------------------------------------------------------------
511 
512 PythonDictionary::PythonDictionary(PyInitialValue value)
513     : PythonObject()
514 {
515     if (value == PyInitialValue::Empty)
516         Reset(PyRefType::Owned, PyDict_New());
517 }
518 
519 PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
520     : PythonObject()
521 {
522     Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
523 }
524 
525 PythonDictionary::PythonDictionary(const PythonDictionary &object)
526     : PythonObject(object)
527 {
528 }
529 
530 PythonDictionary::~PythonDictionary ()
531 {
532 }
533 
534 bool
535 PythonDictionary::Check(PyObject *py_obj)
536 {
537     if (!py_obj)
538         return false;
539 
540     return PyDict_Check(py_obj);
541 }
542 
543 void
544 PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
545 {
546     // Grab the desired reference type so that if we end up rejecting
547     // `py_obj` it still gets decremented if necessary.
548     PythonObject result(type, py_obj);
549 
550     if (!PythonDictionary::Check(py_obj))
551     {
552         PythonObject::Reset();
553         return;
554     }
555 
556     // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
557     // back into the virtual implementation.
558     PythonObject::Reset(PyRefType::Borrowed, result.get());
559 }
560 
561 uint32_t
562 PythonDictionary::GetSize() const
563 {
564     if (IsValid())
565         return PyDict_Size(m_py_obj);
566     return 0;
567 }
568 
569 PythonList
570 PythonDictionary::GetKeys() const
571 {
572     if (IsValid())
573         return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
574     return PythonList(PyInitialValue::Invalid);
575 }
576 
577 PythonObject
578 PythonDictionary::GetItemForKey(const PythonObject &key) const
579 {
580     if (IsAllocated() && key.IsValid())
581         return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
582     return PythonObject();
583 }
584 
585 void
586 PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
587 {
588     if (IsAllocated() && key.IsValid() && value.IsValid())
589         PyDict_SetItem(m_py_obj, key.get(), value.get());
590 }
591 
592 StructuredData::DictionarySP
593 PythonDictionary::CreateStructuredDictionary() const
594 {
595     StructuredData::DictionarySP result(new StructuredData::Dictionary);
596     PythonList keys(GetKeys());
597     uint32_t num_keys = keys.GetSize();
598     for (uint32_t i = 0; i < num_keys; ++i)
599     {
600         PythonObject key = keys.GetItemAtIndex(i);
601         PythonObject value = GetItemForKey(key);
602         StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
603         result->AddItem(key.Str().GetString(), structured_value);
604     }
605     return result;
606 }
607 
608 PythonFile::PythonFile(File &file, const char *mode)
609 {
610     Reset(file, mode);
611 }
612 
613 PythonFile::PythonFile(const char *path, const char *mode)
614 {
615     FILE *fp = nullptr;
616     fp = fopen(path, mode);
617     lldb_private::File file(fp, true);
618     Reset(file, mode);
619 }
620 
621 PythonFile::PythonFile(PyRefType type, PyObject *o)
622 {
623     Reset(type, o);
624 }
625 
626 PythonFile::~PythonFile()
627 {
628 }
629 
630 bool
631 PythonFile::Check(PyObject *py_obj)
632 {
633 #if PY_MAJOR_VERSION < 3
634     return PyFile_Check(py_obj);
635 #else
636     // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
637     // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper
638     // over `io.open()`, which returns some object derived from `io.IOBase`.
639     // As a result, the only way to detect a file in Python 3 is to check whether
640     // it inherits from `io.IOBase`.  Since it is possible for non-files to also
641     // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
642     // attribute, which should guarantee that it is backed by the file system.
643     PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
644     PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
645     PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
646 
647     PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
648 
649     if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
650         return false;
651     if (!object_type.HasAttribute("fileno"))
652         return false;
653 
654     return true;
655 #endif
656 }
657 
658 void
659 PythonFile::Reset(PyRefType type, PyObject *py_obj)
660 {
661     // Grab the desired reference type so that if we end up rejecting
662     // `py_obj` it still gets decremented if necessary.
663     PythonObject result(type, py_obj);
664 
665     if (!PythonFile::Check(py_obj))
666     {
667         PythonObject::Reset();
668         return;
669     }
670 
671     // Calling PythonObject::Reset(const PythonObject&) will lead to stack
672     // overflow since it calls back into the virtual implementation.
673     PythonObject::Reset(PyRefType::Borrowed, result.get());
674 }
675 
676 void
677 PythonFile::Reset(File &file, const char *mode)
678 {
679     char *cmode = const_cast<char *>(mode);
680 #if PY_MAJOR_VERSION >= 3
681     Reset(PyRefType::Owned,
682         PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
683 #else
684     // Read through the Python source, doesn't seem to modify these strings
685     Reset(PyRefType::Owned,
686         PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
687 #endif
688 }
689 
690 bool
691 PythonFile::GetUnderlyingFile(File &file) const
692 {
693     if (!IsValid())
694         return false;
695 
696     file.Close();
697     // We don't own the file descriptor returned by this function, make sure the
698     // File object knows about that.
699     file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
700     return file.IsValid();
701 }
702 
703 
704 #endif
705