Skip to content

[lldb] Refactor DataBuffer so we can map files as read-only #4176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lldb/include/lldb/Core/ValueObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,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);

Expand Down
20 changes: 13 additions & 7 deletions lldb/include/lldb/Host/FileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#define LLDB_HOST_FILESYSTEM_H

#include "lldb/Host/File.h"
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"

Expand Down Expand Up @@ -144,12 +144,18 @@ class FileSystem {

//// Create memory buffer from path.
/// \{
std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const llvm::Twine &path,
uint64_t size = 0,
uint64_t offset = 0);
std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const FileSpec &file_spec,
uint64_t size = 0,
uint64_t offset = 0);
std::shared_ptr<DataBuffer> CreateDataBuffer(const llvm::Twine &path,
uint64_t size = 0,
uint64_t offset = 0);
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.
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Host/common/NativeRegisterContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class NativeRegisterContext
virtual Status WriteRegister(const RegisterInfo *reg_info,
const RegisterValue &reg_value) = 0;

virtual Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) = 0;
virtual Status ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) = 0;

virtual Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) = 0;

Expand Down
7 changes: 4 additions & 3 deletions lldb/include/lldb/Symbol/CompactUnwindInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 6 additions & 3 deletions lldb/include/lldb/Symbol/ObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
/// more than one architecture or object.
ObjectFile(const lldb::ModuleSP &module_sp, const FileSpec *file_spec_ptr,
lldb::offset_t file_offset, lldb::offset_t length,
const lldb::DataBufferSP &data_sp, lldb::offset_t data_offset);
lldb::DataBufferSP data_sp, lldb::offset_t data_offset);

ObjectFile(const lldb::ModuleSP &module_sp, const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr, lldb::DataBufferSP &data_sp);
lldb::addr_t header_addr, lldb::DataBufferSP data_sp);

/// Destructor.
///
Expand Down Expand Up @@ -185,7 +185,7 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
static lldb::ObjectFileSP FindPlugin(const lldb::ModuleSP &module_sp,
const lldb::ProcessSP &process_sp,
lldb::addr_t header_addr,
lldb::DataBufferSP &file_data_sp);
lldb::WritableDataBufferSP file_data_sp);

static size_t
GetModuleSpecifications(const FileSpec &file, lldb::offset_t file_offset,
Expand Down Expand Up @@ -744,6 +744,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);

Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Target/ProcessStructReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions lldb/include/lldb/Target/RegisterCheckpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,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.
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Target/RegisterContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Target/RegisterContextUnwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
104 changes: 79 additions & 25 deletions lldb/include/lldb/Utility/DataBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand All @@ -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;
Expand Down
24 changes: 19 additions & 5 deletions lldb/include/lldb/Utility/DataBufferHeap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand All @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
Loading