Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,15 @@
add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN
PythonDataObjects.cpp
PythonExceptionState.cpp
ScriptInterpreterPython.cpp
LINK_LIBS
lldbBreakpoint
lldbCore
lldbDataFormatters
lldbHost
lldbInterpreter
lldbTarget
LINK_COMPONENTS
Support
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,474 @@
//===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
#ifndef LLDB_DISABLE_PYTHON
// LLDB Python header must be included first
#include "lldb-python.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Utility/Flags.h"
#include "lldb/Host/File.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-defines.h"
#include "llvm/ADT/ArrayRef.h"
namespace lldb_private {
class PythonBytes;
class PythonString;
class PythonList;
class PythonDictionary;
class PythonInteger;
class StructuredPythonObject : public StructuredData::Generic {
public:
StructuredPythonObject() : StructuredData::Generic() {}
StructuredPythonObject(void *obj) : StructuredData::Generic(obj) {
Py_XINCREF(GetValue());
}
~StructuredPythonObject() override {
if (Py_IsInitialized())
Py_XDECREF(GetValue());
SetValue(nullptr);
}
bool IsValid() const override { return GetValue() && GetValue() != Py_None; }
void Dump(Stream &s, bool pretty_print = true) const override;
private:
DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
};
enum class PyObjectType {
Unknown,
None,
Integer,
Dictionary,
List,
String,
Bytes,
ByteArray,
Module,
Callable,
Tuple,
File
};
enum class PyRefType {
Borrowed, // We are not given ownership of the incoming PyObject.
// We cannot safely hold it without calling Py_INCREF.
Owned // We have ownership of the incoming PyObject. We should
// not call Py_INCREF.
};
enum class PyInitialValue { Invalid, Empty };
class PythonObject {
public:
PythonObject() : m_py_obj(nullptr) {}
PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) {
Reset(type, py_obj);
}
PythonObject(const PythonObject &rhs) : m_py_obj(nullptr) { Reset(rhs); }
virtual ~PythonObject() { Reset(); }
void Reset() {
// Avoid calling the virtual method since it's not necessary
// to actually validate the type of the PyObject if we're
// just setting to null.
if (Py_IsInitialized())
Py_XDECREF(m_py_obj);
m_py_obj = nullptr;
}
void Reset(const PythonObject &rhs) {
// Avoid calling the virtual method if it's not necessary
// to actually validate the type of the PyObject.
if (!rhs.IsValid())
Reset();
else
Reset(PyRefType::Borrowed, rhs.m_py_obj);
}
// PythonObject is implicitly convertible to PyObject *, which will call the
// wrong overload. We want to explicitly disallow this, since a PyObject
// *always* owns its reference. Therefore the overload which takes a
// PyRefType doesn't make sense, and the copy constructor should be used.
void Reset(PyRefType type, const PythonObject &ref) = delete;
virtual void Reset(PyRefType type, PyObject *py_obj) {
if (py_obj == m_py_obj)
return;
if (Py_IsInitialized())
Py_XDECREF(m_py_obj);
m_py_obj = py_obj;
// If this is a borrowed reference, we need to convert it to
// an owned reference by incrementing it. If it is an owned
// reference (for example the caller allocated it with PyDict_New()
// then we must *not* increment it.
if (Py_IsInitialized() && type == PyRefType::Borrowed)
Py_XINCREF(m_py_obj);
}
void Dump() const {
if (m_py_obj)
_PyObject_Dump(m_py_obj);
else
puts("NULL");
}
void Dump(Stream &strm) const;
PyObject *get() const { return m_py_obj; }
PyObject *release() {
PyObject *result = m_py_obj;
m_py_obj = nullptr;
return result;
}
PythonObject &operator=(const PythonObject &other) {
Reset(PyRefType::Borrowed, other.get());
return *this;
}
PyObjectType GetObjectType() const;
PythonString Repr() const;
PythonString Str() const;
static PythonObject ResolveNameWithDictionary(llvm::StringRef name,
const PythonDictionary &dict);
template <typename T>
static T ResolveNameWithDictionary(llvm::StringRef name,
const PythonDictionary &dict) {
return ResolveNameWithDictionary(name, dict).AsType<T>();
}
PythonObject ResolveName(llvm::StringRef name) const;
template <typename T> T ResolveName(llvm::StringRef name) const {
return ResolveName(name).AsType<T>();
}
bool HasAttribute(llvm::StringRef attribute) const;
PythonObject GetAttributeValue(llvm::StringRef attribute) const;
bool IsValid() const;
bool IsAllocated() const;
bool IsNone() const;
template <typename T> T AsType() const {
if (!T::Check(m_py_obj))
return T();
return T(PyRefType::Borrowed, m_py_obj);
}
StructuredData::ObjectSP CreateStructuredObject() const;
protected:
PyObject *m_py_obj;
};
class PythonBytes : public PythonObject {
public:
PythonBytes();
explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
PythonBytes(const uint8_t *bytes, size_t length);
PythonBytes(PyRefType type, PyObject *o);
PythonBytes(const PythonBytes &object);
~PythonBytes() override;
static bool Check(PyObject *py_obj);
// Bring in the no-argument base class version
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
llvm::ArrayRef<uint8_t> GetBytes() const;
size_t GetSize() const;
void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
StructuredData::StringSP CreateStructuredString() const;
};
class PythonByteArray : public PythonObject {
public:
PythonByteArray();
explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes);
PythonByteArray(const uint8_t *bytes, size_t length);
PythonByteArray(PyRefType type, PyObject *o);
PythonByteArray(const PythonBytes &object);
~PythonByteArray() override;
static bool Check(PyObject *py_obj);
// Bring in the no-argument base class version
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
llvm::ArrayRef<uint8_t> GetBytes() const;
size_t GetSize() const;
void SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
StructuredData::StringSP CreateStructuredString() const;
};
class PythonString : public PythonObject {
public:
PythonString();
explicit PythonString(llvm::StringRef string);
explicit PythonString(const char *string);
PythonString(PyRefType type, PyObject *o);
PythonString(const PythonString &object);
~PythonString() override;
static bool Check(PyObject *py_obj);
// Bring in the no-argument base class version
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
llvm::StringRef GetString() const;
size_t GetSize() const;
void SetString(llvm::StringRef string);
StructuredData::StringSP CreateStructuredString() const;
};
class PythonInteger : public PythonObject {
public:
PythonInteger();
explicit PythonInteger(int64_t value);
PythonInteger(PyRefType type, PyObject *o);
PythonInteger(const PythonInteger &object);
~PythonInteger() override;
static bool Check(PyObject *py_obj);
// Bring in the no-argument base class version
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
int64_t GetInteger() const;
void SetInteger(int64_t value);
StructuredData::IntegerSP CreateStructuredInteger() const;
};
class PythonList : public PythonObject {
public:
PythonList() {}
explicit PythonList(PyInitialValue value);
explicit PythonList(int list_size);
PythonList(PyRefType type, PyObject *o);
PythonList(const PythonList &list);
~PythonList() override;
static bool Check(PyObject *py_obj);
// Bring in the no-argument base class version
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
uint32_t GetSize() const;
PythonObject GetItemAtIndex(uint32_t index) const;
void SetItemAtIndex(uint32_t index, const PythonObject &object);
void AppendItem(const PythonObject &object);
StructuredData::ArraySP CreateStructuredArray() const;
};
class PythonTuple : public PythonObject {
public:
PythonTuple() {}
explicit PythonTuple(PyInitialValue value);
explicit PythonTuple(int tuple_size);
PythonTuple(PyRefType type, PyObject *o);
PythonTuple(const PythonTuple &tuple);
PythonTuple(std::initializer_list<PythonObject> objects);
PythonTuple(std::initializer_list<PyObject *> objects);
~PythonTuple() override;
static bool Check(PyObject *py_obj);
// Bring in the no-argument base class version
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
uint32_t GetSize() const;
PythonObject GetItemAtIndex(uint32_t index) const;
void SetItemAtIndex(uint32_t index, const PythonObject &object);
StructuredData::ArraySP CreateStructuredArray() const;
};
class PythonDictionary : public PythonObject {
public:
PythonDictionary() {}
explicit PythonDictionary(PyInitialValue value);
PythonDictionary(PyRefType type, PyObject *o);
PythonDictionary(const PythonDictionary &dict);
~PythonDictionary() override;
static bool Check(PyObject *py_obj);
// Bring in the no-argument base class version
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
uint32_t GetSize() const;
PythonList GetKeys() const;
PythonObject GetItemForKey(const PythonObject &key) const;
void SetItemForKey(const PythonObject &key, const PythonObject &value);
StructuredData::DictionarySP CreateStructuredDictionary() const;
};
class PythonModule : public PythonObject {
public:
PythonModule();
PythonModule(PyRefType type, PyObject *o);
PythonModule(const PythonModule &dict);
~PythonModule() override;
static bool Check(PyObject *py_obj);
static PythonModule BuiltinsModule();
static PythonModule MainModule();
static PythonModule AddModule(llvm::StringRef module);
static PythonModule ImportModule(llvm::StringRef module);
// Bring in the no-argument base class version
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
PythonDictionary GetDictionary() const;
};
class PythonCallable : public PythonObject {
public:
struct ArgInfo {
size_t count;
bool is_bound_method : 1;
bool has_varargs : 1;
bool has_kwargs : 1;
};
PythonCallable();
PythonCallable(PyRefType type, PyObject *o);
PythonCallable(const PythonCallable &dict);
~PythonCallable() override;
static bool Check(PyObject *py_obj);
// Bring in the no-argument base class version
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
ArgInfo GetNumArguments() const;
PythonObject operator()();
PythonObject operator()(std::initializer_list<PyObject *> args);
PythonObject operator()(std::initializer_list<PythonObject> args);
template <typename Arg, typename... Args>
PythonObject operator()(const Arg &arg, Args... args) {
return operator()({arg, args...});
}
};
class PythonFile : public PythonObject {
public:
PythonFile();
PythonFile(File &file, const char *mode);
PythonFile(const char *path, const char *mode);
PythonFile(PyRefType type, PyObject *o);
~PythonFile() override;
static bool Check(PyObject *py_obj);
using PythonObject::Reset;
void Reset(PyRefType type, PyObject *py_obj) override;
void Reset(File &file, const char *mode);
static uint32_t GetOptionsFromMode(llvm::StringRef mode);
bool GetUnderlyingFile(File &file) const;
};
} // namespace lldb_private
#endif
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H

