diff options
author | Pavel Labath <labath@google.com> | 2017-12-15 14:23:58 +0000 |
---|---|---|
committer | Pavel Labath <labath@google.com> | 2017-12-15 14:23:58 +0000 |
commit | e2867bc4a07b942724fa3be95c6c671b196fe1ae (patch) | |
tree | 28b1d7e03a3c5313a17f7ae6ff86e31b920cc7d8 /lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | |
parent | 786431231f8916e36477d4fba07ce158adddce4e (diff) | |
download | bcm5719-llvm-e2867bc4a07b942724fa3be95c6c671b196fe1ae.tar.gz bcm5719-llvm-e2867bc4a07b942724fa3be95c6c671b196fe1ae.zip |
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
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r-- | lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index fc42dde8284..9869a94f06b 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -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 §ion_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(); +} |