diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -65,6 +65,9 @@ bool GetSetLLDBGlobals() const { return m_set_lldb_globals; } + // If this is true then any exceptions raised by the script will be + // cleared with PyErr_Clear(). If false then they will be left for + // the caller to clean up bool GetMaskoutErrors() const { return m_maskout_errors; } ExecuteScriptOptions &SetEnableIO(bool enable) { diff --git a/lldb/scripts/Python/python-extensions.swig b/lldb/scripts/Python/python-extensions.swig --- a/lldb/scripts/Python/python-extensions.swig +++ b/lldb/scripts/Python/python-extensions.swig @@ -9,9 +9,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -25,9 +25,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -41,9 +41,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; @@ -72,9 +72,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -89,9 +89,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -122,9 +122,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; @@ -151,9 +151,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; %pythoncode %{ @@ -180,9 +180,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -196,9 +196,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -212,9 +212,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; @@ -243,9 +243,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -259,9 +259,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -275,9 +275,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -291,9 +291,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; @@ -322,9 +322,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -338,9 +338,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -354,9 +354,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; @@ -385,9 +385,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -402,9 +402,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; @@ -433,9 +433,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -450,9 +450,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -467,9 +467,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -483,9 +483,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; @@ -527,9 +527,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; %pythoncode %{ @@ -556,9 +556,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -572,9 +572,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -589,9 +589,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; @@ -620,9 +620,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -636,9 +636,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -652,9 +652,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; %pythoncode %{ @@ -681,9 +681,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -697,9 +697,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -713,9 +713,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -729,9 +729,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -745,9 +745,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; %pythoncode %{ @@ -774,9 +774,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; %pythoncode %{ @@ -803,9 +803,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; %pythoncode %{ @@ -832,9 +832,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; %pythoncode %{ @@ -861,9 +861,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -886,9 +886,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } @@ -902,9 +902,9 @@ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r')) --desc_len; if (desc_len > 0) - return lldb_private::PythonString(llvm::StringRef(desc, desc_len)).release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); else - return lldb_private::PythonString("").release(); + return PythonString("").release(); } %clearnothreadallow; } diff --git a/lldb/scripts/Python/python-typemaps.swig b/lldb/scripts/Python/python-typemaps.swig --- a/lldb/scripts/Python/python-typemaps.swig +++ b/lldb/scripts/Python/python-typemaps.swig @@ -1,7 +1,7 @@ /* Typemap definitions, to allow SWIG to properly handle 'char**' data types. */ %typemap(in) char ** { - using namespace lldb_private; + /* Check if is a list */ if (PythonList::Check($input)) { PythonList list(PyRefType::Borrowed, $input); @@ -30,7 +30,7 @@ %typemap(typecheck) char ** { /* Check if is a list */ $1 = 1; - using namespace lldb_private; + if (PythonList::Check($input)) { PythonList list(PyRefType::Borrowed, $input); int size = list.GetSize(); @@ -55,7 +55,7 @@ int i; len = 0; while ($1[len]) len++; - using namespace lldb_private; + PythonList list(len); for (i = 0; i < len; i++) list.SetItemAtIndex(i, PythonString($1[i])); @@ -64,7 +64,7 @@ %typemap(in) lldb::tid_t { - using namespace lldb_private; + if (PythonInteger::Check($input)) { PythonInteger py_int(PyRefType::Borrowed, $input); @@ -78,7 +78,7 @@ } %typemap(in) lldb::StateType { - using namespace lldb_private; + if (PythonInteger::Check($input)) { PythonInteger py_int(PyRefType::Borrowed, $input); @@ -122,12 +122,12 @@ %typemap(argout) (char *dst, size_t dst_len) { Py_XDECREF($result); /* Blow away any previous result */ if (result == 0) { - lldb_private::PythonString string(""); + PythonString string(""); $result = string.release(); Py_INCREF($result); } else { llvm::StringRef ref(static_cast($1), result); - lldb_private::PythonString string(ref); + PythonString string(ref); $result = string.release(); } free($1); @@ -142,7 +142,7 @@ // Ditto for SBProcess::PutSTDIN(const char *src, size_t src_len). %typemap(in) (const char *cstr, uint32_t cstr_len), (const char *src, size_t src_len) { - using namespace lldb_private; + if (PythonString::Check($input)) { PythonString str(PyRefType::Borrowed, $input); $1 = (char*)str.GetString().data(); @@ -166,7 +166,7 @@ // For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput. %typemap(in) (const void *buf, size_t size), (const void *data, size_t data_len) { - using namespace lldb_private; + if (PythonString::Check($input)) { PythonString str(PyRefType::Borrowed, $input); $1 = (void*)str.GetString().data(); @@ -214,7 +214,7 @@ $result = Py_None; Py_INCREF($result); } else { - lldb_private::PythonBytes bytes(static_cast($1), result); + PythonBytes bytes(static_cast($1), result); $result = bytes.release(); } free($1); @@ -374,7 +374,7 @@ %typemap(in) lldb::FileSP { - using namespace lldb_private; + PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); @@ -387,7 +387,7 @@ } %typemap(in) lldb::FileSP FORCE_IO_METHODS { - using namespace lldb_private; + PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); @@ -400,7 +400,7 @@ } %typemap(in) lldb::FileSP BORROWED { - using namespace lldb_private; + PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); @@ -413,7 +413,7 @@ } %typemap(in) lldb::FileSP BORROWED_FORCE_IO_METHODS { - using namespace lldb_private; + PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { PyErr_SetString(PyExc_TypeError, "not a file"); @@ -426,7 +426,7 @@ } %typecheck(SWIG_TYPECHECK_POINTER) lldb::FileSP { - if (lldb_private::PythonFile::Check($input)) { + if (PythonFile::Check($input)) { $1 = 1; } else { PyErr_Clear(); @@ -435,7 +435,7 @@ } %typemap(out) lldb::FileSP { - using namespace lldb_private; + $result = nullptr; lldb::FileSP &sp = $1; if (sp) { @@ -452,7 +452,7 @@ } %typemap(in) (const char* string, int len) { - using namespace lldb_private; + if ($input == Py_None) { $1 = NULL; diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig --- a/lldb/scripts/Python/python-wrapper.swig +++ b/lldb/scripts/Python/python-wrapper.swig @@ -48,7 +48,7 @@ const lldb::BreakpointLocationSP& bp_loc_sp ) { - using namespace lldb_private; + lldb::SBFrame sb_frame (frame_sp); lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); @@ -83,7 +83,7 @@ const lldb::WatchpointSP& wp_sp ) { - using namespace lldb_private; + lldb::SBFrame sb_frame (frame_sp); lldb::SBWatchpoint sb_wp(wp_sp); @@ -118,7 +118,7 @@ std::string& retval ) { - using namespace lldb_private; + lldb::SBValue sb_value (valobj_sp); lldb::SBTypeSummaryOptions sb_options(options_sp.get()); @@ -190,7 +190,7 @@ const lldb::ValueObjectSP& valobj_sp ) { - using namespace lldb_private; + if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) Py_RETURN_NONE; @@ -228,7 +228,7 @@ const lldb::DebuggerSP debugger_sp ) { - using namespace lldb_private; + if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) Py_RETURN_NONE; @@ -260,7 +260,7 @@ const lldb::ThreadPlanSP& thread_plan_sp ) { - using namespace lldb_private; + if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) Py_RETURN_NONE; @@ -319,7 +319,7 @@ bool &got_error ) { - using namespace lldb_private; + got_error = false; @@ -368,7 +368,7 @@ lldb::BreakpointSP &breakpoint_sp ) { - using namespace lldb_private; + if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) Py_RETURN_NONE; @@ -412,7 +412,7 @@ lldb_private::SymbolContext *sym_ctx ) { - using namespace lldb_private; + PyErr_Cleaner py_err_cleaner(false); PythonObject self(PyRefType::Borrowed, static_cast(implementor)); @@ -464,7 +464,7 @@ bool* was_found = NULL ) { - using namespace lldb_private; + PyErr_Cleaner py_err_cleaner(false); @@ -493,7 +493,7 @@ uint32_t max ) { - using namespace lldb_private; + PythonObject self(PyRefType::Borrowed, implementor); auto pfunc = self.ResolveName("num_children"); @@ -536,7 +536,7 @@ uint32_t idx ) { - using namespace lldb_private; + PyErr_Cleaner py_err_cleaner(true); PythonObject self(PyRefType::Borrowed, implementor); @@ -567,7 +567,7 @@ const char* child_name ) { - using namespace lldb_private; + PyErr_Cleaner py_err_cleaner(true); PythonObject self(PyRefType::Borrowed, implementor); @@ -687,7 +687,7 @@ lldb::ExecutionContextRefSP exe_ctx_ref_sp ) { - using namespace lldb_private; + lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj); lldb::SBDebugger debugger_sb(debugger); lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp); @@ -728,7 +728,7 @@ lldb::ExecutionContextRefSP exe_ctx_ref_sp ) { - using namespace lldb_private; + lldb::SBCommandReturnObject cmd_retobj_sb(cmd_retobj); lldb::SBDebugger debugger_sb(debugger); lldb::SBExecutionContext exe_ctx_sb(exe_ctx_ref_sp); @@ -760,7 +760,7 @@ const lldb::ProcessSP& process_sp ) { - using namespace lldb_private; + if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) Py_RETURN_NONE; @@ -795,7 +795,7 @@ const char *session_dictionary_name ) { - using namespace lldb_private; + if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) Py_RETURN_NONE; @@ -823,7 +823,7 @@ const lldb::StackFrameSP& frame_sp ) { - using namespace lldb_private; + static char callee_name[] = "get_recognized_arguments"; @@ -839,7 +839,7 @@ SWIGEXPORT void* LLDBSWIGPython_GetDynamicSetting (void* module, const char* setting, const lldb::TargetSP& target_sp) { - using namespace lldb_private; + if (!module || !setting) Py_RETURN_NONE; @@ -866,7 +866,7 @@ std::string& output) { - using namespace lldb_private; + if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -896,7 +896,7 @@ std::string& output) { - using namespace lldb_private; + if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -926,7 +926,7 @@ std::string& output) { - using namespace lldb_private; + if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -956,7 +956,7 @@ std::string& output) { - using namespace lldb_private; + if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -986,7 +986,7 @@ std::string& output) { - using namespace lldb_private; + if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -1016,7 +1016,7 @@ lldb::DebuggerSP& debugger ) { - using namespace lldb_private; + std::string python_function_name_string = python_module_name; python_function_name_string += ".__lldb_init_module"; diff --git a/lldb/scripts/lldb.swig b/lldb/scripts/lldb.swig --- a/lldb/scripts/lldb.swig +++ b/lldb/scripts/lldb.swig @@ -174,6 +174,11 @@ #include "../source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h" #include "../scripts/Python/python-swigsafecast.swig" + +using namespace lldb_private; +using namespace lldb_private::python; +using namespace lldb; + %} /* Various liblldb typedefs that SWIG needs to know about. */ diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt --- a/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt +++ b/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt @@ -5,7 +5,6 @@ add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN PythonDataObjects.cpp - PythonExceptionState.cpp ScriptInterpreterPython.cpp LINK_LIBS diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -59,6 +59,7 @@ #include "llvm/ADT/ArrayRef.h" namespace lldb_private { +namespace python { class PythonObject; class PythonBytes; @@ -113,7 +114,6 @@ // not call Py_INCREF. }; -namespace python { // Take a reference that you already own, and turn it into // a PythonObject. @@ -175,7 +175,20 @@ operator const char *() { return str; } }; -} // namespace python +inline llvm::Error nullDeref() { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "A NULL PyObject* was dereferenced"); +} + +inline llvm::Error exception(const char *s = nullptr) { + return llvm::make_error(s); +} + +inline llvm::Error keyError() { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "key not in dict"); +} + enum class PyInitialValue { Invalid, Empty }; @@ -191,6 +204,11 @@ static auto get(long long value) { return value; } }; +template <> struct PythonFormat { + static constexpr char format = 'O'; + static auto get(PyObject *value) { return value; } +}; + template struct PythonFormat< T, typename std::enable_if::value>::type> { @@ -202,8 +220,14 @@ public: PythonObject() : m_py_obj(nullptr) {} - PythonObject(PyRefType type, PyObject *py_obj) : m_py_obj(nullptr) { - Reset(type, py_obj); + PythonObject(PyRefType type, PyObject *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 (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) + Py_XINCREF(m_py_obj); } PythonObject(const PythonObject &rhs) @@ -222,23 +246,6 @@ m_py_obj = nullptr; } - 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 (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) - Py_XINCREF(m_py_obj); - } - void Dump() const { if (m_py_obj) _PyObject_Dump(m_py_obj); @@ -304,17 +311,6 @@ StructuredData::ObjectSP CreateStructuredObject() const; protected: - static llvm::Error nullDeref() { - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "A NULL PyObject* was dereferenced"); - } - static llvm::Error exception(const char *s = nullptr) { - return llvm::make_error(s); - } - static llvm::Error keyError() { - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "key not in dict"); - } #if PY_MAJOR_VERSION < 3 // The python 2 API declares some arguments as char* that should @@ -348,7 +344,6 @@ } llvm::Expected GetAttribute(const llvm::Twine &name) const { - using namespace python; if (!m_py_obj) return nullDeref(); PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name)); @@ -389,7 +384,6 @@ PyObject *m_py_obj; }; -namespace python { // This is why C++ needs monads. template llvm::Expected As(llvm::Expected &&obj) { @@ -409,7 +403,6 @@ template <> llvm::Expected As(llvm::Expected &&obj); -} // namespace python template class TypedPythonObject : public PythonObject { public: @@ -417,16 +410,12 @@ // This can be eliminated once we drop python 2 support. static void Convert(PyRefType &type, PyObject *&py_obj) {} - void Reset() { PythonObject::Reset(); } - - void Reset(PyRefType type, PyObject *py_obj) = delete; - TypedPythonObject(PyRefType type, PyObject *py_obj) { if (!py_obj) return; T::Convert(type, py_obj); if (T::Check(py_obj)) - PythonObject::Reset(type, py_obj); + PythonObject::operator=(PythonObject(type, py_obj)); else if (type == PyRefType::Owned) Py_DECREF(py_obj); } @@ -698,6 +687,9 @@ ~PythonException(); void log(llvm::raw_ostream &OS) const override; std::error_code convertToErrorCode() const override; + bool Matches(PyObject *exc) const; + std::string ReadBacktraceRecursive(unsigned limit = 1u) const; + std::string ReadBacktrace() const { return ReadBacktraceRecursive(); }; }; // This extracts the underlying T out of an Expected and returns it. @@ -732,7 +724,6 @@ return T(); } -namespace python { // This is only here to help incrementally migrate old, exception-unsafe // code. template T unwrapIgnoringErrors(llvm::Expected expected) { @@ -741,8 +732,50 @@ llvm::consumeError(expected.takeError()); return T(); } -} // namespace python +llvm::Expected runStringOneLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals); + +llvm::Expected runStringMultiLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals); + +// Sometimes the best way to interact with a python interpreter is +// to run some python code. You construct a PythonScript with +// script string. The script assigns some function to `_function_` +// and you get a C++ callable object that calls the python function. +// +// Example: +// +// const char script[] = R"( +// def main(x, y): +// .... +// )"; +// +// Expected cpp_foo_wrapper(PythonObject x, PythonObject y) { +// // no need to synchronize access to this global, we already have the GIL +// static PythonScript foo(script) +// return foo(x, y); +// } +class PythonScript { + const char *script; + PythonCallable function; + + llvm::Error Init(); + +public: + PythonScript(const char *script) : script(script), function() {} + + template + llvm::Expected operator()(Args &&... args) { + if (llvm::Error error = Init()) + return std::move(error); + return function.Call(std::forward(args)...); + } +}; + +} // namespace python } // namespace lldb_private #endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -261,8 +261,7 @@ void PythonBytes::SetBytes(llvm::ArrayRef bytes) { const char *data = reinterpret_cast(bytes.data()); - PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size()); - PythonObject::Reset(PyRefType::Owned, py_bytes); + *this = Take(PyBytes_FromStringAndSize(data, bytes.size())); } StructuredData::StringSP PythonBytes::CreateStructuredString() const { @@ -486,7 +485,7 @@ } void PythonInteger::SetInteger(int64_t value) { - PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); + *this = Take(PyLong_FromLongLong(value)); } StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { @@ -510,7 +509,7 @@ } void PythonBoolean::SetValue(bool value) { - PythonObject::Reset(PyRefType::Owned, PyBool_FromLong(value)); + *this = Take(PyBool_FromLong(value)); } StructuredData::BooleanSP PythonBoolean::CreateStructuredBoolean() const { @@ -826,7 +825,7 @@ from inspect import signature, Parameter, ismethod from collections import namedtuple ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method']) -def get_arg_info(f): +def main(f): count = 0 varargs = False for parameter in signature(f).parameters.values(): @@ -852,28 +851,9 @@ #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 - // this global is protected by the GIL - static PythonCallable get_arg_info; - - if (!get_arg_info.IsValid()) { - PythonDictionary globals(PyInitialValue::Empty); - - auto builtins = PythonModule::BuiltinsModule(); - Error error = globals.SetItem("__builtins__", builtins); - if (error) - return std::move(error); - PyObject *o = PyRun_String(get_arg_info_script, Py_file_input, - globals.get(), globals.get()); - if (!o) - return exception(); - Take(o); - auto function = As(globals.GetItem("get_arg_info")); - if (!function) - return function.takeError(); - get_arg_info = std::move(function.get()); - } - - Expected pyarginfo = get_arg_info.Call(*this); + // no need to synchronize access to this global, we already have the GIL + static PythonScript get_arg_info(get_arg_info_script); + Expected pyarginfo = get_arg_info(*this); if (!pyarginfo) return pyarginfo.takeError(); result.count = cantFail(As(pyarginfo.get().GetAttribute("count"))); @@ -1056,6 +1036,54 @@ return llvm::inconvertibleErrorCode(); } +bool PythonException::Matches(PyObject *exc) const { + return PyErr_GivenExceptionMatches(m_exception_type, exc); +} + +const char read_exception_script[] = R"( +import sys +from traceback import print_exception +if sys.version_info.major < 3: + from StringIO import StringIO +else: + from io import StringIO +def main(exc_type, exc_value, tb): + f = StringIO() + print_exception(exc_type, exc_value, tb, file=f) + return f.getvalue() +)"; + +std::string PythonException::ReadBacktraceRecursive(unsigned limit) const { + + if (!m_traceback) + return toCString(); + + // no need to synchronize access to this global, we already have the GIL + static PythonScript read_exception(read_exception_script); + + Expected backtrace = As( + read_exception(m_exception_type, m_exception, m_traceback)); + + if (!backtrace) { + Twine message = + Twine(toCString()) + "\n" + + "Traceback unavailble, an error occurred while reading it:\n"; + if (limit == 0) + return (message + llvm::toString(backtrace.takeError())).str(); + + std::string backtrace2; + Error error = + llvm::handleErrors(backtrace.takeError(), [&](PythonException &E) { + backtrace2 = E.ReadBacktraceRecursive(limit - 1); + }); + if (error) + backtrace2 = llvm::toString(std::move(error)); + return (message + backtrace2).str(); + } + + return std::move(backtrace.get()); +} + char PythonException::ID = 0; llvm::Expected @@ -1496,4 +1524,69 @@ return Take(file_obj); } +Error PythonScript::Init() { + if (function.IsValid()) + return Error::success(); + + PythonDictionary globals(PyInitialValue::Empty); + auto builtins = PythonModule::BuiltinsModule(); + if (Error error = globals.SetItem("__builtins__", builtins)) + return error; + PyObject *o = + PyRun_String(script, Py_file_input, globals.get(), globals.get()); + if (!o) + return exception(); + Take(o); + auto f = As(globals.GetItem("main")); + if (!f) + return f.takeError(); + function = std::move(f.get()); + + return Error::success(); +} + +llvm::Expected +python::runStringOneLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals) { + if (!globals.IsValid() || !locals.IsValid()) + return nullDeref(); + + PyObject *code = + Py_CompileString(NullTerminated(string), "", Py_eval_input); + if (!code) { + PyErr_Clear(); + code = + Py_CompileString(NullTerminated(string), "", Py_single_input); + } + if (!code) + return exception(); + auto code_ref = Take(code); + +#if PY_MAJOR_VERSION < 3 + PyObject *result = + PyEval_EvalCode((PyCodeObject *)code, globals.get(), locals.get()); +#else + PyObject *result = PyEval_EvalCode(code, globals.get(), locals.get()); +#endif + + if (!result) + return exception(); + + return Take(result); +} + +llvm::Expected +python::runStringMultiLine(const llvm::Twine &string, + const PythonDictionary &globals, + const PythonDictionary &locals) { + if (!globals.IsValid() || !locals.IsValid()) + return nullDeref(); + PyObject *result = PyRun_String(NullTerminated(string), Py_file_input, + globals.get(), locals.get()); + if (!result) + return exception(); + return Take(result); +} + #endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h deleted file mode 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h +++ /dev/null @@ -1,56 +0,0 @@ -//===-- PythonExceptionState.h ----------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#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 diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp deleted file mode 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp +++ /dev/null @@ -1,169 +0,0 @@ -//===-- PythonExceptionState.cpp --------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#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("StringIO"); - if (!stringIO_builder.IsAllocated()) - return retval; - - auto stringIO_buffer = stringIO_builder(); - if (!stringIO_buffer.IsAllocated()) - return retval; - - auto printTB = traceback_module.ResolveName("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("getvalue"); - if (!stringIO_getvalue.IsAllocated()) - return retval; - - auto printTB_string = stringIO_getvalue().AsType(); - if (!printTB_string.IsAllocated()) - return retval; - - llvm::StringRef string_data(printTB_string.GetString()); - retval.assign(string_data.data(), string_data.size()); - - return retval; -} - -#endif diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -16,7 +16,6 @@ #include "lldb-python.h" #include "PythonDataObjects.h" -#include "PythonExceptionState.h" #include "ScriptInterpreterPythonImpl.h" #include "lldb/API/SBFrame.h" @@ -56,6 +55,7 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::python; +using llvm::Expected; // Defined in the SWIG source file #if PY_MAJOR_VERSION >= 3 @@ -747,9 +747,9 @@ return true; } -PythonObject &ScriptInterpreterPythonImpl::GetMainModule() { +PythonModule &ScriptInterpreterPythonImpl::GetMainModule() { if (!m_main_module.IsValid()) - m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__")); + m_main_module = unwrapIgnoringErrors(PythonModule::Import("__main__")); return m_main_module; } @@ -1030,6 +1030,7 @@ "can't interrupt"); return false; } + bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options) { @@ -1040,151 +1041,111 @@ Locker::NoSTDIN, Locker::FreeAcquiredLock | Locker::TearDownSession); - PythonObject py_return; - PythonObject &main_module = GetMainModule(); - PythonDictionary globals(PyRefType::Borrowed, - PyModule_GetDict(main_module.get())); - PythonObject py_error; - bool ret_success = false; - int success; + PythonModule &main_module = GetMainModule(); + PythonDictionary globals = main_module.GetDictionary(); PythonDictionary locals = GetSessionDictionary(); - - if (!locals.IsValid()) { + if (!locals.IsValid()) locals = unwrapIgnoringErrors( As(globals.GetAttribute(m_dictionary_name))); - } - if (!locals.IsValid()) locals = globals; - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) - PyErr_Clear(); - - std::string as_string = in_string.str(); - { // scope for PythonInputReaderManager - // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL); - py_return.Reset(PyRefType::Owned, - PyRun_String(as_string.c_str(), Py_eval_input, - globals.get(), locals.get())); - if (!py_return.IsValid()) { - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) - PyErr_Clear(); - - py_return.Reset(PyRefType::Owned, - PyRun_String(as_string.c_str(), Py_single_input, - globals.get(), locals.get())); - } + Expected maybe_py_return = + runStringOneLine(in_string, globals, locals); + + if (!maybe_py_return) { + llvm::handleAllErrors( + maybe_py_return.takeError(), + [&](PythonException &E) { + E.Restore(); + if (options.GetMaskoutErrors()) { + if (E.Matches(PyExc_SyntaxError)) { + PyErr_Print(); + } + PyErr_Clear(); + } + }, + [](const llvm::ErrorInfoBase &E) {}); + return false; } - if (py_return.IsValid()) { - switch (return_type) { - case eScriptReturnTypeCharPtr: // "char *" - { - const char format[3] = "s#"; - success = PyArg_Parse(py_return.get(), format, (char **)ret_value); - break; - } - case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == - // Py_None - { - const char format[3] = "z"; - success = PyArg_Parse(py_return.get(), format, (char **)ret_value); - break; - } - case eScriptReturnTypeBool: { - const char format[2] = "b"; - success = PyArg_Parse(py_return.get(), format, (bool *)ret_value); - break; - } - case eScriptReturnTypeShortInt: { - const char format[2] = "h"; - success = PyArg_Parse(py_return.get(), format, (short *)ret_value); - break; - } - case eScriptReturnTypeShortIntUnsigned: { - const char format[2] = "H"; - success = - PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value); - break; - } - case eScriptReturnTypeInt: { - const char format[2] = "i"; - success = PyArg_Parse(py_return.get(), format, (int *)ret_value); - break; - } - case eScriptReturnTypeIntUnsigned: { - const char format[2] = "I"; - success = PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value); - break; - } - case eScriptReturnTypeLongInt: { - const char format[2] = "l"; - success = PyArg_Parse(py_return.get(), format, (long *)ret_value); - break; - } - case eScriptReturnTypeLongIntUnsigned: { - const char format[2] = "k"; - success = - PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value); - break; - } - case eScriptReturnTypeLongLong: { - const char format[2] = "L"; - success = PyArg_Parse(py_return.get(), format, (long long *)ret_value); - break; - } - case eScriptReturnTypeLongLongUnsigned: { - const char format[2] = "K"; - success = - PyArg_Parse(py_return.get(), format, (unsigned long long *)ret_value); - break; - } - case eScriptReturnTypeFloat: { - const char format[2] = "f"; - success = PyArg_Parse(py_return.get(), format, (float *)ret_value); - break; - } - case eScriptReturnTypeDouble: { - const char format[2] = "d"; - success = PyArg_Parse(py_return.get(), format, (double *)ret_value); - break; - } - case eScriptReturnTypeChar: { - const char format[2] = "c"; - success = PyArg_Parse(py_return.get(), format, (char *)ret_value); - break; - } - case eScriptReturnTypeOpaqueObject: { - success = true; - PyObject *saved_value = py_return.get(); - Py_XINCREF(saved_value); - *((PyObject **)ret_value) = saved_value; - break; - } - } + PythonObject py_return = std::move(maybe_py_return.get()); + assert(py_return.IsValid()); - ret_success = success; + switch (return_type) { + case eScriptReturnTypeCharPtr: // "char *" + { + const char format[3] = "s#"; + return PyArg_Parse(py_return.get(), format, (char **)ret_value); + } + case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == + // Py_None + { + const char format[3] = "z"; + return PyArg_Parse(py_return.get(), format, (char **)ret_value); + } + case eScriptReturnTypeBool: { + const char format[2] = "b"; + return PyArg_Parse(py_return.get(), format, (bool *)ret_value); + } + case eScriptReturnTypeShortInt: { + const char format[2] = "h"; + return PyArg_Parse(py_return.get(), format, (short *)ret_value); + } + case eScriptReturnTypeShortIntUnsigned: { + const char format[2] = "H"; + return PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value); + } + case eScriptReturnTypeInt: { + const char format[2] = "i"; + return PyArg_Parse(py_return.get(), format, (int *)ret_value); + } + case eScriptReturnTypeIntUnsigned: { + const char format[2] = "I"; + return PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value); + } + case eScriptReturnTypeLongInt: { + const char format[2] = "l"; + return PyArg_Parse(py_return.get(), format, (long *)ret_value); + } + case eScriptReturnTypeLongIntUnsigned: { + const char format[2] = "k"; + return PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value); + } + case eScriptReturnTypeLongLong: { + const char format[2] = "L"; + return PyArg_Parse(py_return.get(), format, (long long *)ret_value); + } + case eScriptReturnTypeLongLongUnsigned: { + const char format[2] = "K"; + return PyArg_Parse(py_return.get(), format, + (unsigned long long *)ret_value); + } + case eScriptReturnTypeFloat: { + const char format[2] = "f"; + return PyArg_Parse(py_return.get(), format, (float *)ret_value); + } + case eScriptReturnTypeDouble: { + const char format[2] = "d"; + return PyArg_Parse(py_return.get(), format, (double *)ret_value); + } + case eScriptReturnTypeChar: { + const char format[2] = "c"; + return PyArg_Parse(py_return.get(), format, (char *)ret_value); + } + case eScriptReturnTypeOpaqueObject: { + *((PyObject **)ret_value) = py_return.release(); + return true; } - - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) { - ret_success = false; - if (options.GetMaskoutErrors()) { - if (PyErr_GivenExceptionMatches(py_error.get(), PyExc_SyntaxError)) - PyErr_Print(); - PyErr_Clear(); - } } - - return ret_success; } Status ScriptInterpreterPythonImpl::ExecuteMultipleLines( const char *in_string, const ExecuteScriptOptions &options) { - Status error; + + if (in_string == nullptr) + return Status(); Locker locker(this, Locker::AcquireLock | Locker::InitSession | @@ -1192,51 +1153,32 @@ Locker::NoSTDIN, Locker::FreeAcquiredLock | Locker::TearDownSession); - PythonObject return_value; - PythonObject &main_module = GetMainModule(); - PythonDictionary globals(PyRefType::Borrowed, - PyModule_GetDict(main_module.get())); - PythonObject py_error; + PythonModule &main_module = GetMainModule(); + PythonDictionary globals = main_module.GetDictionary(); PythonDictionary locals = GetSessionDictionary(); - if (!locals.IsValid()) locals = unwrapIgnoringErrors( As(globals.GetAttribute(m_dictionary_name))); - if (!locals.IsValid()) locals = globals; - py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); - if (py_error.IsValid()) - PyErr_Clear(); - - if (in_string != nullptr) { - PythonObject code_object; - code_object.Reset(PyRefType::Owned, - Py_CompileString(in_string, "temp.py", Py_file_input)); + Expected return_value = + runStringMultiLine(in_string, globals, locals); - if (code_object.IsValid()) { -// In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it -// takes a PyObject. They are convertible (hence the function -// PyCode_Check(PyObject*), so we have to do the cast for Python 2.x -#if PY_MAJOR_VERSION >= 3 - PyObject *py_code_obj = code_object.get(); -#else - PyCodeObject *py_code_obj = - reinterpret_cast(code_object.get()); -#endif - return_value.Reset( - PyRefType::Owned, - PyEval_EvalCode(py_code_obj, globals.get(), locals.get())); - } + if (!return_value) { + llvm::Error error = + llvm::handleErrors(return_value.takeError(), [&](PythonException &E) { + llvm::Error error = llvm::createStringError( + llvm::inconvertibleErrorCode(), E.ReadBacktrace()); + if (!options.GetMaskoutErrors()) + E.Restore(); + return error; + }); + return Status(std::move(error)); } - PythonExceptionState exception_state(!options.GetMaskoutErrors()); - if (exception_state.IsError()) - error.SetErrorString(exception_state.Format().c_str()); - - return error; + return Status(); } void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback( @@ -2030,15 +1972,22 @@ if (!generic) return StructuredData::DictionarySP(); - PythonObject reply_pyobj; Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); TargetSP target_sp(target->shared_from_this()); - reply_pyobj.Reset(PyRefType::Owned, - (PyObject *)LLDBSWIGPython_GetDynamicSetting( - generic->GetValue(), setting_name, target_sp)); - PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get()); + auto setting = (PyObject *)LLDBSWIGPython_GetDynamicSetting( + generic->GetValue(), setting_name, target_sp); + + if (!setting) + return StructuredData::DictionarySP(); + + PythonDictionary py_dict = + unwrapIgnoringErrors(As(Take(setting))); + + if (!py_dict) + return StructuredData::DictionarySP(); + return py_dict.CreateStructuredDictionary(); } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -23,6 +23,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +using namespace lldb_private::python; + namespace lldb_private { class IOHandlerPythonInterpreter; class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { @@ -363,7 +365,7 @@ eIOHandlerWatchpoint }; - PythonObject &GetMainModule(); + PythonModule &GetMainModule(); PythonDictionary &GetSessionDictionary(); @@ -377,7 +379,7 @@ PythonObject m_saved_stdin; PythonObject m_saved_stdout; PythonObject m_saved_stderr; - PythonObject m_main_module; + PythonModule m_main_module; PythonDictionary m_session_dict; PythonDictionary m_sys_module_dict; PythonObject m_run_one_line_function; diff --git a/lldb/unittests/ScriptInterpreter/Python/CMakeLists.txt b/lldb/unittests/ScriptInterpreter/Python/CMakeLists.txt --- a/lldb/unittests/ScriptInterpreter/Python/CMakeLists.txt +++ b/lldb/unittests/ScriptInterpreter/Python/CMakeLists.txt @@ -1,6 +1,5 @@ add_lldb_unittest(ScriptInterpreterPythonTests PythonDataObjectsTests.cpp - PythonExceptionStateTests.cpp PythonTestSuite.cpp LINK_LIBS diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp --- a/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp +++ b/lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp @@ -21,6 +21,8 @@ using namespace lldb_private; using namespace lldb_private::python; +using llvm::Error; +using llvm::Expected; class PythonDataObjectsTest : public PythonTestSuite { public: @@ -771,4 +773,72 @@ } #endif +} + +TEST_F(PythonDataObjectsTest, TestScript) { + + static const char script[] = R"( +def factorial(n): + if n > 1: + return n * factorial(n-1) + else: + return 1; +main = factorial +)"; + + PythonScript factorial(script); + Expected r = As(factorial(5ll)); + bool ok = (bool)r; + ASSERT_TRUE(ok); + EXPECT_EQ(r.get(), 120); +} + +TEST_F(PythonDataObjectsTest, TestExceptions) { + + static const char script[] = R"( +def foo(): + return bar() +def bar(): + return baz() +def baz(): + return 1 / 0 +main = foo +)"; + + PythonScript foo(script); + + EXPECT_THAT_EXPECTED(foo(), + llvm::Failed(testing::Property( + &PythonException::ReadBacktrace, + testing::ContainsRegex("line 3, in foo..*" + "line 5, in bar.*" + "line 7, in baz.*" + "ZeroDivisionError")))); +} + +TEST_F(PythonDataObjectsTest, TestRun) { + + PythonDictionary globals(PyInitialValue::Empty); + + auto x = As(runStringOneLine("40 + 2", globals, globals)); + ASSERT_THAT_EXPECTED(x, llvm::Succeeded()); + EXPECT_EQ(x.get(), 42l); + + Expected r = runStringOneLine("n = 42", globals, globals); + ASSERT_THAT_EXPECTED(r, llvm::Succeeded()); + auto y = As(globals.GetItem("n")); + ASSERT_THAT_EXPECTED(y, llvm::Succeeded()); + EXPECT_EQ(y.get(), 42l); + + const char script[] = R"( +def foobar(): + return "foo" + "bar" + "baz" +g = foobar() +)"; + + r = runStringMultiLine(script, globals, globals); + ASSERT_THAT_EXPECTED(r, llvm::Succeeded()); + auto g = As(globals.GetItem("g")); + ASSERT_THAT_EXPECTED(g, llvm::Succeeded()); + EXPECT_EQ(g.get(), "foobarbaz"); } \ No newline at end of file diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonExceptionStateTests.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonExceptionStateTests.cpp deleted file mode 100644 --- a/lldb/unittests/ScriptInterpreter/Python/PythonExceptionStateTests.cpp +++ /dev/null @@ -1,164 +0,0 @@ -//===-- PythonExceptionStateTest.cpp ------------------------------*- C++ -//-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "gtest/gtest.h" - -#include "Plugins/ScriptInterpreter/Python/PythonDataObjects.h" -#include "Plugins/ScriptInterpreter/Python/PythonExceptionState.h" -#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h" -#include "Plugins/ScriptInterpreter/Python/lldb-python.h" - -#include "PythonTestSuite.h" - -using namespace lldb_private; - -class PythonExceptionStateTest : public PythonTestSuite { -public: -protected: - void RaiseException() { - PyErr_SetString(PyExc_RuntimeError, "PythonExceptionStateTest test error"); - } -}; - -TEST_F(PythonExceptionStateTest, TestExceptionStateChecking) { - PyErr_Clear(); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - - RaiseException(); - EXPECT_TRUE(PythonExceptionState::HasErrorOccurred()); - - PyErr_Clear(); -} - -TEST_F(PythonExceptionStateTest, TestAcquisitionSemantics) { - PyErr_Clear(); - PythonExceptionState no_error(false); - EXPECT_FALSE(no_error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - - PyErr_Clear(); - RaiseException(); - PythonExceptionState error(false); - EXPECT_TRUE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - error.Discard(); - - PyErr_Clear(); - RaiseException(); - error.Acquire(false); - EXPECT_TRUE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - - PyErr_Clear(); -} - -TEST_F(PythonExceptionStateTest, TestDiscardSemantics) { - PyErr_Clear(); - - // Test that discarding an exception does not restore the exception - // state even when auto-restore==true is set - RaiseException(); - PythonExceptionState error(true); - EXPECT_TRUE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - - error.Discard(); - EXPECT_FALSE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); -} - -TEST_F(PythonExceptionStateTest, TestResetSemantics) { - PyErr_Clear(); - - // Resetting when auto-restore is true should restore. - RaiseException(); - PythonExceptionState error(true); - EXPECT_TRUE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - error.Reset(); - EXPECT_FALSE(error.IsError()); - EXPECT_TRUE(PythonExceptionState::HasErrorOccurred()); - - PyErr_Clear(); - - // Resetting when auto-restore is false should discard. - RaiseException(); - PythonExceptionState error2(false); - EXPECT_TRUE(error2.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - error2.Reset(); - EXPECT_FALSE(error2.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - - PyErr_Clear(); -} - -TEST_F(PythonExceptionStateTest, TestManualRestoreSemantics) { - PyErr_Clear(); - RaiseException(); - PythonExceptionState error(false); - EXPECT_TRUE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - - error.Restore(); - EXPECT_FALSE(error.IsError()); - EXPECT_TRUE(PythonExceptionState::HasErrorOccurred()); - - PyErr_Clear(); -} - -TEST_F(PythonExceptionStateTest, TestAutoRestoreSemantics) { - PyErr_Clear(); - // Test that using the auto-restore flag correctly restores the exception - // state on destruction, and not using the auto-restore flag correctly - // does NOT restore the state on destruction. - { - RaiseException(); - PythonExceptionState error(false); - EXPECT_TRUE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - } - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - - PyErr_Clear(); - { - RaiseException(); - PythonExceptionState error(true); - EXPECT_TRUE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - } - EXPECT_TRUE(PythonExceptionState::HasErrorOccurred()); - - PyErr_Clear(); -} - -TEST_F(PythonExceptionStateTest, TestAutoRestoreChanged) { - // Test that if we re-acquire with different auto-restore semantics, - // that the new semantics are respected. - PyErr_Clear(); - - RaiseException(); - PythonExceptionState error(false); - EXPECT_TRUE(error.IsError()); - - error.Reset(); - EXPECT_FALSE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - - RaiseException(); - error.Acquire(true); - EXPECT_TRUE(error.IsError()); - EXPECT_FALSE(PythonExceptionState::HasErrorOccurred()); - - error.Reset(); - EXPECT_FALSE(error.IsError()); - EXPECT_TRUE(PythonExceptionState::HasErrorOccurred()); - - PyErr_Clear(); -}