[lld] r273661 - [ELF] - Support of compressed input sections implemented.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 24 04:18:46 PDT 2016


Author: grimar
Date: Fri Jun 24 06:18:44 2016
New Revision: 273661

URL: http://llvm.org/viewvc/llvm-project?rev=273661&view=rev
Log:
[ELF] - Support of compressed input sections implemented.

Patch implements support of zlib style compressed sections.
SHF_COMPRESSED flag is used to recognize that decompression is required.
After that decompression is performed and flag is removed from output.

Differential revision: http://reviews.llvm.org/D20272

Added:
    lld/trunk/test/ELF/compressed-debug-input.s
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=273661&r1=273660&r2=273661&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Fri Jun 24 06:18:44 2016
@@ -521,10 +521,14 @@ template <class ELFT> void LinkerDriver:
   // any call of MergeInputSection::getOffset. Do that.
   for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
        Symtab.getObjectFiles())
-    for (InputSectionBase<ELFT> *S : F->getSections())
-      if (S && S != &InputSection<ELFT>::Discarded && S->Live)
-        if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(S))
-          MS->splitIntoPieces();
+    for (InputSectionBase<ELFT> *S : F->getSections()) {
+      if (!S || S == &InputSection<ELFT>::Discarded || !S->Live)
+        continue;
+      if (S->Compressed)
+        S->uncompress();
+      if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(S))
+        MS->splitIntoPieces();
+    }
 
   writeResult<ELFT>(&Symtab);
 }

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=273661&r1=273660&r2=273661&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Fri Jun 24 06:18:44 2016
@@ -15,6 +15,7 @@
 #include "OutputSections.h"
 #include "Target.h"
 
+#include "llvm/Support/Compression.h"
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;
@@ -29,7 +30,8 @@ template <class ELFT>
 InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
                                          const Elf_Shdr *Header,
                                          Kind SectionKind)
-    : Header(Header), File(File), SectionKind(SectionKind), Repl(this) {
+    : Header(Header), File(File), SectionKind(SectionKind), Repl(this),
+      Compressed(Header->sh_flags & SHF_COMPRESSED) {
   // The garbage collector sets sections' Live bits.
   // If GC is disabled, all sections are considered live by default.
   Live = !Config->GcSections;
@@ -52,6 +54,9 @@ template <class ELFT> StringRef InputSec
 
 template <class ELFT>
 ArrayRef<uint8_t> InputSectionBase<ELFT>::getSectionData() const {
+  if (Compressed)
+    return ArrayRef<uint8_t>((const uint8_t *)Uncompressed.data(),
+                             Uncompressed.size());
   return check(this->File->getObj().getSectionContents(this->Header));
 }
 
@@ -78,6 +83,27 @@ typename ELFT::uint InputSectionBase<ELF
   llvm_unreachable("invalid section kind");
 }
 
+template <class ELFT> void InputSectionBase<ELFT>::uncompress() {
+  typedef typename std::conditional<ELFT::Is64Bits, Elf64_Chdr,
+                                    Elf32_Chdr>::type Elf_Chdr;
+  const endianness E = ELFT::TargetEndianness;
+
+  if (!zlib::isAvailable())
+    fatal("build lld with zlib to enable compressed sections support");
+
+  ArrayRef<uint8_t> Data =
+      check(this->File->getObj().getSectionContents(this->Header));
+  if (read32<E>(Data.data()) != ELFCOMPRESS_ZLIB)
+    fatal("unsupported elf compression type");
+
+  size_t UncompressedSize =
+      reinterpret_cast<const Elf_Chdr *>(Data.data())->ch_size;
+  size_t HdrSize = sizeof(Elf_Chdr);
+  StringRef Buf((const char *)Data.data() + HdrSize, Data.size() - HdrSize);
+  if (zlib::uncompress(Buf, Uncompressed, UncompressedSize) != zlib::StatusOK)
+    fatal("error uncompressing section");
+}
+
 template <class ELFT>
 typename ELFT::uint
 InputSectionBase<ELFT>::getOffset(const DefinedRegular<ELFT> &Sym) const {

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=273661&r1=273660&r2=273661&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Fri Jun 24 06:18:44 2016
@@ -41,6 +41,9 @@ protected:
   // The file this section is from.
   ObjectFile<ELFT> *File;
 
+  // If a section is compressed, this vector has uncompressed section data.
+  SmallVector<char, 0> Uncompressed;
+
 public:
   enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions };
   Kind SectionKind;
@@ -78,8 +81,12 @@ public:
 
   ArrayRef<uint8_t> getSectionData() const;
 
+  void uncompress();
+
   void relocate(uint8_t *Buf, uint8_t *BufEnd);
   std::vector<Relocation<ELFT>> Relocations;
+
+  bool Compressed;
 };
 
 template <class ELFT> InputSectionBase<ELFT> InputSectionBase<ELFT>::Discarded;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=273661&r1=273660&r2=273661&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Jun 24 06:18:44 2016
