blob: 70a63bd1004b3f2b0cdff0b7a89687fa338f175a [file] [log] [blame]
Nick Kledzik2458bec2014-07-16 19:49:02 +00001//===- 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
Pete Cooperd75b7182016-02-08 21:50:45 +000010#ifndef LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
11#define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
12
Nick Kledzik7e9808f2014-07-23 00:51:37 +000013#include "Atoms.h"
Nick Kledzik4121bce2014-10-14 01:51:42 +000014#include "File.h"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000015#include "MachONormalizedFile.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000016#include "lld/Core/LLVM.h"
Pete Cooper1e009112016-03-30 20:15:06 +000017#include "lld/Core/Error.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000018#include "lld/Core/Reference.h"
19#include "lld/Core/Simple.h"
20#include "lld/ReaderWriter/MachOLinkingContext.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000021#include "llvm/ADT/Triple.h"
22
Nick Kledzik2458bec2014-07-16 19:49:02 +000023namespace lld {
24namespace mach_o {
25
26///
27/// The ArchHandler class handles all architecture specific aspects of
28/// mach-o linking.
29///
30class ArchHandler {
31public:
32 virtual ~ArchHandler();
Shankar Easwarana1d36372015-02-22 23:54:38 +000033
Nick Kledzik2458bec2014-07-16 19:49:02 +000034 /// 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;
Shankar Easwarana1d36372015-02-22 23:54:38 +000040
41 /// Convert mach-o Arch to Reference::KindArch.
Nick Kledzik2458bec2014-07-16 19:49:02 +000042 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 virtual bool isGOTAccess(const Reference &, bool &canBypassGOT) {
50 return false;
51 }
52
Lang Hames49047032015-06-23 20:35:31 +000053 /// Used by TLVPass to locate TLV References.
54 virtual bool isTLVAccess(const Reference &) const { return false; }
55
56 /// Used by the TLVPass to update TLV References.
57 virtual void updateReferenceToTLV(const Reference *) {}
58
Nick Kledzik4121bce2014-10-14 01:51:42 +000059 /// Used by ShimPass to insert shims in branches that switch mode.
60 virtual bool isNonCallBranch(const Reference &) = 0;
61
Nick Kledzik2458bec2014-07-16 19:49:02 +000062 /// Used by GOTPass to update GOT References
63 virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
64
Tim Northovercf78d372014-09-30 21:29:54 +000065 /// 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
Tim Northover1cc4fb72014-10-15 19:32:21 +000078 /// Architecture specific compact unwind type that signals __eh_frame should
79 /// actually be used.
80 virtual uint32_t dwarfCompactUnwindType() = 0;
81
Pete Cooperebecd6c2016-03-15 21:33:10 +000082 /// 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
Tim Northover995abe32014-10-15 20:26:24 +000087 /// Reference from an __eh_frame FDE to the CIE it's based on.
88 virtual Reference::KindValue unwindRefToCIEKind() = 0;
89
Tim Northovera6a6ab92014-10-15 18:19:31 +000090 /// 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;
Tim Northovercf78d372014-09-30 21:29:54 +000094
Tim Northover1cc4fb72014-10-15 19:32:21 +000095 /// 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
Pete Cooper1a6098b2016-02-02 00:02:50 +0000101 /// 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
Tim Northover933bead2014-10-16 20:52:18 +0000105 virtual const Atom *fdeTargetFunction(const DefinedAtom *fde);
106
Shankar Easwarana1d36372015-02-22 23:54:38 +0000107 /// Used by normalizedFromAtoms() to know where to generated rebasing and
Nick Kledzik2458bec2014-07-16 19:49:02 +0000108 /// binding info in final executables.
109 virtual bool isPointer(const Reference &) = 0;
Shankar Easwarana1d36372015-02-22 23:54:38 +0000110
111 /// Used by normalizedFromAtoms() to know where to generated lazy binding
Nick Kledzik2458bec2014-07-16 19:49:02 +0000112 /// info in final executables.
113 virtual bool isLazyPointer(const Reference &);
114
115 /// Returns true if the specified relocation is paired to the next relocation.
116 virtual bool isPairedReloc(const normalized::Relocation &) = 0;
117
Shankar Easwarana1d36372015-02-22 23:54:38 +0000118 /// Prototype for a helper function. Given a sectionIndex and address,
119 /// finds the atom and offset with that atom of that address.
Pete Cooper1e009112016-03-30 20:15:06 +0000120 typedef std::function<llvm::Error (uint32_t sectionIndex, uint64_t addr,
Shankar Easwarana1d36372015-02-22 23:54:38 +0000121 const lld::Atom **, Reference::Addend *)>
Nick Kledzik2458bec2014-07-16 19:49:02 +0000122 FindAtomBySectionAndAddress;
Shankar Easwarana1d36372015-02-22 23:54:38 +0000123
Nick Kledzik2458bec2014-07-16 19:49:02 +0000124 /// Prototype for a helper function. Given a symbolIndex, finds the atom
125 /// representing that symbol.
Pete Cooper1e009112016-03-30 20:15:06 +0000126 typedef std::function<llvm::Error (uint32_t symbolIndex,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000127 const lld::Atom **)> FindAtomBySymbolIndex;
128
129 /// Analyzes a relocation from a .o file and returns the info
130 /// (kind, target, addend) needed to instantiate a Reference.
131 /// Two helper functions are passed as parameters to find the target atom
132 /// given a symbol index or address.
Pete Cooper1e009112016-03-30 20:15:06 +0000133 virtual llvm::Error
Nick Kledzik2458bec2014-07-16 19:49:02 +0000134 getReferenceInfo(const normalized::Relocation &reloc,
135 const DefinedAtom *inAtom,
136 uint32_t offsetInAtom,
Tim Northover40d3ad32014-10-27 22:48:35 +0000137 uint64_t fixupAddress, bool isBigEndian,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000138 FindAtomBySectionAndAddress atomFromAddress,
139 FindAtomBySymbolIndex atomFromSymbolIndex,
Shankar Easwarana1d36372015-02-22 23:54:38 +0000140 Reference::KindValue *kind,
141 const lld::Atom **target,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000142 Reference::Addend *addend) = 0;
143
144 /// Analyzes a pair of relocations from a .o file and returns the info
145 /// (kind, target, addend) needed to instantiate a Reference.
146 /// Two helper functions are passed as parameters to find the target atom
147 /// given a symbol index or address.
Pete Cooper1e009112016-03-30 20:15:06 +0000148 virtual llvm::Error
Nick Kledzik2458bec2014-07-16 19:49:02 +0000149 getPairReferenceInfo(const normalized::Relocation &reloc1,
150 const normalized::Relocation &reloc2,
151 const DefinedAtom *inAtom,
152 uint32_t offsetInAtom,
Tim Northover40d3ad32014-10-27 22:48:35 +0000153 uint64_t fixupAddress, bool isBig, bool scatterable,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000154 FindAtomBySectionAndAddress atomFromAddress,
155 FindAtomBySymbolIndex atomFromSymbolIndex,
Shankar Easwarana1d36372015-02-22 23:54:38 +0000156 Reference::KindValue *kind,
157 const lld::Atom **target,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000158 Reference::Addend *addend) = 0;
159
Nick Kledzik2d432352014-07-17 23:16:21 +0000160 /// Prototype for a helper function. Given an atom, finds the symbol table
161 /// index for it in the output file.
162 typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
163
164 /// Prototype for a helper function. Given an atom, finds the index
165 /// of the section that will contain the atom.
166 typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
167
168 /// Prototype for a helper function. Given an atom, finds the address
169 /// assigned to it in the output file.
170 typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
171
172 /// Some architectures require local symbols on anonymous atoms.
173 virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
174 return false;
175 }
176
177 /// Copy raw content then apply all fixup References on an Atom.
178 virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
179 FindAddressForAtom findAddress,
Tim Northover1cc4fb72014-10-15 19:32:21 +0000180 FindAddressForAtom findSectionAddress,
Tim Northovercf78d372014-09-30 21:29:54 +0000181 uint64_t imageBaseAddress,
Pete Cooper47e53992016-03-23 22:19:16 +0000182 llvm::MutableArrayRef<uint8_t> atomContentBuffer) = 0;
Nick Kledzik2d432352014-07-17 23:16:21 +0000183
184 /// Used in -r mode to convert a Reference to a mach-o relocation.
185 virtual void appendSectionRelocations(const DefinedAtom &atom,
186 uint64_t atomSectionOffset,
187 const Reference &ref,
188 FindSymbolIndexForAtom,
189 FindSectionIndexForAtom,
190 FindAddressForAtom,
191 normalized::Relocations&) = 0;
192
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000193 /// Add arch-specific References.
194 virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
195
Nick Kledzik21921372014-07-24 23:06:56 +0000196 // Add Reference for data-in-code marker.
197 virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
198 uint16_t length, uint16_t kind) { }
199
200 /// Returns true if the specificed Reference value marks the start or end
201 /// of a data-in-code range in an atom.
202 virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
203 return false;
204 }
205
206 /// Returns the Reference value for a Reference that marks that start of
207 /// a data-in-code range.
208 virtual Reference::KindValue dataInCodeTransitionStart(
209 const MachODefinedAtom &atom) {
210 return 0;
211 }
212
213 /// Returns the Reference value for a Reference that marks that end of
214 /// a data-in-code range.
215 virtual Reference::KindValue dataInCodeTransitionEnd(
216 const MachODefinedAtom &atom) {
217 return 0;
218 }
219
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000220 /// Only relevant for 32-bit arm archs.
221 virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000222
Nick Kledzik4121bce2014-10-14 01:51:42 +0000223 /// Only relevant for 32-bit arm archs.
224 virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
225 const DefinedAtom &) {
226 llvm_unreachable("shims only support on arm");
227 }
228
Tim Northover1cc4fb72014-10-15 19:32:21 +0000229 /// Does a given unwind-cfi atom represent a CIE (as opposed to an FDE).
Tim Northover40d3ad32014-10-27 22:48:35 +0000230 static bool isDwarfCIE(bool isBig, const DefinedAtom *atom);
Tim Northover1cc4fb72014-10-15 19:32:21 +0000231
Nick Kledzik2458bec2014-07-16 19:49:02 +0000232 struct ReferenceInfo {
233 Reference::KindArch arch;
234 uint16_t kind;
235 uint32_t offset;
236 int32_t addend;
237 };
238
Nick Kledzik1bebb282014-09-09 23:52:59 +0000239 struct OptionalRefInfo {
240 bool used;
241 uint16_t kind;
242 uint32_t offset;
243 int32_t addend;
244 };
245
Nick Kledzik2458bec2014-07-16 19:49:02 +0000246 /// Table of architecture specific information for creating stubs.
247 struct StubInfo {
248 const char* binderSymbolName;
249 ReferenceInfo lazyPointerReferenceToHelper;
250 ReferenceInfo lazyPointerReferenceToFinal;
251 ReferenceInfo nonLazyPointerReferenceToBinder;
252 uint8_t codeAlignment;
Shankar Easwarana1d36372015-02-22 23:54:38 +0000253
Nick Kledzik2458bec2014-07-16 19:49:02 +0000254 uint32_t stubSize;
255 uint8_t stubBytes[16];
256 ReferenceInfo stubReferenceToLP;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000257 OptionalRefInfo optStubReferenceToLP;
258
Nick Kledzik2458bec2014-07-16 19:49:02 +0000259 uint32_t stubHelperSize;
260 uint8_t stubHelperBytes[16];
261 ReferenceInfo stubHelperReferenceToImm;
262 ReferenceInfo stubHelperReferenceToHelperCommon;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000263
Pete Coopere8d9df42016-02-09 20:11:17 +0000264 DefinedAtom::ContentType stubHelperImageCacheContentType;
265
Nick Kledzik2458bec2014-07-16 19:49:02 +0000266 uint32_t stubHelperCommonSize;
Pete Cooper35c33182016-02-09 18:56:37 +0000267 uint8_t stubHelperCommonAlignment;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000268 uint8_t stubHelperCommonBytes[36];
269 ReferenceInfo stubHelperCommonReferenceToCache;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000270 OptionalRefInfo optStubHelperCommonReferenceToCache;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000271 ReferenceInfo stubHelperCommonReferenceToBinder;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000272 OptionalRefInfo optStubHelperCommonReferenceToBinder;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000273 };
274
275 virtual const StubInfo &stubInfo() = 0;
276
277protected:
278 ArchHandler();
279
280 static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
281 static std::unique_ptr<mach_o::ArchHandler> create_x86();
282 static std::unique_ptr<mach_o::ArchHandler> create_arm();
Nick Kledzik1bebb282014-09-09 23:52:59 +0000283 static std::unique_ptr<mach_o::ArchHandler> create_arm64();
Nick Kledzik2458bec2014-07-16 19:49:02 +0000284
285 // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
286 typedef uint16_t RelocPattern;
287 enum {
288 rScattered = 0x8000,
289 rPcRel = 0x4000,
290 rExtern = 0x2000,
291 rLength1 = 0x0000,
292 rLength2 = 0x0100,
293 rLength4 = 0x0200,
Nick Kledzikb78ad892014-07-22 23:07:49 +0000294 rLength8 = 0x0300,
295 rLenArmLo = rLength1,
296 rLenArmHi = rLength2,
297 rLenThmbLo = rLength4,
298 rLenThmbHi = rLength8
Nick Kledzik2458bec2014-07-16 19:49:02 +0000299 };
Nick Kledzik2d432352014-07-17 23:16:21 +0000300 /// Extract RelocPattern from normalized mach-o relocation.
Nick Kledzik2458bec2014-07-16 19:49:02 +0000301 static RelocPattern relocPattern(const normalized::Relocation &reloc);
Nick Kledzik2d432352014-07-17 23:16:21 +0000302 /// Create normalized Relocation initialized from pattern.
303 static normalized::Relocation relocFromPattern(RelocPattern pattern);
304 /// One liner to add a relocation.
305 static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
306 uint32_t symbol, uint32_t value,
307 RelocPattern pattern);
308
Nick Kledzik2458bec2014-07-16 19:49:02 +0000309
Tim Northover40d3ad32014-10-27 22:48:35 +0000310 static int16_t readS16(const uint8_t *addr, bool isBig);
311 static int32_t readS32(const uint8_t *addr, bool isBig);
312 static uint32_t readU32(const uint8_t *addr, bool isBig);
313 static int64_t readS64(const uint8_t *addr, bool isBig);
Nick Kledzik2458bec2014-07-16 19:49:02 +0000314};
315
316} // namespace mach_o
317} // namespace lld
318
319#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H