diff options
author | Lawrence D'Anna <lawrence_danna@apple.com> | 2019-10-03 04:01:07 +0000 |
---|---|---|
committer | Lawrence D'Anna <lawrence_danna@apple.com> | 2019-10-03 04:01:07 +0000 |
commit | dbc9b76bbe7665866966282595f16ef17f01f2ec (patch) | |
tree | 7e2808bbcd737515dbbe91d95cdf70dae0449d24 /source | |
parent | adb85e91313e1c409cdee08805b6d7c1140e1530 (diff) | |
download | lldb-dbc9b76bbe7665866966282595f16ef17f01f2ec.tar.gz |
new api class: SBFile
Summary:
SBFile is a scripting API wrapper for lldb_private::File
This is the first step in a project to enable arbitrary python
io.IOBase file objects -- including those that override the read()
and write() methods -- to be used as the main debugger IOStreams.
Currently this is impossible because python file objects must first
be converted into FILE* streams by SWIG in order to be passed into
the debugger.
full prototype: https://github.com/smoofra/llvm-project/tree/files
Reviewers: JDevlieghere, jasonmolenda, zturner, jingham, labath
Reviewed By: labath
Subscribers: labath, mgorny, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D67793
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@373562 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'source')
-rw-r--r-- | source/API/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/API/SBFile.cpp | 113 | ||||
-rw-r--r-- | source/API/SBReproducer.cpp | 1 | ||||
-rw-r--r-- | source/Host/common/File.cpp | 25 | ||||
-rw-r--r-- | source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp | 19 | ||||
-rw-r--r-- | source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h | 2 |
6 files changed, 138 insertions, 23 deletions
diff --git a/source/API/CMakeLists.txt b/source/API/CMakeLists.txt index d93b8b5e3..f06ed1fcd 100644 --- a/source/API/CMakeLists.txt +++ b/source/API/CMakeLists.txt @@ -34,6 +34,7 @@ add_lldb_library(liblldb SHARED SBExecutionContext.cpp SBExpressionOptions.cpp SBFileSpec.cpp + SBFile.cpp SBFileSpecList.cpp SBFrame.cpp SBFunction.cpp diff --git a/source/API/SBFile.cpp b/source/API/SBFile.cpp new file mode 100644 index 000000000..fc4f5572f --- /dev/null +++ b/source/API/SBFile.cpp @@ -0,0 +1,113 @@ +//===-- SBFile.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 "lldb/API/SBFile.h" +#include "SBReproducerPrivate.h" +#include "lldb/API/SBError.h" +#include "lldb/Host/File.h" + +using namespace lldb; +using namespace lldb_private; + +SBFile::~SBFile() {} + +SBFile::SBFile() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFile); } + +SBFile::SBFile(FILE *file, bool transfer_ownership) { + m_opaque_sp = std::make_shared<File>(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); + auto options = File::GetOptionsFromMode(mode); + m_opaque_sp = std::make_shared<File>(fd, options, transfer_owndership); +} + +SBError SBFile::Read(uint8_t *buf, size_t num_bytes, size_t *bytes_read) { + LLDB_RECORD_DUMMY(lldb::SBError, SBFile, Read, (uint8_t *, size_t, size_t *), + buf, num_bytes, bytes_read); + SBError error; + if (!m_opaque_sp) { + error.SetErrorString("invalid SBFile"); + *bytes_read = 0; + } else { + Status status = m_opaque_sp->Read(buf, num_bytes); + error.SetError(status); + *bytes_read = num_bytes; + } + return LLDB_RECORD_RESULT(error); +} + +SBError SBFile::Write(const uint8_t *buf, size_t num_bytes, + size_t *bytes_written) { + LLDB_RECORD_DUMMY(lldb::SBError, SBFile, Write, + (const uint8_t *, size_t, size_t *), buf, num_bytes, + bytes_written); + SBError error; + if (!m_opaque_sp) { + error.SetErrorString("invalid SBFile"); + *bytes_written = 0; + } else { + Status status = m_opaque_sp->Write(buf, num_bytes); + error.SetError(status); + *bytes_written = num_bytes; + } + return LLDB_RECORD_RESULT(error); +} + +SBError SBFile::Flush() { + LLDB_RECORD_METHOD_NO_ARGS(lldb::SBError, SBFile, Flush); + SBError error; + if (!m_opaque_sp) { + error.SetErrorString("invalid SBFile"); + } else { + Status status = m_opaque_sp->Flush(); + error.SetError(status); + } + return LLDB_RECORD_RESULT(error); +} + +bool SBFile::IsValid() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFile, IsValid); + return m_opaque_sp && m_opaque_sp->IsValid(); +} + +SBError SBFile::Close() { + LLDB_RECORD_METHOD_NO_ARGS(lldb::SBError, SBFile, Close); + SBError error; + if (m_opaque_sp) { + Status status = m_opaque_sp->Close(); + error.SetError(status); + } + return LLDB_RECORD_RESULT(error); +} + +SBFile::operator bool() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFile, operator bool); + return LLDB_RECORD_RESULT(IsValid()); +} + +bool SBFile::operator!() const { + LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFile, operator!); + return LLDB_RECORD_RESULT(!IsValid()); +} + +namespace lldb_private { +namespace repro { +template <> void RegisterMethods<SBFile>(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,()); + LLDB_REGISTER_METHOD_CONST(bool, SBFile, operator!,()); + LLDB_REGISTER_METHOD(lldb::SBError, SBFile, Close, ()); +} +} // namespace repro +} // namespace lldb_private diff --git a/source/API/SBReproducer.cpp b/source/API/SBReproducer.cpp index 439ee5a70..6e11b2c63 100644 --- a/source/API/SBReproducer.cpp +++ b/source/API/SBReproducer.cpp @@ -52,6 +52,7 @@ SBRegistry::SBRegistry() { RegisterMethods<SBEvent>(R); RegisterMethods<SBExecutionContext>(R); RegisterMethods<SBExpressionOptions>(R); + RegisterMethods<SBFile>(R); RegisterMethods<SBFileSpec>(R); RegisterMethods<SBFileSpecList>(R); RegisterMethods<SBFrame>(R); diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp index b79c00378..eff4197db 100644 --- a/source/Host/common/File.cpp +++ b/source/Host/common/File.cpp @@ -68,6 +68,20 @@ static const char *GetStreamOpenModeFromOptions(uint32_t options) { return nullptr; } +uint32_t File::GetOptionsFromMode(llvm::StringRef mode) { + return llvm::StringSwitch<uint32_t>(mode) + .Case("r", File::eOpenOptionRead) + .Case("w", File::eOpenOptionWrite) + .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend | + File::eOpenOptionCanCreate) + .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite) + .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite | + File::eOpenOptionCanCreate | File::eOpenOptionTruncate) + .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite | + File::eOpenOptionAppend | File::eOpenOptionCanCreate) + .Default(0); +} + int File::kInvalidDescriptor = -1; FILE *File::kInvalidStream = nullptr; @@ -143,9 +157,14 @@ uint32_t File::GetPermissions(Status &error) const { Status File::Close() { Status error; - if (StreamIsValid() && m_own_stream) { - if (::fclose(m_stream) == EOF) - error.SetErrorToErrno(); + if (StreamIsValid()) { + if (m_own_stream) { + if (::fclose(m_stream) == EOF) + error.SetErrorToErrno(); + } else { + if (::fflush(m_stream) == EOF) + error.SetErrorToErrno(); + } } if (DescriptorIsValid() && m_own_descriptor) { diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 6d9a74d39..20745d42e 100644 --- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -949,7 +949,6 @@ PythonFile::PythonFile() : PythonObject() {} PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); } - PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); } PythonFile::~PythonFile() {} @@ -1014,22 +1013,6 @@ void PythonFile::Reset(File &file, const char *mode) { #endif } -uint32_t PythonFile::GetOptionsFromMode(llvm::StringRef mode) { - if (mode.empty()) - return 0; - - return llvm::StringSwitch<uint32_t>(mode.str()) - .Case("r", File::eOpenOptionRead) - .Case("w", File::eOpenOptionWrite) - .Case("a", File::eOpenOptionWrite | File::eOpenOptionAppend | - File::eOpenOptionCanCreate) - .Case("r+", File::eOpenOptionRead | File::eOpenOptionWrite) - .Case("w+", File::eOpenOptionRead | File::eOpenOptionWrite | - File::eOpenOptionCanCreate | File::eOpenOptionTruncate) - .Case("a+", File::eOpenOptionRead | File::eOpenOptionWrite | - File::eOpenOptionAppend | File::eOpenOptionCanCreate) - .Default(0); -} FileUP PythonFile::GetUnderlyingFile() const { if (!IsValid()) @@ -1038,7 +1021,7 @@ FileUP PythonFile::GetUnderlyingFile() const { // We don't own the file descriptor returned by this function, make sure the // File object knows about that. PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>(); - auto options = PythonFile::GetOptionsFromMode(py_mode.GetString()); + auto options = File::GetOptionsFromMode(py_mode.GetString()); auto file = std::make_unique<File>(PyObject_AsFileDescriptor(m_py_obj), options, false); if (!file->IsValid()) diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 14484d931..8fd2be146 100644 --- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -466,8 +466,6 @@ public: void Reset(PyRefType type, PyObject *py_obj) override; void Reset(File &file, const char *mode); - static uint32_t GetOptionsFromMode(llvm::StringRef mode); - lldb::FileUP GetUnderlyingFile() const; }; |