Coverage Report

Created: 2018-01-17 21:32

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