blob: df063167699f510bec23b0e19800faadb79686e4 [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 Kledzik2458bec2014-07-16 19:49:02 +000012
13#include "lld/Core/LLVM.h"
14#include "lld/Core/Reference.h"
15#include "lld/Core/Simple.h"
16#include "lld/ReaderWriter/MachOLinkingContext.h"
17
18#include "llvm/ADT/Triple.h"
19
20#ifndef LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
21#define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
22
23namespace 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();
33
34 /// 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;
40
41 /// Convert mach-o Arch to Reference::KindArch.
42 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
53 /// Used by GOTPass to update GOT References
54 virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
55
Tim Northovercf78d372014-09-30 21:29:54 +000056 /// Does this architecture make use of __unwind_info sections for exception
57 /// handling? If so, it will need a separate pass to create them.
58 virtual bool needsCompactUnwind() = 0;
59
60 /// Returns the kind of reference to use to synthesize a 32-bit image-offset
61 /// value, used in the __unwind_info section.
62 virtual Reference::KindValue imageOffsetKind() = 0;
63
64 /// Returns the kind of reference to use to synthesize a 32-bit image-offset
65 /// indirect value. Used for personality functions in the __unwind_info
66 /// section.
67 virtual Reference::KindValue imageOffsetKindIndirect() = 0;
68
69
Nick Kledzik2458bec2014-07-16 19:49:02 +000070 /// Used by normalizedFromAtoms() to know where to generated rebasing and
71 /// binding info in final executables.
72 virtual bool isPointer(const Reference &) = 0;
73
74 /// Used by normalizedFromAtoms() to know where to generated lazy binding
75 /// info in final executables.
76 virtual bool isLazyPointer(const Reference &);
77
78 /// Returns true if the specified relocation is paired to the next relocation.
79 virtual bool isPairedReloc(const normalized::Relocation &) = 0;
80
81 /// Prototype for a helper function. Given a sectionIndex and address,
82 /// finds the atom and offset with that atom of that address.
83 typedef std::function<std::error_code (uint32_t sectionIndex, uint64_t addr,
84 const lld::Atom **, Reference::Addend *)>
85 FindAtomBySectionAndAddress;
86
87 /// Prototype for a helper function. Given a symbolIndex, finds the atom
88 /// representing that symbol.
89 typedef std::function<std::error_code (uint32_t symbolIndex,
90 const lld::Atom **)> FindAtomBySymbolIndex;
91
92 /// Analyzes a relocation from a .o file and returns the info
93 /// (kind, target, addend) needed to instantiate a Reference.
94 /// Two helper functions are passed as parameters to find the target atom
95 /// given a symbol index or address.
96 virtual std::error_code
97 getReferenceInfo(const normalized::Relocation &reloc,
98 const DefinedAtom *inAtom,
99 uint32_t offsetInAtom,
100 uint64_t fixupAddress, bool swap,
101 FindAtomBySectionAndAddress atomFromAddress,
102 FindAtomBySymbolIndex atomFromSymbolIndex,
103 Reference::KindValue *kind,
104 const lld::Atom **target,
105 Reference::Addend *addend) = 0;
106
107 /// Analyzes a pair of relocations from a .o file and returns the info
108 /// (kind, target, addend) needed to instantiate a Reference.
109 /// Two helper functions are passed as parameters to find the target atom
110 /// given a symbol index or address.
111 virtual std::error_code
112 getPairReferenceInfo(const normalized::Relocation &reloc1,
113 const normalized::Relocation &reloc2,
114 const DefinedAtom *inAtom,
115 uint32_t offsetInAtom,
116 uint64_t fixupAddress, bool swap,
117 FindAtomBySectionAndAddress atomFromAddress,
118 FindAtomBySymbolIndex atomFromSymbolIndex,
119 Reference::KindValue *kind,
120 const lld::Atom **target,
121 Reference::Addend *addend) = 0;
122
Nick Kledzik2d432352014-07-17 23:16:21 +0000123 /// Prototype for a helper function. Given an atom, finds the symbol table
124 /// index for it in the output file.
125 typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
126
127 /// Prototype for a helper function. Given an atom, finds the index
128 /// of the section that will contain the atom.
129 typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
130
131 /// Prototype for a helper function. Given an atom, finds the address
132 /// assigned to it in the output file.
133 typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
134
135 /// Some architectures require local symbols on anonymous atoms.
136 virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
137 return false;
138 }
139
140 /// Copy raw content then apply all fixup References on an Atom.
141 virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
142 FindAddressForAtom findAddress,
Tim Northovercf78d372014-09-30 21:29:54 +0000143 uint64_t imageBaseAddress,
Nick Kledzik2d432352014-07-17 23:16:21 +0000144 uint8_t *atomContentBuffer) = 0;
145
146 /// Used in -r mode to convert a Reference to a mach-o relocation.
147 virtual void appendSectionRelocations(const DefinedAtom &atom,
148 uint64_t atomSectionOffset,
149 const Reference &ref,
150 FindSymbolIndexForAtom,
151 FindSectionIndexForAtom,
152 FindAddressForAtom,
153 normalized::Relocations&) = 0;
154
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000155 /// Add arch-specific References.
156 virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
157
Nick Kledzik21921372014-07-24 23:06:56 +0000158 // Add Reference for data-in-code marker.
159 virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
160 uint16_t length, uint16_t kind) { }
161
162 /// Returns true if the specificed Reference value marks the start or end
163 /// of a data-in-code range in an atom.
164 virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
165 return false;
166 }
167
168 /// Returns the Reference value for a Reference that marks that start of
169 /// a data-in-code range.
170 virtual Reference::KindValue dataInCodeTransitionStart(
171 const MachODefinedAtom &atom) {
172 return 0;
173 }
174
175 /// Returns the Reference value for a Reference that marks that end of
176 /// a data-in-code range.
177 virtual Reference::KindValue dataInCodeTransitionEnd(
178 const MachODefinedAtom &atom) {
179 return 0;
180 }
181
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000182 /// Only relevant for 32-bit arm archs.
183 virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000184
185 struct ReferenceInfo {
186 Reference::KindArch arch;
187 uint16_t kind;
188 uint32_t offset;
189 int32_t addend;
190 };
191
Nick Kledzik1bebb282014-09-09 23:52:59 +0000192 struct OptionalRefInfo {
193 bool used;
194 uint16_t kind;
195 uint32_t offset;
196 int32_t addend;
197 };
198
Nick Kledzik2458bec2014-07-16 19:49:02 +0000199 /// Table of architecture specific information for creating stubs.
200 struct StubInfo {
201 const char* binderSymbolName;
202 ReferenceInfo lazyPointerReferenceToHelper;
203 ReferenceInfo lazyPointerReferenceToFinal;
204 ReferenceInfo nonLazyPointerReferenceToBinder;
205 uint8_t codeAlignment;
206
207 uint32_t stubSize;
208 uint8_t stubBytes[16];
209 ReferenceInfo stubReferenceToLP;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000210 OptionalRefInfo optStubReferenceToLP;
211
Nick Kledzik2458bec2014-07-16 19:49:02 +0000212 uint32_t stubHelperSize;
213 uint8_t stubHelperBytes[16];
214 ReferenceInfo stubHelperReferenceToImm;
215 ReferenceInfo stubHelperReferenceToHelperCommon;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000216
Nick Kledzik2458bec2014-07-16 19:49:02 +0000217 uint32_t stubHelperCommonSize;
218 uint8_t stubHelperCommonBytes[36];
219 ReferenceInfo stubHelperCommonReferenceToCache;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000220 OptionalRefInfo optStubHelperCommonReferenceToCache;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000221 ReferenceInfo stubHelperCommonReferenceToBinder;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000222 OptionalRefInfo optStubHelperCommonReferenceToBinder;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000223 };
224
225 virtual const StubInfo &stubInfo() = 0;
226
227protected:
228 ArchHandler();
229
230 static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
231 static std::unique_ptr<mach_o::ArchHandler> create_x86();
232 static std::unique_ptr<mach_o::ArchHandler> create_arm();
Nick Kledzik1bebb282014-09-09 23:52:59 +0000233 static std::unique_ptr<mach_o::ArchHandler> create_arm64();
Nick Kledzik2458bec2014-07-16 19:49:02 +0000234
235 // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
236 typedef uint16_t RelocPattern;
237 enum {
238 rScattered = 0x8000,
239 rPcRel = 0x4000,
240 rExtern = 0x2000,
241 rLength1 = 0x0000,
242 rLength2 = 0x0100,
243 rLength4 = 0x0200,
Nick Kledzikb78ad892014-07-22 23:07:49 +0000244 rLength8 = 0x0300,
245 rLenArmLo = rLength1,
246 rLenArmHi = rLength2,
247 rLenThmbLo = rLength4,
248 rLenThmbHi = rLength8
Nick Kledzik2458bec2014-07-16 19:49:02 +0000249 };
Nick Kledzik2d432352014-07-17 23:16:21 +0000250 /// Extract RelocPattern from normalized mach-o relocation.
Nick Kledzik2458bec2014-07-16 19:49:02 +0000251 static RelocPattern relocPattern(const normalized::Relocation &reloc);
Nick Kledzik2d432352014-07-17 23:16:21 +0000252 /// Create normalized Relocation initialized from pattern.
253 static normalized::Relocation relocFromPattern(RelocPattern pattern);
254 /// One liner to add a relocation.
255 static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
256 uint32_t symbol, uint32_t value,
257 RelocPattern pattern);
258
Nick Kledzik2458bec2014-07-16 19:49:02 +0000259
260 static int16_t readS16(bool swap, const uint8_t *addr);
261 static int32_t readS32(bool swap, const uint8_t *addr);
262 static uint32_t readU32(bool swap, const uint8_t *addr);
263 static int64_t readS64(bool swap, const uint8_t *addr);
264};
265
266} // namespace mach_o
267} // namespace lld
268
269#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H