View File

@ -0,0 +1,171 @@
//===-- PythonExceptionState.cpp --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_DISABLE_PYTHON
// LLDB Python header must be included first
#include "lldb-python.h"
#include "PythonExceptionState.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
using namespace lldb_private;
PythonExceptionState::PythonExceptionState(bool restore_on_exit)
: m_restore_on_exit(restore_on_exit) {
Acquire(restore_on_exit);
}
PythonExceptionState::~PythonExceptionState() {
if (m_restore_on_exit)
Restore();
}
void PythonExceptionState::Acquire(bool restore_on_exit) {
// If a state is already acquired, the user needs to decide whether they
// want to discard or restore it. Don't allow the potential silent
// loss of a valid state.
assert(!IsError());
if (!HasErrorOccurred())
return;
PyObject *py_type = nullptr;
PyObject *py_value = nullptr;
PyObject *py_traceback = nullptr;
PyErr_Fetch(&py_type, &py_value, &py_traceback);
// PyErr_Fetch clears the error flag.
assert(!HasErrorOccurred());
// Ownership of the objects returned by `PyErr_Fetch` is transferred
// to us.
m_type.Reset(PyRefType::Owned, py_type);
m_value.Reset(PyRefType::Owned, py_value);
m_traceback.Reset(PyRefType::Owned, py_traceback);
m_restore_on_exit = restore_on_exit;
}
void PythonExceptionState::Restore() {
if (m_type.IsValid()) {
// The documentation for PyErr_Restore says "Do not pass a null type and
// non-null value or traceback. So only restore if type was non-null
// to begin with. In this case we're passing ownership back to Python
// so release them all.
PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release());
}
// After we restore, we should not hold onto the exception state. Demand that
// it be re-acquired.
Discard();
}
void PythonExceptionState::Discard() {
m_type.Reset();
m_value.Reset();
m_traceback.Reset();
}
void PythonExceptionState::Reset() {
if (m_restore_on_exit)
Restore();
else
Discard();
}
bool PythonExceptionState::HasErrorOccurred() { return PyErr_Occurred(); }
bool PythonExceptionState::IsError() const {
return m_type.IsValid() || m_value.IsValid() || m_traceback.IsValid();
}
PythonObject PythonExceptionState::GetType() const { return m_type; }
PythonObject PythonExceptionState::GetValue() const { return m_value; }
PythonObject PythonExceptionState::GetTraceback() const { return m_traceback; }
std::string PythonExceptionState::Format() const {
// Don't allow this function to modify the error state.
PythonExceptionState state(true);
std::string backtrace = ReadBacktrace();
if (!IsError())
return std::string();
// It's possible that ReadPythonBacktrace generated another exception.
// If this happens we have to clear the exception, because otherwise
// PyObject_Str() will assert below. That's why we needed to do the
// save / restore at the beginning of this function.
PythonExceptionState bt_error_state(false);
std::string error_string;
llvm::raw_string_ostream error_stream(error_string);
error_stream << m_value.Str().GetString() << "\n";
if (!bt_error_state.IsError()) {
// If we were able to read the backtrace, just append it.
error_stream << backtrace << "\n";
} else {
// Otherwise, append some information about why we were unable to
// obtain the backtrace.
PythonString bt_error = bt_error_state.GetValue().Str();
error_stream << "An error occurred while retrieving the backtrace: "
<< bt_error.GetString() << "\n";
}
return error_stream.str();
}
std::string PythonExceptionState::ReadBacktrace() const {
std::string retval("backtrace unavailable");
auto traceback_module = PythonModule::ImportModule("traceback");
#if PY_MAJOR_VERSION >= 3
auto stringIO_module = PythonModule::ImportModule("io");
#else
auto stringIO_module = PythonModule::ImportModule("StringIO");
#endif
if (!m_traceback.IsAllocated())
return retval;
if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated())
return retval;
auto stringIO_builder =
stringIO_module.ResolveName<PythonCallable>("StringIO");
if (!stringIO_builder.IsAllocated())
return retval;
auto stringIO_buffer = stringIO_builder();
if (!stringIO_buffer.IsAllocated())
return retval;
auto printTB = traceback_module.ResolveName<PythonCallable>("print_tb");
if (!printTB.IsAllocated())
return retval;
auto printTB_result =
printTB(m_traceback.get(), Py_None, stringIO_buffer.get());
auto stringIO_getvalue =
stringIO_buffer.ResolveName<PythonCallable>("getvalue");
if (!stringIO_getvalue.IsAllocated())
return retval;
auto printTB_string = stringIO_getvalue().AsType<PythonString>();
if (!printTB_string.IsAllocated())
return retval;
llvm::StringRef string_data(printTB_string.GetString());
retval.assign(string_data.data(), string_data.size());
return retval;
}
#endif

