Coverage Report

Created: 2017-09-19 22:28

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler.h
Line
Count
Source (jump to first uncovered line)
1
//===- lib/FileFormat/MachO/ArchHandler.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_ARCH_HANDLER_H
11
#define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
12
13
#include "Atoms.h"
14
#include "File.h"
15
#include "MachONormalizedFile.h"
16
#include "lld/Core/LLVM.h"
17
#include "lld/Core/Error.h"
18
#include "lld/Core/Reference.h"
19
#include "lld/Core/Simple.h"
20
#include "lld/ReaderWriter/MachOLinkingContext.h"
21
#include "llvm/ADT/Triple.h"
22
23
namespace lld {
24
namespace mach_o {
25
26
///
27
/// The ArchHandler class handles all architecture specific aspects of
28
/// mach-o linking.
29
///
30
class ArchHandler {
31
public:
32
  virtual ~ArchHandler();
33
34
  /// There is no public interface to subclasses of ArchHandler, so this
35
  /// is the only way to instantiate an ArchHandler.
36
  static std::unique_ptr<ArchHandler> create(MachOLinkingContext::Arch arch);
37
38
  /// Get (arch specific) kind strings used by Registry.
39
  virtual const Registry::KindStrings *kindStrings() = 0;
40
41
  /// Convert mach-o Arch to Reference::KindArch.
42
  virtual Reference::KindArch kindArch() = 0;
43
44
  /// Used by StubPass to update References to shared library functions
45
  /// to be references to a stub.
46
  virtual bool isCallSite(const Reference &) = 0;
47
48
  /// Used by GOTPass to locate GOT References
49
0
  virtual bool isGOTAccess(const Reference &, bool &canBypassGOT) {
50
0
    return false;
51
0
  }
52
53
  /// Used by TLVPass to locate TLV References.
54
217
  virtual bool isTLVAccess(const Reference &) const { return false; }
55
56
  /// Used by the TLVPass to update TLV References.
57
0
  virtual void updateReferenceToTLV(const Reference *) {}
58
59
  /// Used by ShimPass to insert shims in branches that switch mode.
60
  virtual bool isNonCallBranch(const Reference &) = 0;
61
62
  /// Used by GOTPass to update GOT References
63
0
  virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
64
65
  /// Does this architecture make use of __unwind_info sections for exception
66
  /// handling? If so, it will need a separate pass to create them.
67
  virtual bool needsCompactUnwind() = 0;
68
69
  /// Returns the kind of reference to use to synthesize a 32-bit image-offset
70
  /// value, used in the __unwind_info section.
71
  virtual Reference::KindValue imageOffsetKind() = 0;
72
73
  /// Returns the kind of reference to use to synthesize a 32-bit image-offset
74
  /// indirect value. Used for personality functions in the __unwind_info
75
  /// section.
76
  virtual Reference::KindValue imageOffsetKindIndirect() = 0;
77
78
  /// Architecture specific compact unwind type that signals __eh_frame should
79
  /// actually be used.
80
  virtual uint32_t dwarfCompactUnwindType() = 0;
81
82
  /// Reference from an __eh_frame CIE atom to its personality function it's
83
  /// describing. Usually pointer-sized and PC-relative, but differs in whether
84
  /// it needs to be in relocatable objects.
85
  virtual Reference::KindValue unwindRefToPersonalityFunctionKind() = 0;
86
87
  /// Reference from an __eh_frame FDE to the CIE it's based on.
88
  virtual Reference::KindValue unwindRefToCIEKind() = 0;
89
90
  /// Reference from an __eh_frame FDE atom to the function it's
91
  /// describing. Usually pointer-sized and PC-relative, but differs in whether
92
  /// it needs to be in relocatable objects.
93
  virtual Reference::KindValue unwindRefToFunctionKind() = 0;
94
95
  /// Reference from an __unwind_info entry of dwarfCompactUnwindType to the
96
  /// required __eh_frame entry. On current architectures, the low 24 bits
97
  /// represent the offset of the function's FDE entry from the start of
98
  /// __eh_frame.
99
  virtual Reference::KindValue unwindRefToEhFrameKind() = 0;
100
101
  /// Returns a pointer sized reference kind.  On 64-bit targets this will
102
  /// likely be something like pointer64, and pointer32 on 32-bit targets.
103
  virtual Reference::KindValue pointerKind() = 0;
104
105
  virtual const Atom *fdeTargetFunction(const DefinedAtom *fde);
106
107
  /// Used by normalizedFromAtoms() to know where to generated rebasing and
108
  /// binding info in final executables.
109
  virtual bool isPointer(const Reference &) = 0;
110
111
  /// Used by normalizedFromAtoms() to know where to generated lazy binding
112
  /// info in final executables.
113
  virtual bool isLazyPointer(const Reference &);
114
115
  /// Reference from an __stub_helper entry to the required offset of the
116
  /// lazy bind commands.
117
  virtual Reference::KindValue lazyImmediateLocationKind() = 0;
118
119
  /// Returns true if the specified relocation is paired to the next relocation.
120
  virtual bool isPairedReloc(const normalized::Relocation &) = 0;
121
122
  /// Prototype for a helper function.  Given a sectionIndex and address,
123
  /// finds the atom and offset with that atom of that address.
124
  typedef std::function<llvm::Error (uint32_t sectionIndex, uint64_t addr,
125
                        const lld::Atom **, Reference::Addend *)>
126
                        FindAtomBySectionAndAddress;
127
128
  /// Prototype for a helper function.  Given a symbolIndex, finds the atom
129
  /// representing that symbol.
130
  typedef std::function<llvm::Error (uint32_t symbolIndex,
131
                        const lld::Atom **)> FindAtomBySymbolIndex;
132
133
  /// Analyzes a relocation from a .o file and returns the info
134
  /// (kind, target, addend) needed to instantiate a Reference.
135
  /// Two helper functions are passed as parameters to find the target atom
136
  /// given a symbol index or address.
137
  virtual llvm::Error
138
          getReferenceInfo(const normalized::Relocation &reloc,
139
                           const DefinedAtom *inAtom,
140
                           uint32_t offsetInAtom,
141
                           uint64_t fixupAddress, bool isBigEndian,
142
                           FindAtomBySectionAndAddress atomFromAddress,
143
                           FindAtomBySymbolIndex atomFromSymbolIndex,
144
                           Reference::KindValue *kind,
145
                           const lld::Atom **target,
146
                           Reference::Addend *addend) = 0;
147
148
  /// Analyzes a pair of relocations from a .o file and returns the info
149
  /// (kind, target, addend) needed to instantiate a Reference.
150
  /// Two helper functions are passed as parameters to find the target atom
151
  /// given a symbol index or address.
152
  virtual llvm::Error
153
      getPairReferenceInfo(const normalized::Relocation &reloc1,
154
                           const normalized::Relocation &reloc2,
155
                           const DefinedAtom *inAtom,
156
                           uint32_t offsetInAtom,
157
                           uint64_t fixupAddress, bool isBig, bool scatterable,
158
                           FindAtomBySectionAndAddress atomFromAddress,
159
                           FindAtomBySymbolIndex atomFromSymbolIndex,
160
                           Reference::KindValue *kind,
161
                           const lld::Atom **target,
162
                           Reference::Addend *addend) = 0;
163
164
  /// Prototype for a helper function.  Given an atom, finds the symbol table
165
  /// index for it in the output file.
166
  typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
167
168
  /// Prototype for a helper function.  Given an atom, finds the index
169
  /// of the section that will contain the atom.
170
  typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
171
172
  /// Prototype for a helper function.  Given an atom, finds the address
173
  /// assigned to it in the output file.
174
  typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
175
176
  /// Some architectures require local symbols on anonymous atoms.
177
19
  virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
178
19
    return false;
179
19
  }
180
181
  /// Copy raw content then apply all fixup References on an Atom.
182
  virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
183
                                   FindAddressForAtom findAddress,
184
                                   FindAddressForAtom findSectionAddress,
185
                                   uint64_t imageBaseAddress,
186
                          llvm::MutableArrayRef<uint8_t> atomContentBuffer) = 0;
187
188
  /// Used in -r mode to convert a Reference to a mach-o relocation.
189
  virtual void appendSectionRelocations(const DefinedAtom &atom,
190
                                        uint64_t atomSectionOffset,
191
                                        const Reference &ref,
192
                                        FindSymbolIndexForAtom,
193
                                        FindSectionIndexForAtom,
194
                                        FindAddressForAtom,
195
                                        normalized::Relocations&) = 0;
196
197
  /// Add arch-specific References.
198
444
  virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
199
200
  // Add Reference for data-in-code marker.
201
  virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
202
0
                                      uint16_t length, uint16_t kind) { }
