Coverage Report

Created: 2019-07-24 05:18

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