Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h
Line
Count
Source (jump to first uncovered line)
1
//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h ------------===//
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
#ifndef LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
10
#define LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
11
12
#include "MachONormalizedFile.h"
13
#include "lld/Common/LLVM.h"
14
#include "lld/Core/Error.h"
15
#include "llvm/ADT/StringRef.h"
16
#include "llvm/BinaryFormat/MachO.h"
17
#include "llvm/Support/Casting.h"
18
#include "llvm/Support/Endian.h"
19
#include "llvm/Support/ErrorHandling.h"
20
#include "llvm/Support/Host.h"
21
#include "llvm/Support/LEB128.h"
22
#include <system_error>
23
24
namespace lld {
25
namespace mach_o {
26
namespace normalized {
27
28
class ByteBuffer {
29
public:
30
1.83k
  ByteBuffer() : _ostream(_bytes) { }
31
32
4.61k
  void append_byte(uint8_t b) {
33
4.61k
    _ostream << b;
34
4.61k
  }
35
932
  void append_uleb128(uint64_t value) {
36
932
    llvm::encodeULEB128(value, _ostream);
37
932
  }
38
0
  void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
39
0
    unsigned min = llvm::getULEB128Size(value);
40
0
    assert(min <= byteCount);
41
0
    unsigned pad = byteCount - min;
42
0
    llvm::encodeULEB128(value, _ostream, pad);
43
0
  }
44
0
  void append_sleb128(int64_t value) {
45
0
    llvm::encodeSLEB128(value, _ostream);
46
0
  }
47
332
  void append_string(StringRef str) {
48
332
    _ostream << str;
49
332
    append_byte(0);
50
332
  }
51
669
  void align(unsigned alignment) {
52
3.49k
    while ( (_ostream.tell() % alignment) != 0 )
53
2.82k
      append_byte(0);
54
669
  }
55
2.04k
  size_t size() {
56
2.04k
    return _ostream.tell();
57
2.04k
  }
58
640
  const uint8_t *bytes() {
59
640
    return reinterpret_cast<const uint8_t*>(_ostream.str().data());
60
640
  }
61
62
private:
63
  SmallVector<char, 128>        _bytes;
64
  // Stream ivar must be after SmallVector ivar to construct properly.
65
  llvm::raw_svector_ostream     _ostream;
66
};
67
68
using namespace llvm::support::endian;
69
using llvm::sys::getSwappedBytes;
70
71
template<typename T>
72
20
static inline uint16_t read16(const T *loc, bool isBig) {
73
20
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
74
20
  return isBig ? 
read16be(loc)0
: read16le(loc);
75
20
}
Unexecuted instantiation: ArchHandler.cpp:unsigned short lld::mach_o::normalized::read16<unsigned char>(unsigned char const*, bool)
MachONormalizedFileBinaryReader.cpp:unsigned short lld::mach_o::normalized::read16<unsigned short>(unsigned short const*, bool)
Line
Count
Source
72
10
static inline uint16_t read16(const T *loc, bool isBig) {
73
10
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
74
10
  return isBig ? 
read16be(loc)0
: read16le(loc);
75
10
}
MachONormalizedFileBinaryReader.cpp:unsigned short lld::mach_o::normalized::read16<unsigned char>(unsigned char const*, bool)
Line
Count
Source
72
10
static inline uint16_t read16(const T *loc, bool isBig) {
73
10
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
74
10
  return isBig ? 
read16be(loc)0
: read16le(loc);
75
10
}
76
77
template<typename T>
78
1.91k
static inline uint32_t read32(const T *loc, bool isBig) {
79
1.91k
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
80
1.91k
  return isBig ? 
read32be(loc)95
:
read32le(loc)1.81k
;
81
1.91k
}
ArchHandler.cpp:unsigned int lld::mach_o::normalized::read32<unsigned char>(unsigned char const*, bool)
Line
Count
Source
78
140
static inline uint32_t read32(const T *loc, bool isBig) {
79
140
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
80
140
  return isBig ? 
read32be(loc)0
: read32le(loc);
81
140
}
Unexecuted instantiation: ArchHandler.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
Unexecuted instantiation: ArchHandler_arm.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
Unexecuted instantiation: ArchHandler_arm64.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
Unexecuted instantiation: ArchHandler_x86.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
Unexecuted instantiation: ArchHandler_x86_64.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
CompactUnwindPass.cpp:unsigned int lld::mach_o::normalized::read32<unsigned char>(unsigned char const*, bool)
Line
Count
Source
78
28
static inline uint32_t read32(const T *loc, bool isBig) {
79
28
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
80
28
  return isBig ? 
read32be(loc)0
: read32le(loc);
81
28
}
Unexecuted instantiation: CompactUnwindPass.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
MachONormalizedFileBinaryReader.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
Line
Count
Source
78
1.49k
static inline uint32_t read32(const T *loc, bool isBig) {
79
1.49k
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
80
1.49k
  return isBig ? 
read32be(loc)87
:
read32le(loc)1.40k
;
81
1.49k
}
MachONormalizedFileBinaryReader.cpp:unsigned int lld::mach_o::normalized::read32<unsigned char>(unsigned char const*, bool)
Line
Count
Source
78
101
static inline uint32_t read32(const T *loc, bool isBig) {
79
101
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
80
101
  return isBig ? 
read32be(loc)8
:
read32le(loc)93
;
81
101
}
Unexecuted instantiation: MachONormalizedFileBinaryWriter.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
Unexecuted instantiation: MachONormalizedFileFromAtoms.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
MachONormalizedFileToAtoms.cpp:unsigned int lld::mach_o::normalized::read32<unsigned char>(unsigned char const*, bool)
Line
Count
Source
78
145
static inline uint32_t read32(const T *loc, bool isBig) {
79
145
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
80
145
  return isBig ? 
read32be(loc)0
: read32le(loc);
81
145
}
Unexecuted instantiation: MachONormalizedFileToAtoms.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
Unexecuted instantiation: ObjCPass.cpp:unsigned int lld::mach_o::normalized::read32<unsigned int>(unsigned int const*, bool)
82
83
template<typename T>
84
156
static inline uint64_t read64(const T *loc, bool isBig) {
85
156
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
86
156
  return isBig ? 
read64be(loc)0
: read64le(loc);
87
156
}
Unexecuted instantiation: ArchHandler.cpp:unsigned long long lld::mach_o::normalized::read64<unsigned char>(unsigned char const*, bool)
MachONormalizedFileBinaryReader.cpp:unsigned long long lld::mach_o::normalized::read64<unsigned long long>(unsigned long long const*, bool)
Line
Count
Source
84
126
static inline uint64_t read64(const T *loc, bool isBig) {
85
126
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
86
126
  return isBig ? 
read64be(loc)0
: read64le(loc);
87
126
}
MachONormalizedFileToAtoms.cpp:unsigned long long lld::mach_o::normalized::read64<unsigned char>(unsigned char const*, bool)
Line
Count
Source
84
30
static inline uint64_t read64(const T *loc, bool isBig) {
85
30
  assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
86
30
  return isBig ? 
read64be(loc)0
: read64le(loc);
87
30
}
88
89
20
inline void write16(uint8_t *loc, uint16_t value, bool isBig) {
90
20
  if (isBig)
91
0
    write16be(loc, value);
92
20
  else
93
20
    write16le(loc, value);
94
20
}
95
96
137
inline void write32(uint8_t *loc, uint32_t value, bool isBig) {
97
137
  if (isBig)
98
0
    write32be(loc, value);
99
137
  else
100
137
    write32le(loc, value);
101
137
}
102
103
0
inline void write64(uint8_t *loc, uint64_t value, bool isBig) {
104
0
  if (isBig)
105
0
    write64be(loc, value);
106
0
  else
107
0
    write64le(loc, value);
108
0
}
109
110
inline uint32_t
111
bitFieldExtract(uint32_t value, bool isBigEndianBigField, uint8_t firstBit,
112
1.36k
                                                          uint8_t bitCount) {
113
1.36k
  const uint32_t mask = ((1<<bitCount)-1);
114
1.36k
  const uint8_t shift = isBigEndianBigField ? 
(32-firstBit-bitCount)403
:
firstBit965
;
115
1.36k
  return (value >> shift) & mask;
116
1.36k
}
117
118
inline void
119
bitFieldSet(uint32_t &bits, bool isBigEndianBigField, uint32_t newBits,
120
2.47k
                            uint8_t firstBit, uint8_t bitCount) {
121
2.47k
  const uint32_t mask = ((1<<bitCount)-1);
122
2.47k
  assert((newBits & mask) == newBits);
123
2.47k
  const uint8_t shift = isBigEndianBigField ? 
(32-firstBit-bitCount)740
:
firstBit1.73k
;
124
2.47k
  bits &= ~(mask << shift);
125
2.47k
  bits |= (newBits << shift);
126
2.47k
}
127
128
inline Relocation unpackRelocation(const llvm::MachO::any_relocation_info &r,
129
291
                                   bool isBigEndian) {
130
291
  uint32_t r0 = read32(&r.r_word0, isBigEndian);
131
291
  uint32_t r1 = read32(&r.r_word1, isBigEndian);
132
291
133
291
  Relocation result;
134
291
  if (r0 & llvm::MachO::R_SCATTERED) {
135
87
    // scattered relocation record always laid out like big endian bit field
136
87
    result.offset     = bitFieldExtract(r0, true, 8, 24);
137
87
    result.scattered  = true;
138
87
    result.type       = (RelocationInfoType)
139
87
                        bitFieldExtract(r0, true, 4, 4);
140
87
    result.length     = bitFieldExtract(r0, true, 2, 2);
141
87
    result.pcRel      = bitFieldExtract(r0, true, 1, 1);
142
87
    result.isExtern   = false;
143
87
    result.value      = r1;
144
87
    result.symbol     = 0;
145
204
  } else {
146
204
    result.offset     = r0;
147
204
    result.scattered  = false;
148
204
    result.type       = (RelocationInfoType)
149
204
                        bitFieldExtract(r1, isBigEndian, 28, 4);
150
204
    result.length     = bitFieldExtract(r1, isBigEndian, 25, 2);
151
204
    result.pcRel      = bitFieldExtract(r1, isBigEndian, 24, 1);
152
204
    result.isExtern   = bitFieldExtract(r1, isBigEndian, 27, 1);
153
204
    result.value      = 0;
154
204
    result.symbol     = bitFieldExtract(r1, isBigEndian, 0, 24);
155
204
  }
156
291
  return result;
157
291
}
158
159
160
inline llvm::MachO::any_relocation_info
161
494
packRelocation(const Relocation &r, bool swap, bool isBigEndian) {
162
494
  uint32_t r0 = 0;
163
494
  uint32_t r1 = 0;
164
494
165
494
  if (r.scattered) {
166
137
    r1 = r.value;
167
137
    bitFieldSet(r0, true, r.offset,    8, 24);
168
137
    bitFieldSet(r0, true, r.type,      4, 4);
169
137
    bitFieldSet(r0, true, r.length,    2, 2);
170
137
    bitFieldSet(r0, true, r.pcRel,     1, 1);
171
137
    bitFieldSet(r0, true, r.scattered, 0, 1); // R_SCATTERED
172
357
  } else {
173
357
    r0 = r.offset;
174
357
    bitFieldSet(r1, isBigEndian, r.type,     28, 4);
175
357
    bitFieldSet(r1, isBigEndian, r.isExtern, 27, 1);
176
357
    bitFieldSet(r1, isBigEndian, r.length,   25, 2);
177
357
    bitFieldSet(r1, isBigEndian, r.pcRel,    24, 1);
178
357
    bitFieldSet(r1, isBigEndian, r.symbol,   0,  24);
179
357
  }
180
494
181
494
  llvm::MachO::any_relocation_info result;
182
494
  result.r_word0 = swap ? 
getSwappedBytes(r0)23
:
r0471
;
183
494
  result.r_word1 = swap ? 
getSwappedBytes(r1)23
:
r1471
;
184
494
  return result;
185
494
}
186
187
172
inline StringRef getString16(const char s[16]) {
188
172
  // The StringRef(const char *) constructor passes the const char * to
189
172
  // strlen(), so we can't use this constructor here, because if there is no
190
172
  // null terminator in s, then strlen() will read past the end of the array.
191
172
  return StringRef(s, strnlen(s, 16));
192
172
}
193
194
1.04k
inline void setString16(StringRef str, char s[16]) {
195
1.04k
  memset(s, 0, 16);
196
1.04k
  memcpy(s, str.begin(), (str.size() > 16) ? 
160
: str.size());
197
1.04k
}
198
199
// Implemented in normalizedToAtoms() and used by normalizedFromAtoms() so
200
// that the same table can be used to map mach-o sections to and from
201
// DefinedAtom::ContentType.
202
void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
203
                                          StringRef &segmentName,
204
                                          StringRef &sectionName,
205
                                          SectionType &sectionType,
206
                                          SectionAttr &sectionAttrs,
207
                                          bool &relocsToDefinedCanBeImplicit);
208
209
} // namespace normalized
210
} // namespace mach_o
211
} // namespace lld
212
213
#endif // LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H