summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-objcopy/Object.cpp
diff options
context:
space:
mode:
authorPuyan Lotfi <puyan@puyan.org>2018-10-01 10:29:41 +0000
committerPuyan Lotfi <puyan@puyan.org>2018-10-01 10:29:41 +0000
commitaf048648d367cc23f923e11ea8cbf909e2c3bde4 (patch)
tree7bbd5fc23a18580adc552662585b40e42452cc51 /llvm/tools/llvm-objcopy/Object.cpp
parent8600fee52ee134e84175f5b578f72133b9d2edca (diff)
downloadbcm5719-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.cpp77
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() {
OpenPOWER on IntegriCloud