Index: lldb/trunk/include/lldb/Core/DataBufferHeap.h =================================================================== --- lldb/trunk/include/lldb/Core/DataBufferHeap.h +++ lldb/trunk/include/lldb/Core/DataBufferHeap.h @@ -25,7 +25,8 @@ /// the object. This class is best used to store chunks of data that /// are created or read from sources that can't intelligently and lazily /// fault new data pages in. Large amounts of data that comes from files -/// should probably use the DataBufferMemoryMap class. +/// should probably use DataBufferLLVM, which can intelligently determine +/// when memory mapping is optimal. //---------------------------------------------------------------------- class DataBufferHeap : public DataBuffer { public: Index: lldb/trunk/include/lldb/Core/DataBufferLLVM.h =================================================================== --- lldb/trunk/include/lldb/Core/DataBufferLLVM.h +++ lldb/trunk/include/lldb/Core/DataBufferLLVM.h @@ -0,0 +1,46 @@ +//===--- DataBufferLLVM.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_CORE_DATABUFFERLLVM_H +#define LLDB_CORE_DATABUFFERLLVM_H + +#include "lldb/Core/DataBuffer.h" + +#include + +namespace llvm { +class MemoryBuffer; +} + +namespace lldb_private { + +class DataBufferLLVM : public DataBuffer { +public: + ~DataBufferLLVM(); + + static std::shared_ptr + CreateFromPath(llvm::StringRef Path, uint64_t Size, uint64_t Offset); + static std::shared_ptr + CreateFromFileSpec(const FileSpec &F, uint64_t Size, uint64_t Offset); + + uint8_t *GetBytes() override; + const uint8_t *GetBytes() const override; + lldb::offset_t GetByteSize() const override; + +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; +}; +} + +#endif Index: lldb/trunk/include/lldb/Core/DataBufferMemoryMap.h =================================================================== --- lldb/trunk/include/lldb/Core/DataBufferMemoryMap.h +++ lldb/trunk/include/lldb/Core/DataBufferMemoryMap.h @@ -1,154 +0,0 @@ -//===-- DataBufferMemoryMap.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_DataBufferMemoryMap_h_ -#define liblldb_DataBufferMemoryMap_h_ - -#include "lldb/Core/DataBuffer.h" -#include "lldb/Utility/Error.h" -#include "lldb/lldb-private.h" -#include - -namespace lldb_private { - -//---------------------------------------------------------------------- -/// @class DataBufferMemoryMap DataBufferMemoryMap.h -/// "lldb/Core/DataBufferMemoryMap.h" -/// @brief A subclass of DataBuffer that memory maps data. -/// -/// This class memory maps data and stores any needed data for the -/// memory mapping in its internal state. Memory map requests are not -/// required to have any alignment or size constraints, this class will -/// work around any host OS issues regarding such things. -/// -/// This class is designed to allow pages to be faulted in as needed and -/// works well data from large files that won't be accessed all at once. -//---------------------------------------------------------------------- -class DataBufferMemoryMap : public DataBuffer { -public: - //------------------------------------------------------------------ - /// Default Constructor - //------------------------------------------------------------------ - DataBufferMemoryMap(); - - //------------------------------------------------------------------ - /// Destructor. - /// - /// Virtual destructor since this class inherits from a pure virtual - /// base class #DataBuffer. - //------------------------------------------------------------------ - ~DataBufferMemoryMap() override; - - //------------------------------------------------------------------ - /// Reverts this object to an empty state by unmapping any memory - /// that is currently owned. - //------------------------------------------------------------------ - void Clear(); - - //------------------------------------------------------------------ - /// @copydoc DataBuffer::GetBytes() - //------------------------------------------------------------------ - uint8_t *GetBytes() override; - - //------------------------------------------------------------------ - /// @copydoc DataBuffer::GetBytes() const - //------------------------------------------------------------------ - const uint8_t *GetBytes() const override; - - //------------------------------------------------------------------ - /// @copydoc DataBuffer::GetByteSize() const - //------------------------------------------------------------------ - lldb::offset_t GetByteSize() const override; - - //------------------------------------------------------------------ - /// Error get accessor. - /// - /// @return - /// A const reference to Error object in case memory mapping - /// fails. - //------------------------------------------------------------------ - const Error &GetError() const; - - //------------------------------------------------------------------ - /// Memory map all or part of a file. - /// - /// Memory map \a length bytes from \a file starting \a offset - /// bytes into the file. If \a length is set to \c SIZE_MAX, - /// then map as many bytes as possible. - /// - /// @param[in] file - /// The file specification from which to map data. - /// - /// @param[in] offset - /// The offset in bytes from the beginning of the file where - /// memory mapping should begin. - /// - /// @param[in] length - /// The size in bytes that should be mapped starting \a offset - /// bytes into the file. If \a length is \c SIZE_MAX, map - /// as many bytes as possible. Even though it may be possible - /// for a 32-bit host debugger to debug a 64-bit target, size_t - /// still dictates the maximum possible size that can be mapped - /// into this process. For this kind of cross-arch debugging - /// scenario, mappings and views should be managed at a higher - /// level. - /// - /// @return - /// The number of bytes mapped starting from the \a offset. - //------------------------------------------------------------------ - size_t MemoryMapFromFileSpec(const FileSpec *file, lldb::offset_t offset = 0, - size_t length = SIZE_MAX, - bool writeable = false); - - //------------------------------------------------------------------ - /// Memory map all or part of a file. - /// - /// Memory map \a length bytes from an opened file descriptor \a fd - /// starting \a offset bytes into the file. If \a length is set to - /// \c SIZE_MAX, then map as many bytes as possible. - /// - /// @param[in] fd - /// The posix file descriptor for an already opened file - /// from which to map data. - /// - /// @param[in] offset - /// The offset in bytes from the beginning of the file where - /// memory mapping should begin. - /// - /// @param[in] length - /// The size in bytes that should be mapped starting \a offset - /// bytes into the file. If \a length is \c SIZE_MAX, map - /// as many bytes as possible. - /// - /// @return - /// The number of bytes mapped starting from the \a offset. - //------------------------------------------------------------------ - size_t MemoryMapFromFileDescriptor(int fd, lldb::offset_t offset, - size_t length, bool write, - bool fd_is_file); - -protected: - //------------------------------------------------------------------ - // Classes that inherit from DataBufferMemoryMap can see and modify these - //------------------------------------------------------------------ - uint8_t *m_mmap_addr; ///< The actual pointer that was returned from \c mmap() - size_t m_mmap_size; ///< The actual number of bytes that were mapped when \c - ///mmap() was called - uint8_t *m_data; ///< The data the user requested somewhere within the memory - ///mapped data. - lldb::offset_t - m_size; ///< The size of the data the user got when data was requested - -private: - DISALLOW_COPY_AND_ASSIGN(DataBufferMemoryMap); -}; - -} // namespace lldb_private - -#endif // liblldb_DataBufferMemoryMap_h_ Index: lldb/trunk/include/lldb/Host/FileSpec.h =================================================================== --- lldb/trunk/include/lldb/Host/FileSpec.h +++ lldb/trunk/include/lldb/Host/FileSpec.h @@ -499,75 +499,6 @@ size_t MemorySize() const; //------------------------------------------------------------------ - /// Memory map part of, or the entire contents of, a file. - /// - /// Returns a shared pointer to a data buffer that contains all or - /// part of the contents of a file. The data is memory mapped and - /// will lazily page in data from the file as memory is accessed. - /// The data that is mapped will start \a offset bytes into the - /// file, and \a length bytes will be mapped. If \a length is - /// greater than the number of bytes available in the file starting - /// at \a offset, the number of bytes will be appropriately - /// truncated. The final number of bytes that get mapped can be - /// verified using the DataBuffer::GetByteSize() function on the return - /// shared data pointer object contents. - /// - /// @param[in] offset - /// The offset in bytes from the beginning of the file where - /// memory mapping should begin. - /// - /// @param[in] length - /// The size in bytes that should be mapped starting \a offset - /// bytes into the file. If \a length is \c SIZE_MAX, map - /// as many bytes as possible. - /// - /// @return - /// A shared pointer to the memory mapped data. This shared - /// pointer can contain a nullptr DataBuffer pointer, so the contained - /// pointer must be checked prior to using it. - //------------------------------------------------------------------ - lldb::DataBufferSP MemoryMapFileContents(off_t offset = 0, - size_t length = SIZE_MAX) const; - - //------------------------------------------------------------------ - /// Memory map part of, or the entire contents of, a file only if - /// the file is local (not on a network mount). - /// - /// Returns a shared pointer to a data buffer that contains all or - /// part of the contents of a file. The data will be memory mapped - /// if the file is local and will lazily page in data from the file - /// as memory is accessed. If the data is memory mapped, the data - /// that is mapped will start \a offset bytes into the file, and - /// \a length bytes will be mapped. If \a length is - /// greater than the number of bytes available in the file starting - /// at \a offset, the number of bytes will be appropriately - /// truncated. The final number of bytes that get mapped can be - /// verified using the DataBuffer::GetByteSize() function on the return - /// shared data pointer object contents. - /// - /// If the file is on a network mount the data will be read into a - /// heap buffer immediately so that accesses to the data won't later - /// cause a crash if we touch a page that isn't paged in and the - /// network mount has been disconnected or gone away. - /// - /// @param[in] offset - /// The offset in bytes from the beginning of the file where - /// memory mapping should begin. - /// - /// @param[in] length - /// The size in bytes that should be mapped starting \a offset - /// bytes into the file. If \a length is \c SIZE_MAX, map - /// as many bytes as possible. - /// - /// @return - /// A shared pointer to the memory mapped data. This shared - /// pointer can contain a nullptr DataBuffer pointer, so the contained - /// pointer must be checked prior to using it. - //------------------------------------------------------------------ - lldb::DataBufferSP MemoryMapFileContentsIfLocal(off_t file_offset, - size_t file_size) const; - - //------------------------------------------------------------------ /// Read part of, or the entire contents of, a file into a heap based data /// buffer. /// Index: lldb/trunk/source/Core/CMakeLists.txt =================================================================== --- lldb/trunk/source/Core/CMakeLists.txt +++ lldb/trunk/source/Core/CMakeLists.txt @@ -10,7 +10,7 @@ Communication.cpp Connection.cpp DataBufferHeap.cpp - DataBufferMemoryMap.cpp + DataBufferLLVM.cpp DataEncoder.cpp DataExtractor.cpp Debugger.cpp Index: lldb/trunk/source/Core/DataBufferLLVM.cpp =================================================================== --- lldb/trunk/source/Core/DataBufferLLVM.cpp +++ lldb/trunk/source/Core/DataBufferLLVM.cpp @@ -0,0 +1,58 @@ +//===--- DataBufferLLVM.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/DataBufferLLVM.h" + +#include "lldb/Host/FileSpec.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" + +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"); +} + +DataBufferLLVM::~DataBufferLLVM() {} + +std::shared_ptr +DataBufferLLVM::CreateFromPath(llvm::StringRef Path, uint64_t Size, + uint64_t Offset) { + // If the file resides non-locally, pass the volatile flag so that we don't + // mmap it. + bool Volatile = !llvm::sys::fs::is_local(Path); + + auto Buffer = llvm::MemoryBuffer::getFileSlice(Path, Size, Offset, Volatile); + if (!Buffer) + return nullptr; + return std::shared_ptr( + new DataBufferLLVM(std::move(*Buffer))); +} + +std::shared_ptr +DataBufferLLVM::CreateFromFileSpec(const FileSpec &F, uint64_t Size, + uint64_t Offset) { + return CreateFromPath(F.GetPath(), Size, Offset); +} + +uint8_t *DataBufferLLVM::GetBytes() { + return const_cast(GetBuffer()); +} + +const uint8_t *DataBufferLLVM::GetBytes() const { return GetBuffer(); } + +lldb::offset_t DataBufferLLVM::GetByteSize() const { + return Buffer->getBufferSize(); +} + +const uint8_t *DataBufferLLVM::GetBuffer() const { + return reinterpret_cast(Buffer->getBufferStart()); +} Index: lldb/trunk/source/Core/DataBufferMemoryMap.cpp =================================================================== --- lldb/trunk/source/Core/DataBufferMemoryMap.cpp +++ lldb/trunk/source/Core/DataBufferMemoryMap.cpp @@ -1,299 +0,0 @@ -//===-- DataBufferMemoryMap.cpp ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -#include -#include -#ifdef _WIN32 -#include "lldb/Host/windows/windows.h" -#else -#include - -#define MAP_EXTRA_HOST_READ_FLAGS 0 - -#if defined(__APPLE__) -//---------------------------------------------------------------------- -// Newer versions of MacOSX have a flag that will allow us to read from -// binaries whose code signature is invalid without crashing by using -// the MAP_RESILIENT_CODESIGN flag. Also if a file from removable media -// is mapped we can avoid crashing and return zeroes to any pages we try -// to read if the media becomes unavailable by using the -// MAP_RESILIENT_MEDIA flag. -//---------------------------------------------------------------------- -#if defined(MAP_RESILIENT_CODESIGN) -#undef MAP_EXTRA_HOST_READ_FLAGS -#if defined(MAP_RESILIENT_MEDIA) -#define MAP_EXTRA_HOST_READ_FLAGS MAP_RESILIENT_CODESIGN | MAP_RESILIENT_MEDIA -#else -#define MAP_EXTRA_HOST_READ_FLAGS MAP_RESILIENT_CODESIGN -#endif -#endif // #if defined(MAP_RESILIENT_CODESIGN) -#endif // #if defined (__APPLE__) - -#endif // #else #ifdef _WIN32 -// C++ Includes -#include -#include - -// Other libraries and framework includes -#include "llvm/Support/MathExtras.h" - -// Project includes -#include "lldb/Core/DataBufferMemoryMap.h" -#include "lldb/Core/Log.h" -#include "lldb/Host/File.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Utility/Error.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// Default Constructor -//---------------------------------------------------------------------- -DataBufferMemoryMap::DataBufferMemoryMap() - : m_mmap_addr(nullptr), m_mmap_size(0), m_data(nullptr), m_size(0) {} - -//---------------------------------------------------------------------- -// Virtual destructor since this class inherits from a pure virtual -// base class. -//---------------------------------------------------------------------- -DataBufferMemoryMap::~DataBufferMemoryMap() { Clear(); } - -//---------------------------------------------------------------------- -// Return a pointer to the bytes owned by this object, or nullptr if -// the object contains no bytes. -//---------------------------------------------------------------------- -uint8_t *DataBufferMemoryMap::GetBytes() { return m_data; } - -//---------------------------------------------------------------------- -// Return a const pointer to the bytes owned by this object, or nullptr -// if the object contains no bytes. -//---------------------------------------------------------------------- -const uint8_t *DataBufferMemoryMap::GetBytes() const { return m_data; } - -//---------------------------------------------------------------------- -// Return the number of bytes this object currently contains. -//---------------------------------------------------------------------- -uint64_t DataBufferMemoryMap::GetByteSize() const { return m_size; } - -//---------------------------------------------------------------------- -// Reverts this object to an empty state by unmapping any memory -// that is currently owned. -//---------------------------------------------------------------------- -void DataBufferMemoryMap::Clear() { - if (m_mmap_addr != nullptr) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MMAP)); - if (log) - log->Printf("DataBufferMemoryMap::Clear() m_mmap_addr = %p, m_mmap_size " - "= %" PRIu64 "", - (void *)m_mmap_addr, (uint64_t)m_mmap_size); -#ifdef _WIN32 - UnmapViewOfFile(m_mmap_addr); -#else - ::munmap((void *)m_mmap_addr, m_mmap_size); -#endif - m_mmap_addr = nullptr; - m_mmap_size = 0; - m_data = nullptr; - m_size = 0; - } -} - -//---------------------------------------------------------------------- -// Memory map "length" bytes from "file" starting "offset" -// bytes into the file. If "length" is set to SIZE_MAX, then -// map as many bytes as possible. -// -// Returns the number of bytes mapped starting from the requested -// offset. -//---------------------------------------------------------------------- -size_t DataBufferMemoryMap::MemoryMapFromFileSpec(const FileSpec *filespec, - lldb::offset_t offset, - size_t length, - bool writeable) { - if (filespec != nullptr) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MMAP)); - if (log) { - log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec(file=\"%s\", " - "offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i", - filespec->GetPath().c_str(), offset, (uint64_t)length, - writeable); - } - char path[PATH_MAX]; - if (filespec->GetPath(path, sizeof(path))) { - uint32_t options = File::eOpenOptionRead; - if (writeable) - options |= File::eOpenOptionWrite; - - File file; - Error error(file.Open(path, options)); - if (error.Success()) { - const bool fd_is_file = true; - return MemoryMapFromFileDescriptor(file.GetDescriptor(), offset, length, - writeable, fd_is_file); - } - } - } - // We should only get here if there was an error - Clear(); - return 0; -} - -#ifdef _WIN32 -static size_t win32memmapalignment = 0; -void LoadWin32MemMapAlignment() { - SYSTEM_INFO data; - GetSystemInfo(&data); - win32memmapalignment = data.dwAllocationGranularity; -} -#endif - -//---------------------------------------------------------------------- -// The file descriptor FD is assumed to already be opened as read only -// and the STAT structure is assumed to a valid pointer and already -// containing valid data from a call to stat(). -// -// Memory map FILE_LENGTH bytes in FILE starting FILE_OFFSET bytes into -// the file. If FILE_LENGTH is set to SIZE_MAX, then map as many bytes -// as possible. -// -// RETURNS -// Number of bytes mapped starting from the requested offset. -//---------------------------------------------------------------------- -size_t DataBufferMemoryMap::MemoryMapFromFileDescriptor(int fd, - lldb::offset_t offset, - size_t length, - bool writeable, - bool fd_is_file) { - Clear(); - if (fd >= 0) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MMAP)); - LLDB_LOGV(log, - "(fd={0}, offset={1:x}, length={2:x}, " - "writeable={3}, fd_is_file={4})", - fd, offset, length, writeable, fd_is_file); -#ifdef _WIN32 - HANDLE handle = (HANDLE)_get_osfhandle(fd); - DWORD file_size_low, file_size_high; - file_size_low = GetFileSize(handle, &file_size_high); - const lldb::offset_t file_size = - llvm::Make_64(file_size_high, file_size_low); - const lldb::offset_t max_bytes_available = file_size - offset; - const size_t max_bytes_mappable = - (size_t)std::min(SIZE_MAX, max_bytes_available); - if (length == SIZE_MAX || length > max_bytes_mappable) { - // Cap the length if too much data was requested - length = max_bytes_mappable; - } - - if (length > 0) { - HANDLE fileMapping = CreateFileMapping( - handle, nullptr, writeable ? PAGE_READWRITE : PAGE_READONLY, - file_size_high, file_size_low, nullptr); - if (fileMapping != nullptr) { - if (win32memmapalignment == 0) - LoadWin32MemMapAlignment(); - lldb::offset_t realoffset = offset; - lldb::offset_t delta = 0; - if (realoffset % win32memmapalignment != 0) { - realoffset = realoffset / win32memmapalignment * win32memmapalignment; - delta = offset - realoffset; - } - - LPVOID data = MapViewOfFile(fileMapping, - writeable ? FILE_MAP_WRITE : FILE_MAP_READ, - 0, realoffset, length + delta); - m_mmap_addr = (uint8_t *)data; - if (!data) { - Error error; - error.SetErrorToErrno(); - } else { - m_data = m_mmap_addr + delta; - m_size = length; - } - CloseHandle(fileMapping); - } - } -#else - struct stat stat; - if (::fstat(fd, &stat) == 0) { - if (S_ISREG(stat.st_mode) && - (stat.st_size > static_cast(offset))) { - const size_t max_bytes_available = stat.st_size - offset; - if (length == SIZE_MAX) { - length = max_bytes_available; - } else if (length > max_bytes_available) { - // Cap the length if too much data was requested - length = max_bytes_available; - } - - if (length > 0) { - int prot = PROT_READ; - int flags = MAP_PRIVATE; - if (writeable) - prot |= PROT_WRITE; - else - flags |= MAP_EXTRA_HOST_READ_FLAGS; - - if (fd_is_file) - flags |= MAP_FILE; - - m_mmap_addr = - (uint8_t *)::mmap(nullptr, length, prot, flags, fd, offset); - Error error; - - if (m_mmap_addr == (void *)-1) { - error.SetErrorToErrno(); - if (error.GetError() == EINVAL) { - // We may still have a shot at memory mapping if we align things - // correctly - size_t page_offset = offset % HostInfo::GetPageSize(); - if (page_offset != 0) { - m_mmap_addr = - (uint8_t *)::mmap(nullptr, length + page_offset, prot, - flags, fd, offset - page_offset); - if (m_mmap_addr == (void *)-1) { - // Failed to map file - m_mmap_addr = nullptr; - } else if (m_mmap_addr != nullptr) { - // We recovered and were able to memory map - // after we aligned things to page boundaries - - // Save the actual mmap'ed size - m_mmap_size = length + page_offset; - // Our data is at an offset into the mapped data - m_data = m_mmap_addr + page_offset; - // Our pretend size is the size that was requested - m_size = length; - } - } - } - if (error.GetError() == ENOMEM) { - error.SetErrorStringWithFormat("could not allocate %" PRId64 - " bytes of memory to mmap in file", - (uint64_t)length); - } - } else { - // We were able to map the requested data in one chunk - // where our mmap and actual data are the same. - m_mmap_size = length; - m_data = m_mmap_addr; - m_size = length; - } - LLDB_LOGV(log, "m_mmap_addr = {0}, m_mmap_size = {1}, error = {2}", - m_mmap_addr, m_mmap_size, error); - } - } - } -#endif - } - return GetByteSize(); -} Index: lldb/trunk/source/Host/common/FileSpec.cpp =================================================================== --- lldb/trunk/source/Host/common/FileSpec.cpp +++ lldb/trunk/source/Host/common/FileSpec.cpp @@ -27,7 +27,6 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataBufferMemoryMap.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/FileSystem.h" @@ -826,39 +825,6 @@ } //------------------------------------------------------------------ -// Returns a shared pointer to a data buffer that contains all or -// part of the contents of a file. The data is memory mapped and -// will lazily page in data from the file as memory is accessed. -// The data that is mapped will start "file_offset" bytes into the -// file, and "file_size" bytes will be mapped. If "file_size" is -// greater than the number of bytes available in the file starting -// at "file_offset", the number of bytes will be appropriately -// truncated. The final number of bytes that get mapped can be -// verified using the DataBuffer::GetByteSize() function. -//------------------------------------------------------------------ -DataBufferSP FileSpec::MemoryMapFileContents(off_t file_offset, - size_t file_size) const { - DataBufferSP data_sp; - std::unique_ptr mmap_data(new DataBufferMemoryMap()); - if (mmap_data.get()) { - const size_t mapped_length = - mmap_data->MemoryMapFromFileSpec(this, file_offset, file_size); - if (((file_size == SIZE_MAX) && (mapped_length > 0)) || - (mapped_length >= file_size)) - data_sp.reset(mmap_data.release()); - } - return data_sp; -} - -DataBufferSP FileSpec::MemoryMapFileContentsIfLocal(off_t file_offset, - size_t file_size) const { - if (FileSystem::IsLocal(*this)) - return MemoryMapFileContents(file_offset, file_size); - else - return ReadFileContents(file_offset, file_size, NULL); -} - -//------------------------------------------------------------------ // Return the size in bytes that this object takes in memory. This // returns the size in bytes of this object, not any shared string // values it may refer to. Index: lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ lldb/trunk/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -28,7 +28,7 @@ #endif #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBuffer.h" +#include "lldb/Core/DataBufferLLVM.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -37,6 +37,8 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/Stream.h" +#include "llvm/Support/MemoryBuffer.h" + using namespace lldb; using namespace lldb_private; @@ -290,62 +292,65 @@ lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length) { ConstString object_name(module_sp->GetObjectName()); - if (object_name) { - if (data_sp) { - // We have data, which means this is the first 512 bytes of the file - // Check to see if the magic bytes match and if they do, read the entire - // table of contents for the archive and cache it - DataExtractor data; - data.SetData(data_sp, data_offset, length); - if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) { - Timer scoped_timer( - LLVM_PRETTY_FUNCTION, - "ObjectContainerBSDArchive::CreateInstance (module = %s, file = " - "%p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")", - module_sp->GetFileSpec().GetPath().c_str(), - static_cast(file), static_cast(file_offset), - static_cast(length)); - - // Map the entire .a file to be sure that we don't lose any data if the - // file - // gets updated by a new build while this .a file is being used for - // debugging - DataBufferSP archive_data_sp( - file->MemoryMapFileContentsIfLocal(file_offset, length)); - lldb::offset_t archive_data_offset = 0; - - Archive::shared_ptr archive_sp(Archive::FindCachedArchive( - *file, module_sp->GetArchitecture(), - module_sp->GetModificationTime(), file_offset)); - std::unique_ptr container_ap( - new ObjectContainerBSDArchive(module_sp, archive_data_sp, - archive_data_offset, file, - file_offset, length)); - - if (container_ap.get()) { - if (archive_sp) { - // We already have this archive in our cache, use it - container_ap->SetArchive(archive_sp); - return container_ap.release(); - } else if (container_ap->ParseHeader()) - return container_ap.release(); - } - } - } else { - // No data, just check for a cached archive + if (!object_name) + return nullptr; + + if (data_sp) { + // We have data, which means this is the first 512 bytes of the file + // Check to see if the magic bytes match and if they do, read the entire + // table of contents for the archive and cache it + DataExtractor data; + data.SetData(data_sp, data_offset, length); + if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) { + Timer scoped_timer( + LLVM_PRETTY_FUNCTION, + "ObjectContainerBSDArchive::CreateInstance (module = %s, file = " + "%p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")", + module_sp->GetFileSpec().GetPath().c_str(), + static_cast(file), static_cast(file_offset), + static_cast(length)); + + // Map the entire .a file to be sure that we don't lose any data if the + // file gets updated by a new build while this .a file is being used for + // debugging + DataBufferSP archive_data_sp = + DataBufferLLVM::CreateFromFileSpec(*file, length, file_offset); + if (!archive_data_sp) + return nullptr; + + lldb::offset_t archive_data_offset = 0; + Archive::shared_ptr archive_sp(Archive::FindCachedArchive( *file, module_sp->GetArchitecture(), module_sp->GetModificationTime(), file_offset)); - if (archive_sp) { - std::unique_ptr container_ap( - new ObjectContainerBSDArchive(module_sp, data_sp, data_offset, file, - file_offset, length)); + std::unique_ptr container_ap( + new ObjectContainerBSDArchive(module_sp, archive_data_sp, + archive_data_offset, file, file_offset, + length)); - if (container_ap.get()) { + if (container_ap.get()) { + if (archive_sp) { // We already have this archive in our cache, use it container_ap->SetArchive(archive_sp); return container_ap.release(); - } + } else if (container_ap->ParseHeader()) + return container_ap.release(); + } + } + } else { + // No data, just check for a cached archive + Archive::shared_ptr archive_sp(Archive::FindCachedArchive( + *file, module_sp->GetArchitecture(), module_sp->GetModificationTime(), + file_offset)); + if (archive_sp) { + std::unique_ptr container_ap( + new ObjectContainerBSDArchive(module_sp, data_sp, data_offset, file, + file_offset, length)); + + if (container_ap.get()) { + // We already have this archive in our cache, use it + container_ap->SetArchive(archive_sp); + return container_ap.release(); } } } @@ -453,63 +458,63 @@ // table of contents for the archive and cache it DataExtractor data; data.SetData(data_sp, data_offset, data_sp->GetByteSize()); - if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) { - const size_t initial_count = specs.GetSize(); - llvm::sys::TimePoint<> file_mod_time = - FileSystem::GetModificationTime(file); - Archive::shared_ptr archive_sp(Archive::FindCachedArchive( - file, ArchSpec(), file_mod_time, file_offset)); - bool set_archive_arch = false; - if (!archive_sp) { - set_archive_arch = true; - DataBufferSP data_sp( - file.MemoryMapFileContentsIfLocal(file_offset, file_size)); + if (!file || !data_sp || !ObjectContainerBSDArchive::MagicBytesMatch(data)) + return 0; + + const size_t initial_count = specs.GetSize(); + llvm::sys::TimePoint<> file_mod_time = FileSystem::GetModificationTime(file); + Archive::shared_ptr archive_sp( + Archive::FindCachedArchive(file, ArchSpec(), file_mod_time, file_offset)); + bool set_archive_arch = false; + if (!archive_sp) { + set_archive_arch = true; + data_sp = DataBufferLLVM::CreateFromFileSpec(file, file_size, file_offset); + if (data_sp) { data.SetData(data_sp, 0, data_sp->GetByteSize()); archive_sp = Archive::ParseAndCacheArchiveForFile( file, ArchSpec(), file_mod_time, file_offset, data); } + } - if (archive_sp) { - const size_t num_objects = archive_sp->GetNumObjects(); - for (size_t idx = 0; idx < num_objects; ++idx) { - const Object *object = archive_sp->GetObjectAtIndex(idx); - if (object) { - const lldb::offset_t object_file_offset = - file_offset + object->ar_file_offset; - if (object->ar_file_offset < file_size && - file_size > object_file_offset) { - if (ObjectFile::GetModuleSpecifications( - file, object_file_offset, file_size - object_file_offset, - specs)) { - ModuleSpec &spec = - specs.GetModuleSpecRefAtIndex(specs.GetSize() - 1); - llvm::sys::TimePoint<> object_mod_time( - std::chrono::seconds(object->ar_date)); - spec.GetObjectName() = object->ar_name; - spec.SetObjectOffset(object_file_offset); - spec.SetObjectSize(file_size - object_file_offset); - spec.GetObjectModificationTime() = object_mod_time; - } + if (archive_sp) { + const size_t num_objects = archive_sp->GetNumObjects(); + for (size_t idx = 0; idx < num_objects; ++idx) { + const Object *object = archive_sp->GetObjectAtIndex(idx); + if (object) { + const lldb::offset_t object_file_offset = + file_offset + object->ar_file_offset; + if (object->ar_file_offset < file_size && + file_size > object_file_offset) { + if (ObjectFile::GetModuleSpecifications( + file, object_file_offset, file_size - object_file_offset, + specs)) { + ModuleSpec &spec = + specs.GetModuleSpecRefAtIndex(specs.GetSize() - 1); + llvm::sys::TimePoint<> object_mod_time( + std::chrono::seconds(object->ar_date)); + spec.GetObjectName() = object->ar_name; + spec.SetObjectOffset(object_file_offset); + spec.SetObjectSize(file_size - object_file_offset); + spec.GetObjectModificationTime() = object_mod_time; } } } } - const size_t end_count = specs.GetSize(); - size_t num_specs_added = end_count - initial_count; - if (set_archive_arch && num_specs_added > 0) { - // The archive was created but we didn't have an architecture - // so we need to set it - for (size_t i = initial_count; i < end_count; ++i) { - ModuleSpec module_spec; - if (specs.GetModuleSpecAtIndex(i, module_spec)) { - if (module_spec.GetArchitecture().IsValid()) { - archive_sp->SetArchitecture(module_spec.GetArchitecture()); - break; - } + } + const size_t end_count = specs.GetSize(); + size_t num_specs_added = end_count - initial_count; + if (set_archive_arch && num_specs_added > 0) { + // The archive was created but we didn't have an architecture + // so we need to set it + for (size_t i = initial_count; i < end_count; ++i) { + ModuleSpec module_spec; + if (specs.GetModuleSpecAtIndex(i, module_spec)) { + if (module_spec.GetArchitecture().IsValid()) { + archive_sp->SetArchitecture(module_spec.GetArchitecture()); + break; } } } - return num_specs_added; } - return 0; + return num_specs_added; } Index: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -14,7 +14,7 @@ #include #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBuffer.h" +#include "lldb/Core/DataBufferLLVM.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" @@ -33,6 +33,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MipsABIFlags.h" #define CASE_AND_STREAM(s, def, width) \ @@ -386,31 +387,40 @@ lldb::offset_t file_offset, lldb::offset_t length) { if (!data_sp) { - data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length); + data_sp = DataBufferLLVM::CreateFromFileSpec(*file, length, file_offset); + if (!data_sp) + return nullptr; data_offset = 0; } - if (data_sp && - data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset)) { - const uint8_t *magic = data_sp->GetBytes() + data_offset; - if (ELFHeader::MagicBytesMatch(magic)) { - // Update the data to contain the entire file if it doesn't already - if (data_sp->GetByteSize() < length) { - data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length); - data_offset = 0; - magic = data_sp->GetBytes(); - } - unsigned address_size = ELFHeader::AddressSizeInBytes(magic); - if (address_size == 4 || address_size == 8) { - std::unique_ptr objfile_ap(new ObjectFileELF( - module_sp, data_sp, data_offset, file, file_offset, length)); - ArchSpec spec; - if (objfile_ap->GetArchitecture(spec) && - objfile_ap->SetModulesArchitecture(spec)) - return objfile_ap.release(); - } - } + assert(data_sp); + + if (data_sp->GetByteSize() <= (llvm::ELF::EI_NIDENT + data_offset)) + return nullptr; + + const uint8_t *magic = data_sp->GetBytes() + data_offset; + if (!ELFHeader::MagicBytesMatch(magic)) + return nullptr; + + // Update the data to contain the entire file if it doesn't already + if (data_sp->GetByteSize() < length) { + data_sp = DataBufferLLVM::CreateFromFileSpec(*file, length, file_offset); + if (!data_sp) + return nullptr; + data_offset = 0; + magic = data_sp->GetBytes(); + } + + unsigned address_size = ELFHeader::AddressSizeInBytes(magic); + if (address_size == 4 || address_size == 8) { + std::unique_ptr objfile_ap(new ObjectFileELF( + module_sp, data_sp, data_offset, file, file_offset, length)); + ArchSpec spec; + if (objfile_ap->GetArchitecture(spec) && + objfile_ap->SetModulesArchitecture(spec)) + return objfile_ap.release(); } + return NULL; } @@ -653,22 +663,24 @@ size_t section_header_end = header.e_shoff + header.e_shentsize; if (header.HasHeaderExtension() && section_header_end > data_sp->GetByteSize()) { - data_sp = file.MemoryMapFileContentsIfLocal (file_offset, - section_header_end); - data.SetData(data_sp); - lldb::offset_t header_offset = data_offset; - header.Parse(data, &header_offset); + data_sp = DataBufferLLVM::CreateFromFileSpec( + file, section_header_end, file_offset); + if (data_sp) { + data.SetData(data_sp); + lldb::offset_t header_offset = data_offset; + header.Parse(data, &header_offset); + } } // Try to get the UUID from the section list. Usually that's at the - // end, so - // map the file in if we don't have it already. + // end, so map the file in if we don't have it already. section_header_end = header.e_shoff + header.e_shnum * header.e_shentsize; if (section_header_end > data_sp->GetByteSize()) { - data_sp = file.MemoryMapFileContentsIfLocal(file_offset, - section_header_end); - data.SetData(data_sp); + data_sp = DataBufferLLVM::CreateFromFileSpec( + file, section_header_end, file_offset); + if (data_sp) + data.SetData(data_sp); } uint32_t gnu_debuglink_crc = 0; @@ -703,17 +715,17 @@ (file.GetByteSize() - file_offset) / 1024); // For core files - which usually don't happen to have a - // gnu_debuglink, - // and are pretty bulky - calculating whole contents crc32 would - // be too much of luxury. - // Thus we will need to fallback to something simpler. + // gnu_debuglink, and are pretty bulky - calculating whole + // contents crc32 would be too much of luxury. Thus we will need + // to fallback to something simpler. if (header.e_type == llvm::ELF::ET_CORE) { size_t program_headers_end = header.e_phoff + header.e_phnum * header.e_phentsize; if (program_headers_end > data_sp->GetByteSize()) { - data_sp = file.MemoryMapFileContentsIfLocal( - file_offset, program_headers_end); - data.SetData(data_sp); + data_sp = DataBufferLLVM::CreateFromFileSpec( + file, program_headers_end, file_offset); + if (data_sp) + data.SetData(data_sp); } ProgramHeaderColl program_headers; GetProgramHeaderInfo(program_headers, set_data, header); @@ -726,9 +738,10 @@ } if (segment_data_end > data_sp->GetByteSize()) { - data_sp = file.MemoryMapFileContentsIfLocal(file_offset, - segment_data_end); - data.SetData(data_sp); + data_sp = DataBufferLLVM::CreateFromFileSpec( + file, segment_data_end, file_offset); + if (data_sp) + data.SetData(data_sp); } core_notes_crc = @@ -736,10 +749,12 @@ } else { // Need to map entire file into memory to calculate the crc. data_sp = - file.MemoryMapFileContentsIfLocal(file_offset, SIZE_MAX); - data.SetData(data_sp); - gnu_debuglink_crc = calc_gnu_debuglink_crc32( - data.GetDataStart(), data.GetByteSize()); + DataBufferLLVM::CreateFromFileSpec(file, -1, file_offset); + if (data_sp) { + data.SetData(data_sp); + gnu_debuglink_crc = calc_gnu_debuglink_crc32( + data.GetDataStart(), data.GetByteSize()); + } } } if (gnu_debuglink_crc) { Index: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -18,7 +18,7 @@ #include "Plugins/Process/Utility/RegisterContextDarwin_i386.h" #include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBuffer.h" +#include "lldb/Core/DataBufferLLVM.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Log.h" @@ -47,6 +47,8 @@ #include "lldb/Utility/SafeMachO.h" +#include "llvm/Support/MemoryBuffer.h" + #include "ObjectFileMachO.h" #if defined(__APPLE__) && \ @@ -857,22 +859,28 @@ lldb::offset_t file_offset, lldb::offset_t length) { if (!data_sp) { - data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length); + data_sp = DataBufferLLVM::CreateFromFileSpec(*file, length, file_offset); + if (!data_sp) + return nullptr; data_offset = 0; } - if (ObjectFileMachO::MagicBytesMatch(data_sp, data_offset, length)) { - // Update the data to contain the entire file if it doesn't already - if (data_sp->GetByteSize() < length) { - data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length); - data_offset = 0; - } - std::unique_ptr objfile_ap(new ObjectFileMachO( - module_sp, data_sp, data_offset, file, file_offset, length)); - if (objfile_ap.get() && objfile_ap->ParseHeader()) - return objfile_ap.release(); + if (!ObjectFileMachO::MagicBytesMatch(data_sp, data_offset, length)) + return nullptr; + + // Update the data to contain the entire file if it doesn't already + if (data_sp->GetByteSize() < length) { + data_sp = DataBufferLLVM::CreateFromFileSpec(*file, length, file_offset); + if (!data_sp) + return nullptr; + data_offset = 0; } - return NULL; + auto objfile_ap = llvm::make_unique( + module_sp, data_sp, data_offset, file, file_offset, length); + if (!objfile_ap || !objfile_ap->ParseHeader()) + return nullptr; + + return objfile_ap.release(); } ObjectFile *ObjectFileMachO::CreateMemoryInstance( @@ -2085,22 +2093,22 @@ const ByteOrder byte_order, const uint32_t addr_byte_size) { UUID dsc_uuid; - DataBufferSP dsc_data_sp = dyld_shared_cache.MemoryMapFileContentsIfLocal( - 0, sizeof(struct lldb_copy_dyld_cache_header_v1)); - if (dsc_data_sp) { - DataExtractor dsc_header_data(dsc_data_sp, byte_order, addr_byte_size); + DataBufferSP DscData = DataBufferLLVM::CreateFromFileSpec( + dyld_shared_cache, sizeof(struct lldb_copy_dyld_cache_header_v1), 0); + if (!DscData) + return dsc_uuid; + DataExtractor dsc_header_data(DscData, byte_order, addr_byte_size); - char version_str[7]; - lldb::offset_t offset = 0; - memcpy(version_str, dsc_header_data.GetData(&offset, 6), 6); - version_str[6] = '\0'; - if (strcmp(version_str, "dyld_v") == 0) { - offset = offsetof(struct lldb_copy_dyld_cache_header_v1, uuid); - uint8_t uuid_bytes[sizeof(uuid_t)]; - memcpy(uuid_bytes, dsc_header_data.GetData(&offset, sizeof(uuid_t)), - sizeof(uuid_t)); - dsc_uuid.SetBytes(uuid_bytes); - } + char version_str[7]; + lldb::offset_t offset = 0; + memcpy(version_str, dsc_header_data.GetData(&offset, 6), 6); + version_str[6] = '\0'; + if (strcmp(version_str, "dyld_v") == 0) { + offset = offsetof(struct lldb_copy_dyld_cache_header_v1, uuid); + uint8_t uuid_bytes[sizeof(uuid_t)]; + memcpy(uuid_bytes, dsc_header_data.GetData(&offset, sizeof(uuid_t)), + sizeof(uuid_t)); + dsc_uuid.SetBytes(uuid_bytes); } return dsc_uuid; } @@ -2692,8 +2700,8 @@ // Process the dyld shared cache header to find the unmapped symbols - DataBufferSP dsc_data_sp = dsc_filespec.MemoryMapFileContentsIfLocal( - 0, sizeof(struct lldb_copy_dyld_cache_header_v1)); + DataBufferSP dsc_data_sp = DataBufferLLVM::CreateFromFileSpec( + dsc_filespec, sizeof(struct lldb_copy_dyld_cache_header_v1), 0); if (!dsc_uuid.IsValid()) { dsc_uuid = GetSharedCacheUUID(dsc_filespec, byte_order, addr_byte_size); } @@ -2726,9 +2734,11 @@ mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v1)) { DataBufferSP dsc_mapping_info_data_sp = - dsc_filespec.MemoryMapFileContentsIfLocal( - mappingOffset, - sizeof(struct lldb_copy_dyld_cache_mapping_info)); + DataBufferLLVM::CreateFromFileSpec( + dsc_filespec, + sizeof(struct lldb_copy_dyld_cache_mapping_info), + mappingOffset); + DataExtractor dsc_mapping_info_data(dsc_mapping_info_data_sp, byte_order, addr_byte_size); offset = 0; @@ -2750,9 +2760,11 @@ if (localSymbolsOffset && localSymbolsSize) { // Map the local symbols - if (DataBufferSP dsc_local_symbols_data_sp = - dsc_filespec.MemoryMapFileContentsIfLocal( - localSymbolsOffset, localSymbolsSize)) { + DataBufferSP dsc_local_symbols_data_sp = + DataBufferLLVM::CreateFromFileSpec( + dsc_filespec, localSymbolsSize, localSymbolsOffset); + + if (dsc_local_symbols_data_sp) { DataExtractor dsc_local_symbols_data(dsc_local_symbols_data_sp, byte_order, addr_byte_size); Index: lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ lldb/trunk/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -13,8 +13,8 @@ #include "llvm/Support/COFF.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBuffer.h" #include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataBufferLLVM.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -30,6 +30,8 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/StreamString.h" +#include "llvm/Support/MemoryBuffer.h" + #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ #define IMAGE_NT_SIGNATURE 0x00004550 // PE00 #define OPT_HEADER_MAGIC_PE32 0x010b @@ -65,20 +67,28 @@ lldb::offset_t file_offset, lldb::offset_t length) { if (!data_sp) { - data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length); + data_sp = DataBufferLLVM::CreateFromFileSpec(*file, length, file_offset); + if (!data_sp) + return nullptr; data_offset = 0; } - if (ObjectFilePECOFF::MagicBytesMatch(data_sp)) { - // Update the data to contain the entire file if it doesn't already - if (data_sp->GetByteSize() < length) - data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length); - std::unique_ptr objfile_ap(new ObjectFilePECOFF( - module_sp, data_sp, data_offset, file, file_offset, length)); - if (objfile_ap.get() && objfile_ap->ParseHeader()) - return objfile_ap.release(); + if (!ObjectFilePECOFF::MagicBytesMatch(data_sp)) + return nullptr; + + // Update the data to contain the entire file if it doesn't already + if (data_sp->GetByteSize() < length) { + data_sp = DataBufferLLVM::CreateFromFileSpec(*file, length, file_offset); + if (!data_sp) + return nullptr; } - return NULL; + + auto objfile_ap = llvm::make_unique( + module_sp, data_sp, data_offset, file, file_offset, length); + if (!objfile_ap || !objfile_ap->ParseHeader()) + return nullptr; + + return objfile_ap.release(); } ObjectFile *ObjectFilePECOFF::CreateMemoryInstance( Index: lldb/trunk/source/Plugins/Process/minidump/ProcessMinidump.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ lldb/trunk/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -12,7 +12,7 @@ #include "ThreadMinidump.h" // Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataBufferLLVM.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -25,6 +25,7 @@ #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/LLDBAssert.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Threading.h" // C includes @@ -50,20 +51,25 @@ lldb::ProcessSP process_sp; // Read enough data for the Minidump header - const size_t header_size = sizeof(MinidumpHeader); - lldb::DataBufferSP data_sp(crash_file->MemoryMapFileContents(0, header_size)); - if (!data_sp) + constexpr size_t header_size = sizeof(MinidumpHeader); + auto DataPtr = + DataBufferLLVM::CreateFromFileSpec(*crash_file, header_size, 0); + if (!DataPtr) return nullptr; + assert(DataPtr->GetByteSize() == header_size); + // first, only try to parse the header, beacuse we need to be fast - llvm::ArrayRef header_data(data_sp->GetBytes(), header_size); - const MinidumpHeader *header = MinidumpHeader::Parse(header_data); + llvm::ArrayRef HeaderBytes = DataPtr->GetData(); + const MinidumpHeader *header = MinidumpHeader::Parse(HeaderBytes); + if (header == nullptr) + return nullptr; - if (data_sp->GetByteSize() != header_size || header == nullptr) + auto AllData = DataBufferLLVM::CreateFromFileSpec(*crash_file, -1, 0); + if (!AllData) return nullptr; - lldb::DataBufferSP all_data_sp(crash_file->MemoryMapFileContents()); - auto minidump_parser = MinidumpParser::Create(all_data_sp); + auto minidump_parser = MinidumpParser::Create(AllData); // check if the parser object is valid if (!minidump_parser) return nullptr; Index: lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp =================================================================== --- lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp +++ lldb/trunk/unittests/Process/minidump/MinidumpParserTest.cpp @@ -19,6 +19,7 @@ #include "gtest/gtest.h" #include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataBufferLLVM.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Host/FileSpec.h" #include "lldb/Target/MemoryRegionInfo.h" @@ -26,6 +27,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" // C includes @@ -49,11 +51,11 @@ void SetUpData(const char *minidump_filename, size_t load_size = SIZE_MAX) { llvm::SmallString<128> filename = inputs_folder; llvm::sys::path::append(filename, minidump_filename); - FileSpec minidump_file(filename.c_str(), false); - lldb::DataBufferSP data_sp( - minidump_file.MemoryMapFileContents(0, load_size)); + + auto BufferPtr = DataBufferLLVM::CreateFromPath(filename, load_size, 0); + llvm::Optional optional_parser = - MinidumpParser::Create(data_sp); + MinidumpParser::Create(BufferPtr); ASSERT_TRUE(optional_parser.hasValue()); parser.reset(new MinidumpParser(optional_parser.getValue())); ASSERT_GT(parser->GetData().size(), 0UL);