1 //===-- Decompressor.cpp --------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Object/Decompressor.h" 10 #include "llvm/BinaryFormat/ELF.h" 11 #include "llvm/Object/ObjectFile.h" 12 #include "llvm/Support/Compression.h" 13 #include "llvm/Support/DataExtractor.h" 14 #include "llvm/Support/Endian.h" 15 16 using namespace llvm; 17 using namespace llvm::support::endian; 18 using namespace object; 19 20 Expected<Decompressor> Decompressor::create(StringRef Name, StringRef Data, 21 bool IsLE, bool Is64Bit) { 22 if (!compression::zlib::isAvailable()) 23 return createError("zlib is not available"); 24 25 Decompressor D(Data); 26 if (Error Err = D.consumeCompressedZLibHeader(Is64Bit, IsLE)) 27 return std::move(Err); 28 return D; 29 } 30 31 Decompressor::Decompressor(StringRef Data) 32 : SectionData(Data), DecompressedSize(0) {} 33 34 Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit, 35 bool IsLittleEndian) { 36 using namespace ELF; 37 uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr); 38 if (SectionData.size() < HdrSize) 39 return createError("corrupted compressed section header"); 40 41 DataExtractor Extractor(SectionData, IsLittleEndian, 0); 42 uint64_t Offset = 0; 43 if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word) 44 : sizeof(Elf32_Word)) != 45 ELFCOMPRESS_ZLIB) 46 return createError("unsupported compression type"); 47 48 // Skip Elf64_Chdr::ch_reserved field. 49 if (Is64Bit) 50 Offset += sizeof(Elf64_Word); 51 52 DecompressedSize = Extractor.getUnsigned( 53 &Offset, Is64Bit ? sizeof(Elf64_Xword) : sizeof(Elf32_Word)); 54 SectionData = SectionData.substr(HdrSize); 55 return Error::success(); 56 } 57 58 Error Decompressor::decompress(MutableArrayRef<uint8_t> Buffer) { 59 size_t Size = Buffer.size(); 60 return compression::zlib::uncompress(arrayRefFromStringRef(SectionData), 61 Buffer.data(), Size); 62 } 63