diff options
author | Puyan Lotfi <puyan@puyan.org> | 2018-10-01 10:29:41 +0000 |
---|---|---|
committer | Puyan Lotfi <puyan@puyan.org> | 2018-10-01 10:29:41 +0000 |
commit | af048648d367cc23f923e11ea8cbf909e2c3bde4 (patch) | |
tree | 7bbd5fc23a18580adc552662585b40e42452cc51 /llvm/tools/llvm-objcopy/Object.cpp | |
parent | 8600fee52ee134e84175f5b578f72133b9d2edca (diff) | |
download | bcm5719-llvm-af048648d367cc23f923e11ea8cbf909e2c3bde4.tar.gz bcm5719-llvm-af048648d367cc23f923e11ea8cbf909e2c3bde4.zip |
[llvm-objcopy] Adding support for decompressing zlib compressed dwarf sections.
Summary: I had added support for compressing dwarf sections in a prior commit,
this one adds support for decompressing. Usage is:
llvm-objcopy --decompress-debug-sections input.o output.o
Reviewers: jakehehrlich, jhenderson, alexshap
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D51841
llvm-svn: 343451
Diffstat (limited to 'llvm/tools/llvm-objcopy/Object.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/Object.cpp | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/llvm/tools/llvm-objcopy/Object.cpp b/llvm/tools/llvm-objcopy/Object.cpp index e57a626fcad..ddf811a769b 100644 --- a/llvm/tools/llvm-objcopy/Object.cpp +++ b/llvm/tools/llvm-objcopy/Object.cpp @@ -136,6 +136,63 @@ void SectionWriter::visit(const OwnedDataSection &Sec) { std::copy(std::begin(Sec.Data), std::end(Sec.Data), Buf); } +static const std::vector<uint8_t> ZlibGnuMagic = {'Z', 'L', 'I', 'B'}; + +static bool isDataGnuCompressed(ArrayRef<uint8_t> Data) { + return Data.size() > ZlibGnuMagic.size() && + std::equal(ZlibGnuMagic.begin(), ZlibGnuMagic.end(), Data.data()); +} + +template <class ELFT> +static std::tuple<uint64_t, uint64_t> +getDecompressedSizeAndAlignment(ArrayRef<uint8_t> Data) { + const bool IsGnuDebug = isDataGnuCompressed(Data); + const uint64_t DecompressedSize = + IsGnuDebug + ? support::endian::read64be(reinterpret_cast<const uint64_t *>( + Data.data() + ZlibGnuMagic.size())) + : reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data.data())->ch_size; + const uint64_t DecompressedAlign = + IsGnuDebug ? 1 + : reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data.data()) + ->ch_addralign; + + return std::make_tuple(DecompressedSize, DecompressedAlign); +} + +template <class ELFT> +void ELFSectionWriter<ELFT>::visit(const DecompressedSection &Sec) { + uint8_t *Buf = Out.getBufferStart() + Sec.Offset; + + if (!zlib::isAvailable()) { + std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf); + return; + } + + const size_t DataOffset = isDataGnuCompressed(Sec.OriginalData) + ? (ZlibGnuMagic.size() + sizeof(Sec.Size)) + : sizeof(Elf_Chdr_Impl<ELFT>); + + StringRef CompressedContent( + reinterpret_cast<const char *>(Sec.OriginalData.data()) + DataOffset, + Sec.OriginalData.size() - DataOffset); + + SmallVector<char, 128> DecompressedContent; + if (Error E = zlib::uncompress(CompressedContent, DecompressedContent, + static_cast<size_t>(Sec.Size))) + reportError(Sec.Name, std::move(E)); + + std::copy(DecompressedContent.begin(), DecompressedContent.end(), Buf); +} + +void BinarySectionWriter::visit(const DecompressedSection &Sec) { + error("Cannot write compressed section '" + Sec.Name + "' "); +} + +void DecompressedSection::accept(SectionVisitor &Visitor) const { + Visitor.visit(*this); +} + void OwnedDataSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } @@ -206,6 +263,14 @@ CompressedSection::CompressedSection(const SectionBase &Sec, Align = 8; } +CompressedSection::CompressedSection(ArrayRef<uint8_t> CompressedData, + uint64_t DecompressedSize, + uint64_t DecompressedAlign) + : CompressionType(DebugCompressionType::None), + DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) { + OriginalData = CompressedData; +} + void CompressedSection::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } @@ -969,10 +1034,20 @@ SectionBase &ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) { } case SHT_NOBITS: return Obj.addSection<Section>(Data); - default: + default: { Data = unwrapOrError(ElfFile.getSectionContents(&Shdr)); + + if (isDataGnuCompressed(Data) || (Shdr.sh_flags & ELF::SHF_COMPRESSED)) { + uint64_t DecompressedSize, DecompressedAlign; + std::tie(DecompressedSize, DecompressedAlign) = + getDecompressedSizeAndAlignment<ELFT>(Data); + return Obj.addSection<CompressedSection>(Data, DecompressedSize, + DecompressedAlign); + } + return Obj.addSection<Section>(Data); } + } } template <class ELFT> void ELFBuilder<ELFT>::readSectionHeaders() { |