14bf30831SGeorge Rimar //===-- Decompressor.cpp --------------------------------------------------===//
24bf30831SGeorge Rimar //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64bf30831SGeorge Rimar //
74bf30831SGeorge Rimar //===----------------------------------------------------------------------===//
84bf30831SGeorge Rimar
94bf30831SGeorge Rimar #include "llvm/Object/Decompressor.h"
10264b5d9eSZachary Turner #include "llvm/BinaryFormat/ELF.h"
11e72c195fSserge-sans-paille #include "llvm/Object/ObjectFile.h"
124bf30831SGeorge Rimar #include "llvm/Support/Compression.h"
134bf30831SGeorge Rimar #include "llvm/Support/DataExtractor.h"
146bda14b3SChandler Carruth #include "llvm/Support/Endian.h"
154bf30831SGeorge Rimar
164bf30831SGeorge Rimar using namespace llvm;
174bf30831SGeorge Rimar using namespace llvm::support::endian;
184bf30831SGeorge Rimar using namespace object;
194bf30831SGeorge Rimar
create(StringRef Name,StringRef Data,bool IsLE,bool Is64Bit)204bf30831SGeorge Rimar Expected<Decompressor> Decompressor::create(StringRef Name, StringRef Data,
214bf30831SGeorge Rimar bool IsLE, bool Is64Bit) {
22ea61750cSCole Kissane if (!compression::zlib::isAvailable())
234bf30831SGeorge Rimar return createError("zlib is not available");
244bf30831SGeorge Rimar
253ae41704SVedant Kumar Decompressor D(Data);
26*141c9d77SFangrui Song if (Error Err = D.consumeCompressedZLibHeader(Is64Bit, IsLE))
27c55cf4afSBill Wendling return std::move(Err);
284bf30831SGeorge Rimar return D;
294bf30831SGeorge Rimar }
304bf30831SGeorge Rimar
Decompressor(StringRef Data)313ae41704SVedant Kumar Decompressor::Decompressor(StringRef Data)
323ae41704SVedant Kumar : SectionData(Data), DecompressedSize(0) {}
334bf30831SGeorge Rimar
consumeCompressedZLibHeader(bool Is64Bit,bool IsLittleEndian)344bf30831SGeorge Rimar Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit,
354bf30831SGeorge Rimar bool IsLittleEndian) {
364bf30831SGeorge Rimar using namespace ELF;
374bf30831SGeorge Rimar uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
384bf30831SGeorge Rimar if (SectionData.size() < HdrSize)
394bf30831SGeorge Rimar return createError("corrupted compressed section header");
404bf30831SGeorge Rimar
414bf30831SGeorge Rimar DataExtractor Extractor(SectionData, IsLittleEndian, 0);
42f26a70a5SIgor Kudrin uint64_t Offset = 0;
434bf30831SGeorge Rimar if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word)
444bf30831SGeorge Rimar : sizeof(Elf32_Word)) !=
454bf30831SGeorge Rimar ELFCOMPRESS_ZLIB)
464bf30831SGeorge Rimar return createError("unsupported compression type");
474bf30831SGeorge Rimar
484bf30831SGeorge Rimar // Skip Elf64_Chdr::ch_reserved field.
494bf30831SGeorge Rimar if (Is64Bit)
504bf30831SGeorge Rimar Offset += sizeof(Elf64_Word);
514bf30831SGeorge Rimar
524bf30831SGeorge Rimar DecompressedSize = Extractor.getUnsigned(
534bf30831SGeorge Rimar &Offset, Is64Bit ? sizeof(Elf64_Xword) : sizeof(Elf32_Word));
544bf30831SGeorge Rimar SectionData = SectionData.substr(HdrSize);
554bf30831SGeorge Rimar return Error::success();
564bf30831SGeorge Rimar }
574bf30831SGeorge Rimar
decompress(MutableArrayRef<uint8_t> Buffer)58e690137dSFangrui Song Error Decompressor::decompress(MutableArrayRef<uint8_t> Buffer) {
594bf30831SGeorge Rimar size_t Size = Buffer.size();
60e690137dSFangrui Song return compression::zlib::uncompress(arrayRefFromStringRef(SectionData),
61e690137dSFangrui Song Buffer.data(), Size);
624bf30831SGeorge Rimar }
63