diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -44,13 +44,21 @@ const char *GetError(); - size_t PutOutput(FILE *fh); + size_t PutOutput(FILE *fh); // DEPRECATED + + size_t PutOutput(SBFile file); + + size_t PutOutput(FileSP file); size_t GetOutputSize(); size_t GetErrorSize(); - size_t PutError(FILE *fh); + size_t PutError(FILE *fh); // DEPRECATED + + size_t PutError(SBFile file); + + size_t PutError(FileSP file); void Clear(); @@ -68,14 +76,21 @@ bool GetDescription(lldb::SBStream &description); - // deprecated, these two functions do not take ownership of file handle - void SetImmediateOutputFile(FILE *fh); + void SetImmediateOutputFile(FILE *fh); // DEPRECATED + + void SetImmediateErrorFile(FILE *fh); // DEPRECATED + + void SetImmediateOutputFile(FILE *fh, bool transfer_ownership); // DEPRECATED + + void SetImmediateErrorFile(FILE *fh, bool transfer_ownership); // DEPRECATED + + void SetImmediateOutputFile(SBFile file); - void SetImmediateErrorFile(FILE *fh); + void SetImmediateErrorFile(SBFile file); - void SetImmediateOutputFile(FILE *fh, bool transfer_ownership); + void SetImmediateOutputFile(FileSP file); - void SetImmediateErrorFile(FILE *fh, bool transfer_ownership); + void SetImmediateErrorFile(FileSP file); void PutCString(const char *string, int len = -1); diff --git a/lldb/include/lldb/API/SBFile.h b/lldb/include/lldb/API/SBFile.h --- a/lldb/include/lldb/API/SBFile.h +++ b/lldb/include/lldb/API/SBFile.h @@ -15,6 +15,7 @@ class LLDB_API SBFile { friend class SBDebugger; + friend class SBCommandReturnObject; public: SBFile(); diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -62,13 +62,13 @@ return m_err_stream; } - void SetImmediateOutputFile(FILE *fh, bool transfer_fh_ownership = false) { - lldb::StreamSP stream_sp(new StreamFile(fh, transfer_fh_ownership)); + void SetImmediateOutputFile(lldb::FileSP file_sp) { + lldb::StreamSP stream_sp(new StreamFile(file_sp)); m_out_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp); } - void SetImmediateErrorFile(FILE *fh, bool transfer_fh_ownership = false) { - lldb::StreamSP stream_sp(new StreamFile(fh, transfer_fh_ownership)); + void SetImmediateErrorFile(lldb::FileSP file_sp) { + lldb::StreamSP stream_sp(new StreamFile(file_sp)); m_err_stream.SetStreamAtIndex(eImmediateStreamIndex, stream_sp); } diff --git a/lldb/include/lldb/Utility/ReproducerInstrumentation.h b/lldb/include/lldb/Utility/ReproducerInstrumentation.h --- a/lldb/include/lldb/Utility/ReproducerInstrumentation.h +++ b/lldb/include/lldb/Utility/ReproducerInstrumentation.h @@ -238,9 +238,12 @@ struct ValueTag {}; struct FundamentalPointerTag {}; struct FundamentalReferenceTag {}; +struct NotImplementedTag {}; /// Return the deserialization tag for the given type T. -template struct serializer_tag { typedef ValueTag type; }; +template struct serializer_tag { + typedef typename std::conditional::value, ValueTag, NotImplementedTag>::type type; +}; template struct serializer_tag { typedef typename std::conditional::value, @@ -304,6 +307,11 @@ } private: + template T Read(NotImplementedTag) { + m_buffer = m_buffer.drop_front(sizeof(T)); + return T(); + } + template T Read(ValueTag) { assert(HasData(sizeof(T))); T t; diff --git a/lldb/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py b/lldb/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py --- a/lldb/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py +++ b/lldb/packages/Python/lldbsuite/test/python_api/file_handle/TestFileHandle.py @@ -309,7 +309,7 @@ @add_test_categories(['pyapi']) - @expectedFailure # FIXME need SBFile interfaces on SBCommandReturnObject + @skipIf(py_version=['<', (3,)]) def test_immediate_string(self): f = io.StringIO() ret = lldb.SBCommandReturnObject() @@ -325,7 +325,7 @@ @add_test_categories(['pyapi']) - @expectedFailure # FIXME need SBFile interfaces on SBCommandReturnObject + @skipIf(py_version=['<', (3,)]) def test_immediate_sbfile_string(self): f = io.StringIO() ret = lldb.SBCommandReturnObject() diff --git a/lldb/scripts/interface/SBCommandReturnObject.i b/lldb/scripts/interface/SBCommandReturnObject.i --- a/lldb/scripts/interface/SBCommandReturnObject.i +++ b/lldb/scripts/interface/SBCommandReturnObject.i @@ -49,10 +49,16 @@ GetError (bool if_no_immediate); size_t - PutOutput (FILE *fh); + PutOutput (lldb::SBFile file); size_t - PutError (FILE *fh); + PutError (lldb::SBFile file); + + size_t + PutOutput (lldb::FileSP BORROWED); + + size_t + PutError (lldb::FileSP BORROWED); void Clear(); @@ -85,15 +91,20 @@ bool GetDescription (lldb::SBStream &description); + void SetImmediateOutputFile(lldb::SBFile file); + void SetImmediateErrorFile(lldb::SBFile file); + void SetImmediateOutputFile(lldb::FileSP BORROWED); + void SetImmediateErrorFile(lldb::FileSP BORROWED); - // wrapping here so that lldb takes ownership of the - // new FILE* created inside of the swig interface %extend { - void SetImmediateOutputFile(FILE *fh) { - self->SetImmediateOutputFile(fh, true); + // transfer_ownership does nothing, and is here for compatibility with + // old scripts. Ownership is tracked by reference count in the ordinary way. + + void SetImmediateOutputFile(lldb::FileSP BORROWED, bool transfer_ownership) { + self->SetImmediateOutputFile(BORROWED); } - void SetImmediateErrorFile(FILE *fh) { - self->SetImmediateErrorFile(fh, true); + void SetImmediateErrorFile(lldb::FileSP BORROWED, bool transfer_ownership) { + self->SetImmediateErrorFile(BORROWED); } } diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -10,6 +10,7 @@ #include "SBReproducerPrivate.h" #include "Utils.h" #include "lldb/API/SBError.h" +#include "lldb/API/SBFile.h" #include "lldb/API/SBStream.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Utility/ConstString.h" @@ -116,7 +117,6 @@ size_t SBCommandReturnObject::PutOutput(FILE *fh) { LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *), fh); - if (fh) { size_t num_bytes = GetOutputSize(); if (num_bytes) @@ -125,6 +125,21 @@ return 0; } +size_t SBCommandReturnObject::PutOutput(FileSP file_sp) { + LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutOutput, (FileSP), + file_sp); + if (!file_sp) + return 0; + return file_sp->Printf("%s", GetOutput()); +} + +size_t SBCommandReturnObject::PutOutput(SBFile file) { + LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutOutput, (SBFile), file); + if (!file.m_opaque_sp) + return 0; + return file.m_opaque_sp->Printf("%s", GetOutput()); +} + size_t SBCommandReturnObject::PutError(FILE *fh) { LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *), fh); @@ -136,6 +151,21 @@ return 0; } +size_t SBCommandReturnObject::PutError(FileSP file_sp) { + LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (FileSP), + file_sp); + if (!file_sp) + return 0; + return file_sp->Printf("%s", GetError()); +} + +size_t SBCommandReturnObject::PutError(SBFile file) { + LLDB_RECORD_METHOD(size_t, SBCommandReturnObject, PutError, (SBFile), file); + if (!file.m_opaque_sp) + return 0; + return file.m_opaque_sp->Printf("%s", GetError()); +} + void SBCommandReturnObject::Clear() { LLDB_RECORD_METHOD_NO_ARGS(void, SBCommandReturnObject, Clear); @@ -242,16 +272,40 @@ bool transfer_ownership) { LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, (FILE *, bool), fh, transfer_ownership); - - ref().SetImmediateOutputFile(fh, transfer_ownership); + FileSP file = std::make_shared(fh, transfer_ownership); + ref().SetImmediateOutputFile(file); } void SBCommandReturnObject::SetImmediateErrorFile(FILE *fh, bool transfer_ownership) { LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, (FILE *, bool), fh, transfer_ownership); + FileSP file = std::make_shared(fh, transfer_ownership); + ref().SetImmediateErrorFile(file); +} - ref().SetImmediateErrorFile(fh, transfer_ownership); +void SBCommandReturnObject::SetImmediateOutputFile(SBFile file) { + LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, + (SBFile), file); + ref().SetImmediateOutputFile(file.m_opaque_sp); +} + +void SBCommandReturnObject::SetImmediateErrorFile(SBFile file) { + LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, + (SBFile), file); + ref().SetImmediateErrorFile(file.m_opaque_sp); +} + +void SBCommandReturnObject::SetImmediateOutputFile(FileSP file_sp) { + LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, + (FileSP), file_sp); + SetImmediateOutputFile(SBFile(file_sp)); +} + +void SBCommandReturnObject::SetImmediateErrorFile(FileSP file_sp) { + LLDB_RECORD_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, + (FileSP), file_sp); + SetImmediateErrorFile(SBFile(file_sp)); } void SBCommandReturnObject::PutCString(const char *string, int len) { @@ -335,6 +389,10 @@ LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, GetErrorSize, ()); LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FILE *)); LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FILE *)); + LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (SBFile)); + LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (SBFile)); + LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutOutput, (FileSP)); + LLDB_REGISTER_METHOD(size_t, SBCommandReturnObject, PutError, (FileSP)); LLDB_REGISTER_METHOD(void, SBCommandReturnObject, Clear, ()); LLDB_REGISTER_METHOD(lldb::ReturnStatus, SBCommandReturnObject, GetStatus, ()); @@ -353,6 +411,14 @@ LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, (FILE *)); LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, + (SBFile)); + LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, + (SBFile)); + LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, + (FileSP)); + LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, + (FileSP)); + LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateOutputFile, (FILE *, bool)); LLDB_REGISTER_METHOD(void, SBCommandReturnObject, SetImmediateErrorFile, (FILE *, bool)); diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -468,9 +468,9 @@ sb_interpreter.HandleCommand(command, result, false); if (GetErrorFileHandle() != nullptr) - result.PutError(GetErrorFileHandle()); + result.PutError(GetErrorFile()); if (GetOutputFileHandle() != nullptr) - result.PutOutput(GetOutputFileHandle()); + result.PutOutput(GetOutputFile()); if (!m_opaque_sp->GetAsyncExecution()) { SBProcess process(GetCommandInterpreter().GetProcess()); diff --git a/lldb/source/API/SBFile.cpp b/lldb/source/API/SBFile.cpp --- a/lldb/source/API/SBFile.cpp +++ b/lldb/source/API/SBFile.cpp @@ -23,12 +23,13 @@ SBFile::SBFile() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFile); } SBFile::SBFile(FILE *file, bool transfer_ownership) { + LLDB_RECORD_DUMMY(void, SBFile, (FILE *, bool), file, transfer_ownership); m_opaque_sp = std::make_shared(file, transfer_ownership); } SBFile::SBFile(int fd, const char *mode, bool transfer_owndership) { - LLDB_RECORD_CONSTRUCTOR(SBFile, (int, const char *, bool), fd, mode, - transfer_owndership); + LLDB_RECORD_DUMMY(void, SBFile, (int, const char *, bool), fd, mode, + transfer_owndership); auto options = File::GetOptionsFromMode(mode); m_opaque_sp = std::make_shared(fd, options, transfer_owndership); } @@ -104,9 +105,9 @@ namespace lldb_private { namespace repro { + template <> void RegisterMethods(Registry &R) { - LLDB_REGISTER_CONSTRUCTOR(SBFile, ()); - LLDB_REGISTER_CONSTRUCTOR(SBFile, (int, const char *, bool)); + LLDB_REGISTER_METHOD(lldb::SBError, SBFile, Flush, ()); LLDB_REGISTER_METHOD_CONST(bool, SBFile, IsValid, ()); LLDB_REGISTER_METHOD_CONST(bool, SBFile, operator bool,()); 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 @@ -879,8 +879,9 @@ ::setbuf(outfile_handle, nullptr); result->SetImmediateOutputFile( - debugger.GetOutputFile().GetStream()); - result->SetImmediateErrorFile(debugger.GetErrorFile().GetStream()); + debugger.GetOutputStream().GetFileSP()); + result->SetImmediateErrorFile( + debugger.GetErrorStream().GetFileSP()); } } } diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -11,6 +11,7 @@ #include "lldb/API/SBCommandInterpreter.h" #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBDebugger.h" +#include "lldb/API/SBFile.h" #include "lldb/API/SBHostOS.h" #include "lldb/API/SBLanguageRuntime.h" #include "lldb/API/SBReproducer.h" @@ -499,16 +500,16 @@ SBCommandReturnObject result; sb_interpreter.SourceInitFileInHomeDirectory(result); if (m_option_data.m_debug_mode) { - result.PutError(m_debugger.GetErrorFileHandle()); - result.PutOutput(m_debugger.GetOutputFileHandle()); + result.PutError(m_debugger.GetErrorFile()); + result.PutOutput(m_debugger.GetOutputFile()); } // Source the local .lldbinit file if it exists and we're allowed to source. // Here we want to always print the return object because it contains the // warning and instructions to load local lldbinit files. sb_interpreter.SourceInitFileInCurrentWorkingDirectory(result); - result.PutError(m_debugger.GetErrorFileHandle()); - result.PutOutput(m_debugger.GetOutputFileHandle()); + result.PutError(m_debugger.GetErrorFile()); + result.PutOutput(m_debugger.GetOutputFile()); // We allow the user to specify an exit code when calling quit which we will // return when exiting. @@ -574,8 +575,8 @@ } if (m_option_data.m_debug_mode) { - result.PutError(m_debugger.GetErrorFileHandle()); - result.PutOutput(m_debugger.GetOutputFileHandle()); + result.PutError(m_debugger.GetErrorFile()); + result.PutOutput(m_debugger.GetOutputFile()); } const bool handle_events = true;