annotate lib/Object/Decompressor.cpp @ 128:c347d3398279 default tip

fix
author mir3636
date Wed, 06 Dec 2017 14:37:17 +0900
parents 803732b1fca8
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
121
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
1 //===-- Decompressor.cpp --------------------------------------------------===//
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
2 //
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
3 // The LLVM Compiler Infrastructure
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
4 //
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
5 // This file is distributed under the University of Illinois Open Source
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
6 // License. See LICENSE.TXT for details.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
7 //
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
8 //===----------------------------------------------------------------------===//
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
9
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
10 #include "llvm/Object/Decompressor.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
11 #include "llvm/BinaryFormat/ELF.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
12 #include "llvm/Object/ELFObjectFile.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
13 #include "llvm/Support/Compression.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
14 #include "llvm/Support/DataExtractor.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
15 #include "llvm/Support/Endian.h"
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
16
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
17 using namespace llvm;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
18 using namespace llvm::support::endian;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
19 using namespace object;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
20
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
21 Expected<Decompressor> Decompressor::create(StringRef Name, StringRef Data,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
22 bool IsLE, bool Is64Bit) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
23 if (!zlib::isAvailable())
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
24 return createError("zlib is not available");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
25
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
26 Decompressor D(Data);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
27 Error Err = isGnuStyle(Name) ? D.consumeCompressedGnuHeader()
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
28 : D.consumeCompressedZLibHeader(Is64Bit, IsLE);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
29 if (Err)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
30 return std::move(Err);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
31 return D;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
32 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
33
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
34 Decompressor::Decompressor(StringRef Data)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
35 : SectionData(Data), DecompressedSize(0) {}
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
36
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
37 Error Decompressor::consumeCompressedGnuHeader() {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
38 if (!SectionData.startswith("ZLIB"))
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
39 return createError("corrupted compressed section header");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
40
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
41 SectionData = SectionData.substr(4);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
42
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
43 // Consume uncompressed section size (big-endian 8 bytes).
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
44 if (SectionData.size() < 8)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
45 return createError("corrupted uncompressed section size");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
46 DecompressedSize = read64be(SectionData.data());
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
47 SectionData = SectionData.substr(8);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
48
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
49 return Error::success();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
50 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
51
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
52 Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit,
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
53 bool IsLittleEndian) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
54 using namespace ELF;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
55 uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
56 if (SectionData.size() < HdrSize)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
57 return createError("corrupted compressed section header");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
58
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
59 DataExtractor Extractor(SectionData, IsLittleEndian, 0);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
60 uint32_t Offset = 0;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
61 if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
62 : sizeof(Elf32_Word)) !=
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
63 ELFCOMPRESS_ZLIB)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
64 return createError("unsupported compression type");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
65
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
66 // Skip Elf64_Chdr::ch_reserved field.
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
67 if (Is64Bit)
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
68 Offset += sizeof(Elf64_Word);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
69
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
70 DecompressedSize = Extractor.getUnsigned(
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
71 &Offset, Is64Bit ? sizeof(Elf64_Xword) : sizeof(Elf32_Word));
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
72 SectionData = SectionData.substr(HdrSize);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
73 return Error::success();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
74 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
75
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
76 bool Decompressor::isGnuStyle(StringRef Name) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
77 return Name.startswith(".zdebug");
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
78 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
79
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
80 bool Decompressor::isCompressed(const object::SectionRef &Section) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
81 StringRef Name;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
82 if (Section.getName(Name))
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
83 return false;
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
84 return Section.isCompressed() || isGnuStyle(Name);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
85 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
86
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
87 bool Decompressor::isCompressedELFSection(uint64_t Flags, StringRef Name) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
88 return (Flags & ELF::SHF_COMPRESSED) || isGnuStyle(Name);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
89 }
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
90
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
91 Error Decompressor::decompress(MutableArrayRef<char> Buffer) {
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
92 size_t Size = Buffer.size();
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
93 return zlib::uncompress(SectionData, Buffer.data(), Size);
803732b1fca8 LLVM 5.0
kono
parents:
diff changeset
94 }