[Lldb-commits] [lldb] fc54427 - [lldb] Refactor DataBuffer so we can map files as read-only

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Tue Apr 5 13:46:46 PDT 2022


Author: Jonas Devlieghere
Date: 2022-04-05T13:46:37-07:00
New Revision: fc54427e76c89e567390dd4a1d64a65568f4ec26

URL: https://github.com/llvm/llvm-project/commit/fc54427e76c89e567390dd4a1d64a65568f4ec26
DIFF: https://github.com/llvm/llvm-project/commit/fc54427e76c89e567390dd4a1d64a65568f4ec26.diff

LOG: [lldb] Refactor DataBuffer so we can map files as read-only

Currently, all data buffers are assumed to be writable. This is a
problem on macOS where it's not allowed to load unsigned binaries in
memory as writable. To be more precise, MAP_RESILIENT_CODESIGN and
MAP_RESILIENT_MEDIA need to be set for mapped (unsigned) binaries on our
platform.

Binaries are mapped through FileSystem::CreateDataBuffer which returns a
DataBufferLLVM. The latter is backed by a llvm::WritableMemoryBuffer
because every DataBuffer in LLDB is considered to be writable. In order
to use a read-only llvm::MemoryBuffer I had to split our abstraction
around it.

This patch distinguishes between a DataBuffer (read-only) and
WritableDataBuffer (read-write) and updates LLDB to use the appropriate
one.

rdar://74890607

Differential revision: https://reviews.llvm.org/D122856

Added: 
    lldb/unittests/Utility/DataBufferTest.cpp

Modified: 
    lldb/include/lldb/Core/ValueObject.h
    lldb/include/lldb/Host/FileSystem.h
    lldb/include/lldb/Symbol/CompactUnwindInfo.h
    lldb/include/lldb/Symbol/ObjectFile.h
    lldb/include/lldb/Target/ProcessStructReader.h
    lldb/include/lldb/Target/RegisterCheckpoint.h
    lldb/include/lldb/Target/RegisterContext.h
    lldb/include/lldb/Target/RegisterContextUnwind.h
    lldb/include/lldb/Utility/DataBuffer.h
    lldb/include/lldb/Utility/DataBufferHeap.h
    lldb/include/lldb/Utility/DataBufferLLVM.h
    lldb/include/lldb/lldb-forward.h
    lldb/source/Commands/CommandObjectMemory.cpp
    lldb/source/Core/SourceManager.cpp
    lldb/source/Core/ValueObject.cpp
    lldb/source/DataFormatters/StringPrinter.cpp
    lldb/source/DataFormatters/TypeFormat.cpp
    lldb/source/Expression/IRExecutionUnit.cpp
    lldb/source/Host/common/FileSystem.cpp
    lldb/source/Host/common/Host.cpp
    lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
    lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
    lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
    lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
    lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
    lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
    lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
    lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
    lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
    lldb/source/Plugins/Language/ObjC/CF.cpp
    lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
    lldb/source/Plugins/Language/ObjC/NSSet.cpp
    lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
    lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
    lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
    lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
    lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
    lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
    lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
    lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
    lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
    lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
    lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextDummy.h
    lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextHistory.h
    lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextMemory.h
    lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
    lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
    lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
    lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
    lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
    lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
    lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp
    lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
    lldb/source/Symbol/ObjectFile.cpp
    lldb/source/Target/Platform.cpp
    lldb/source/Target/RegisterContextUnwind.cpp
    lldb/source/Utility/DataBufferHeap.cpp
    lldb/source/Utility/DataBufferLLVM.cpp
    lldb/unittests/Utility/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h
