mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-11 21:57:55 +00:00
ef935cd26f
No any changes, will follow up with D28807 commit containing APLi change for clang to fix build issues happened. Original commit message: [Support/Compression] - Change zlib API to return Error instead of custom status. Previously API returned custom enum values. Patch changes it to return Error with string description. That should help users to report errors in universal way. Differential revision: https://reviews.llvm.org/D28684 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292226 91177308-0d34-0410-b5e6-96231b3b80d8
100 lines
3.2 KiB
C++
100 lines
3.2 KiB
C++
//===-- Decompressor.cpp --------------------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Object/Decompressor.h"
|
|
#include "llvm/Object/ELFObjectFile.h"
|
|
#include "llvm/Support/Compression.h"
|
|
#include "llvm/Support/DataExtractor.h"
|
|
#include "llvm/Support/Endian.h"
|
|
#include "llvm/Support/ELF.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::support::endian;
|
|
using namespace object;
|
|
|
|
Expected<Decompressor> Decompressor::create(StringRef Name, StringRef Data,
|
|
bool IsLE, bool Is64Bit) {
|
|
if (!zlib::isAvailable())
|
|
return createError("zlib is not available");
|
|
|
|
Decompressor D(Data);
|
|
Error Err = isGnuStyle(Name) ? D.consumeCompressedGnuHeader()
|
|
: D.consumeCompressedZLibHeader(Is64Bit, IsLE);
|
|
if (Err)
|
|
return std::move(Err);
|
|
return D;
|
|
}
|
|
|
|
Decompressor::Decompressor(StringRef Data)
|
|
: SectionData(Data), DecompressedSize(0) {}
|
|
|
|
Error Decompressor::consumeCompressedGnuHeader() {
|
|
if (!SectionData.startswith("ZLIB"))
|
|
return createError("corrupted compressed section header");
|
|
|
|
SectionData = SectionData.substr(4);
|
|
|
|
// Consume uncompressed section size (big-endian 8 bytes).
|
|
if (SectionData.size() < 8)
|
|
return createError("corrupted uncompressed section size");
|
|
DecompressedSize = read64be(SectionData.data());
|
|
SectionData = SectionData.substr(8);
|
|
|
|
return Error::success();
|
|
}
|
|
|
|
Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit,
|
|
bool IsLittleEndian) {
|
|
using namespace ELF;
|
|
uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
|
|
if (SectionData.size() < HdrSize)
|
|
return createError("corrupted compressed section header");
|
|
|
|
DataExtractor Extractor(SectionData, IsLittleEndian, 0);
|
|
uint32_t Offset = 0;
|
|
if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word)
|
|
: sizeof(Elf32_Word)) !=
|
|
ELFCOMPRESS_ZLIB)
|
|
return createError("unsupported compression type");
|
|
|
|
// Skip Elf64_Chdr::ch_reserved field.
|
|
if (Is64Bit)
|
|
Offset += sizeof(Elf64_Word);
|
|
|
|
DecompressedSize = Extractor.getUnsigned(
|
|
&Offset, Is64Bit ? sizeof(Elf64_Xword) : sizeof(Elf32_Word));
|
|
SectionData = SectionData.substr(HdrSize);
|
|
return Error::success();
|
|
}
|
|
|
|
bool Decompressor::isGnuStyle(StringRef Name) {
|
|
return Name.startswith(".zdebug");
|
|
}
|
|
|
|
bool Decompressor::isCompressed(const object::SectionRef &Section) {
|
|
StringRef Name;
|
|
if (Section.getName(Name))
|
|
return false;
|
|
return Section.isCompressed() || isGnuStyle(Name);
|
|
}
|
|
|
|
bool Decompressor::isCompressedELFSection(uint64_t Flags, StringRef Name) {
|
|
return (Flags & ELF::SHF_COMPRESSED) || isGnuStyle(Name);
|
|
}
|
|
|
|
Error Decompressor::decompress(SmallString<32> &Out) {
|
|
Out.resize(DecompressedSize);
|
|
return decompress({Out.data(), (size_t)DecompressedSize});
|
|
}
|
|
|
|
Error Decompressor::decompress(MutableArrayRef<char> Buffer) {
|
|
size_t Size = Buffer.size();
|
|
return zlib::uncompress(SectionData, Buffer.data(), Size);
|
|
}
|