203
204
  /// Returns true if the specificed Reference value marks the start or end
205
  /// of a data-in-code range in an atom.
206
487
  virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
207
487
    return false;
208
487
  }
209
210
  /// Returns the Reference value for a Reference that marks that start of
211
  /// a data-in-code range.
212
  virtual Reference::KindValue dataInCodeTransitionStart(
213
0
                                                const MachODefinedAtom &atom) {
214
0
    return 0;
215
0
  }
216
217
  /// Returns the Reference value for a Reference that marks that end of
218
  /// a data-in-code range.
219
  virtual Reference::KindValue dataInCodeTransitionEnd(
220
0
                                                const MachODefinedAtom &atom) {
221
0
    return 0;
222
0
  }
223
224
  /// Only relevant for 32-bit arm archs.
225
558
  virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
226
227
  /// Only relevant for 32-bit arm archs.
228
  virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
229
0
                                        const DefinedAtom &) {
230
0
    llvm_unreachable("shims only support on arm");
231
0
  }
232
233
  /// Does a given unwind-cfi atom represent a CIE (as opposed to an FDE).
234
  static bool isDwarfCIE(bool isBig, const DefinedAtom *atom);
235
236
  struct ReferenceInfo {
237
    Reference::KindArch arch;
238
    uint16_t            kind;
239
    uint32_t            offset;
240
    int32_t             addend;
241
  };
