[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
This commit is contained in:
Jonas Devlieghere
2022-04-01 15:59:18 -07:00
parent 4169650537
commit fc54427e76
80 changed files with 433 additions and 170 deletions

View File

@@ -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);
}