[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:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user