index dac7aac062464..4a4bd4dd3ae62 100644
--- a/lldb/include/lldb/Core/ValueObject.h
+++ b/lldb/include/lldb/Core/ValueObject.h
@@ -679,7 +679,7 @@ class ValueObject {
   bool IsCStringContainer(bool check_pointer = false);
 
   std::pair<size_t, bool>
-  ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error,
+  ReadPointedString(lldb::WritableDataBufferSP &buffer_sp, Status &error,
                     uint32_t max_length = 0, bool honor_array = true,
                     lldb::Format item_format = lldb::eFormatCharArray);
 

diff  --git a/lldb/include/lldb/Host/FileSystem.h b/lldb/include/lldb/Host/FileSystem.h
index feb2051812b0a..8a4ee8470af24 100644
--- a/lldb/include/lldb/Host/FileSystem.h
+++ b/lldb/include/lldb/Host/FileSystem.h
@@ -148,6 +148,12 @@ class FileSystem {
   std::shared_ptr<DataBuffer> CreateDataBuffer(const FileSpec &file_spec,
                                                uint64_t size = 0,
                                                uint64_t offset = 0);
+  std::shared_ptr<WritableDataBuffer>
+  CreateWritableDataBuffer(const llvm::Twine &path, uint64_t size = 0,
+                           uint64_t offset = 0);
+  std::shared_ptr<WritableDataBuffer>
+  CreateWritableDataBuffer(const FileSpec &file_spec, uint64_t size = 0,
+                           uint64_t offset = 0);
   /// \}
 
   /// Call into the Host to see if it can help find the file.

diff  --git a/lldb/include/lldb/Symbol/CompactUnwindInfo.h b/lldb/include/lldb/Symbol/CompactUnwindInfo.h
index 402155cbe08da..5f7c2286d35a0 100644
--- a/lldb/include/lldb/Symbol/CompactUnwindInfo.h
+++ b/lldb/include/lldb/Symbol/CompactUnwindInfo.h
@@ -138,9 +138,10 @@ class CompactUnwindInfo {
 
   ObjectFile &m_objfile;
   lldb::SectionSP m_section_sp;
-  lldb::DataBufferSP m_section_contents_if_encrypted; // if the binary is
-                                                      // encrypted, read the
-                                                      // sect contents
+  lldb::WritableDataBufferSP
+      m_section_contents_if_encrypted; // if the binary is
+                                       // encrypted, read the
+                                       // sect contents
   // out of live memory and cache them here
   std::mutex m_mutex;
   std::vector<UnwindIndex> m_indexes;

diff  --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h
index 8bf047cd45141..73202a2d6ec55 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -759,6 +759,9 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
   ///     false otherwise.
   bool SetModulesArchitecture(const ArchSpec &new_arch);
 
+  /// The number of bytes to read when going through the plugins.
+  static size_t g_initial_bytes_to_read;
+
   static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size,
                                         uint64_t Offset);
 

diff  --git a/lldb/include/lldb/Target/ProcessStructReader.h b/lldb/include/lldb/Target/ProcessStructReader.h
index 0a91bef8048b9..8046ef4958bbe 100644
--- a/lldb/include/lldb/Target/ProcessStructReader.h
+++ b/lldb/include/lldb/Target/ProcessStructReader.h
@@ -69,7 +69,7 @@ class ProcessStructReader {
     auto total_size = struct_type.GetByteSize(nullptr);
     if (!total_size)
       return;
-    lldb::DataBufferSP buffer_sp(new DataBufferHeap(*total_size, 0));
+    lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(*total_size, 0));
     Status error;
     process->ReadMemoryFromInferior(base_addr, buffer_sp->GetBytes(),
                                     *total_size, error);

diff  --git a/lldb/include/lldb/Target/RegisterCheckpoint.h b/lldb/include/lldb/Target/RegisterCheckpoint.h
index 8681fb9628018..bc92b239a5179 100644
--- a/lldb/include/lldb/Target/RegisterCheckpoint.h
+++ b/lldb/include/lldb/Target/RegisterCheckpoint.h
@@ -35,12 +35,12 @@ class RegisterCheckpoint : public UserID {
 
   ~RegisterCheckpoint() = default;
 
-  lldb::DataBufferSP &GetData() { return m_data_sp; }
+  lldb::WritableDataBufferSP &GetData() { return m_data_sp; }
 
-  const lldb::DataBufferSP &GetData() const { return m_data_sp; }
+  const lldb::WritableDataBufferSP &GetData() const { return m_data_sp; }
 
 protected:
-  lldb::DataBufferSP m_data_sp;
+  lldb::WritableDataBufferSP m_data_sp;
   Reason m_reason;
 
   // Make RegisterCheckpointSP if you wish to share the data in this class.

diff  --git a/lldb/include/lldb/Target/RegisterContext.h b/lldb/include/lldb/Target/RegisterContext.h
index 392b462ecf072..de0efd982daaa 100644
--- a/lldb/include/lldb/Target/RegisterContext.h
+++ b/lldb/include/lldb/Target/RegisterContext.h
@@ -43,7 +43,7 @@ class RegisterContext : public std::enable_shared_from_this<RegisterContext>,
   virtual bool WriteRegister(const RegisterInfo *reg_info,
                              const RegisterValue &reg_value) = 0;
 
-  virtual bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) {
+  virtual bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) {
     return false;
   }
 

diff  --git a/lldb/include/lldb/Target/RegisterContextUnwind.h b/lldb/include/lldb/Target/RegisterContextUnwind.h
index edda281d5aa78..ef03a6746d723 100644
--- a/lldb/include/lldb/Target/RegisterContextUnwind.h
+++ b/lldb/include/lldb/Target/RegisterContextUnwind.h
@@ -50,7 +50,7 @@ class RegisterContextUnwind : public lldb_private::RegisterContext {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/include/lldb/Utility/DataBuffer.h b/lldb/include/lldb/Utility/DataBuffer.h
index c778299b89ade..c52c7e0e10a0c 100644
--- a/lldb/include/lldb/Utility/DataBuffer.h
+++ b/lldb/include/lldb/Utility/DataBuffer.h
@@ -20,12 +20,12 @@
 namespace lldb_private {
 
 /// \class DataBuffer DataBuffer.h "lldb/Core/DataBuffer.h"
-/// A pure virtual protocol class for abstracted data buffers.
+/// A pure virtual protocol class for abstracted read only data buffers.
 ///
-/// DataBuffer is an abstract class that gets packaged into a shared pointer
-/// that can use to implement various ways to store data (on the heap, memory
-/// mapped, cached inferior memory). It gets used by DataExtractor so many
-/// DataExtractor objects can share the same data and sub-ranges of that
+/// DataBuffer is an abstract class that gets packaged into a shared
+/// pointer that can use to implement various ways to store data (on the heap,
+/// memory mapped, cached inferior memory). It gets used by DataExtractor so
+/// many DataExtractor objects can share the same data and sub-ranges of that
 /// shared data, and the last object that contains a reference to the shared
 /// data will free it.
 ///
@@ -42,52 +42,106 @@ namespace lldb_private {
 /// with some extra function calls to load the data before it gets accessed.
 class DataBuffer {
 public:
-  /// Destructor
-  ///
-  /// The destructor is virtual as other classes will inherit from this class
-  /// and be downcast to the DataBuffer pure virtual interface. The virtual
-  /// destructor ensures that destructing the base class will destruct the
-  /// class that inherited from it correctly.
   virtual ~DataBuffer() = default;
 
-  /// Get a pointer to the data.
+  /// Get the number of bytes in the data buffer.
   ///
   /// \return
-  ///     A pointer to the bytes owned by this object, or NULL if the
-  ///     object contains no bytes.
-  virtual uint8_t *GetBytes() = 0;
+  ///     The number of bytes this object currently contains.
+  virtual lldb::offset_t GetByteSize() const = 0;
 
   /// Get a const pointer to the data.
   ///
   /// \return
   ///     A const pointer to the bytes owned by this object, or NULL
   ///     if the object contains no bytes.
-  virtual const uint8_t *GetBytes() const = 0;
-
-  /// Get the number of bytes in the data buffer.
-  ///
-  /// \return
-  ///     The number of bytes this object currently contains.
-  virtual lldb::offset_t GetByteSize() const = 0;
+  const uint8_t *GetBytes() const { return GetBytesImpl(); }
 
   llvm::ArrayRef<uint8_t> GetData() const {
     return llvm::ArrayRef<uint8_t>(GetBytes(), GetByteSize());
   }
 
+  /// LLVM RTTI support.
+  /// {
+  static char ID;
+  virtual bool isA(const void *ClassID) const { return ClassID == &ID; }
+  static bool classof(const DataBuffer *data_buffer) {
+    return data_buffer->isA(&ID);
+  }
+  /// }
+
+protected:
+  /// Get a const pointer to the data.
+  ///
+  /// \return
+  ///     A const pointer to the bytes owned by this object, or NULL
+  ///     if the object contains no bytes.
+  virtual const uint8_t *GetBytesImpl() const = 0;
+};
+
+/// \class DataBuffer DataBuffer.h "lldb/Core/DataBuffer.h"
+/// A pure virtual protocol class for abstracted writable data buffers.
+///
+/// DataBuffer is an abstract class that gets packaged into a shared pointer
+/// that can use to implement various ways to store data (on the heap, memory
+/// mapped, cached inferior memory). It gets used by DataExtractor so many
+/// DataExtractor objects can share the same data and sub-ranges of that
+/// shared data, and the last object that contains a reference to the shared
+/// data will free it.
+class WritableDataBuffer : public DataBuffer {
+public:
+  /// Destructor
+  ///
+  /// The destructor is virtual as other classes will inherit from this class
+  /// and be downcast to the DataBuffer pure virtual interface. The virtual
+  /// destructor ensures that destructing the base class will destruct the
+  /// class that inherited from it correctly.
+  virtual ~WritableDataBuffer() = default;
+
+  using DataBuffer::GetBytes;
+  using DataBuffer::GetData;
+
+  /// Get a pointer to the data.
+  ///
+  /// \return
+  ///     A pointer to the bytes owned by this object, or NULL if the
+  ///     object contains no bytes.
+  uint8_t *GetBytes() { return const_cast<uint8_t *>(GetBytesImpl()); }
+
   llvm::MutableArrayRef<uint8_t> GetData() {
     return llvm::MutableArrayRef<uint8_t>(GetBytes(), GetByteSize());
   }
+
+  /// LLVM RTTI support.
+  /// {
+  static char ID;
+  bool isA(const void *ClassID) const override {
+    return ClassID == &ID || DataBuffer::isA(ClassID);
+  }
+  static bool classof(const DataBuffer *data_buffer) {
+    return data_buffer->isA(&ID);
+  }
+  /// }
 };
 
-class DataBufferUnowned : public DataBuffer {
+class DataBufferUnowned : public WritableDataBuffer {
 public:
   DataBufferUnowned(uint8_t *bytes, lldb::offset_t size)
       : m_bytes(bytes), m_size(size) {}
 
-  uint8_t *GetBytes() override { return m_bytes; }
-  const uint8_t *GetBytes() const override { return m_bytes; }
+  const uint8_t *GetBytesImpl() const override { return m_bytes; }
   lldb::offset_t GetByteSize() const override { return m_size; }
 
+  /// LLVM RTTI support.
+  /// {
+  static char ID;
+  bool isA(const void *ClassID) const override {
+    return ClassID == &ID || WritableDataBuffer::isA(ClassID);
+  }
+  static bool classof(const DataBuffer *data_buffer) {
+    return data_buffer->isA(&ID);
+  }
+  /// }
 private:
   uint8_t *m_bytes;
   lldb::offset_t m_size;

diff  --git a/lldb/include/lldb/Utility/DataBufferHeap.h b/lldb/include/lldb/Utility/DataBufferHeap.h
index f50cec2479d10..a7270e95bf6d8 100644
--- a/lldb/include/lldb/Utility/DataBufferHeap.h
+++ b/lldb/include/lldb/Utility/DataBufferHeap.h
@@ -27,7 +27,7 @@ namespace lldb_private {
 /// pages in. Large amounts of data that comes from files should probably use
 /// DataBufferLLVM, which can intelligently determine when memory mapping is
 /// optimal.
-class DataBufferHeap : public DataBuffer {
+class DataBufferHeap : public WritableDataBuffer {
 public:
   /// Default constructor
   ///
@@ -54,17 +54,20 @@ class DataBufferHeap : public DataBuffer {
   ///     The number of bytes in \a src to copy.
   DataBufferHeap(const void *src, lldb::offset_t src_len);
 
+  /// Construct by making a copy of a DataBuffer.
+  ///
+  /// \param[in] data_buffer
+  ///     A read only data buffer to copy.
+  DataBufferHeap(const DataBuffer &data_buffer);
+
   /// Destructor.
   ///
   /// Virtual destructor since this class inherits from a pure virtual base
   /// class #DataBuffer.
   ~DataBufferHeap() override;
 
-  /// \copydoc DataBuffer::GetBytes()
-  uint8_t *GetBytes() override;
-
   /// \copydoc DataBuffer::GetBytes() const
-  const uint8_t *GetBytes() const override;
+  const uint8_t *GetBytesImpl() const override;
 
   /// \copydoc DataBuffer::GetByteSize() const
   lldb::offset_t GetByteSize() const override;
@@ -100,6 +103,17 @@ class DataBufferHeap : public DataBuffer {
 
   void Clear();
 
+  /// LLVM RTTI support.
+  /// {
+  static char ID;
+  bool isA(const void *ClassID) const override {
+    return ClassID == &ID || WritableDataBuffer::isA(ClassID);
+  }
+  static bool classof(const DataBuffer *data_buffer) {
+    return data_buffer->isA(&ID);
+  }
+  /// }
+
 private:
   // This object uses a std::vector<uint8_t> to store its data. This takes care
   // of free the data when the object is deleted.

diff  --git a/lldb/include/lldb/Utility/DataBufferLLVM.h b/lldb/include/lldb/Utility/DataBufferLLVM.h
index eeb17c51f6e13..1058d7ac0811c 100644
--- a/lldb/include/lldb/Utility/DataBufferLLVM.h
+++ b/lldb/include/lldb/Utility/DataBufferLLVM.h
@@ -17,26 +17,63 @@
 
 namespace llvm {
 class WritableMemoryBuffer;
+class MemoryBuffer;
 class Twine;
 } // namespace llvm
 
 namespace lldb_private {
-
 class FileSystem;
+
 class DataBufferLLVM : public DataBuffer {
 public:
   ~DataBufferLLVM() override;
 
-  uint8_t *GetBytes() override;
-  const uint8_t *GetBytes() const override;
+  const uint8_t *GetBytesImpl() const override;
   lldb::offset_t GetByteSize() const override;
 
-private:
-  friend FileSystem;
+  /// LLVM RTTI support.
+  /// {
+  static char ID;
+  bool isA(const void *ClassID) const override {
+    return ClassID == &ID || DataBuffer::isA(ClassID);
+  }
+  static bool classof(const DataBuffer *data_buffer) {
+    return data_buffer->isA(&ID);
+  }
+  /// }
+
+  /// Construct a DataBufferLLVM from \p Buffer.  \p Buffer must be a valid
+  /// pointer.
+  explicit DataBufferLLVM(std::unique_ptr<llvm::MemoryBuffer> Buffer);
+
+protected:
+  std::unique_ptr<llvm::MemoryBuffer> Buffer;
+};
+
+class WritableDataBufferLLVM : public WritableDataBuffer {
+public:
+  ~WritableDataBufferLLVM() override;
+
+  const uint8_t *GetBytesImpl() const override;
+  lldb::offset_t GetByteSize() const override;
+
+  /// LLVM RTTI support.
+  /// {
+  static char ID;
+  bool isA(const void *ClassID) const override {
+    return ClassID == &ID || WritableDataBuffer::isA(ClassID);
+  }
+  static bool classof(const DataBuffer *data_buffer) {
+    return data_buffer->isA(&ID);
+  }
+  /// }
+
   /// Construct a DataBufferLLVM from \p Buffer.  \p Buffer must be a valid
   /// pointer.
-  explicit DataBufferLLVM(std::unique_ptr<llvm::WritableMemoryBuffer> Buffer);
+  explicit WritableDataBufferLLVM(
+      std::unique_ptr<llvm::WritableMemoryBuffer> Buffer);
 
+protected:
   std::unique_ptr<llvm::WritableMemoryBuffer> Buffer;
 };
 } // namespace lldb_private

diff  --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 6f8c52ff37494..487b2f20792b9 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -67,6 +67,7 @@ class DWARFCallFrameInfo;
 class DWARFDataExtractor;
 class DWARFExpression;
 class DataBuffer;
+class WritableDataBuffer;
 class DataBufferHeap;
 class DataEncoder;
 class DataExtractor;
@@ -309,6 +310,7 @@ typedef std::shared_ptr<lldb_private::CommandObject> CommandObjectSP;
 typedef std::shared_ptr<lldb_private::Connection> ConnectionSP;
 typedef std::shared_ptr<lldb_private::CompileUnit> CompUnitSP;
 typedef std::shared_ptr<lldb_private::DataBuffer> DataBufferSP;
+typedef std::shared_ptr<lldb_private::WritableDataBuffer> WritableDataBufferSP;
 typedef std::shared_ptr<lldb_private::DataExtractor> DataExtractorSP;
 typedef std::shared_ptr<lldb_private::Debugger> DebuggerSP;
 typedef std::weak_ptr<lldb_private::Debugger> DebuggerWP;

diff  --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index 381a41e8ae67b..b7b28bc799091 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -639,7 +639,7 @@ class CommandObjectMemoryRead : public CommandObjectParsed {
       return false;
     }
 
-    DataBufferSP data_sp;
+    WritableDataBufferSP data_sp;
     size_t bytes_read = 0;
     if (compiler_type.GetOpaqueQualType()) {
       // Make sure we don't display our type as ASCII bytes like the default

diff  --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp
index 2e3835d5f451f..8599c0a6a2284 100644
--- a/lldb/source/Core/SourceManager.cpp
+++ b/lldb/source/Core/SourceManager.cpp
@@ -644,7 +644,7 @@ bool SourceManager::File::CalculateLineOffsets(uint32_t line) {
       if (m_data_sp.get() == nullptr)
         return false;
 
-      const char *start = (char *)m_data_sp->GetBytes();
+      const char *start = (const char *)m_data_sp->GetBytes();
       if (start) {
         const char *end = start + m_data_sp->GetByteSize();
 
@@ -694,7 +694,7 @@ bool SourceManager::File::GetLine(uint32_t line_no, std::string &buffer) {
   if (end_offset == UINT32_MAX) {
     end_offset = m_data_sp->GetByteSize();
   }
-  buffer.assign((char *)m_data_sp->GetBytes() + start_offset,
+  buffer.assign((const char *)m_data_sp->GetBytes() + start_offset,
                 end_offset - start_offset);
 
   return true;

diff  --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index ddc2c3262b10b..0b99b988a67fe 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -848,7 +848,7 @@ bool ValueObject::SetData(DataExtractor &data, Status &error) {
 }
 
 static bool CopyStringDataToBufferSP(const StreamString &source,
-                                     lldb::DataBufferSP &destination) {
+                                     lldb::WritableDataBufferSP &destination) {
   llvm::StringRef src = source.GetString();
   src = src.rtrim('\0');
   destination = std::make_shared<DataBufferHeap>(src.size(), 0);
@@ -857,9 +857,9 @@ static bool CopyStringDataToBufferSP(const StreamString &source,
 }
 
 std::pair<size_t, bool>
-ValueObject::ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error,
-                               uint32_t max_length, bool honor_array,
-                               Format item_format) {
+ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
+                               Status &error, uint32_t max_length,
+                               bool honor_array, Format item_format) {
   bool was_capped = false;
   StreamString s;
   ExecutionContext exe_ctx(GetExecutionContextRef());
@@ -1184,7 +1184,7 @@ bool ValueObject::DumpPrintableRepresentation(
                eFormatVectorOfChar)) // print char[] & char* directly
       {
         Status error;
-        lldb::DataBufferSP buffer_sp;
+        lldb::WritableDataBufferSP buffer_sp;
         std::pair<size_t, bool> read_string = ReadPointedString(
             buffer_sp, error, 0, (custom_format == eFormatVectorOfChar) ||
                                      (custom_format == eFormatCharArray));

diff  --git a/lldb/source/DataFormatters/StringPrinter.cpp b/lldb/source/DataFormatters/StringPrinter.cpp
index ec8664ebe17ac..0dd5d518f60b8 100644
--- a/lldb/source/DataFormatters/StringPrinter.cpp
+++ b/lldb/source/DataFormatters/StringPrinter.cpp
@@ -293,7 +293,7 @@ static bool DumpEncodedBufferToStream(
       data_ptr = (const SourceDataType *)data.GetDataStart();
     }
 
-    lldb::DataBufferSP utf8_data_buffer_sp;
+    lldb::WritableDataBufferSP utf8_data_buffer_sp;
     llvm::UTF8 *utf8_data_ptr = nullptr;
     llvm::UTF8 *utf8_data_end_ptr = nullptr;
 
@@ -450,7 +450,7 @@ static bool ReadEncodedBufferAndDumpToStream(
   }
 
   const int bufferSPSize = sourceSize * type_width;
-  lldb::DataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize, 0));
+  lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(bufferSPSize, 0));
 
   // Check if we got bytes. We never get any bytes if we have an empty
   // string, but we still continue so that we end up actually printing

diff  --git a/lldb/source/DataFormatters/TypeFormat.cpp b/lldb/source/DataFormatters/TypeFormat.cpp
index 9c50466870130..ae9d8d806a5b8 100644
--- a/lldb/source/DataFormatters/TypeFormat.cpp
+++ b/lldb/source/DataFormatters/TypeFormat.cpp
@@ -77,7 +77,8 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj,
             if (target_sp) {
               size_t max_len = target_sp->GetMaximumSizeOfStringSummary();
               Status error;
-              DataBufferSP buffer_sp(new DataBufferHeap(max_len + 1, 0));
+              WritableDataBufferSP buffer_sp(
+                  new DataBufferHeap(max_len + 1, 0));
               Address address(valobj->GetPointerValue());
               if (target_sp->ReadCStringFromMemory(
                       address, (char *)buffer_sp->GetBytes(), max_len, error) &&

diff  --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp
index 91b92f1ba3003..49fa72f7112de 100644
--- a/lldb/source/Expression/IRExecutionUnit.cpp
+++ b/lldb/source/Expression/IRExecutionUnit.cpp
@@ -151,7 +151,8 @@ Status IRExecutionUnit::DisassembleFunction(Stream &stream,
     return ret;
   }
 
-  lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
+  lldb::WritableDataBufferSP buffer_sp(
+      new DataBufferHeap(func_range.second, 0));
 
   Process *process = exe_ctx.GetProcessPtr();
   Status err;

diff  --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp
index 683b6716b47cc..501062f99a539 100644
--- a/lldb/source/Host/common/FileSystem.cpp
+++ b/lldb/source/Host/common/FileSystem.cpp
@@ -273,27 +273,54 @@ void FileSystem::Resolve(FileSpec &file_spec) {
   file_spec.SetIsResolved(true);
 }
 
-std::shared_ptr<DataBuffer>
-FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size,
-                             uint64_t offset) {
-  const bool is_volatile = !IsLocal(path);
-  std::unique_ptr<llvm::WritableMemoryBuffer> buffer;
+template <typename T>
+static std::unique_ptr<T> GetMemoryBuffer(const llvm::Twine &path,
+                                          uint64_t size, uint64_t offset,
+                                          bool is_volatile) {
+  std::unique_ptr<T> buffer;
   if (size == 0) {
-    auto buffer_or_error =
-        llvm::WritableMemoryBuffer::getFile(path, is_volatile);
+    auto buffer_or_error = T::getFile(path, is_volatile);
     if (!buffer_or_error)
       return nullptr;
     buffer = std::move(*buffer_or_error);
   } else {
-    auto buffer_or_error = llvm::WritableMemoryBuffer::getFileSlice(
-        path, size, offset, is_volatile);
+    auto buffer_or_error = T::getFileSlice(path, size, offset, is_volatile);
     if (!buffer_or_error)
       return nullptr;
     buffer = std::move(*buffer_or_error);
   }
+  return buffer;
+}
+
+std::shared_ptr<WritableDataBuffer>
+FileSystem::CreateWritableDataBuffer(const llvm::Twine &path, uint64_t size,
+                                     uint64_t offset) {
+  const bool is_volatile = !IsLocal(path);
+  auto buffer = GetMemoryBuffer<llvm::WritableMemoryBuffer>(path, size, offset,
+                                                            is_volatile);
+  if (!buffer)
+    return {};
+  return std::shared_ptr<WritableDataBufferLLVM>(
+      new WritableDataBufferLLVM(std::move(buffer)));
+}
+
+std::shared_ptr<DataBuffer>
+FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size,
+                             uint64_t offset) {
+  const bool is_volatile = !IsLocal(path);
+  auto buffer =
+      GetMemoryBuffer<llvm::MemoryBuffer>(path, size, offset, is_volatile);
+  if (!buffer)
+    return {};
   return std::shared_ptr<DataBufferLLVM>(new DataBufferLLVM(std::move(buffer)));
 }
 
+std::shared_ptr<WritableDataBuffer>
+FileSystem::CreateWritableDataBuffer(const FileSpec &file_spec, uint64_t size,
+                                     uint64_t offset) {
+  return CreateWritableDataBuffer(file_spec.GetPath(), size, offset);
+}
+
 std::shared_ptr<DataBuffer>
 FileSystem::CreateDataBuffer(const FileSpec &file_spec, uint64_t size,
                              uint64_t offset) {

diff  --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index c406901bae585..28232eadd350b 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -524,8 +524,9 @@ Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args,
             error.SetErrorStringWithFormat(
                 "shell command output is too large to fit into a std::string");
           } else {
-            auto Buffer =
-                FileSystem::Instance().CreateDataBuffer(output_file_spec);
+            WritableDataBufferSP Buffer =
+                FileSystem::Instance().CreateWritableDataBuffer(
+                    output_file_spec);
             if (error.Success())
               command_output_ptr->assign(
                   reinterpret_cast<char *>(Buffer->GetBytes()),

diff  --git a/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp b/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
index 9ed042df4e501..ecc5f6ffd2880 100644
--- a/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
+++ b/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp
@@ -1668,7 +1668,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
     ProcessSP process_sp(thread.GetProcess());
     ByteOrder byte_order = process_sp->GetByteOrder();
 
-    DataBufferSP data_sp(new DataBufferHeap(*byte_size, 0));
+    WritableDataBufferSP data_sp(new DataBufferHeap(*byte_size, 0));
     uint32_t data_offset = 0;
 
     for (uint32_t reg_index = 0; reg_index < vfp_count; reg_index++) {

diff  --git a/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp b/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
index 366876e364a40..9d8ef339432da 100644
--- a/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
+++ b/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp
@@ -873,7 +873,7 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
           DataExtractor f1_data;
           reg_ctx->ReadRegister(f1_info, f1_value);
           DataExtractor *copy_from_extractor = nullptr;
-          DataBufferSP data_sp(new DataBufferHeap(8, 0));
+          WritableDataBufferSP data_sp(new DataBufferHeap(8, 0));
           DataExtractor return_ext(
               data_sp, target_byte_order,
               target->GetArchitecture().GetAddressByteSize());

diff  --git a/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp b/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
index a0deec041be54..24571ead527ff 100644
--- a/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
+++ b/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp
@@ -827,7 +827,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
             DataExtractor f2_data;
             reg_ctx->ReadRegister(f2_info, f2_value);
             DataExtractor *copy_from_extractor = nullptr;
-            DataBufferSP data_sp(new DataBufferHeap(16, 0));
+            WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
             DataExtractor return_ext(
                 data_sp, target_byte_order,
                 target->GetArchitecture().GetAddressByteSize());
@@ -867,7 +867,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
              type_flags & eTypeIsVector) {
     // Any structure of up to 16 bytes in size is returned in the registers.
     if (*byte_size <= 16) {
-      DataBufferSP data_sp(new DataBufferHeap(16, 0));
+      WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
       DataExtractor return_ext(data_sp, target_byte_order,
                                target->GetArchitecture().GetAddressByteSize());
 

diff  --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
index a7135b23c42c6..1ef3b8ca3961e 100644
--- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
+++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp
@@ -666,7 +666,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
     bool is_memory = true;
     if (*bit_width <= 128) {
       ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
-      DataBufferSP data_sp(new DataBufferHeap(16, 0));
+      WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
       DataExtractor return_ext(data_sp, target_byte_order,
                                target->GetArchitecture().GetAddressByteSize());
 

diff  --git a/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
index 1140e79cba25f..031ccf5f54cc7 100644
--- a/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
+++ b/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp
@@ -645,7 +645,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
                           0, aggregate_field_offsets,
                           aggregate_compiler_types)) {
       ByteOrder byte_order = target->GetArchitecture().GetByteOrder();
-      DataBufferSP data_sp(new DataBufferHeap(16, 0));
+      WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));
       DataExtractor return_ext(data_sp, byte_order,
                                target->GetArchitecture().GetAddressByteSize());
 

diff  --git a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
index f8e9b58b7f066..b91ba32a97cfa 100644
--- a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
+++ b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp
@@ -642,7 +642,7 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectImpl(
                            0, aggregate_field_offsets,
                            aggregate_compiler_types)) {
     ByteOrder byte_order = target->GetArchitecture().GetByteOrder();
-    DataBufferSP data_sp(
+    WritableDataBufferSP data_sp(
         new DataBufferHeap(max_register_value_bit_width / 8, 0));
     DataExtractor return_ext(data_sp, byte_order,
         target->GetArchitecture().GetAddressByteSize());

diff  --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
index 438cec75cabbf..9a41a11ef5040 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -804,7 +804,8 @@ bool DynamicLoaderMacOSXDYLD::ReadMachHeader(lldb::addr_t addr,
         return true; // We were able to read the mach_header and weren't asked
                      // to read the load command bytes
 
-      DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0));
+      WritableDataBufferSP load_cmd_data_sp(
+          new DataBufferHeap(header->sizeofcmds, 0));
 
       size_t load_cmd_bytes_read =
           m_process->ReadMemory(load_cmd_addr, load_cmd_data_sp->GetBytes(),

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 129e10f3a8dc7..9731173b7a885 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -296,7 +296,7 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
         llvm::Optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
         if (!size)
           return false;
-        DataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
+        WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
         ProcessSP process_sp(target_sp->GetProcessSP());
         Status error;
         process_sp->ReadMemory(addr, buffer_sp->GetBytes(),

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
index 81eae9384f80b..3e3727ac55a1f 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
@@ -214,7 +214,7 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex(
   llvm::Optional<uint64_t> size = m_bool_type.GetByteSize(nullptr);
   if (!size)
     return {};
-  DataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
+  WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
   if (bit_set && buffer_sp && buffer_sp->GetBytes()) {
     // regardless of endianness, anything non-zero is true
     *(buffer_sp->GetBytes()) = 1;

diff  --git a/lldb/source/Plugins/Language/ObjC/CF.cpp b/lldb/source/Plugins/Language/ObjC/CF.cpp
index 6a4631e69387f..fa2130e4b01e3 100644
--- a/lldb/source/Plugins/Language/ObjC/CF.cpp
+++ b/lldb/source/Plugins/Language/ObjC/CF.cpp
@@ -158,7 +158,7 @@ bool lldb_private::formatters::CFBitVectorSummaryProvider(
   // make sure we do not try to read huge amounts of data
   if (num_bytes > 1024)
     num_bytes = 1024;
-  DataBufferSP buffer_sp(new DataBufferHeap(num_bytes, 0));
+  WritableDataBufferSP buffer_sp(new DataBufferHeap(num_bytes, 0));
   num_bytes =
       process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error);
   if (error.Fail() || num_bytes == 0)

diff  --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
index cde925dbc778f..2c6998451ad60 100644
--- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -713,7 +713,7 @@ lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex(
     if (!m_pair_type.IsValid())
       return ValueObjectSP();
 
-    DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
+    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
 
     if (m_ptr_size == 8) {
       uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
@@ -840,7 +840,7 @@ lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::GetChildAtIndex(
     if (!m_pair_type.IsValid())
       return ValueObjectSP();
 
-    DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
+    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
 
     switch (m_ptr_size) {
     case 0: // architecture has no clue - fail
@@ -961,7 +961,7 @@ lldb::ValueObjectSP lldb_private::formatters::
     if (!m_pair_type.IsValid())
       return ValueObjectSP();
 
-    DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
+    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
 
     if (m_ptr_size == 8) {
       uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
@@ -1038,7 +1038,7 @@ lldb_private::formatters::NSDictionary1SyntheticFrontEnd::GetChildAtIndex(
   auto pair_type =
       GetLLDBNSPairType(process_sp->GetTarget().shared_from_this());
 
-  DataBufferSP buffer_sp(new DataBufferHeap(2 * ptr_size, 0));
+  WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * ptr_size, 0));
 
   if (ptr_size == 8) {
     uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
@@ -1203,7 +1203,7 @@ lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<
     if (!m_pair_type.IsValid())
       return ValueObjectSP();
 
-    DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
+    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
 
     if (m_ptr_size == 8) {
       uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
@@ -1357,7 +1357,7 @@ lldb_private::formatters::Foundation1100::
     if (!m_pair_type.IsValid())
       return ValueObjectSP();
 
-    DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
+    WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
 
     if (m_ptr_size == 8) {
       uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();

diff  --git a/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
index 671d391977c6d..0a6b445d97c86 100644
--- a/lldb/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSSet.cpp
@@ -635,7 +635,7 @@ lldb_private::formatters::NSCFSetSyntheticFrontEnd::GetChildAtIndex(
   SetItemDescriptor &set_item = m_children[idx];
   if (!set_item.valobj_sp) {
 
-    DataBufferSP buffer_sp(new DataBufferHeap(m_ptr_size, 0));
+    WritableDataBufferSP buffer_sp(new DataBufferHeap(m_ptr_size, 0));
 
     switch (m_ptr_size) {
     case 0: // architecture has no clue - fail

diff  --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index cd4a8499c9286..65f00f5e4d022 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -222,7 +222,7 @@ void AppleObjCRuntimeV1::ClassDescriptorV1::Initialize(
     return;
   }
 
-  lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+  lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
 
   size_t count = process_sp->ReadCStringFromMemory(
       name_ptr, (char *)buffer_sp->GetBytes(), 1024, error);
@@ -233,7 +233,7 @@ void AppleObjCRuntimeV1::ClassDescriptorV1::Initialize(
   }
 
   if (count)
-    m_name = ConstString((char *)buffer_sp->GetBytes());
+    m_name = ConstString(reinterpret_cast<const char *>(buffer_sp->GetBytes()));
   else
     m_name = ConstString();
 

diff  --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index b1d6d6b9b8222..7164a490078d8 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -343,7 +343,7 @@ void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() {
   // Ingest the whole descriptor array:
   const lldb::addr_t desc_ptr = m_header_addr + header_size;
   const size_t desc_array_size = num_descriptors * descriptor_size;
-  DataBufferSP data_sp(new DataBufferHeap(desc_array_size, '\0'));
+  WritableDataBufferSP data_sp(new DataBufferHeap(desc_array_size, '\0'));
   uint8_t *dst = (uint8_t *)data_sp->GetBytes();
 
   DataExtractor desc_extractor(dst, desc_array_size, process_sp->GetByteOrder(),

diff  --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 1d91fb8f4cd8f..2cf166bc8a1d5 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -2442,7 +2442,7 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
   auto data_sp = FileSystem::Instance().CreateDataBuffer(file.GetPath());
 
   // Cast start of buffer to FileHeader and use pointer to read metadata
-  void *file_buf = data_sp->GetBytes();
+  const void *file_buf = data_sp->GetBytes();
   if (file_buf == nullptr ||
       data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) +
                                 sizeof(AllocationDetails::ElementHeader))) {
@@ -2451,7 +2451,7 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
     return false;
   }
   const AllocationDetails::FileHeader *file_header =
-      static_cast<AllocationDetails::FileHeader *>(file_buf);
+      static_cast<const AllocationDetails::FileHeader *>(file_buf);
 
   // Check file starts with ascii characters "RSAD"
   if (memcmp(file_header->ident, "RSAD", 4)) {
@@ -2463,8 +2463,9 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
 
   // Look at the type of the root element in the header
   AllocationDetails::ElementHeader root_el_hdr;
-  memcpy(&root_el_hdr, static_cast<uint8_t *>(file_buf) +
-                           sizeof(AllocationDetails::FileHeader),
+  memcpy(&root_el_hdr,
+         static_cast<const uint8_t *>(file_buf) +
+             sizeof(AllocationDetails::FileHeader),
          sizeof(AllocationDetails::ElementHeader));
 
   LLDB_LOGF(log, "%s - header type %" PRIu32 ", element size %" PRIu32,
@@ -2515,7 +2516,7 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
   }
 
   // Advance buffer past header
-  file_buf = static_cast<uint8_t *>(file_buf) + file_header->hdr_size;
+  file_buf = static_cast<const uint8_t *>(file_buf) + file_header->hdr_size;
 
   // Calculate size of allocation data in file
   size_t size = data_sp->GetByteSize() - file_header->hdr_size;

diff  --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 0e39f203e489a..ce71c71b71371 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -341,11 +341,13 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
                                           const lldb_private::FileSpec *file,
                                           lldb::offset_t file_offset,
                                           lldb::offset_t length) {
+  bool mapped_writable = false;
   if (!data_sp) {
-    data_sp = MapFileData(*file, length, file_offset);
+    data_sp = MapFileDataWritable(*file, length, file_offset);
     if (!data_sp)
       return nullptr;
     data_offset = 0;
+    mapped_writable = true;
   }
 
   assert(data_sp);
@@ -359,10 +361,19 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
 
   // Update the data to contain the entire file if it doesn't already
   if (data_sp->GetByteSize() < length) {
-    data_sp = MapFileData(*file, length, file_offset);
+    data_sp = MapFileDataWritable(*file, length, file_offset);
     if (!data_sp)
       return nullptr;
     data_offset = 0;
+    mapped_writable = true;
+    magic = data_sp->GetBytes();
+  }
+
+  // If we didn't map the data as writable take ownership of the buffer.
+  if (!mapped_writable) {
+    data_sp = std::make_shared<DataBufferHeap>(data_sp->GetBytes(),
+                                               data_sp->GetByteSize());
+    data_offset = 0;
     magic = data_sp->GetBytes();
   }
 
@@ -2621,8 +2632,11 @@ unsigned ObjectFileELF::ApplyRelocations(
         if (symbol) {
           addr_t value = symbol->GetAddressRef().GetFileAddress();
           DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
+          // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
+          WritableDataBuffer *data_buffer =
+              llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
           uint64_t *dst = reinterpret_cast<uint64_t *>(
-              data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
+              data_buffer->GetBytes() + rel_section->GetFileOffset() +
               ELFRelocation::RelocOffset64(rel));
           uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel);
           memcpy(dst, &val_offset, sizeof(uint64_t));
@@ -2647,8 +2661,11 @@ unsigned ObjectFileELF::ApplyRelocations(
           }
           uint32_t truncated_addr = (value & 0xFFFFFFFF);
           DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
+          // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
+          WritableDataBuffer *data_buffer =
+              llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
           uint32_t *dst = reinterpret_cast<uint32_t *>(
-              data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
+              data_buffer->GetBytes() + rel_section->GetFileOffset() +
               ELFRelocation::RelocOffset32(rel));
           memcpy(dst, &truncated_addr, sizeof(uint32_t));
         }
@@ -3412,3 +3429,10 @@ ObjectFileELF::GetLoadableData(Target &target) {
   }
   return loadables;
 }
+
+lldb::WritableDataBufferSP
+ObjectFileELF::MapFileDataWritable(const FileSpec &file, uint64_t Size,
+                                   uint64_t Offset) {
+  return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size,
+                                                         Offset);
+}

diff  --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 0229c414e74fa..d55d88697f4bc 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -159,6 +159,10 @@ class ObjectFileELF : public lldb_private::ObjectFile {
   std::vector<LoadableData>
   GetLoadableData(lldb_private::Target &target) override;
 
+  static lldb::WritableDataBufferSP
+  MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size,
+                      uint64_t Offset);
+
 private:
   ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
                 lldb::offset_t data_offset, const lldb_private::FileSpec *file,

diff  --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index f19124eff571c..d0863590c31f8 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -43,7 +43,7 @@ static bool ValidateModuleHeader(const DataBufferSP &data_sp) {
       llvm::file_magic::wasm_object)
     return false;
 
-  uint8_t *Ptr = data_sp->GetBytes() + sizeof(llvm::wasm::WasmMagic);
+  const uint8_t *Ptr = data_sp->GetBytes() + sizeof(llvm::wasm::WasmMagic);
 
   uint32_t version = llvm::support::endian::read32le(Ptr);
   return version == llvm::wasm::WasmVersion;

diff  --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index 42de703e8ed07..a274065fded23 100644
--- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -229,7 +229,7 @@ lldb_private::Status PlatformPOSIX::GetFile(
     }
 
     if (error.Success()) {
-      lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+      lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
       uint64_t offset = 0;
       error.Clear();
       while (error.Success()) {

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index e1d3b6ecd7d09..33bab249d9609 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -1236,7 +1236,7 @@ bool RegisterContextDarwin_arm::WriteRegister(const RegisterInfo *reg_info,
 }
 
 bool RegisterContextDarwin_arm::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
   if (data_sp && ReadGPR(false) == KERN_SUCCESS &&
       ReadFPU(false) == KERN_SUCCESS && ReadEXC(false) == KERN_SUCCESS) {

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
index 1bd60f7564873..7ff1bded81f4b 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
@@ -66,7 +66,7 @@ class RegisterContextDarwin_arm : public lldb_private::RegisterContext {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &reg_value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index 50f710e268152..11b300bc44fbb 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -643,7 +643,7 @@ bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info,
 }
 
 bool RegisterContextDarwin_arm64::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
   if (ReadGPR(false) == KERN_SUCCESS && ReadFPU(false) == KERN_SUCCESS &&
       ReadEXC(false) == KERN_SUCCESS) {

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
index 010e566be32c7..a0d7821ae9e8b 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
@@ -48,7 +48,7 @@ class RegisterContextDarwin_arm64 : public lldb_private::RegisterContext {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &reg_value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index 5f56e6f1636a2..9158f8acc2e7e 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -793,7 +793,7 @@ bool RegisterContextDarwin_i386::WriteRegister(const RegisterInfo *reg_info,
 }
 
 bool RegisterContextDarwin_i386::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
   if (ReadGPR(false) == 0 && ReadFPU(false) == 0 && ReadEXC(false) == 0) {
     uint8_t *dst = data_sp->GetBytes();

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
index 9c759c31caed9..be933f3be2661 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
@@ -35,7 +35,7 @@ class RegisterContextDarwin_i386 : public lldb_private::RegisterContext {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 567df8fc980ce..ad25ebbbb8040 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -852,7 +852,7 @@ bool RegisterContextDarwin_x86_64::WriteRegister(const RegisterInfo *reg_info,
 }
 
 bool RegisterContextDarwin_x86_64::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
   if (ReadGPR(false) == 0 && ReadFPU(false) == 0 && ReadEXC(false) == 0) {
     uint8_t *dst = data_sp->GetBytes();

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
index d9ba8d0b23191..a132f92d4d497 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
@@ -35,7 +35,7 @@ class RegisterContextDarwin_x86_64 : public lldb_private::RegisterContext {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp
index 4c2e291c62d6e..f41aa2ca599e8 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp
@@ -102,7 +102,8 @@ bool RegisterContextDummy::WriteRegister(
   return false;
 }
 
-bool RegisterContextDummy::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) {
+bool RegisterContextDummy::ReadAllRegisterValues(
+    lldb::WritableDataBufferSP &data_sp) {
   return false;
 }
 

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h
index de98767693fe1..631ad30b16a8b 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.h
@@ -43,7 +43,7 @@ class RegisterContextDummy : public lldb_private::RegisterContext {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp
index 5779587389009..f06af93cfa830 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp
@@ -104,7 +104,7 @@ bool RegisterContextHistory::WriteRegister(
 }
 
 bool RegisterContextHistory::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   return false;
 }
 

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h
index 407640d2bdb9e..a1eadac5d1b73 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.h
@@ -43,7 +43,7 @@ class RegisterContextHistory : public lldb_private::RegisterContext {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
index 49a4c86690220..ead8c4b4a80d9 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp
@@ -32,9 +32,9 @@ RegisterContextMemory::RegisterContextMemory(Thread &thread,
   m_reg_valid.resize(num_regs);
 
   // Make a heap based buffer that is big enough to store all registers
-  DataBufferSP reg_data_sp(
-      new DataBufferHeap(reg_infos.GetRegisterDataByteSize(), 0));
-  m_reg_data.SetData(reg_data_sp);
+  m_data =
+      std::make_shared<DataBufferHeap>(reg_infos.GetRegisterDataByteSize(), 0);
+  m_reg_data.SetData(m_data);
 }
 
 // Destructor
@@ -76,7 +76,7 @@ bool RegisterContextMemory::ReadRegister(const RegisterInfo *reg_info,
                                          RegisterValue &reg_value) {
   const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
   if (!m_reg_valid[reg_num]) {
-    if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer()))
+    if (!ReadAllRegisterValues(m_data))
       return false;
   }
   const bool partial_data_ok = false;
@@ -99,7 +99,8 @@ bool RegisterContextMemory::WriteRegister(const RegisterInfo *reg_info,
   return false;
 }
 
-bool RegisterContextMemory::ReadAllRegisterValues(DataBufferSP &data_sp) {
+bool RegisterContextMemory::ReadAllRegisterValues(
+    WritableDataBufferSP &data_sp) {
   if (m_reg_data_addr != LLDB_INVALID_ADDRESS) {
     ProcessSP process_sp(CalculateProcess());
     if (process_sp) {

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h
index c3b9ec72ca227..2aad99ec9b210 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextMemory.h
@@ -50,7 +50,7 @@ class RegisterContextMemory : public lldb_private::RegisterContext {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &reg_value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 
@@ -61,6 +61,7 @@ class RegisterContextMemory : public lldb_private::RegisterContext {
 
   lldb_private::DynamicRegisterInfo &m_reg_infos;
   std::vector<bool> m_reg_valid;
+  lldb::WritableDataBufferSP m_data;
   lldb_private::DataExtractor m_reg_data;
   lldb::addr_t m_reg_data_addr; // If this is valid, then we have a register
                                 // context that is stored in memmory

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
index 4866cbd235e8c..b5f2b0d2212d0 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
@@ -107,7 +107,7 @@ bool RegisterContextThreadMemory::WriteRegister(
 }
 
 bool RegisterContextThreadMemory::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   UpdateRegisterContext();
   if (m_reg_ctx_sp)
     return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
index 40688a502a66e..0a7314528f0ae 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
@@ -51,7 +51,7 @@ class RegisterContextThreadMemory : public lldb_private::RegisterContext {
   // is a somewhat disruptive operation,
   // so these API's should only be used when this behavior is needed.
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
index f0aee04b5f620..3a62081827c6a 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
@@ -55,7 +55,7 @@ bool RegisterContextCorePOSIX_arm::ReadRegister(const RegisterInfo *reg_info,
 }
 
 bool RegisterContextCorePOSIX_arm::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   return false;
 }
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
index de343f9001e06..8d773a046bcac 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
@@ -30,7 +30,7 @@ class RegisterContextCorePOSIX_arm : public RegisterContextPOSIX_arm {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index e56aa88b57d9e..bb88ce9e9e502 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -230,7 +230,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
 }
 
 bool RegisterContextCorePOSIX_arm64::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   return false;
 }
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
index 3988e3539b897..f8548562adba3 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
@@ -31,7 +31,7 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index 5b1eb8b5437db..56e68742ead77 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -72,7 +72,7 @@ bool RegisterContextCorePOSIX_mips64::ReadRegister(const RegisterInfo *reg_info,
 }
 
 bool RegisterContextCorePOSIX_mips64::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   return false;
 }
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
index b42a76c082f0e..529b00215e352 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
@@ -30,7 +30,7 @@ class RegisterContextCorePOSIX_mips64 : public RegisterContextPOSIX_mips64 {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
index 8380731692a33..4e7be91c38959 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
@@ -92,7 +92,7 @@ bool RegisterContextCorePOSIX_powerpc::ReadRegister(
 }
 
 bool RegisterContextCorePOSIX_powerpc::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   return false;
 }
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
index cf50b6e0bf70b..5364c5589238a 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
@@ -29,7 +29,7 @@ class RegisterContextCorePOSIX_powerpc : public RegisterContextPOSIX_powerpc {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
index f1cd6897616de..69707eeb3f1e6 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
@@ -77,7 +77,7 @@ bool RegisterContextCorePOSIX_s390x::ReadRegister(const RegisterInfo *reg_info,
 }
 
 bool RegisterContextCorePOSIX_s390x::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   return false;
 }
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h
index 4560f062e06f4..edb7cbc9462f6 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h
@@ -29,7 +29,7 @@ class RegisterContextCorePOSIX_s390x : public RegisterContextPOSIX_s390x {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index 6eaad9f381d68..6bc8edb9226f0 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -80,7 +80,7 @@ bool RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info,
 }
 
 bool RegisterContextCorePOSIX_x86_64::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   return false;
 }
 

diff  --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
index 9adfbf7e6852c..46416a2381dbf 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
@@ -26,7 +26,7 @@ class RegisterContextCorePOSIX_x86_64 : public RegisterContextPOSIX_x86 {
   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
                      const lldb_private::RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index fc0b41fcd7ee2..0ffc3289a7b9f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -643,7 +643,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadMemoryTags(lldb::addr_t addr,
   }
 
   size_t expected_bytes = response.GetBytesLeft() / 2;
-  DataBufferSP buffer_sp(new DataBufferHeap(expected_bytes, 0));
+  WritableDataBufferSP buffer_sp(new DataBufferHeap(expected_bytes, 0));
   size_t got_bytes = response.GetHexBytesAvail(buffer_sp->GetData());
   // Check both because in some situations chars are consumed even
   // if the decoding fails.
@@ -3442,7 +3442,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid,
       !response.IsNormalResponse())
     return nullptr;
 
-  DataBufferSP buffer_sp(
+  WritableDataBufferSP buffer_sp(
       new DataBufferHeap(response.GetStringRef().size() / 2, 0));
   response.GetHexBytes(buffer_sp->GetData(), '\xcc');
   return buffer_sp;
@@ -3457,7 +3457,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) {
       !response.IsNormalResponse())
     return nullptr;
 
-  DataBufferSP buffer_sp(
+  WritableDataBufferSP buffer_sp(
       new DataBufferHeap(response.GetStringRef().size() / 2, 0));
   response.GetHexBytes(buffer_sp->GetData(), '\xcc');
   return buffer_sp;

diff  --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 1b66e8c162817..7ad4f4968eac9 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -517,7 +517,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
 }
 
 bool GDBRemoteRegisterContext::ReadAllRegisterValues(
-    lldb::DataBufferSP &data_sp) {
+    lldb::WritableDataBufferSP &data_sp) {
   ExecutionContext exe_ctx(CalculateThread());
 
   Process *process = exe_ctx.GetProcessPtr();
@@ -536,9 +536,13 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues(
     if (gdb_comm.SyncThreadState(m_thread.GetProtocolID()))
       InvalidateAllRegisters();
 
-    if (use_g_packet &&
-        (data_sp = gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())))
-      return true;
+    if (use_g_packet) {
+      if (DataBufferSP data_buffer =
+              gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) {
+        data_sp = std::make_shared<DataBufferHeap>(*data_buffer);
+        return true;
+      }
+    }
 
     // We're going to read each register
     // individually and store them as binary data in a buffer.

diff  --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 83c809c5aab6b..d185cb5aede1e 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -65,7 +65,7 @@ class GDBRemoteRegisterContext : public RegisterContext {
   bool WriteRegister(const RegisterInfo *reg_info,
                      const RegisterValue &value) override;
 
-  bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
 
   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
 

diff  --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 2e652e11ea110..af983690a120e 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1671,7 +1671,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
 
       for (const auto &pair : expedited_register_map) {
         StringExtractor reg_value_extractor(pair.second);
-        DataBufferSP buffer_sp(new DataBufferHeap(
+        WritableDataBufferSP buffer_sp(new DataBufferHeap(
             reg_value_extractor.GetStringRef().size() / 2, 0));
         reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc');
         uint32_t lldb_regnum =
@@ -2050,7 +2050,8 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) {
                   bytes.SetFilePos(0);
 
                   const size_t byte_size = bytes.GetStringRef().size() / 2;
-                  DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
+                  WritableDataBufferSP data_buffer_sp(
+                      new DataBufferHeap(byte_size, 0));
                   const size_t bytes_copied =
                       bytes.GetHexBytes(data_buffer_sp->GetData(), 0);
                   if (bytes_copied == byte_size)
@@ -2212,7 +2213,8 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
           if (!addr_str.getAsInteger(0, mem_cache_addr)) {
             StringExtractor bytes(bytes_str);
             const size_t byte_size = bytes.GetBytesLeft() / 2;
-            DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
+            WritableDataBufferSP data_buffer_sp(
+                new DataBufferHeap(byte_size, 0));
             const size_t bytes_copied =
                 bytes.GetHexBytes(data_buffer_sp->GetData(), 0);
             if (bytes_copied == byte_size)

diff  --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp
index 38d7de77e3bf4..7681002c6fb82 100644
--- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp
+++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp
@@ -27,7 +27,7 @@ lldb::DataBufferSP lldb_private::minidump::ConvertMinidumpContext_x86_32(
 
   const RegisterInfo *reg_info = target_reg_interface->GetRegisterInfo();
 
-  lldb::DataBufferSP result_context_buf(
+  lldb::WritableDataBufferSP result_context_buf(
       new DataBufferHeap(target_reg_interface->GetGPRSize(), 0));
   uint8_t *result_base = result_context_buf->GetBytes();
 

diff  --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
index 3c593f0db6ec1..917140cab2976 100644
--- a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
+++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
@@ -50,7 +50,7 @@ lldb::DataBufferSP lldb_private::minidump::ConvertMinidumpContext_x86_64(
 
   const RegisterInfo *reg_info = target_reg_interface->GetRegisterInfo();
 
-  lldb::DataBufferSP result_context_buf(
+  lldb::WritableDataBufferSP result_context_buf(
       new DataBufferHeap(target_reg_interface->GetGPRSize(), 0));
   uint8_t *result_base = result_context_buf->GetBytes();
 

diff  --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp
index c7c5d84c9ac0c..b3c0fd452204b 100644
--- a/lldb/source/Symbol/ObjectFile.cpp
+++ b/lldb/source/Symbol/ObjectFile.cpp
@@ -30,6 +30,7 @@ using namespace lldb;
 using namespace lldb_private;
 
 char ObjectFile::ID;
+size_t ObjectFile::g_initial_bytes_to_read = 512;
 
 static ObjectFileSP
 CreateObjectFromContainer(const lldb::ModuleSP &module_sp, const FileSpec *file,
@@ -81,8 +82,8 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
     // container plug-ins can use these bytes to see if they can parse this
     // file.
     if (file_size > 0) {
-      data_sp = FileSystem::Instance().CreateDataBuffer(file->GetPath(), 512,
-                                                        file_offset);
+      data_sp = FileSystem::Instance().CreateDataBuffer(
+          file->GetPath(), g_initial_bytes_to_read, file_offset);
       data_offset = 0;
     }
   }
@@ -115,7 +116,7 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
         // We failed to find any cached object files in the container plug-
         // ins, so lets read the first 512 bytes and try again below...
         data_sp = FileSystem::Instance().CreateDataBuffer(
-            archive_file.GetPath(), 512, file_offset);
+            archive_file.GetPath(), g_initial_bytes_to_read, file_offset);
       }
     }
   }
@@ -189,8 +190,8 @@ size_t ObjectFile::GetModuleSpecifications(const FileSpec &file,
                                            ModuleSpecList &specs,
                                            DataBufferSP data_sp) {
   if (!data_sp)
-    data_sp = FileSystem::Instance().CreateDataBuffer(file.GetPath(), 512,
-                                                      file_offset);
+    data_sp = FileSystem::Instance().CreateDataBuffer(
+        file.GetPath(), g_initial_bytes_to_read, file_offset);
   if (data_sp) {
     if (file_size == 0) {
       const lldb::offset_t actual_file_size =

diff  --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index cd71dae41cd4e..2dff0dbfae9ee 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -1393,7 +1393,7 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
     return error;
   if (dest_file == UINT64_MAX)
     return Status("unable to open target file");
-  lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024 * 16, 0));
+  lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(1024 * 16, 0));
   uint64_t offset = 0;
   for (;;) {
     size_t bytes_read = buffer_sp->GetByteSize();

diff  --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp
index 98bfdf07f6cea..339e4c6ad0fde 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -2231,7 +2231,8 @@ bool RegisterContextUnwind::WriteRegister(const RegisterInfo *reg_info,
 }
 
 // Don't need to implement this one
-bool RegisterContextUnwind::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) {
+bool RegisterContextUnwind::ReadAllRegisterValues(
+    lldb::WritableDataBufferSP &data_sp) {
   return false;
 }
 

diff  --git a/lldb/source/Utility/DataBufferHeap.cpp b/lldb/source/Utility/DataBufferHeap.cpp
index 9154b3f041a75..ea84a36f16977 100644
--- a/lldb/source/Utility/DataBufferHeap.cpp
+++ b/lldb/source/Utility/DataBufferHeap.cpp
@@ -26,18 +26,16 @@ DataBufferHeap::DataBufferHeap(const void *src, lldb::offset_t src_len)
   CopyData(src, src_len);
 }
 
+DataBufferHeap::DataBufferHeap(const DataBuffer &data_buffer) : m_data() {
+  CopyData(data_buffer.GetBytes(), data_buffer.GetByteSize());
+}
+
 // Virtual destructor since this class inherits from a pure virtual base class.
 DataBufferHeap::~DataBufferHeap() = default;
 
-// Return a pointer to the bytes owned by this object, or nullptr if the object
-// contains no bytes.
-uint8_t *DataBufferHeap::GetBytes() {
-  return (m_data.empty() ? nullptr : m_data.data());
-}
-
 // Return a const pointer to the bytes owned by this object, or nullptr if the
 // object contains no bytes.
-const uint8_t *DataBufferHeap::GetBytes() const {
+const uint8_t *DataBufferHeap::GetBytesImpl() const {
   return (m_data.empty() ? nullptr : m_data.data());
 }
 
@@ -69,3 +67,8 @@ void DataBufferHeap::Clear() {
   buffer_t empty;
   m_data.swap(empty);
 }
+
+char DataBuffer::ID;
+char WritableDataBuffer::ID;
+char DataBufferUnowned::ID;
+char DataBufferHeap::ID;

diff  --git a/lldb/source/Utility/DataBufferLLVM.cpp b/lldb/source/Utility/DataBufferLLVM.cpp
index c5aeddd683f4d..376fe0689ecf0 100644
--- a/lldb/source/Utility/DataBufferLLVM.cpp
+++ b/lldb/source/Utility/DataBufferLLVM.cpp
@@ -14,8 +14,7 @@
 
 using namespace lldb_private;
 
-DataBufferLLVM::DataBufferLLVM(
-    std::unique_ptr<llvm::WritableMemoryBuffer> MemBuffer)
+DataBufferLLVM::DataBufferLLVM(std::unique_ptr<llvm::MemoryBuffer> MemBuffer)
     : Buffer(std::move(MemBuffer)) {
   assert(Buffer != nullptr &&
          "Cannot construct a DataBufferLLVM with a null buffer");
@@ -23,14 +22,30 @@ DataBufferLLVM::DataBufferLLVM(
 
 DataBufferLLVM::~DataBufferLLVM() = default;
 
-uint8_t *DataBufferLLVM::GetBytes() {
-  return reinterpret_cast<uint8_t *>(Buffer->getBufferStart());
+const uint8_t *DataBufferLLVM::GetBytesImpl() const {
+  return reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
+}
+
+lldb::offset_t DataBufferLLVM::GetByteSize() const {
+  return Buffer->getBufferSize();
+}
+
+WritableDataBufferLLVM::WritableDataBufferLLVM(
+    std::unique_ptr<llvm::WritableMemoryBuffer> MemBuffer)
+    : Buffer(std::move(MemBuffer)) {
+  assert(Buffer != nullptr &&
+         "Cannot construct a WritableDataBufferLLVM with a null buffer");
 }
 
-const uint8_t *DataBufferLLVM::GetBytes() const {
+WritableDataBufferLLVM::~WritableDataBufferLLVM() = default;
+
+const uint8_t *WritableDataBufferLLVM::GetBytesImpl() const {
   return reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
 }
 
-lldb::offset_t DataBufferLLVM::GetByteSize() const {
+lldb::offset_t WritableDataBufferLLVM::GetByteSize() const {
   return Buffer->getBufferSize();
 }
+
+char DataBufferLLVM::ID;
+char WritableDataBufferLLVM::ID;

diff  --git a/lldb/unittests/Utility/CMakeLists.txt b/lldb/unittests/Utility/CMakeLists.txt
index 9a76b8a83099d..a074b606f8226 100644
--- a/lldb/unittests/Utility/CMakeLists.txt
+++ b/lldb/unittests/Utility/CMakeLists.txt
@@ -6,6 +6,7 @@ add_lldb_unittest(UtilityTests
   BroadcasterTest.cpp
   ConstStringTest.cpp
   CompletionRequestTest.cpp
+  DataBufferTest.cpp
   DataEncoderTest.cpp
   DataExtractorTest.cpp
   EnvironmentTest.cpp

diff  --git a/lldb/unittests/Utility/DataBufferTest.cpp b/lldb/unittests/Utility/DataBufferTest.cpp
new file mode 100644
index 0000000000000..548690354959e
--- /dev/null
+++ b/lldb/unittests/Utility/DataBufferTest.cpp
@@ -0,0 +1,56 @@
+//===-- DataBufferTest.cpp ------------------------------------------------===//
+//
+// 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 "lldb/Utility/DataBuffer.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/DataBufferLLVM.h"
+
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+TEST(DataBufferTest, RTTI) {
+  {
+    DataBufferSP data_buffer_sp = std::make_shared<DataBufferHeap>();
+    DataBuffer *data_buffer = data_buffer_sp.get();
+
+    EXPECT_TRUE(llvm::isa<DataBuffer>(data_buffer));
+    EXPECT_TRUE(llvm::isa<WritableDataBuffer>(data_buffer));
+    EXPECT_TRUE(llvm::isa<DataBufferHeap>(data_buffer));
+    EXPECT_FALSE(llvm::isa<DataBufferLLVM>(data_buffer));
+  }
+
+  {
+    llvm::StringRef data;
+    DataBufferSP data_buffer_sp = std::make_shared<DataBufferLLVM>(
+        llvm::MemoryBuffer::getMemBufferCopy(data));
+    DataBuffer *data_buffer = data_buffer_sp.get();
+
+    EXPECT_TRUE(llvm::isa<DataBuffer>(data_buffer));
+    EXPECT_TRUE(llvm::isa<DataBufferLLVM>(data_buffer));
+    EXPECT_FALSE(llvm::isa<WritableDataBuffer>(data_buffer));
+    EXPECT_FALSE(llvm::isa<WritableDataBufferLLVM>(data_buffer));
+    EXPECT_FALSE(llvm::isa<DataBufferHeap>(data_buffer));
+  }
+
+  {
+    DataBufferSP data_buffer_sp = std::make_shared<WritableDataBufferLLVM>(
+        llvm::WritableMemoryBuffer::getNewMemBuffer(1));
+    DataBuffer *data_buffer = data_buffer_sp.get();
+
+    EXPECT_TRUE(llvm::isa<DataBuffer>(data_buffer));
+    EXPECT_TRUE(llvm::isa<WritableDataBuffer>(data_buffer));
+    EXPECT_TRUE(llvm::isa<WritableDataBufferLLVM>(data_buffer));
+    EXPECT_FALSE(llvm::isa<DataBufferLLVM>(data_buffer));
+    EXPECT_FALSE(llvm::isa<DataBufferHeap>(data_buffer));
+  }
+}


        


More information about the lldb-commits mailing list