ObjectFileELF: Add support for compressed sections

Summary:
We use the llvm decompressor to decompress SHF_COMPRESSED sections. This enables
us to read data from debug info sections, which are sometimes compressed,
particuarly in the split-dwarf case.  This functionality is only available if
llvm is compiled with zlib support.

Reviewers: clayborg, zturner

Subscribers: emaste, mgorny, aprantl, lldb-commits

Differential Revision: https://reviews.llvm.org/D40616

llvm-svn: 320813
This commit is contained in:
Pavel Labath
2017-12-15 14:23:58 +00:00
parent 786431231f
commit e2867bc4a0
10 changed files with 116 additions and 3 deletions

View File

@@ -23,6 +23,7 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
@@ -31,6 +32,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Decompressor.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -3460,3 +3462,56 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
}
return eStrataUnknown;
}
size_t ObjectFileELF::ReadSectionData(Section *section,
lldb::offset_t section_offset, void *dst,
size_t dst_len) {
// If some other objectfile owns this data, pass this to them.
if (section->GetObjectFile() != this)
return section->GetObjectFile()->ReadSectionData(section, section_offset,
dst, dst_len);
if (!section->Test(SHF_COMPRESSED))
return ObjectFile::ReadSectionData(section, section_offset, dst, dst_len);
// For compressed sections we need to read to full data to be able to
// decompress.
DataExtractor data;
ReadSectionData(section, data);
return data.CopyData(section_offset, dst_len, dst);
}
size_t ObjectFileELF::ReadSectionData(Section *section,
DataExtractor &section_data) {
// If some other objectfile owns this data, pass this to them.
if (section->GetObjectFile() != this)
return section->GetObjectFile()->ReadSectionData(section, section_data);
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
size_t result = ObjectFile::ReadSectionData(section, section_data);
if (result == 0 || !section->Test(SHF_COMPRESSED))
return result;
auto Decompressor = llvm::object::Decompressor::create(
section->GetName().GetStringRef(),
{reinterpret_cast<const char *>(section_data.GetDataStart()),
section_data.GetByteSize()},
GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
if (!Decompressor) {
LLDB_LOG(log, "Unable to initialize decompressor for section {0}: {1}",
section->GetName(), llvm::toString(Decompressor.takeError()));
return result;
}
auto buffer_sp =
std::make_shared<DataBufferHeap>(Decompressor->getDecompressedSize(), 0);
if (auto Error = Decompressor->decompress(
{reinterpret_cast<char *>(buffer_sp->GetBytes()),
buffer_sp->GetByteSize()})) {
LLDB_LOG(log, "Decompression of section {0} failed: {1}",
section->GetName(), llvm::toString(std::move(Error)));
return result;
}
section_data.SetData(buffer_sp);
return buffer_sp->GetByteSize();
}