[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / lib / Object / Decompressor.cpp
blob11efd857d1a161a0242954731f94cfedbca31d6b
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 //===----------------------------------------------------------------------===//
9 #include "llvm/Object/Decompressor.h"
10 #include "llvm/BinaryFormat/ELF.h"
11 #include "llvm/Object/ELFObjectFile.h"
12 #include "llvm/Support/Compression.h"
13 #include "llvm/Support/DataExtractor.h"
14 #include "llvm/Support/Endian.h"
16 using namespace llvm;
17 using namespace llvm::support::endian;
18 using namespace object;
20 Expected<Decompressor> Decompressor::create(StringRef Name, StringRef Data,
21 bool IsLE, bool Is64Bit) {
22 if (!zlib::isAvailable())
23 return createError("zlib is not available");
25 Decompressor D(Data);
26 Error Err = isGnuStyle(Name) ? D.consumeCompressedGnuHeader()
27 : D.consumeCompressedZLibHeader(Is64Bit, IsLE);
28 if (Err)
29 return std::move(Err);
30 return D;
33 Decompressor::Decompressor(StringRef Data)
34 : SectionData(Data), DecompressedSize(0) {}
36 Error Decompressor::consumeCompressedGnuHeader() {
37 if (!SectionData.startswith("ZLIB"))
38 return createError("corrupted compressed section header");
40 SectionData = SectionData.substr(4);
42 // Consume uncompressed section size (big-endian 8 bytes).
43 if (SectionData.size() < 8)
44 return createError("corrupted uncompressed section size");
45 DecompressedSize = read64be(SectionData.data());
46 SectionData = SectionData.substr(8);
48 return Error::success();
51 Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit,
52 bool IsLittleEndian) {
53 using namespace ELF;
54 uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
55 if (SectionData.size() < HdrSize)
56 return createError("corrupted compressed section header");
58 DataExtractor Extractor(SectionData, IsLittleEndian, 0);
59 uint64_t Offset = 0;
60 if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word)
61 : sizeof(Elf32_Word)) !=
62 ELFCOMPRESS_ZLIB)
63 return createError("unsupported compression type");
65 // Skip Elf64_Chdr::ch_reserved field.
66 if (Is64Bit)
67 Offset += sizeof(Elf64_Word);
69 DecompressedSize = Extractor.getUnsigned(
70 &Offset, Is64Bit ? sizeof(Elf64_Xword) : sizeof(Elf32_Word));
71 SectionData = SectionData.substr(HdrSize);
72 return Error::success();
75 bool Decompressor::isGnuStyle(StringRef Name) {
76 return Name.startswith(".zdebug");
79 bool Decompressor::isCompressed(const object::SectionRef &Section) {
80 if (Section.isCompressed())
81 return true;
83 Expected<StringRef> SecNameOrErr = Section.getName();
84 if (SecNameOrErr)
85 return isGnuStyle(*SecNameOrErr);
87 consumeError(SecNameOrErr.takeError());
88 return false;
91 bool Decompressor::isCompressedELFSection(uint64_t Flags, StringRef Name) {
92 return (Flags & ELF::SHF_COMPRESSED) || isGnuStyle(Name);
95 Error Decompressor::decompress(MutableArrayRef<char> Buffer) {
96 size_t Size = Buffer.size();
97 return zlib::uncompress(SectionData, Buffer.data(), Size);