blob: 4cdd8ac7a527ece031c43be680dfd82280e75e4d [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"
17#include "lld/Core/Reference.h"
18#include "lld/Core/Simple.h"
19#include "lld/ReaderWriter/MachOLinkingContext.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000020#include "llvm/ADT/Triple.h"
21
Nick Kledzik2458bec2014-07-16 19:49:02 +000022namespace lld {
23namespace mach_o {
24
25///
26/// The ArchHandler class handles all architecture specific aspects of
27/// mach-o linking.
28///
29class ArchHandler {
30public:
31 virtual ~ArchHandler();
Shankar Easwarana1d36372015-02-22 23:54:38 +000032
Nick Kledzik2458bec2014-07-16 19:49:02 +000033 /// 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;
Shankar Easwarana1d36372015-02-22 23:54:38 +000039
40 /// Convert mach-o Arch to Reference::KindArch.
Nick Kledzik2458bec2014-07-16 19:49:02 +000041 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 virtual bool isGOTAccess(const Reference &, bool &canBypassGOT) {
49 return false;
50 }
51
Lang Hames49047032015-06-23 20:35:31 +000052 /// Used by TLVPass to locate TLV References.
53 virtual bool isTLVAccess(const Reference &) const { return false; }
54
55 /// Used by the TLVPass to update TLV References.
56 virtual void updateReferenceToTLV(const Reference *) {}
57
Nick Kledzik4121bce2014-10-14 01:51:42 +000058 /// Used by ShimPass to insert shims in branches that switch mode.
59 virtual bool isNonCallBranch(const Reference &) = 0;
60
Nick Kledzik2458bec2014-07-16 19:49:02 +000061 /// Used by GOTPass to update GOT References
62 virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
63
Tim Northovercf78d372014-09-30 21:29:54 +000064 /// 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
Tim Northover1cc4fb72014-10-15 19:32:21 +000077 /// Architecture specific compact unwind type that signals __eh_frame should
78 /// actually be used.
79 virtual uint32_t dwarfCompactUnwindType() = 0;
80
Tim Northover995abe32014-10-15 20:26:24 +000081 /// Reference from an __eh_frame FDE to the CIE it's based on.
82 virtual Reference::KindValue unwindRefToCIEKind() = 0;
83
Tim Northovera6a6ab92014-10-15 18:19:31 +000084 /// Reference from an __eh_frame FDE atom to the function it's
85 /// describing. Usually pointer-sized and PC-relative, but differs in whether
86 /// it needs to be in relocatable objects.
87 virtual Reference::KindValue unwindRefToFunctionKind() = 0;
Tim Northovercf78d372014-09-30 21:29:54 +000088
Tim Northover1cc4fb72014-10-15 19:32:21 +000089 /// Reference from an __unwind_info entry of dwarfCompactUnwindType to the
90 /// required __eh_frame entry. On current architectures, the low 24 bits
91 /// represent the offset of the function's FDE entry from the start of
92 /// __eh_frame.
93 virtual Reference::KindValue unwindRefToEhFrameKind() = 0;
94
Pete Cooper1a6098b2016-02-02 00:02:50 +000095 /// Returns a pointer sized reference kind. On 64-bit targets this will
96 /// likely be something like pointer64, and pointer32 on 32-bit targets.
97 virtual Reference::KindValue pointerKind() = 0;
98
Tim Northover933bead2014-10-16 20:52:18 +000099 virtual const Atom *fdeTargetFunction(const DefinedAtom *fde);
100
Shankar Easwarana1d36372015-02-22 23:54:38 +0000101 /// Used by normalizedFromAtoms() to know where to generated rebasing and
Nick Kledzik2458bec2014-07-16 19:49:02 +0000102 /// binding info in final executables.
103 virtual bool isPointer(const Reference &) = 0;
Shankar Easwarana1d36372015-02-22 23:54:38 +0000104
105 /// Used by normalizedFromAtoms() to know where to generated lazy binding
Nick Kledzik2458bec2014-07-16 19:49:02 +0000106 /// info in final executables.
107 virtual bool isLazyPointer(const Reference &);
108
109 /// Returns true if the specified relocation is paired to the next relocation.
110 virtual bool isPairedReloc(const normalized::Relocation &) = 0;
111
Shankar Easwarana1d36372015-02-22 23:54:38 +0000112 /// Prototype for a helper function. Given a sectionIndex and address,
113 /// finds the atom and offset with that atom of that address.
114 typedef std::function<std::error_code (uint32_t sectionIndex, uint64_t addr,
115 const lld::Atom **, Reference::Addend *)>
Nick Kledzik2458bec2014-07-16 19:49:02 +0000116 FindAtomBySectionAndAddress;
Shankar Easwarana1d36372015-02-22 23:54:38 +0000117
Nick Kledzik2458bec2014-07-16 19:49:02 +0000118 /// Prototype for a helper function. Given a symbolIndex, finds the atom
119 /// representing that symbol.
Shankar Easwarana1d36372015-02-22 23:54:38 +0000120 typedef std::function<std::error_code (uint32_t symbolIndex,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000121 const lld::Atom **)> FindAtomBySymbolIndex;
122
123 /// Analyzes a relocation from a .o file and returns the info
124 /// (kind, target, addend) needed to instantiate a Reference.
125 /// Two helper functions are passed as parameters to find the target atom
126 /// given a symbol index or address.
Shankar Easwarana1d36372015-02-22 23:54:38 +0000127 virtual std::error_code
Nick Kledzik2458bec2014-07-16 19:49:02 +0000128 getReferenceInfo(const normalized::Relocation &reloc,
129 const DefinedAtom *inAtom,
130 uint32_t offsetInAtom,
Tim Northover40d3ad32014-10-27 22:48:35 +0000131 uint64_t fixupAddress, bool isBigEndian,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000132 FindAtomBySectionAndAddress atomFromAddress,
133 FindAtomBySymbolIndex atomFromSymbolIndex,
Shankar Easwarana1d36372015-02-22 23:54:38 +0000134 Reference::KindValue *kind,
135 const lld::Atom **target,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000136 Reference::Addend *addend) = 0;
137
138 /// Analyzes a pair of relocations from a .o file and returns the info
139 /// (kind, target, addend) needed to instantiate a Reference.
140 /// Two helper functions are passed as parameters to find the target atom
141 /// given a symbol index or address.
Shankar Easwarana1d36372015-02-22 23:54:38 +0000142 virtual std::error_code
Nick Kledzik2458bec2014-07-16 19:49:02 +0000143 getPairReferenceInfo(const normalized::Relocation &reloc1,
144 const normalized::Relocation &reloc2,
145 const DefinedAtom *inAtom,
146 uint32_t offsetInAtom,
Tim Northover40d3ad32014-10-27 22:48:35 +0000147 uint64_t fixupAddress, bool isBig, bool scatterable,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000148 FindAtomBySectionAndAddress atomFromAddress,
149 FindAtomBySymbolIndex atomFromSymbolIndex,
Shankar Easwarana1d36372015-02-22 23:54:38 +0000150 Reference::KindValue *kind,
151 const lld::Atom **target,
Nick Kledzik2458bec2014-07-16 19:49:02 +0000152 Reference::Addend *addend) = 0;
153
Nick Kledzik2d432352014-07-17 23:16:21 +0000154 /// Prototype for a helper function. Given an atom, finds the symbol table
155 /// index for it in the output file.
156 typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
157
158 /// Prototype for a helper function. Given an atom, finds the index
159 /// of the section that will contain the atom.
160 typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
161
162 /// Prototype for a helper function. Given an atom, finds the address
163 /// assigned to it in the output file.
164 typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
165
166 /// Some architectures require local symbols on anonymous atoms.
167 virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
168 return false;
169 }
170
171 /// Copy raw content then apply all fixup References on an Atom.
172 virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
173 FindAddressForAtom findAddress,
Tim Northover1cc4fb72014-10-15 19:32:21 +0000174 FindAddressForAtom findSectionAddress,
Tim Northovercf78d372014-09-30 21:29:54 +0000175 uint64_t imageBaseAddress,
Nick Kledzik2d432352014-07-17 23:16:21 +0000176 uint8_t *atomContentBuffer) = 0;
177
178 /// Used in -r mode to convert a Reference to a mach-o relocation.
179 virtual void appendSectionRelocations(const DefinedAtom &atom,
180 uint64_t atomSectionOffset,
181 const Reference &ref,
182 FindSymbolIndexForAtom,
183 FindSectionIndexForAtom,
184 FindAddressForAtom,
185 normalized::Relocations&) = 0;
186
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000187 /// Add arch-specific References.
188 virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
189
Nick Kledzik21921372014-07-24 23:06:56 +0000190 // Add Reference for data-in-code marker.
191 virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
192 uint16_t length, uint16_t kind) { }
193
194 /// Returns true if the specificed Reference value marks the start or end
195 /// of a data-in-code range in an atom.
196 virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
197 return false;
198 }
199
200 /// Returns the Reference value for a Reference that marks that start of
201 /// a data-in-code range.
202 virtual Reference::KindValue dataInCodeTransitionStart(
203 const MachODefinedAtom &atom) {
204 return 0;
205 }
206
207 /// Returns the Reference value for a Reference that marks that end of
208 /// a data-in-code range.
209 virtual Reference::KindValue dataInCodeTransitionEnd(
210 const MachODefinedAtom &atom) {
211 return 0;
212 }
213
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000214 /// Only relevant for 32-bit arm archs.
215 virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000216
Nick Kledzik4121bce2014-10-14 01:51:42 +0000217 /// Only relevant for 32-bit arm archs.
218 virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
219 const DefinedAtom &) {
220 llvm_unreachable("shims only support on arm");
221 }
222
Tim Northover1cc4fb72014-10-15 19:32:21 +0000223 /// Does a given unwind-cfi atom represent a CIE (as opposed to an FDE).
Tim Northover40d3ad32014-10-27 22:48:35 +0000224 static bool isDwarfCIE(bool isBig, const DefinedAtom *atom);
Tim Northover1cc4fb72014-10-15 19:32:21 +0000225
Nick Kledzik2458bec2014-07-16 19:49:02 +0000226 struct ReferenceInfo {
227 Reference::KindArch arch;
228 uint16_t kind;
229 uint32_t offset;
230 int32_t addend;
231 };
232
Nick Kledzik1bebb282014-09-09 23:52:59 +0000233 struct OptionalRefInfo {
234 bool used;
235 uint16_t kind;
236 uint32_t offset;
237 int32_t addend;
238 };
239
Nick Kledzik2458bec2014-07-16 19:49:02 +0000240 /// Table of architecture specific information for creating stubs.
241 struct StubInfo {
242 const char* binderSymbolName;
243 ReferenceInfo lazyPointerReferenceToHelper;
244 ReferenceInfo lazyPointerReferenceToFinal;
245 ReferenceInfo nonLazyPointerReferenceToBinder;
246 uint8_t codeAlignment;
Shankar Easwarana1d36372015-02-22 23:54:38 +0000247
Nick Kledzik2458bec2014-07-16 19:49:02 +0000248 uint32_t stubSize;
249 uint8_t stubBytes[16];
250 ReferenceInfo stubReferenceToLP;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000251 OptionalRefInfo optStubReferenceToLP;
252
Nick Kledzik2458bec2014-07-16 19:49:02 +0000253 uint32_t stubHelperSize;
254 uint8_t stubHelperBytes[16];
255 ReferenceInfo stubHelperReferenceToImm;
256 ReferenceInfo stubHelperReferenceToHelperCommon;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000257
Nick Kledzik2458bec2014-07-16 19:49:02 +0000258 uint32_t stubHelperCommonSize;
259 uint8_t stubHelperCommonBytes[36];
260 ReferenceInfo stubHelperCommonReferenceToCache;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000261 OptionalRefInfo optStubHelperCommonReferenceToCache;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000262 ReferenceInfo stubHelperCommonReferenceToBinder;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000263 OptionalRefInfo optStubHelperCommonReferenceToBinder;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000264 };
265
266 virtual const StubInfo &stubInfo() = 0;
267
268protected:
269 ArchHandler();
270
271 static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
272 static std::unique_ptr<mach_o::ArchHandler> create_x86();
273 static std::unique_ptr<mach_o::ArchHandler> create_arm();
Nick Kledzik1bebb282014-09-09 23:52:59 +0000274 static std::unique_ptr<mach_o::ArchHandler> create_arm64();
Nick Kledzik2458bec2014-07-16 19:49:02 +0000275
276 // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
277 typedef uint16_t RelocPattern;
278 enum {
279 rScattered = 0x8000,
280 rPcRel = 0x4000,
281 rExtern = 0x2000,
282 rLength1 = 0x0000,
283 rLength2 = 0x0100,
284 rLength4 = 0x0200,
Nick Kledzikb78ad892014-07-22 23:07:49 +0000285 rLength8 = 0x0300,
286 rLenArmLo = rLength1,
287 rLenArmHi = rLength2,
288 rLenThmbLo = rLength4,
289 rLenThmbHi = rLength8
Nick Kledzik2458bec2014-07-16 19:49:02 +0000290 };
Nick Kledzik2d432352014-07-17 23:16:21 +0000291 /// Extract RelocPattern from normalized mach-o relocation.
Nick Kledzik2458bec2014-07-16 19:49:02 +0000292 static RelocPattern relocPattern(const normalized::Relocation &reloc);
Nick Kledzik2d432352014-07-17 23:16:21 +0000293 /// Create normalized Relocation initialized from pattern.
294 static normalized::Relocation relocFromPattern(RelocPattern pattern);
295 /// One liner to add a relocation.
296 static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
297 uint32_t symbol, uint32_t value,
298 RelocPattern pattern);
299
Nick Kledzik2458bec2014-07-16 19:49:02 +0000300
Tim Northover40d3ad32014-10-27 22:48:35 +0000301 static int16_t readS16(const uint8_t *addr, bool isBig);
302 static int32_t readS32(const uint8_t *addr, bool isBig);
303 static uint32_t readU32(const uint8_t *addr, bool isBig);
304 static int64_t readS64(const uint8_t *addr, bool isBig);
Nick Kledzik2458bec2014-07-16 19:49:02 +0000305};
306
307} // namespace mach_o
308} // namespace lld
309
310#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H