forked from OSchip/llvm-project
[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 llvm-svn: 273661
This commit is contained in:
parent
998fb5c28b
commit
602fbee9fc
|
@ -521,10 +521,14 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
|||
// 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);
|
||||
}
|
||||
|
|
|
@ -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 InputSectionBase<ELFT>::getSectionName() const {
|
|||
|
||||
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<ELFT>::getOffset(uintX_t Offset) const {
|
|||
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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",@progbits,1
|
||||
.LASF2:
|
||||
.string "short unsigned int"
|
||||
.LASF3:
|
||||
.string "unsigned int"
|
||||
.LASF0:
|
||||
.string "long unsigned int"
|
||||
.LASF8:
|
||||
.string "char"
|
||||
.LASF1:
|
||||
.string "unsigned char"
|
Loading…
Reference in New Issue