1 //===-- Decompressor.cpp --------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Object/Decompressor.h"
11 #include "llvm/BinaryFormat/ELF.h"
12 #include "llvm/Object/ELFObjectFile.h"
13 #include "llvm/Support/Compression.h"
14 #include "llvm/Support/DataExtractor.h"
15 #include "llvm/Support/Endian.h"
18 using namespace llvm::support::endian
;
19 using namespace object
;
21 Expected
<Decompressor
> Decompressor::create(StringRef Name
, StringRef Data
,
22 bool IsLE
, bool Is64Bit
) {
23 if (!zlib::isAvailable())
24 return createError("zlib is not available");
27 Error Err
= isGnuStyle(Name
) ? D
.consumeCompressedGnuHeader()
28 : D
.consumeCompressedZLibHeader(Is64Bit
, IsLE
);
30 return std::move(Err
);
34 Decompressor::Decompressor(StringRef Data
)
35 : SectionData(Data
), DecompressedSize(0) {}
37 Error
Decompressor::consumeCompressedGnuHeader() {
38 if (!SectionData
.startswith("ZLIB"))
39 return createError("corrupted compressed section header");
41 SectionData
= SectionData
.substr(4);
43 // Consume uncompressed section size (big-endian 8 bytes).
44 if (SectionData
.size() < 8)
45 return createError("corrupted uncompressed section size");
46 DecompressedSize
= read64be(SectionData
.data());
47 SectionData
= SectionData
.substr(8);
49 return Error::success();
52 Error
Decompressor::consumeCompressedZLibHeader(bool Is64Bit
,
53 bool IsLittleEndian
) {
55 uint64_t HdrSize
= Is64Bit
? sizeof(Elf64_Chdr
) : sizeof(Elf32_Chdr
);
56 if (SectionData
.size() < HdrSize
)
57 return createError("corrupted compressed section header");
59 DataExtractor
Extractor(SectionData
, IsLittleEndian
, 0);
61 if (Extractor
.getUnsigned(&Offset
, Is64Bit
? sizeof(Elf64_Word
)
62 : sizeof(Elf32_Word
)) !=
64 return createError("unsupported compression type");
66 // Skip Elf64_Chdr::ch_reserved field.
68 Offset
+= sizeof(Elf64_Word
);
70 DecompressedSize
= Extractor
.getUnsigned(
71 &Offset
, Is64Bit
? sizeof(Elf64_Xword
) : sizeof(Elf32_Word
));
72 SectionData
= SectionData
.substr(HdrSize
);
73 return Error::success();
76 bool Decompressor::isGnuStyle(StringRef Name
) {
77 return Name
.startswith(".zdebug");
80 bool Decompressor::isCompressed(const object::SectionRef
&Section
) {
82 if (Section
.getName(Name
))
84 return Section
.isCompressed() || isGnuStyle(Name
);
87 bool Decompressor::isCompressedELFSection(uint64_t Flags
, StringRef Name
) {
88 return (Flags
& ELF::SHF_COMPRESSED
) || isGnuStyle(Name
);
91 Error
Decompressor::decompress(MutableArrayRef
<char> Buffer
) {
92 size_t Size
= Buffer
.size();
93 return zlib::uncompress(SectionData
, Buffer
.data(), Size
);