blob: 9c994b7cd50d666fa30a354dfec53bb5a9b2a974 [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
10#include "MachONormalizedFile.h"
Nick Kledzik7e9808f2014-07-23 00:51:37 +000011#include "Atoms.h"
Nick Kledzik4121bce2014-10-14 01:51:42 +000012#include "File.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000013
14#include "lld/Core/LLVM.h"
15#include "lld/Core/Reference.h"
16#include "lld/Core/Simple.h"
17#include "lld/ReaderWriter/MachOLinkingContext.h"
18
19#include "llvm/ADT/Triple.h"
20
21#ifndef LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
22#define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
23
24namespace lld {
25namespace mach_o {
26
27///
28/// The ArchHandler class handles all architecture specific aspects of
29/// mach-o linking.
30///
31class ArchHandler {
32public:
33 virtual ~ArchHandler();
34
35 /// There is no public interface to subclasses of ArchHandler, so this
36 /// is the only way to instantiate an ArchHandler.
37 static std::unique_ptr<ArchHandler> create(MachOLinkingContext::Arch arch);
38
39 /// Get (arch specific) kind strings used by Registry.
40 virtual const Registry::KindStrings *kindStrings() = 0;
41
42 /// Convert mach-o Arch to Reference::KindArch.
43 virtual Reference::KindArch kindArch() = 0;
44
45 /// Used by StubPass to update References to shared library functions
46 /// to be references to a stub.
47 virtual bool isCallSite(const Reference &) = 0;
48
49 /// Used by GOTPass to locate GOT References
50 virtual bool isGOTAccess(const Reference &, bool &canBypassGOT) {
51 return false;
52 }
53
Nick Kledzik4121bce2014-10-14 01:51:42 +000054 /// Used by ShimPass to insert shims in branches that switch mode.
55 virtual bool isNonCallBranch(const Reference &) = 0;
56
Nick Kledzik2458bec2014-07-16 19:49:02 +000057 /// Used by GOTPass to update GOT References
58 virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
59
Tim Northovercf78d372014-09-30 21:29:54 +000060 /// Does this architecture make use of __unwind_info sections for exception
61 /// handling? If so, it will need a separate pass to create them.
62 virtual bool needsCompactUnwind() = 0;
63
64 /// Returns the kind of reference to use to synthesize a 32-bit image-offset
65 /// value, used in the __unwind_info section.
66 virtual Reference::KindValue imageOffsetKind() = 0;
67
68 /// Returns the kind of reference to use to synthesize a 32-bit image-offset
69 /// indirect value. Used for personality functions in the __unwind_info
70 /// section.
71 virtual Reference::KindValue imageOffsetKindIndirect() = 0;
72
Tim Northover1cc4fb72014-10-15 19:32:21 +000073 /// Architecture specific compact unwind type that signals __eh_frame should
74 /// actually be used.
75 virtual uint32_t dwarfCompactUnwindType() = 0;
76
Tim Northovera6a6ab92014-10-15 18:19:31 +000077 /// Reference from an __eh_frame FDE atom to the function it's
78 /// describing. Usually pointer-sized and PC-relative, but differs in whether
79 /// it needs to be in relocatable objects.
80 virtual Reference::KindValue unwindRefToFunctionKind() = 0;
Tim Northovercf78d372014-09-30 21:29:54 +000081
Tim Northover1cc4fb72014-10-15 19:32:21 +000082 /// Reference from an __unwind_info entry of dwarfCompactUnwindType to the
83 /// required __eh_frame entry. On current architectures, the low 24 bits
84 /// represent the offset of the function's FDE entry from the start of
85 /// __eh_frame.
86 virtual Reference::KindValue unwindRefToEhFrameKind() = 0;
87
Nick Kledzik2458bec2014-07-16 19:49:02 +000088 /// Used by normalizedFromAtoms() to know where to generated rebasing and
89 /// binding info in final executables.
90 virtual bool isPointer(const Reference &) = 0;
91
92 /// Used by normalizedFromAtoms() to know where to generated lazy binding
93 /// info in final executables.
94 virtual bool isLazyPointer(const Reference &);
95
96 /// Returns true if the specified relocation is paired to the next relocation.
97 virtual bool isPairedReloc(const normalized::Relocation &) = 0;
98
99 /// Prototype for a helper function. Given a sectionIndex and address,
100 /// finds the atom and offset with that atom of that address.
101 typedef std::function<std::error_code (uint32_t sectionIndex, uint64_t addr,
102 const lld::Atom **, Reference::Addend *)>
103 FindAtomBySectionAndAddress;
104
105 /// Prototype for a helper function. Given a symbolIndex, finds the atom
106 /// representing that symbol.
107 typedef std::function<std::error_code (uint32_t symbolIndex,
108 const lld::Atom **)> FindAtomBySymbolIndex;
109
110 /// Analyzes a relocation from a .o file and returns the info
111 /// (kind, target, addend) needed to instantiate a Reference.
112 /// Two helper functions are passed as parameters to find the target atom
113 /// given a symbol index or address.
114 virtual std::error_code
115 getReferenceInfo(const normalized::Relocation &reloc,
116 const DefinedAtom *inAtom,
117 uint32_t offsetInAtom,
118 uint64_t fixupAddress, bool swap,
119 FindAtomBySectionAndAddress atomFromAddress,
120 FindAtomBySymbolIndex atomFromSymbolIndex,
121 Reference::KindValue *kind,
122 const lld::Atom **target,
123 Reference::Addend *addend) = 0;
124
125 /// Analyzes a pair of relocations from a .o file and returns the info
126 /// (kind, target, addend) needed to instantiate a Reference.
127 /// Two helper functions are passed as parameters to find the target atom
128 /// given a symbol index or address.
129 virtual std::error_code
130 getPairReferenceInfo(const normalized::Relocation &reloc1,
131 const normalized::Relocation &reloc2,
132 const DefinedAtom *inAtom,
133 uint32_t offsetInAtom,
134 uint64_t fixupAddress, bool swap,
135 FindAtomBySectionAndAddress atomFromAddress,
136 FindAtomBySymbolIndex atomFromSymbolIndex,
137 Reference::KindValue *kind,
138 const lld::Atom **target,
139 Reference::Addend *addend) = 0;
140
Nick Kledzik2d432352014-07-17 23:16:21 +0000141 /// Prototype for a helper function. Given an atom, finds the symbol table
142 /// index for it in the output file.
143 typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
144
145 /// Prototype for a helper function. Given an atom, finds the index
146 /// of the section that will contain the atom.
147 typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
148
149 /// Prototype for a helper function. Given an atom, finds the address
150 /// assigned to it in the output file.
151 typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
152
153 /// Some architectures require local symbols on anonymous atoms.
154 virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
155 return false;
156 }
157
158 /// Copy raw content then apply all fixup References on an Atom.
159 virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
160 FindAddressForAtom findAddress,
Tim Northover1cc4fb72014-10-15 19:32:21 +0000161 FindAddressForAtom findSectionAddress,
Tim Northovercf78d372014-09-30 21:29:54 +0000162 uint64_t imageBaseAddress,
Nick Kledzik2d432352014-07-17 23:16:21 +0000163 uint8_t *atomContentBuffer) = 0;
164
165 /// Used in -r mode to convert a Reference to a mach-o relocation.
166 virtual void appendSectionRelocations(const DefinedAtom &atom,
167 uint64_t atomSectionOffset,
168 const Reference &ref,
169 FindSymbolIndexForAtom,
170 FindSectionIndexForAtom,
171 FindAddressForAtom,
172 normalized::Relocations&) = 0;
173
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000174 /// Add arch-specific References.
175 virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
176
Nick Kledzik21921372014-07-24 23:06:56 +0000177 // Add Reference for data-in-code marker.
178 virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
179 uint16_t length, uint16_t kind) { }
180
181 /// Returns true if the specificed Reference value marks the start or end
182 /// of a data-in-code range in an atom.
183 virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
184 return false;
185 }
186
187 /// Returns the Reference value for a Reference that marks that start of
188 /// a data-in-code range.
189 virtual Reference::KindValue dataInCodeTransitionStart(
190 const MachODefinedAtom &atom) {
191 return 0;
192 }
193
194 /// Returns the Reference value for a Reference that marks that end of
195 /// a data-in-code range.
196 virtual Reference::KindValue dataInCodeTransitionEnd(
197 const MachODefinedAtom &atom) {
198 return 0;
199 }
200
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000201 /// Only relevant for 32-bit arm archs.
202 virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000203
Nick Kledzik4121bce2014-10-14 01:51:42 +0000204 /// Only relevant for 32-bit arm archs.
205 virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
206 const DefinedAtom &) {
207 llvm_unreachable("shims only support on arm");
208 }
209
Tim Northover1cc4fb72014-10-15 19:32:21 +0000210 /// Does a given unwind-cfi atom represent a CIE (as opposed to an FDE).
211 static bool isDwarfCIE(bool swap, const DefinedAtom *atom);
212
Nick Kledzik2458bec2014-07-16 19:49:02 +0000213 struct ReferenceInfo {
214 Reference::KindArch arch;
215 uint16_t kind;
216 uint32_t offset;
217 int32_t addend;
218 };
219
Nick Kledzik1bebb282014-09-09 23:52:59 +0000220 struct OptionalRefInfo {
221 bool used;
222 uint16_t kind;
223 uint32_t offset;
224 int32_t addend;
225 };
226
Nick Kledzik2458bec2014-07-16 19:49:02 +0000227 /// Table of architecture specific information for creating stubs.
228 struct StubInfo {
229 const char* binderSymbolName;
230 ReferenceInfo lazyPointerReferenceToHelper;
231 ReferenceInfo lazyPointerReferenceToFinal;
232 ReferenceInfo nonLazyPointerReferenceToBinder;
233 uint8_t codeAlignment;
234
235 uint32_t stubSize;
236 uint8_t stubBytes[16];
237 ReferenceInfo stubReferenceToLP;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000238 OptionalRefInfo optStubReferenceToLP;
239
Nick Kledzik2458bec2014-07-16 19:49:02 +0000240 uint32_t stubHelperSize;
241 uint8_t stubHelperBytes[16];
242 ReferenceInfo stubHelperReferenceToImm;
243 ReferenceInfo stubHelperReferenceToHelperCommon;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000244
Nick Kledzik2458bec2014-07-16 19:49:02 +0000245 uint32_t stubHelperCommonSize;
246 uint8_t stubHelperCommonBytes[36];
247 ReferenceInfo stubHelperCommonReferenceToCache;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000248 OptionalRefInfo optStubHelperCommonReferenceToCache;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000249 ReferenceInfo stubHelperCommonReferenceToBinder;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000250 OptionalRefInfo optStubHelperCommonReferenceToBinder;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000251 };
252
253 virtual const StubInfo &stubInfo() = 0;
254
255protected:
256 ArchHandler();
257
258 static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
259 static std::unique_ptr<mach_o::ArchHandler> create_x86();
260 static std::unique_ptr<mach_o::ArchHandler> create_arm();
Nick Kledzik1bebb282014-09-09 23:52:59 +0000261 static std::unique_ptr<mach_o::ArchHandler> create_arm64();
Nick Kledzik2458bec2014-07-16 19:49:02 +0000262
263 // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
264 typedef uint16_t RelocPattern;
265 enum {
266 rScattered = 0x8000,
267 rPcRel = 0x4000,
268 rExtern = 0x2000,
269 rLength1 = 0x0000,
270 rLength2 = 0x0100,
271 rLength4 = 0x0200,
Nick Kledzikb78ad892014-07-22 23:07:49 +0000272 rLength8 = 0x0300,
273 rLenArmLo = rLength1,
274 rLenArmHi = rLength2,
275 rLenThmbLo = rLength4,
276 rLenThmbHi = rLength8
Nick Kledzik2458bec2014-07-16 19:49:02 +0000277 };
Nick Kledzik2d432352014-07-17 23:16:21 +0000278 /// Extract RelocPattern from normalized mach-o relocation.
Nick Kledzik2458bec2014-07-16 19:49:02 +0000279 static RelocPattern relocPattern(const normalized::Relocation &reloc);
Nick Kledzik2d432352014-07-17 23:16:21 +0000280 /// Create normalized Relocation initialized from pattern.
281 static normalized::Relocation relocFromPattern(RelocPattern pattern);
282 /// One liner to add a relocation.
283 static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
284 uint32_t symbol, uint32_t value,
285 RelocPattern pattern);
286
Nick Kledzik2458bec2014-07-16 19:49:02 +0000287
288 static int16_t readS16(bool swap, const uint8_t *addr);
289 static int32_t readS32(bool swap, const uint8_t *addr);
290 static uint32_t readU32(bool swap, const uint8_t *addr);
291 static int64_t readS64(bool swap, const uint8_t *addr);
292};
293
294} // namespace mach_o
295} // namespace lld
296
297#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H