Skip to content

Commit fc54427

Browse files
committed
[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
1 parent 4169650 commit fc54427

File tree

80 files changed

+429
-166
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+429
-166
lines changed

lldb/include/lldb/Core/ValueObject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ class ValueObject {
679679
bool IsCStringContainer(bool check_pointer = false);
680680

681681
std::pair<size_t, bool>
682-
ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error,
682+
ReadPointedString(lldb::WritableDataBufferSP &buffer_sp, Status &error,
683683
uint32_t max_length = 0, bool honor_array = true,
684684
lldb::Format item_format = lldb::eFormatCharArray);
685685

lldb/include/lldb/Host/FileSystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ class FileSystem {
148148
std::shared_ptr<DataBuffer> CreateDataBuffer(const FileSpec &file_spec,
149149
uint64_t size = 0,
150150
uint64_t offset = 0);
151+
std::shared_ptr<WritableDataBuffer>
152+
CreateWritableDataBuffer(const llvm::Twine &path, uint64_t size = 0,
153+
uint64_t offset = 0);
154+
std::shared_ptr<WritableDataBuffer>
155+
CreateWritableDataBuffer(const FileSpec &file_spec, uint64_t size = 0,
156+
uint64_t offset = 0);
151157
/// \}
152158

153159
/// Call into the Host to see if it can help find the file.

lldb/include/lldb/Symbol/CompactUnwindInfo.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,10 @@ class CompactUnwindInfo {
138138

139139
ObjectFile &m_objfile;
140140
lldb::SectionSP m_section_sp;
141-
lldb::DataBufferSP m_section_contents_if_encrypted; // if the binary is
142-
// encrypted, read the
143-
// sect contents
141+
lldb::WritableDataBufferSP
142+
m_section_contents_if_encrypted; // if the binary is
143+
// encrypted, read the
144+
// sect contents
144145
// out of live memory and cache them here
145146
std::mutex m_mutex;
146147
std::vector<UnwindIndex> m_indexes;

lldb/include/lldb/Symbol/ObjectFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,9 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
759759
/// false otherwise.
760760
bool SetModulesArchitecture(const ArchSpec &new_arch);
761761

762+
/// The number of bytes to read when going through the plugins.
763+
static size_t g_initial_bytes_to_read;
764+
762765
static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size,
763766
uint64_t Offset);
764767

lldb/include/lldb/Target/ProcessStructReader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class ProcessStructReader {
6969
auto total_size = struct_type.GetByteSize(nullptr);
7070
if (!total_size)
7171
return;
72-
lldb::DataBufferSP buffer_sp(new DataBufferHeap(*total_size, 0));
72+
lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(*total_size, 0));
7373
Status error;
7474
process->ReadMemoryFromInferior(base_addr, buffer_sp->GetBytes(),
7575
*total_size, error);

lldb/include/lldb/Target/RegisterCheckpoint.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ class RegisterCheckpoint : public UserID {
3535

3636
~RegisterCheckpoint() = default;
3737

38-
lldb::DataBufferSP &GetData() { return m_data_sp; }
38+
lldb::WritableDataBufferSP &GetData() { return m_data_sp; }
3939

40-
const lldb::DataBufferSP &GetData() const { return m_data_sp; }
40+
const lldb::WritableDataBufferSP &GetData() const { return m_data_sp; }
4141

4242
protected:
43-
lldb::DataBufferSP m_data_sp;
43+
lldb::WritableDataBufferSP m_data_sp;
4444
Reason m_reason;
4545

4646
// Make RegisterCheckpointSP if you wish to share the data in this class.

lldb/include/lldb/Target/RegisterContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class RegisterContext : public std::enable_shared_from_this<RegisterContext>,
4343
virtual bool WriteRegister(const RegisterInfo *reg_info,
4444
const RegisterValue &reg_value) = 0;
4545

46-
virtual bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) {
46+
virtual bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) {
4747
return false;
4848
}
4949

lldb/include/lldb/Target/RegisterContextUnwind.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class RegisterContextUnwind : public lldb_private::RegisterContext {
5050
bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
5151
const lldb_private::RegisterValue &value) override;
5252

53-
bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
53+
bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
5454

5555
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
5656

lldb/include/lldb/Utility/DataBuffer.h

Lines changed: 79 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
namespace lldb_private {
2121

2222
/// \class DataBuffer DataBuffer.h "lldb/Core/DataBuffer.h"
23-
/// A pure virtual protocol class for abstracted data buffers.
23+
/// A pure virtual protocol class for abstracted read only data buffers.
2424
///
25-
/// DataBuffer is an abstract class that gets packaged into a shared pointer
26-
/// that can use to implement various ways to store data (on the heap, memory
27-
/// mapped, cached inferior memory). It gets used by DataExtractor so many
28-
/// DataExtractor objects can share the same data and sub-ranges of that
25+
/// DataBuffer is an abstract class that gets packaged into a shared
26+
/// pointer that can use to implement various ways to store data (on the heap,
27+
/// memory mapped, cached inferior memory). It gets used by DataExtractor so
28+
/// many DataExtractor objects can share the same data and sub-ranges of that
2929
/// shared data, and the last object that contains a reference to the shared
3030
/// data will free it.
3131
///
@@ -42,52 +42,106 @@ namespace lldb_private {
4242
/// with some extra function calls to load the data before it gets accessed.
4343
class DataBuffer {
4444
public:
45-
/// Destructor
46-
///
47-
/// The destructor is virtual as other classes will inherit from this class
48-
/// and be downcast to the DataBuffer pure virtual interface. The virtual
49-
/// destructor ensures that destructing the base class will destruct the
50-
/// class that inherited from it correctly.
5145
virtual ~DataBuffer() = default;
5246

53-
/// Get a pointer to the data.
47+
/// Get the number of bytes in the data buffer.
5448
///
5549
/// \return
56-
/// A pointer to the bytes owned by this object, or NULL if the
57-
/// object contains no bytes.
58-
virtual uint8_t *GetBytes() = 0;
50+
/// The number of bytes this object currently contains.
51+
virtual lldb::offset_t GetByteSize() const = 0;
5952

6053
/// Get a const pointer to the data.
6154
///
6255
/// \return
6356
/// A const pointer to the bytes owned by this object, or NULL
6457
/// if the object contains no bytes.
65-
virtual const uint8_t *GetBytes() const = 0;
66-
67-
/// Get the number of bytes in the data buffer.
68-
///
69-
/// \return
70-
/// The number of bytes this object currently contains.
71-
virtual lldb::offset_t GetByteSize() const = 0;
58+
const uint8_t *GetBytes() const { return GetBytesImpl(); }
7259

7360
llvm::ArrayRef<uint8_t> GetData() const {
7461
return llvm::ArrayRef<uint8_t>(GetBytes(), GetByteSize());
7562
}
7663

64+
/// LLVM RTTI support.
65+
/// {
66+
static char ID;
67+
virtual bool isA(const void *ClassID) const { return ClassID == &ID; }
68+
static bool classof(const DataBuffer *data_buffer) {
69+
return data_buffer->isA(&ID);
70+
}
71+
/// }
72+
73+
protected:
74+
/// Get a const pointer to the data.
75+
///
76+
/// \return
77+
/// A const pointer to the bytes owned by this object, or NULL
78+
/// if the object contains no bytes.
79+
virtual const uint8_t *GetBytesImpl() const = 0;
80+
};
81+
82+
/// \class DataBuffer DataBuffer.h "lldb/Core/DataBuffer.h"
83+
/// A pure virtual protocol class for abstracted writable data buffers.
84+
///
85+
/// DataBuffer is an abstract class that gets packaged into a shared pointer
86+
/// that can use to implement various ways to store data (on the heap, memory
87+
/// mapped, cached inferior memory). It gets used by DataExtractor so many
88+
/// DataExtractor objects can share the same data and sub-ranges of that
89+
/// shared data, and the last object that contains a reference to the shared
90+
/// data will free it.
91+
class WritableDataBuffer : public DataBuffer {
92+
public:
93+
/// Destructor
94+
///
95+
/// The destructor is virtual as other classes will inherit from this class
96+
/// and be downcast to the DataBuffer pure virtual interface. The virtual
97+
/// destructor ensures that destructing the base class will destruct the
98+
/// class that inherited from it correctly.
99+
virtual ~WritableDataBuffer() = default;
100+
101+
using DataBuffer::GetBytes;
102+
using DataBuffer::GetData;
103+
104+
/// Get a pointer to the data.
105+
///
106+
/// \return
107+
/// A pointer to the bytes owned by this object, or NULL if the
108+
/// object contains no bytes.
109+
uint8_t *GetBytes() { return const_cast<uint8_t *>(GetBytesImpl()); }
110+
77111
llvm::MutableArrayRef<uint8_t> GetData() {
78112
return llvm::MutableArrayRef<uint8_t>(GetBytes(), GetByteSize());
79113
}
114+
115+
/// LLVM RTTI support.
116+
/// {
117+
static char ID;
118+
bool isA(const void *ClassID) const override {
119+
return ClassID == &ID || DataBuffer::isA(ClassID);
120+
}
121+
static bool classof(const DataBuffer *data_buffer) {
122+
return data_buffer->isA(&ID);
123+
}
124+
/// }
80125
};
81126

82-
class DataBufferUnowned : public DataBuffer {
127+
class DataBufferUnowned : public WritableDataBuffer {
83128
public:
84129
DataBufferUnowned(uint8_t *bytes, lldb::offset_t size)
85130
: m_bytes(bytes), m_size(size) {}
86131

87-
uint8_t *GetBytes() override { return m_bytes; }
88-
const uint8_t *GetBytes() const override { return m_bytes; }
132+
const uint8_t *GetBytesImpl() const override { return m_bytes; }
89133
lldb::offset_t GetByteSize() const override { return m_size; }
90134

135+
/// LLVM RTTI support.
136+
/// {
137+
static char ID;
138+
bool isA(const void *ClassID) const override {
139+
return ClassID == &ID || WritableDataBuffer::isA(ClassID);
140+
}
141+
static bool classof(const DataBuffer *data_buffer) {
142+
return data_buffer->isA(&ID);
143+
}
144+
/// }
91145
private:
92146
uint8_t *m_bytes;
93147
lldb::offset_t m_size;

lldb/include/lldb/Utility/DataBufferHeap.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace lldb_private {
2727
/// pages in. Large amounts of data that comes from files should probably use
2828
/// DataBufferLLVM, which can intelligently determine when memory mapping is
2929
/// optimal.
30-
class DataBufferHeap : public DataBuffer {
30+
class DataBufferHeap : public WritableDataBuffer {
3131
public:
3232
/// Default constructor
3333
///
@@ -54,17 +54,20 @@ class DataBufferHeap : public DataBuffer {
5454
/// The number of bytes in \a src to copy.
5555
DataBufferHeap(const void *src, lldb::offset_t src_len);
5656

57+
/// Construct by making a copy of a DataBuffer.
58+
///
59+
/// \param[in] data_buffer
60+
/// A read only data buffer to copy.
61+
DataBufferHeap(const DataBuffer &data_buffer);
62+
5763
/// Destructor.
5864
///
5965
/// Virtual destructor since this class inherits from a pure virtual base
6066
/// class #DataBuffer.
6167
~DataBufferHeap() override;
6268

63-
/// \copydoc DataBuffer::GetBytes()
64-
uint8_t *GetBytes() override;
65-
6669
/// \copydoc DataBuffer::GetBytes() const
67-
const uint8_t *GetBytes() const override;
70+
const uint8_t *GetBytesImpl() const override;
6871

6972
/// \copydoc DataBuffer::GetByteSize() const
7073
lldb::offset_t GetByteSize() const override;
@@ -100,6 +103,17 @@ class DataBufferHeap : public DataBuffer {
100103

101104
void Clear();
102105

106+
/// LLVM RTTI support.
107+
/// {
108+
static char ID;
109+
bool isA(const void *ClassID) const override {
110+
return ClassID == &ID || WritableDataBuffer::isA(ClassID);
111+
}
112+
static bool classof(const DataBuffer *data_buffer) {
113+
return data_buffer->isA(&ID);
114+
}
115+
/// }
116+
103117
private:
104118
// This object uses a std::vector<uint8_t> to store its data. This takes care
105119
// of free the data when the object is deleted.

lldb/include/lldb/Utility/DataBufferLLVM.h

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,63 @@
1717

1818
namespace llvm {
1919
class WritableMemoryBuffer;
20+
class MemoryBuffer;
2021
class Twine;
2122
} // namespace llvm
2223

2324
namespace lldb_private {
24-
2525
class FileSystem;
26+
2627
class DataBufferLLVM : public DataBuffer {
2728
public:
2829
~DataBufferLLVM() override;
2930

30-
uint8_t *GetBytes() override;
31-
const uint8_t *GetBytes() const override;
31+
const uint8_t *GetBytesImpl() const override;
3232
lldb::offset_t GetByteSize() const override;
3333

34-
private:
35-
friend FileSystem;
34+
/// LLVM RTTI support.
35+
/// {
36+
static char ID;
37+
bool isA(const void *ClassID) const override {
38+
return ClassID == &ID || DataBuffer::isA(ClassID);
39+
}
40+
static bool classof(const DataBuffer *data_buffer) {
41+
return data_buffer->isA(&ID);
42+
}
43+
/// }
44+
45+
/// Construct a DataBufferLLVM from \p Buffer. \p Buffer must be a valid
46+
/// pointer.
47+
explicit DataBufferLLVM(std::unique_ptr<llvm::MemoryBuffer> Buffer);
48+
49+
protected:
50+
std::unique_ptr<llvm::MemoryBuffer> Buffer;
51+
};
52+
53+
class WritableDataBufferLLVM : public WritableDataBuffer {
54+
public:
55+
~WritableDataBufferLLVM() override;
56+
57+
const uint8_t *GetBytesImpl() const override;
58+
lldb::offset_t GetByteSize() const override;
59+
60+
/// LLVM RTTI support.
61+
/// {
62+
static char ID;
63+
bool isA(const void *ClassID) const override {
64+
return ClassID == &ID || WritableDataBuffer::isA(ClassID);
65+
}
66+
static bool classof(const DataBuffer *data_buffer) {
67+
return data_buffer->isA(&ID);
68+
}
69+
/// }
70+
3671
/// Construct a DataBufferLLVM from \p Buffer. \p Buffer must be a valid
3772
/// pointer.
38-
explicit DataBufferLLVM(std::unique_ptr<llvm::WritableMemoryBuffer> Buffer);
73+
explicit WritableDataBufferLLVM(
74+
std::unique_ptr<llvm::WritableMemoryBuffer> Buffer);
3975

76+
protected:
4077
std::unique_ptr<llvm::WritableMemoryBuffer> Buffer;
4178
};
4279
} // namespace lldb_private

lldb/include/lldb/lldb-forward.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class DWARFCallFrameInfo;
6767
class DWARFDataExtractor;
6868
class DWARFExpression;
6969
class DataBuffer;
70+
class WritableDataBuffer;
7071
class DataBufferHeap;
7172
class DataEncoder;
7273
class DataExtractor;
@@ -309,6 +310,7 @@ typedef std::shared_ptr<lldb_private::CommandObject> CommandObjectSP;
309310
typedef std::shared_ptr<lldb_private::Connection> ConnectionSP;
310311
typedef std::shared_ptr<lldb_private::CompileUnit> CompUnitSP;
311312
typedef std::shared_ptr<lldb_private::DataBuffer> DataBufferSP;
313+
typedef std::shared_ptr<lldb_private::WritableDataBuffer> WritableDataBufferSP;
312314
typedef std::shared_ptr<lldb_private::DataExtractor> DataExtractorSP;
313315
typedef std::shared_ptr<lldb_private::Debugger> DebuggerSP;
314316
typedef std::weak_ptr<lldb_private::Debugger> DebuggerWP;

lldb/source/Commands/CommandObjectMemory.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ class CommandObjectMemoryRead : public CommandObjectParsed {
639639
return false;
640640
}
641641

642-
DataBufferSP data_sp;
642+
WritableDataBufferSP data_sp;
643643
size_t bytes_read = 0;
644644
if (compiler_type.GetOpaqueQualType()) {
645645
// Make sure we don't display our type as ASCII bytes like the default

lldb/source/Core/SourceManager.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ bool SourceManager::File::CalculateLineOffsets(uint32_t line) {
644644
if (m_data_sp.get() == nullptr)
645645
return false;
646646

647-
const char *start = (char *)m_data_sp->GetBytes();
647+
const char *start = (const char *)m_data_sp->GetBytes();
648648
if (start) {
649649
const char *end = start + m_data_sp->GetByteSize();
650650

@@ -694,7 +694,7 @@ bool SourceManager::File::GetLine(uint32_t line_no, std::string &buffer) {
694694
if (end_offset == UINT32_MAX) {
695695
end_offset = m_data_sp->GetByteSize();
696696
}
697-
buffer.assign((char *)m_data_sp->GetBytes() + start_offset,
697+
buffer.assign((const char *)m_data_sp->GetBytes() + start_offset,
698698
end_offset - start_offset);
699699

700700
return true;

0 commit comments

Comments
 (0)