Coverage Report

Created: 2018-01-17 17:22

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h
Line
Count
Source
1
//===- lib/ReaderWriter/MachO/MachONormalizedFile.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
///
11
/// \file These data structures comprise the "normalized" view of
12
/// mach-o object files. The normalized view is an in-memory only data structure
13
/// which is always in native endianness and pointer size.
14
///
15
/// The normalized view easily converts to and from YAML using YAML I/O.
16
///
17
/// The normalized view converts to and from binary mach-o object files using
18
/// the writeBinary() and readBinary() functions.
19
///
20
/// The normalized view converts to and from lld::Atoms using the
21
/// normalizedToAtoms() and normalizedFromAtoms().
22
///
23
/// Overall, the conversion paths available look like:
24
///
25
///                 +---------------+
26
///                 | binary mach-o |
27
///                 +---------------+
28
///                        ^
29
///                        |
30
///                        v
31
///                  +------------+         +------+
32
///                  | normalized |   <->   | yaml |
33
///                  +------------+         +------+
34
///                        ^
35
///                        |
36
///                        v
37
///                    +-------+
38
///                    | Atoms |
39
///                    +-------+
40
///
41
42
#ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
43
#define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
44
45
#include "DebugInfo.h"
46
#include "lld/Common/LLVM.h"
47
#include "lld/Core/Error.h"
48
#include "lld/ReaderWriter/MachOLinkingContext.h"
49
#include "llvm/ADT/SmallString.h"
50
#include "llvm/ADT/StringRef.h"
51
#include "llvm/BinaryFormat/MachO.h"
52
#include "llvm/Support/Allocator.h"
53
#include "llvm/Support/Debug.h"
54
#include "llvm/Support/ErrorOr.h"
55
#include "llvm/Support/YAMLTraits.h"
56
57
using llvm::BumpPtrAllocator;
58
using llvm::yaml::Hex64;
59
using llvm::yaml::Hex32;
60
using llvm::yaml::Hex16;
61
using llvm::yaml::Hex8;
62
using llvm::yaml::SequenceTraits;
63
using llvm::MachO::HeaderFileType;
64
using llvm::MachO::BindType;
65
using llvm::MachO::RebaseType;
66
using llvm::MachO::NListType;
67
using llvm::MachO::RelocationInfoType;
68
using llvm::MachO::SectionType;
69
using llvm::MachO::LoadCommandType;
70
using llvm::MachO::ExportSymbolKind;
71
using llvm::MachO::DataRegionType;
72
73
namespace lld {
74
namespace mach_o {
75
namespace normalized {
76
77
78
/// The real mach-o relocation record is 8-bytes on disk and is
79
/// encoded in one of two different bit-field patterns.  This
80
/// normalized form has the union of all possible fields.
81
struct Relocation {
82
  Relocation() : offset(0), scattered(false),
83
                 type(llvm::MachO::GENERIC_RELOC_VANILLA),
84
                 length(0), pcRel(false), isExtern(false), value(0),
85
1.19k
                 symbol(0) { }
86
87
  Hex32               offset;
88
  bool                scattered;
89
  RelocationInfoType  type;
90
  uint8_t             length;
91
  bool                pcRel;
92
  bool                isExtern;
93
  Hex32               value;
94
  uint32_t            symbol;
95
};
96
97
/// A typedef so that YAML I/O can treat this vector as a sequence.
98
typedef std::vector<Relocation> Relocations;
99
100
/// A typedef so that YAML I/O can process the raw bytes in a section.
101
typedef std::vector<Hex8> ContentBytes;
102
103
/// A typedef so that YAML I/O can treat indirect symbols as a flow sequence.
104
typedef std::vector<uint32_t> IndirectSymbols;
105
106
/// A typedef so that YAML I/O can encode/decode section attributes.
107
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionAttr)
108
109
/// A typedef so that YAML I/O can encode/decode section alignment.
110
LLVM_YAML_STRONG_TYPEDEF(uint16_t, SectionAlignment)
111
112
/// Mach-O has a 32-bit and 64-bit section record.  This normalized form
113
/// can support either kind.
114
struct Section {
115
  Section() : type(llvm::MachO::S_REGULAR),
116
739
              attributes(0), alignment(1), address(0) { }
117
118
  StringRef       segmentName;
119
  StringRef       sectionName;
120
  SectionType     type;
121
  SectionAttr     attributes;
122
  SectionAlignment        alignment;
123
  Hex64           address;
124
  ArrayRef<uint8_t> content;
125
  Relocations     relocations;
126
  IndirectSymbols indirectSymbols;
127
};
128
129
130
/// A typedef so that YAML I/O can encode/decode the scope bits of an nlist.
131
LLVM_YAML_STRONG_TYPEDEF(uint8_t, SymbolScope)
132
133
/// A typedef so that YAML I/O can encode/decode the desc bits of an nlist.
134
LLVM_YAML_STRONG_TYPEDEF(uint16_t, SymbolDesc)
135
136
/// Mach-O has a 32-bit and 64-bit symbol table entry (nlist), and the symbol
137
/// type and scope and mixed in the same n_type field.  This normalized form
138
/// works for any pointer size and separates out the type and scope.
139
struct Symbol {
140
1.23k
  Symbol() : type(llvm::MachO::N_UNDF), scope(0), sect(0), desc(0), value(0) { }
141
142
  StringRef     name;
143
  NListType     type;
144
  SymbolScope   scope;
145
  uint8_t       sect;
146
  SymbolDesc    desc;
147
  Hex64         value;
148
};
149
150
/// Check whether the given section type indicates a zero-filled section.
151
// FIXME: Utility functions of this kind should probably be moved into
152
//        llvm/Support.
153
2.37k
inline bool isZeroFillSection(SectionType T) {
154
2.37k
  return (T == llvm::MachO::S_ZEROFILL ||
155
2.37k
          
T == llvm::MachO::S_THREAD_LOCAL_ZEROFILL2.35k
);
156
2.37k
}
157
158
/// A typedef so that YAML I/O can (de/en)code the protection bits of a segment.
159
LLVM_YAML_STRONG_TYPEDEF(uint32_t, VMProtect)
160
161
/// A typedef to hold verions X.Y.X packed into 32-bit xxxx.yy.zz
162
LLVM_YAML_STRONG_TYPEDEF(uint32_t, PackedVersion)
163
164
/// Segments are only used in normalized final linked images (not in relocatable
165
/// object files). They specify how a range of the file is loaded.
166
struct Segment {
167
  StringRef     name;
168
  Hex64         address;
169
  Hex64         size;
170
  VMProtect     init_access;
171
  VMProtect     max_access;
172
};
173
174
/// Only used in normalized final linked images to specify on which dylibs
175
/// it depends.
176
struct DependentDylib {
177
  StringRef       path;
178
  LoadCommandType kind;
179
  PackedVersion   compatVersion;
180
  PackedVersion   currentVersion;
181
};
182
183
/// A normalized rebasing entry.  Only used in normalized final linked images.
184
struct RebaseLocation {
185
  Hex32         segOffset;
186
  uint8_t       segIndex;
187
  RebaseType    kind;
188
};
189
190
/// A normalized binding entry.  Only used in normalized final linked images.
191
struct BindLocation {
192
  Hex32           segOffset;
193
  uint8_t         segIndex;
194
  BindType        kind;
195
  bool            canBeNull;
196
  int             ordinal;
197
  StringRef       symbolName;
198
  Hex64           addend;
199
};
200
201
/// A typedef so that YAML I/O can encode/decode export flags.
202
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportFlags)
203
204
/// A normalized export entry.  Only used in normalized final linked images.
205
struct Export {
206
  StringRef         name;
207
  Hex64             offset;
208
  ExportSymbolKind  kind;
209
  ExportFlags       flags;
210
  Hex32             otherOffset;
211
  StringRef         otherName;
212
};
213
214
/// A normalized data-in-code entry.
215
struct DataInCode {
216
  Hex32           offset;
217
  Hex16           length;
218
  DataRegionType  kind;
219
};
220
221
/// A typedef so that YAML I/O can encode/decode mach_header.flags.
222
LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags)
223
224
///
225
struct NormalizedFile {
226
  MachOLinkingContext::Arch   arch = MachOLinkingContext::arch_unknown;
227
  HeaderFileType              fileType = llvm::MachO::MH_OBJECT;
228
  FileFlags                   flags = 0;
229
  std::vector<Segment>        segments; // Not used in object files.
230
  std::vector<Section>        sections;
231
232
  // Symbols sorted by kind.
233
  std::vector<Symbol>         localSymbols;
234
  std::vector<Symbol>         globalSymbols;
235
  std::vector<Symbol>         undefinedSymbols;
236
  std::vector<Symbol>         stabsSymbols;
237
238
  // Maps to load commands with no LINKEDIT content (final linked images only).
239
  std::vector<DependentDylib> dependentDylibs;
240
  StringRef                   installName;        // dylibs only
241
  PackedVersion               compatVersion = 0;  // dylibs only
242
  PackedVersion               currentVersion = 0; // dylibs only
243
  bool                        hasUUID = false;
244
  bool                        hasMinVersionLoadCommand = false;
245
  bool                        generateDataInCodeLoadCommand = false;
246
  std::vector<StringRef>      rpaths;
247
  Hex64                       entryAddress = 0;
248
  Hex64                       stackSize = 0;
249
  MachOLinkingContext::OS     os = MachOLinkingContext::OS::unknown;
250
  Hex64                       sourceVersion = 0;
251
  PackedVersion               minOSverson = 0;
252
  PackedVersion               sdkVersion = 0;
253
  LoadCommandType             minOSVersionKind = (LoadCommandType)0;
254
255
  // Maps to load commands with LINKEDIT content (final linked images only).
256
  Hex32                       pageSize = 0;
257
  std::vector<RebaseLocation> rebasingInfo;
258
  std::vector<BindLocation>   bindingInfo;
259
  std::vector<BindLocation>   weakBindingInfo;
260
  std::vector<BindLocation>   lazyBindingInfo;
261
  std::vector<Export>         exportInfo;
262
  std::vector<uint8_t>        functionStarts;
263
  std::vector<DataInCode>     dataInCode;
264
265
  // TODO:
266
  // code-signature
267
  // split-seg-info
268
  // function-starts
269
270
  // For any allocations in this struct which need to be owned by this struct.
271
  BumpPtrAllocator            ownedAllocations;
272
};
273
274
/// Tests if a file is a non-fat mach-o object file.
275
bool isThinObjectFile(StringRef path, MachOLinkingContext::Arch &arch);
276
277
/// If the buffer is a fat file with the request arch, then this function
278
/// returns true with 'offset' and 'size' set to location of the arch slice
279
/// within the buffer.  Otherwise returns false;
280
bool sliceFromFatFile(MemoryBufferRef mb, MachOLinkingContext::Arch arch,
281
                      uint32_t &offset, uint32_t &size);
