summaryrefslogtreecommitdiff
path: root/ELF/InputSection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ELF/InputSection.cpp')
-rw-r--r--ELF/InputSection.cpp73
1 files changed, 12 insertions, 61 deletions
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index e87d92aa207c..358004248373 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -19,6 +19,7 @@
#include "SyntheticSections.h"
#include "Target.h"
#include "Thunks.h"
+#include "llvm/Object/Decompressor.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Endian.h"
#include <mutex>
@@ -35,7 +36,10 @@ using namespace lld::elf;
// Returns a string to construct an error message.
template <class ELFT>
std::string lld::toString(const InputSectionBase<ELFT> *Sec) {
- return (Sec->getFile()->getName() + ":(" + Sec->Name + ")").str();
+ // File can be absent if section is synthetic.
+ std::string FileName =
+ Sec->getFile() ? Sec->getFile()->getName() : "<internal>";
+ return (FileName + ":(" + Sec->Name + ")").str();
}
template <class ELFT>
@@ -102,11 +106,6 @@ template <class ELFT> size_t InputSectionBase<ELFT>::getSize() const {
return Data.size();
}
-// Returns a string for an error message.
-template <class SectionT> static std::string getName(SectionT *Sec) {
- return (Sec->getFile()->getName() + ":(" + Sec->Name + ")").str();
-}
-
template <class ELFT>
typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
switch (kind()) {
@@ -128,71 +127,23 @@ typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
llvm_unreachable("invalid section kind");
}
-template <class ELFT> bool InputSectionBase<ELFT>::isCompressed() const {
- return (Flags & SHF_COMPRESSED) || Name.startswith(".zdebug");
-}
-
-// Returns compressed data and its size when uncompressed.
-template <class ELFT>
-std::pair<ArrayRef<uint8_t>, uint64_t>
-InputSectionBase<ELFT>::getElfCompressedData(ArrayRef<uint8_t> Data) {
- // Compressed section with Elf_Chdr is the ELF standard.
- if (Data.size() < sizeof(Elf_Chdr))
- fatal(toString(this) + ": corrupted compressed section");
- auto *Hdr = reinterpret_cast<const Elf_Chdr *>(Data.data());
- if (Hdr->ch_type != ELFCOMPRESS_ZLIB)
- fatal(toString(this) + ": unsupported compression type");
- return {Data.slice(sizeof(*Hdr)), Hdr->ch_size};
-}
-
-// Returns compressed data and its size when uncompressed.
-template <class ELFT>
-std::pair<ArrayRef<uint8_t>, uint64_t>
-InputSectionBase<ELFT>::getRawCompressedData(ArrayRef<uint8_t> Data) {
- // Compressed sections without Elf_Chdr header contain this header
- // instead. This is a GNU extension.
- struct ZlibHeader {
- char Magic[4]; // Should be "ZLIB"
- char Size[8]; // Uncompressed size in big-endian
- };
-
- if (Data.size() < sizeof(ZlibHeader))
- fatal(toString(this) + ": corrupted compressed section");
- auto *Hdr = reinterpret_cast<const ZlibHeader *>(Data.data());
- if (memcmp(Hdr->Magic, "ZLIB", 4))
- fatal(toString(this) + ": broken ZLIB-compressed section");
- return {Data.slice(sizeof(*Hdr)), read64be(Hdr->Size)};
-}
-
// Uncompress section contents. Note that this function is called
// from parallel_for_each, so it must be thread-safe.
template <class ELFT> void InputSectionBase<ELFT>::uncompress() {
- if (!zlib::isAvailable())
- fatal(toString(this) +
- ": build lld with zlib to enable compressed sections support");
-
- // This section is compressed. Here we decompress it. Ideally, all
- // compressed sections have SHF_COMPRESSED bit and their contents
- // start with headers of Elf_Chdr type. However, sections whose
- // names start with ".zdebug_" don't have the bit and contains a raw
- // ZLIB-compressed data (which is a bad thing because section names
- // shouldn't be significant in ELF.) We need to be able to read both.
- ArrayRef<uint8_t> Buf; // Compressed data
- size_t Size; // Uncompressed size
- if (Flags & SHF_COMPRESSED)
- std::tie(Buf, Size) = getElfCompressedData(Data);
- else
- std::tie(Buf, Size) = getRawCompressedData(Data);
+ Decompressor Decompressor = check(Decompressor::create(
+ Name, toStringRef(Data), ELFT::TargetEndianness == llvm::support::little,
+ ELFT::Is64Bits));
- // Uncompress Buf.
+ size_t Size = Decompressor.getDecompressedSize();
char *OutputBuf;
{
static std::mutex Mu;
std::lock_guard<std::mutex> Lock(Mu);
OutputBuf = BAlloc.Allocate<char>(Size);
}
- if (zlib::uncompress(toStringRef(Buf), OutputBuf, Size) != zlib::StatusOK)
- fatal(toString(this) + ": error while uncompressing section");
+
+ if (Error E = Decompressor.decompress({OutputBuf, Size}))
+ fatal(E, toString(this));
Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size);
}