@@ -623,7 +623,7 @@ SectionKey<ELFT::Is64Bits>
 OutputSectionFactory<ELFT>::createKey(InputSectionBase<ELFT> *C,
                                       StringRef OutsecName) {
   const Elf_Shdr *H = C->getSectionHdr();
-  uintX_t Flags = H->sh_flags & ~SHF_GROUP;
+  uintX_t Flags = H->sh_flags & ~SHF_GROUP & ~SHF_COMPRESSED;
 
   // For SHF_MERGE we create different output sections for each alignment.
   // This makes each output section simple and keeps a single level mapping from

Added: lld/trunk/test/ELF/compressed-debug-input.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/compressed-debug-input.s?rev=273661&view=auto
==============================================================================
--- lld/trunk/test/ELF/compressed-debug-input.s (added)
+++ lld/trunk/test/ELF/compressed-debug-input.s Fri Jun 24 06:18:44 2016
@@ -0,0 +1,55 @@
+# REQUIRES: zlib
+
+# RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: llvm-readobj -sections %t | FileCheck -check-prefix=COMPRESSED %s
+
+# COMPRESSED:      Section {
+# COMPRESSED:        Index: 2
+# COMPRESSED:        Name: .debug_str
+# COMPRESSED-NEXT:   Type: SHT_PROGBITS
+# COMPRESSED-NEXT:   Flags [
+# COMPRESSED-NEXT:     SHF_COMPRESSED (0x800)
+# COMPRESSED-NEXT:     SHF_MERGE (0x10)
+# COMPRESSED-NEXT:     SHF_STRINGS (0x20)
+# COMPRESSED-NEXT:   ]
+# COMPRESSED-NEXT:   Address:
+# COMPRESSED-NEXT:   Offset:
+# COMPRESSED-NEXT:   Size: 66
+# COMPRESSED-NEXT:   Link:
+# COMPRESSED-NEXT:   Info:
+# COMPRESSED-NEXT:   AddressAlignment: 1
+# COMPRESSED-NEXT:   EntrySize: 1
+# COMPRESSED-NEXT: }
+
+# RUN: ld.lld %t -o %t.so -shared
+# RUN: llvm-readobj -sections %t.so | FileCheck -check-prefix=UNCOMPRESSED %s
+
+## Check that section is decompressed and compression flag is removed.
+# UNCOMPRESSED:      Section {
+# UNCOMPRESSED:        Index: 6
+# UNCOMPRESSED:        Name: .debug_str
+# UNCOMPRESSED-NEXT:   Type: SHT_PROGBITS
+# UNCOMPRESSED-NEXT:   Flags [
+# UNCOMPRESSED-NEXT:     SHF_MERGE (0x10)
+# UNCOMPRESSED-NEXT:     SHF_STRINGS (0x20)
+# UNCOMPRESSED-NEXT:   ]
+# UNCOMPRESSED-NEXT:   Address: 0x0
+# UNCOMPRESSED-NEXT:   Offset: 0x1060
+# UNCOMPRESSED-NEXT:   Size: 69
+# UNCOMPRESSED-NEXT:   Link: 0
+# UNCOMPRESSED-NEXT:   Info: 0
+# UNCOMPRESSED-NEXT:   AddressAlignment: 1
+# UNCOMPRESSED-NEXT:   EntrySize: 1
+# UNCOMPRESSED-NEXT: }
+
+.section .debug_str,"MS", at progbits,1
+.LASF2:
+ .string "short unsigned int"
+.LASF3:
+ .string "unsigned int"
+.LASF0:
+ .string "long unsigned int"
+.LASF8:
+ .string "char"
+.LASF1:
+ .string "unsigned char"




More information about the llvm-commits mailing list