282
283
/// Reads a mach-o file and produces an in-memory normalized view.
284
llvm::Expected<std::unique_ptr<NormalizedFile>>
285
readBinary(std::unique_ptr<MemoryBuffer> &mb,
286
           const MachOLinkingContext::Arch arch);
287
288
/// Takes in-memory normalized view and writes a mach-o object file.
289
llvm::Error writeBinary(const NormalizedFile &file, StringRef path);
290
291
size_t headerAndLoadCommandsSize(const NormalizedFile &file);
292
293
294
/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
295
llvm::Expected<std::unique_ptr<NormalizedFile>>
296
readYaml(std::unique_ptr<MemoryBuffer> &mb);
297
298
/// Writes a yaml encoded mach-o files given an in-memory normalized view.
299
std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out);
300
301
llvm::Error
302
normalizedObjectToAtoms(MachOFile *file,
303
                        const NormalizedFile &normalizedFile,
304
                        bool copyRefs);
305
306
llvm::Error
307
normalizedDylibToAtoms(MachODylibFile *file,
308
                       const NormalizedFile &normalizedFile,
309
                       bool copyRefs);
310
311
/// Takes in-memory normalized dylib or object and parses it into lld::File
312
llvm::Expected<std::unique_ptr<lld::File>>
313
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
314
                  bool copyRefs);
315
316
/// Takes atoms and generates a normalized macho-o view.
317
llvm::Expected<std::unique_ptr<NormalizedFile>>
318
normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext &ctxt);
319
320
321
} // namespace normalized
322
323
/// Class for interfacing mach-o yaml files into generic yaml parsing
324
class MachOYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
325
public:
326
  MachOYamlIOTaggedDocumentHandler(MachOLinkingContext::Arch arch)
327
223
    : _arch(arch) { }
328
  bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override;
329
private:
330
  const MachOLinkingContext::Arch _arch;
331
};
332
333
} // namespace mach_o
334
} // namespace lld
335
336
#endif // LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H