blob: 0c82d251b1c96609865c51a9dca9159f276cc4fd [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
73
Nick Kledzik2458bec2014-07-16 19:49:02 +000074 /// Used by normalizedFromAtoms() to know where to generated rebasing and
75 /// binding info in final executables.
76 virtual bool isPointer(const Reference &) = 0;
77
78 /// Used by normalizedFromAtoms() to know where to generated lazy binding
79 /// info in final executables.
80 virtual bool isLazyPointer(const Reference &);
81
82 /// Returns true if the specified relocation is paired to the next relocation.
83 virtual bool isPairedReloc(const normalized::Relocation &) = 0;
84
85 /// Prototype for a helper function. Given a sectionIndex and address,
86 /// finds the atom and offset with that atom of that address.
87 typedef std::function<std::error_code (uint32_t sectionIndex, uint64_t addr,
88 const lld::Atom **, Reference::Addend *)>
89 FindAtomBySectionAndAddress;
90
91 /// Prototype for a helper function. Given a symbolIndex, finds the atom
92 /// representing that symbol.
93 typedef std::function<std::error_code (uint32_t symbolIndex,
94 const lld::Atom **)> FindAtomBySymbolIndex;
95
96 /// Analyzes a relocation from a .o file and returns the info
97 /// (kind, target, addend) needed to instantiate a Reference.
98 /// Two helper functions are passed as parameters to find the target atom
99 /// given a symbol index or address.
100 virtual std::error_code
101 getReferenceInfo(const normalized::Relocation &reloc,
102 const DefinedAtom *inAtom,
103 uint32_t offsetInAtom,
104 uint64_t fixupAddress, bool swap,
105 FindAtomBySectionAndAddress atomFromAddress,
106 FindAtomBySymbolIndex atomFromSymbolIndex,
107 Reference::KindValue *kind,
108 const lld::Atom **target,
109 Reference::Addend *addend) = 0;
110
111 /// Analyzes a pair of relocations from a .o file and returns the info
112 /// (kind, target, addend) needed to instantiate a Reference.
113 /// Two helper functions are passed as parameters to find the target atom
114 /// given a symbol index or address.
115 virtual std::error_code
116 getPairReferenceInfo(const normalized::Relocation &reloc1,
117 const normalized::Relocation &reloc2,
118 const DefinedAtom *inAtom,
119 uint32_t offsetInAtom,
120 uint64_t fixupAddress, bool swap,
121 FindAtomBySectionAndAddress atomFromAddress,
122 FindAtomBySymbolIndex atomFromSymbolIndex,
123 Reference::KindValue *kind,
124 const lld::Atom **target,
125 Reference::Addend *addend) = 0;
126
Nick Kledzik2d432352014-07-17 23:16:21 +0000127 /// Prototype for a helper function. Given an atom, finds the symbol table
128 /// index for it in the output file.
129 typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
130
131 /// Prototype for a helper function. Given an atom, finds the index
132 /// of the section that will contain the atom.
133 typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
134
135 /// Prototype for a helper function. Given an atom, finds the address
136 /// assigned to it in the output file.
137 typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
138
139 /// Some architectures require local symbols on anonymous atoms.
140 virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
141 return false;
142 }
143
144 /// Copy raw content then apply all fixup References on an Atom.
145 virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
146 FindAddressForAtom findAddress,
Tim Northovercf78d372014-09-30 21:29:54 +0000147 uint64_t imageBaseAddress,
Nick Kledzik2d432352014-07-17 23:16:21 +0000148 uint8_t *atomContentBuffer) = 0;
149
150 /// Used in -r mode to convert a Reference to a mach-o relocation.
151 virtual void appendSectionRelocations(const DefinedAtom &atom,
152 uint64_t atomSectionOffset,
153 const Reference &ref,
154 FindSymbolIndexForAtom,
155 FindSectionIndexForAtom,
156 FindAddressForAtom,
157 normalized::Relocations&) = 0;
158
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000159 /// Add arch-specific References.
160 virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
161
Nick Kledzik21921372014-07-24 23:06:56 +0000162 // Add Reference for data-in-code marker.
163 virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
164 uint16_t length, uint16_t kind) { }
165
166 /// Returns true if the specificed Reference value marks the start or end
167 /// of a data-in-code range in an atom.
168 virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
169 return false;
170 }
171
172 /// Returns the Reference value for a Reference that marks that start of
173 /// a data-in-code range.
174 virtual Reference::KindValue dataInCodeTransitionStart(
175 const MachODefinedAtom &atom) {
176 return 0;
177 }
178
179 /// Returns the Reference value for a Reference that marks that end of
180 /// a data-in-code range.
181 virtual Reference::KindValue dataInCodeTransitionEnd(
182 const MachODefinedAtom &atom) {
183 return 0;
184 }
185
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000186 /// Only relevant for 32-bit arm archs.
187 virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000188
Nick Kledzik4121bce2014-10-14 01:51:42 +0000189 /// Only relevant for 32-bit arm archs.
190 virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
191 const DefinedAtom &) {
192 llvm_unreachable("shims only support on arm");
193 }
194
Nick Kledzik2458bec2014-07-16 19:49:02 +0000195 struct ReferenceInfo {
196 Reference::KindArch arch;
197 uint16_t kind;
198 uint32_t offset;
199 int32_t addend;
200 };
201
Nick Kledzik1bebb282014-09-09 23:52:59 +0000202 struct OptionalRefInfo {
203 bool used;
204 uint16_t kind;
205 uint32_t offset;
206 int32_t addend;
207 };
208
Nick Kledzik2458bec2014-07-16 19:49:02 +0000209 /// Table of architecture specific information for creating stubs.
210 struct StubInfo {
211 const char* binderSymbolName;
212 ReferenceInfo lazyPointerReferenceToHelper;
213 ReferenceInfo lazyPointerReferenceToFinal;
214 ReferenceInfo nonLazyPointerReferenceToBinder;
215 uint8_t codeAlignment;
216
217 uint32_t stubSize;
218 uint8_t stubBytes[16];
219 ReferenceInfo stubReferenceToLP;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000220 OptionalRefInfo optStubReferenceToLP;
221
Nick Kledzik2458bec2014-07-16 19:49:02 +0000222 uint32_t stubHelperSize;
223 uint8_t stubHelperBytes[16];
224 ReferenceInfo stubHelperReferenceToImm;
225 ReferenceInfo stubHelperReferenceToHelperCommon;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000226
Nick Kledzik2458bec2014-07-16 19:49:02 +0000227 uint32_t stubHelperCommonSize;
228 uint8_t stubHelperCommonBytes[36];
229 ReferenceInfo stubHelperCommonReferenceToCache;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000230 OptionalRefInfo optStubHelperCommonReferenceToCache;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000231 ReferenceInfo stubHelperCommonReferenceToBinder;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000232 OptionalRefInfo optStubHelperCommonReferenceToBinder;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000233 };
234
235 virtual const StubInfo &stubInfo() = 0;
236
237protected:
238 ArchHandler();
239
240 static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
241 static std::unique_ptr<mach_o::ArchHandler> create_x86();
242 static std::unique_ptr<mach_o::ArchHandler> create_arm();
Nick Kledzik1bebb282014-09-09 23:52:59 +0000243 static std::unique_ptr<mach_o::ArchHandler> create_arm64();
Nick Kledzik2458bec2014-07-16 19:49:02 +0000244
245 // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
246 typedef uint16_t RelocPattern;
247 enum {
248 rScattered = 0x8000,
249 rPcRel = 0x4000,
250 rExtern = 0x2000,
251 rLength1 = 0x0000,
252 rLength2 = 0x0100,
253 rLength4 = 0x0200,
Nick Kledzikb78ad892014-07-22 23:07:49 +0000254 rLength8 = 0x0300,
255 rLenArmLo = rLength1,
256 rLenArmHi = rLength2,
257 rLenThmbLo = rLength4,
258 rLenThmbHi = rLength8
Nick Kledzik2458bec2014-07-16 19:49:02 +0000259 };
Nick Kledzik2d432352014-07-17 23:16:21 +0000260 /// Extract RelocPattern from normalized mach-o relocation.
Nick Kledzik2458bec2014-07-16 19:49:02 +0000261 static RelocPattern relocPattern(const normalized::Relocation &reloc);
Nick Kledzik2d432352014-07-17 23:16:21 +0000262 /// Create normalized Relocation initialized from pattern.
263 static normalized::Relocation relocFromPattern(RelocPattern pattern);
264 /// One liner to add a relocation.
265 static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
266 uint32_t symbol, uint32_t value,
267 RelocPattern pattern);
268
Nick Kledzik2458bec2014-07-16 19:49:02 +0000269
270 static int16_t readS16(bool swap, const uint8_t *addr);
271 static int32_t readS32(bool swap, const uint8_t *addr);
272 static uint32_t readU32(bool swap, const uint8_t *addr);
273 static int64_t readS64(bool swap, const uint8_t *addr);
274};
275
276} // namespace mach_o
277} // namespace lld
278
279#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H