242
243
  struct OptionalRefInfo {
244
    bool                used;
245
    uint16_t            kind;
246
    uint32_t            offset;
247
    int32_t             addend;
248
  };
249
250
  /// Table of architecture specific information for creating stubs.
251
  struct StubInfo {
252
    const char*     binderSymbolName;
253
    ReferenceInfo   lazyPointerReferenceToHelper;
254
    ReferenceInfo   lazyPointerReferenceToFinal;
255
    ReferenceInfo   nonLazyPointerReferenceToBinder;
256
    uint8_t         codeAlignment;
257
258
    uint32_t        stubSize;
259
    uint8_t         stubBytes[16];
260
    ReferenceInfo   stubReferenceToLP;
261
    OptionalRefInfo optStubReferenceToLP;
262
263
    uint32_t        stubHelperSize;
264
    uint8_t         stubHelperBytes[16];
265
    ReferenceInfo   stubHelperReferenceToImm;
266
    ReferenceInfo   stubHelperReferenceToHelperCommon;
267
268
    DefinedAtom::ContentType stubHelperImageCacheContentType;
269
270
    uint32_t        stubHelperCommonSize;
271
    uint8_t         stubHelperCommonAlignment;
272
    uint8_t         stubHelperCommonBytes[36];
273
    ReferenceInfo   stubHelperCommonReferenceToCache;
274
    OptionalRefInfo optStubHelperCommonReferenceToCache;
275
    ReferenceInfo   stubHelperCommonReferenceToBinder;
276
    OptionalRefInfo optStubHelperCommonReferenceToBinder;
277
  };
278
279
  virtual const StubInfo &stubInfo() = 0;
280
281
protected:
282
  ArchHandler();
283
284
  static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
285
  static std::unique_ptr<mach_o::ArchHandler> create_x86();
286
  static std::unique_ptr<mach_o::ArchHandler> create_arm();
287
  static std::unique_ptr<mach_o::ArchHandler> create_arm64();
288
289
  // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
290
  typedef uint16_t RelocPattern;
291
  enum {
292
    rScattered = 0x8000,
293
    rPcRel     = 0x4000,
294
    rExtern    = 0x2000,
295
    rLength1   = 0x0000,
296
    rLength2   = 0x0100,
297
    rLength4   = 0x0200,
298
    rLength8   = 0x0300,
299
    rLenArmLo  = rLength1,
300
    rLenArmHi  = rLength2,
301
    rLenThmbLo = rLength4,
302
    rLenThmbHi = rLength8
303
  };
304
  /// Extract RelocPattern from normalized mach-o relocation.
305
  static RelocPattern relocPattern(const normalized::Relocation &reloc);
306
  /// Create normalized Relocation initialized from pattern.
307
  static normalized::Relocation relocFromPattern(RelocPattern pattern);
308
  /// One liner to add a relocation.
309
  static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
310
                          uint32_t symbol, uint32_t value,
311
                          RelocPattern pattern);
312
313
314
  static int16_t  readS16(const uint8_t *addr, bool isBig);
315
  static int32_t  readS32(const uint8_t *addr, bool isBig);
316
  static uint32_t readU32(const uint8_t *addr, bool isBig);
317
  static int64_t  readS64(const uint8_t *addr, bool isBig);
318
};
319
320
} // namespace mach_o
321
} // namespace lld
322
323
#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H