mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-05 00:48:08 +00:00
[ELF] - Reuse Decompressor class.
Intention of change is to get rid of code duplication. Decompressor was introduced in D28105. Change allows to get rid of few methods relative to decompression. Differential revision: https://reviews.llvm.org/D28106 llvm-svn: 291758
This commit is contained in:
parent
569ad73d6b
commit
0d8af3697a
@ -24,6 +24,7 @@
|
||||
#include "lld/Driver/Driver.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Object/Decompressor.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/TarWriter.h"
|
||||
@ -815,7 +816,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
||||
[](InputSectionBase<ELFT> *S) {
|
||||
if (!S->Live)
|
||||
return;
|
||||
if (S->isCompressed())
|
||||
if (Decompressor::isCompressedELFSection(S->Flags, S->Name))
|
||||
S->uncompress();
|
||||
if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(S))
|
||||
MS->splitIntoPieces();
|
||||
|
@ -103,4 +103,10 @@ void elf::fatal(std::error_code EC, const Twine &Prefix) {
|
||||
fatal(Prefix + ": " + EC.message());
|
||||
}
|
||||
|
||||
void elf::fatal(Error &E, const Twine &Prefix) {
|
||||
handleAllErrors(std::move(E), [&](llvm::ErrorInfoBase &EI) {
|
||||
fatal(Prefix + ": " + EI.message());
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace lld
|
||||
|
@ -44,6 +44,7 @@ void error(std::error_code EC, const Twine &Prefix);
|
||||
LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
|
||||
LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
|
||||
LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix);
|
||||
LLVM_ATTRIBUTE_NORETURN void fatal(Error &E, const Twine &Prefix);
|
||||
|
||||
// check() functions are convenient functions to strip errors
|
||||
// from error-or-value objects.
|
||||
|
@ -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>
|
||||
@ -128,71 +129,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");
|
||||
Decompressor Decompressor = check(Decompressor::create(
|
||||
Name, toStringRef(Data), ELFT::TargetEndianness == llvm::support::little,
|
||||
ELFT::Is64Bits));
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -138,22 +138,12 @@ public:
|
||||
// section.
|
||||
uintX_t getOffset(uintX_t Offset) const;
|
||||
|
||||
// ELF supports ZLIB-compressed section.
|
||||
// Returns true if the section is compressed.
|
||||
bool isCompressed() const;
|
||||
void uncompress();
|
||||
|
||||
// Returns a source location string. Used to construct an error message.
|
||||
std::string getLocation(uintX_t Offset);
|
||||
|
||||
void relocate(uint8_t *Buf, uint8_t *BufEnd);
|
||||
|
||||
private:
|
||||
std::pair<ArrayRef<uint8_t>, uint64_t>
|
||||
getElfCompressedData(ArrayRef<uint8_t> Data);
|
||||
|
||||
std::pair<ArrayRef<uint8_t>, uint64_t>
|
||||
getRawCompressedData(ArrayRef<uint8_t> Data);
|
||||
};
|
||||
|
||||
// SectionPiece represents a piece of splittable section contents.
|
||||
|
Loading…
x
Reference in New Issue
Block a user