Index: include/lldb/Utility/DataBufferLLVM.h =================================================================== --- include/lldb/Utility/DataBufferLLVM.h +++ include/lldb/Utility/DataBufferLLVM.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_CORE_DATABUFFERLLVM_H -#define LLDB_CORE_DATABUFFERLLVM_H +#ifndef LLDB_UTILITY_DATABUFFERLLVM_H +#define LLDB_UTILITY_DATABUFFERLLVM_H #include "lldb/Utility/DataBuffer.h" #include "lldb/lldb-types.h" // for offset_t @@ -17,7 +17,6 @@ #include // for uint8_t, uint64_t namespace llvm { -class MemoryBuffer; class Twine; } @@ -28,24 +27,12 @@ ~DataBufferLLVM(); static std::shared_ptr - CreateSliceFromPath(const llvm::Twine &Path, uint64_t Size, uint64_t Offset, bool Private = false); + CreateSliceFromPath(const llvm::Twine &Path, uint64_t Size, uint64_t Offset); static std::shared_ptr - CreateFromPath(const llvm::Twine &Path, bool NullTerminate = false, bool Private = false); - - uint8_t *GetBytes() override; - const uint8_t *GetBytes() const override; - lldb::offset_t GetByteSize() const override; + CreateFromPath(const llvm::Twine &Path, bool NullTerminate = false); char *GetChars() { return reinterpret_cast(GetBytes()); } - -private: - /// \brief Construct a DataBufferLLVM from \p Buffer. \p Buffer must be a - /// valid pointer. - explicit DataBufferLLVM(std::unique_ptr Buffer); - const uint8_t *GetBuffer() const; - - std::unique_ptr Buffer; }; } Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -404,8 +404,8 @@ lldb::offset_t file_offset, lldb::offset_t length) { if (!data_sp) { - data_sp = - DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true); + data_sp = DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, + file_offset); if (!data_sp) return nullptr; data_offset = 0; @@ -422,8 +422,8 @@ // Update the data to contain the entire file if it doesn't already if (data_sp->GetByteSize() < length) { - data_sp = - DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true); + data_sp = DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, + file_offset); if (!data_sp) return nullptr; data_offset = 0; Index: source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp =================================================================== --- source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -437,7 +437,7 @@ // A bit of a hack, but we intend to write to this buffer, so we can't // mmap it. auto buffer_sp = - DataBufferLLVM::CreateSliceFromPath(m_file.GetPath(), size, offset, true); + DataBufferLLVM::CreateSliceFromPath(m_file.GetPath(), size, offset); return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()); } ProcessSP process_sp(m_process_wp.lock()); Index: source/Utility/DataBufferLLVM.cpp =================================================================== --- source/Utility/DataBufferLLVM.cpp +++ source/Utility/DataBufferLLVM.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Utility/DataBufferLLVM.h" +#include "lldb/Utility/CleanUp.h" +#include "lldb/Utility/Log.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/FileSystem.h" @@ -16,55 +18,141 @@ #include // for assert #include // for move +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include +#else +#include +#endif + using namespace lldb_private; -DataBufferLLVM::DataBufferLLVM(std::unique_ptr MemBuffer) - : Buffer(std::move(MemBuffer)) { - assert(Buffer != nullptr && - "Cannot construct a DataBufferLLVM with a null buffer"); -} +namespace { +class MMapBuffer : public DataBufferLLVM { +public: + static std::shared_ptr + CreateSliceFromPath(const llvm::Twine &Path, uint64_t Size, uint64_t Offset); -DataBufferLLVM::~DataBufferLLVM() {} + uint8_t *GetBytes() override { return Start; } + const uint8_t *GetBytes() const override { return Start; } + lldb::offset_t GetByteSize() const override { return Len; } -std::shared_ptr -DataBufferLLVM::CreateSliceFromPath(const llvm::Twine &Path, uint64_t Size, - uint64_t Offset, bool Private) { - // If the file resides non-locally, pass the volatile flag so that we don't - // mmap it. - if (!Private) - Private = !llvm::sys::fs::is_local(Path); - - auto Buffer = llvm::MemoryBuffer::getFileSlice(Path, Size, Offset, Private); - if (!Buffer) - return nullptr; - return std::shared_ptr( - new DataBufferLLVM(std::move(*Buffer))); +private: + llvm::sys::fs::mapped_file_region MFR; + uint8_t *Start; + lldb::offset_t Len; + + static uint64_t getLegalMapOffset(uint64_t Offset) { + return Offset & ~(llvm::sys::fs::mapped_file_region::alignment() - 1); + } + + static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) { + return Len + (Offset - getLegalMapOffset(Offset)); + } + + MMapBuffer(int FD, uint64_t Len, uint64_t Offset, std::error_code &EC) + : MFR(FD, llvm::sys::fs::mapped_file_region::priv, + getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC), + Start(nullptr), Len(Len) { + if (!EC) + Start = reinterpret_cast(getStart(Len, Offset)); + } + + char *getStart(uint64_t Len, uint64_t Offset) { + return MFR.data() + (Offset - getLegalMapOffset(Offset)); + } +}; + +class MemoryBuffer : public DataBufferLLVM { +public: + /// \brief Construct a MemoryBuffer from \p Buffer. \p Buffer must be a + /// valid pointer. + explicit MemoryBuffer(std::unique_ptr Buffer); + + uint8_t *GetBytes() override { return const_cast(GetBuffer()); } + const uint8_t *GetBytes() const override { return GetBuffer(); } + + lldb::offset_t GetByteSize() const override { + return Buffer->getBufferSize(); + } + +private: + std::unique_ptr Buffer; + + const uint8_t *GetBuffer() const { + return reinterpret_cast(Buffer->getBufferStart()); + } +}; } std::shared_ptr -DataBufferLLVM::CreateFromPath(const llvm::Twine &Path, bool NullTerminate, bool Private) { - // If the file resides non-locally, pass the volatile flag so that we don't - // mmap it. - if (!Private) - Private = !llvm::sys::fs::is_local(Path); - - auto Buffer = llvm::MemoryBuffer::getFile(Path, -1, NullTerminate, Private); - if (!Buffer) +MMapBuffer::CreateSliceFromPath(const llvm::Twine &Path, uint64_t Size, + uint64_t Offset) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + int FD; + if (std::error_code EC = llvm::sys::fs::openFileForRead(Path, FD)) { + LLDB_LOG(log, "Failed to open file `{0}`: {1}", Path, EC.message()); + return nullptr; + } + lldb_utility::CleanUp CleanUpFD(FD, -1, close); + + if (Size == uint64_t(-1)) { + llvm::sys::fs::file_status Status; + if (std::error_code EC = llvm::sys::fs::status(FD, Status)) { + LLDB_LOG(log, "Failed to stat file `{0}`: {1}", Path, EC.message()); + return nullptr; + } + Size = Status.getSize(); + } + + std::error_code EC; + std::shared_ptr SP(new MMapBuffer(FD, Size, Offset, EC)); + if (EC) { + LLDB_LOG(log, "Failed to mmap file `{0}`: {1}", Path, EC.message()); return nullptr; - return std::shared_ptr( - new DataBufferLLVM(std::move(*Buffer))); + } + return SP; } -uint8_t *DataBufferLLVM::GetBytes() { - return const_cast(GetBuffer()); +MemoryBuffer::MemoryBuffer(std::unique_ptr MemBuffer) + : Buffer(std::move(MemBuffer)) { + assert(Buffer && "Cannot construct a MemoryBuffer with a null buffer"); } -const uint8_t *DataBufferLLVM::GetBytes() const { return GetBuffer(); } +DataBufferLLVM::~DataBufferLLVM() = default; + +std::shared_ptr +DataBufferLLVM::CreateSliceFromPath(const llvm::Twine &Path, uint64_t Size, + uint64_t Offset) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + const bool IsVolatile = !llvm::sys::fs::is_local(Path); + if (IsVolatile) { + auto Buffer = + llvm::MemoryBuffer::getFileSlice(Path, Size, Offset, IsVolatile); + if (!Buffer) { + LLDB_LOG(log, "Failed to read file `{0}`: {1}", Path, + Buffer.getError().message()); + return nullptr; + } + return std::make_shared(std::move(*Buffer)); + } -lldb::offset_t DataBufferLLVM::GetByteSize() const { - return Buffer->getBufferSize(); + return MMapBuffer::CreateSliceFromPath(Path, Size, Offset); } -const uint8_t *DataBufferLLVM::GetBuffer() const { - return reinterpret_cast(Buffer->getBufferStart()); +std::shared_ptr +DataBufferLLVM::CreateFromPath(const llvm::Twine &Path, bool NullTerminate) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + const bool IsVolatile = !llvm::sys::fs::is_local(Path); + if (IsVolatile || NullTerminate) { + auto Buffer = + llvm::MemoryBuffer::getFile(Path, -1, NullTerminate, IsVolatile); + if (!Buffer) { + LLDB_LOG(log, "Failed to read file `{0}`: {1}", Path, + Buffer.getError().message()); + return nullptr; + } + return std::make_shared(std::move(*Buffer)); + } + + return MMapBuffer::CreateSliceFromPath(Path, -1, 0); }