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 @@ -8,10 +8,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -24,10 +21,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -40,10 +34,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; @@ -71,10 +62,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -88,10 +76,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -121,10 +106,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; @@ -150,10 +132,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; %pythoncode %{ @@ -179,10 +158,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -195,10 +171,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -211,10 +184,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; @@ -242,10 +212,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -258,10 +225,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -274,10 +238,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -290,10 +251,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; @@ -321,10 +279,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -337,10 +292,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -353,10 +305,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; @@ -384,10 +333,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -401,10 +347,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; @@ -432,10 +375,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -449,10 +389,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -466,10 +403,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -482,10 +416,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; @@ -526,10 +457,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; %pythoncode %{ @@ -555,10 +483,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -571,10 +496,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -588,10 +510,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; @@ -619,10 +538,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -635,10 +551,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -651,10 +564,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; %pythoncode %{ @@ -680,10 +590,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -696,10 +603,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -712,10 +616,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -728,10 +629,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -744,10 +642,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; %pythoncode %{ @@ -773,10 +668,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; %pythoncode %{ @@ -802,10 +694,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; %pythoncode %{ @@ -831,10 +720,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; %pythoncode %{ @@ -860,10 +746,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -885,10 +768,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).release(); } %clearnothreadallow; } @@ -901,10 +781,7 @@ size_t desc_len = description.GetSize(); 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(); - else - return lldb_private::PythonString("").release(); + return PythonString(llvm::StringRef(desc, desc_len)).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,6 @@ /* 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 +29,6 @@ %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 +53,6 @@ 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 +61,6 @@ %typemap(in) lldb::tid_t { - using namespace lldb_private; if (PythonInteger::Check($input)) { PythonInteger py_int(PyRefType::Borrowed, $input); @@ -78,7 +74,6 @@ } %typemap(in) lldb::StateType { - using namespace lldb_private; if (PythonInteger::Check($input)) { PythonInteger py_int(PyRefType::Borrowed, $input); @@ -122,12 +117,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 +137,6 @@ // 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 +160,6 @@ // 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 +207,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 +367,6 @@ %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 +379,6 @@ } %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 +391,6 @@ } %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 +403,6 @@ } %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 +415,7 @@ } %typecheck(SWIG_TYPECHECK_POINTER) lldb::FileSP { - if (lldb_private::PythonFile::Check($input)) { + if (PythonFile::Check($input)) { $1 = 1; } else { PyErr_Clear(); @@ -435,7 +424,6 @@ } %typemap(out) lldb::FileSP { - using namespace lldb_private; $result = nullptr; lldb::FileSP &sp = $1; if (sp) { @@ -452,7 +440,6 @@ } %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,6 @@ 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 +82,6 @@ const lldb::WatchpointSP& wp_sp ) { - using namespace lldb_private; lldb::SBFrame sb_frame (frame_sp); lldb::SBWatchpoint sb_wp(wp_sp); @@ -118,7 +116,6 @@ std::string& retval ) { - using namespace lldb_private; lldb::SBValue sb_value (valobj_sp); lldb::SBTypeSummaryOptions sb_options(options_sp.get()); @@ -190,8 +187,6 @@ 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 +223,6 @@ 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 +254,6 @@ 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 +312,6 @@ bool &got_error ) { - using namespace lldb_private; got_error = false; @@ -368,7 +360,6 @@ 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 +403,6 @@ lldb_private::SymbolContext *sym_ctx ) { - using namespace lldb_private; PyErr_Cleaner py_err_cleaner(false); PythonObject self(PyRefType::Borrowed, static_cast(implementor)); @@ -464,7 +454,6 @@ bool* was_found = NULL ) { - using namespace lldb_private; PyErr_Cleaner py_err_cleaner(false); @@ -493,7 +482,6 @@ uint32_t max ) { - using namespace lldb_private; PythonObject self(PyRefType::Borrowed, implementor); auto pfunc = self.ResolveName("num_children"); @@ -536,7 +524,6 @@ uint32_t idx ) { - using namespace lldb_private; PyErr_Cleaner py_err_cleaner(true); PythonObject self(PyRefType::Borrowed, implementor); @@ -567,7 +554,6 @@ const char* child_name ) { - using namespace lldb_private; PyErr_Cleaner py_err_cleaner(true); PythonObject self(PyRefType::Borrowed, implementor); @@ -687,7 +673,6 @@ 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 +713,6 @@ 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 +744,6 @@ 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 +778,6 @@ 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 +805,6 @@ const lldb::StackFrameSP& frame_sp ) { - using namespace lldb_private; static char callee_name[] = "get_recognized_arguments"; @@ -839,7 +820,6 @@ 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 +846,6 @@ std::string& output) { - using namespace lldb_private; if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -896,7 +875,6 @@ std::string& output) { - using namespace lldb_private; if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -926,7 +904,6 @@ std::string& output) { - using namespace lldb_private; if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -956,7 +933,6 @@ std::string& output) { - using namespace lldb_private; if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -986,7 +962,6 @@ std::string& output) { - using namespace lldb_private; if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) return false; @@ -1016,7 +991,6 @@ 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,19 @@ 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 +203,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 +219,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 +245,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 +310,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 +343,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 +383,6 @@ PyObject *m_py_obj; }; -namespace python { // This is why C++ needs monads. template llvm::Expected As(llvm::Expected &&obj) { @@ -409,7 +402,6 @@ template <> llvm::Expected As(llvm::Expected &&obj); -} // namespace python template class TypedPythonObject : public PythonObject { public: @@ -417,16 +409,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 +686,8 @@ ~PythonException(); void log(llvm::raw_ostream &OS) const override; std::error_code convertToErrorCode() const override; + bool Matches(PyObject *exc) const; + std::string ReadBacktrace() const; }; // This extracts the underlying T out of an Expected and returns it. @@ -732,7 +722,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 +730,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,44 @@ 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::ReadBacktrace() 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) { + std::string message = + std::string(toCString()) + "\n" + + "Traceback unavailble, an error occurred while reading it:\n"; + return (message + llvm::toString(backtrace.takeError())); + } + + return std::move(backtrace.get()); +} + char PythonException::ID = 0; llvm::Expected @@ -1496,4 +1514,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 @@ -363,25 +363,25 @@ eIOHandlerWatchpoint }; - PythonObject &GetMainModule(); + python::PythonModule &GetMainModule(); - PythonDictionary &GetSessionDictionary(); + python::PythonDictionary &GetSessionDictionary(); - PythonDictionary &GetSysModuleDictionary(); + python::PythonDictionary &GetSysModuleDictionary(); bool GetEmbeddedInterpreterModuleObjects(); bool SetStdHandle(lldb::FileSP file, const char *py_name, - PythonObject &save_file, const char *mode); - - PythonObject m_saved_stdin; - PythonObject m_saved_stdout; - PythonObject m_saved_stderr; - PythonObject m_main_module; - PythonDictionary m_session_dict; - PythonDictionary m_sys_module_dict; - PythonObject m_run_one_line_function; - PythonObject m_run_one_line_str_global; + python::PythonObject &save_file, const char *mode); + + python::PythonObject m_saved_stdin; + python::PythonObject m_saved_stdout; + python::PythonObject m_saved_stderr; + python::PythonModule m_main_module; + python::PythonDictionary m_session_dict; + python::PythonDictionary m_sys_module_dict; + python::PythonObject m_run_one_line_function; + python::PythonObject m_run_one_line_str_global; std::string m_dictionary_name; ActiveIOHandler m_active_io_handler; bool m_session_is_active; 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,86 @@ } #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); + + EXPECT_THAT_EXPECTED(As(factorial(5ll)), llvm::HasValue(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")))); + + static const char script2[] = R"( +class MyError(Exception): + def __str__(self): + return self.my_message + +def main(): + raise MyError("lol") + +)"; + + PythonScript lol(script2); + + EXPECT_THAT_EXPECTED(lol(), + llvm::Failed(testing::Property( + &PythonException::ReadBacktrace, + testing::ContainsRegex("unprintable MyError")))); +} + +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::HasValue("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(); -}