View File

@ -0,0 +1,57 @@
//===-- PythonExceptionState.h ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H
#ifndef LLDB_DISABLE_PYTHON
#include "PythonDataObjects.h"
namespace lldb_private {
class PythonExceptionState {
public:
explicit PythonExceptionState(bool restore_on_exit);
~PythonExceptionState();
void Acquire(bool restore_on_exit);
void Restore();
void Discard();
void Reset();
static bool HasErrorOccurred();
bool IsError() const;
PythonObject GetType() const;
PythonObject GetValue() const;
PythonObject GetTraceback() const;
std::string Format() const;
private:
std::string ReadBacktrace() const;
bool m_restore_on_exit;
PythonObject m_type;
PythonObject m_value;
PythonObject m_traceback;
};
}
#endif
#endif

View File

@ -0,0 +1 @@
6c39690268c6e72d03f34c0d3c0704e3f13fbce3

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
//===-- lldb-python.h --------------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
// Python.h needs to be included before any system headers in order to avoid
// redefinition of macros
#ifdef LLDB_DISABLE_PYTHON
// Python is disabled in this build
#else
#include "llvm/Support/Compiler.h"
#if defined(LLVM_ON_WIN32)
// If anyone #includes Host/PosixApi.h later, it will try to typedef pid_t. We
// need to ensure this doesn't happen. At the same time, Python.h will also try
// to redefine a bunch of stuff that PosixApi.h defines. So define it all now
// so that PosixApi.h doesn't redefine it.
#define NO_PID_T
#endif
#if defined(__linux__)
// features.h will define _POSIX_C_SOURCE if _GNU_SOURCE is defined. This value
// may be different from the value that Python defines it to be which results
// in a warning. Undefine _POSIX_C_SOURCE before including Python.h The same
// holds for _XOPEN_SOURCE.
#undef _POSIX_C_SOURCE
#undef _XOPEN_SOURCE
#endif
// Include python for non windows machines
#include <Python.h>
#endif // LLDB_DISABLE_PYTHON
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H