blob: 2f4a3cb18b9e1529b39b67a074f9c14d3d3ff6fb [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
Nick Kledzik7e9808f2014-07-23 00:51:37 +000010#include "Atoms.h"
Nick Kledzik4121bce2014-10-14 01:51:42 +000011#include "File.h"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000012#include "MachONormalizedFile.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000013#include "lld/Core/LLVM.h"
14#include "lld/Core/Reference.h"
15#include "lld/Core/Simple.h"
16#include "lld/ReaderWriter/MachOLinkingContext.h"
Nick Kledzik2458bec2014-07-16 19:49:02 +000017#include "llvm/ADT/Triple.h"
18
19#ifndef LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
20#define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
21
22namespace 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();
32
33 /// 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;
39
40 /// Convert mach-o Arch to Reference::KindArch.
41 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
Nick Kledzik4121bce2014-10-14 01:51:42 +000052 /// Used by ShimPass to insert shims in branches that switch mode.
53 virtual bool isNonCallBranch(const Reference &) = 0;
54
Nick Kledzik2458bec2014-07-16 19:49:02 +000055 /// Used by GOTPass to update GOT References
56 virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
57
Tim Northovercf78d372014-09-30 21:29:54 +000058 /// Does this architecture make use of __unwind_info sections for exception
59 /// handling? If so, it will need a separate pass to create them.
60 virtual bool needsCompactUnwind() = 0;
61
62 /// Returns the kind of reference to use to synthesize a 32-bit image-offset
63 /// value, used in the __unwind_info section.
64 virtual Reference::KindValue imageOffsetKind() = 0;
65
66 /// Returns the kind of reference to use to synthesize a 32-bit image-offset
67 /// indirect value. Used for personality functions in the __unwind_info
68 /// section.
69 virtual Reference::KindValue imageOffsetKindIndirect() = 0;
70
Tim Northover1cc4fb72014-10-15 19:32:21 +000071 /// Architecture specific compact unwind type that signals __eh_frame should
72 /// actually be used.
73 virtual uint32_t dwarfCompactUnwindType() = 0;
74
Tim Northover995abe32014-10-15 20:26:24 +000075 /// Reference from an __eh_frame FDE to the CIE it's based on.
76 virtual Reference::KindValue unwindRefToCIEKind() = 0;
77
Tim Northovera6a6ab92014-10-15 18:19:31 +000078 /// Reference from an __eh_frame FDE atom to the function it's
79 /// describing. Usually pointer-sized and PC-relative, but differs in whether
80 /// it needs to be in relocatable objects.
81 virtual Reference::KindValue unwindRefToFunctionKind() = 0;
Tim Northovercf78d372014-09-30 21:29:54 +000082
Tim Northover1cc4fb72014-10-15 19:32:21 +000083 /// Reference from an __unwind_info entry of dwarfCompactUnwindType to the
84 /// required __eh_frame entry. On current architectures, the low 24 bits
85 /// represent the offset of the function's FDE entry from the start of
86 /// __eh_frame.
87 virtual Reference::KindValue unwindRefToEhFrameKind() = 0;
88
Tim Northover933bead2014-10-16 20:52:18 +000089 virtual const Atom *fdeTargetFunction(const DefinedAtom *fde);
90
Nick Kledzik2458bec2014-07-16 19:49:02 +000091 /// Used by normalizedFromAtoms() to know where to generated rebasing and
92 /// binding info in final executables.
93 virtual bool isPointer(const Reference &) = 0;
94
95 /// Used by normalizedFromAtoms() to know where to generated lazy binding
96 /// info in final executables.
97 virtual bool isLazyPointer(const Reference &);
98
99 /// Returns true if the specified relocation is paired to the next relocation.
100 virtual bool isPairedReloc(const normalized::Relocation &) = 0;
101
102 /// Prototype for a helper function. Given a sectionIndex and address,
103 /// finds the atom and offset with that atom of that address.
104 typedef std::function<std::error_code (uint32_t sectionIndex, uint64_t addr,
105 const lld::Atom **, Reference::Addend *)>
106 FindAtomBySectionAndAddress;
107
108 /// Prototype for a helper function. Given a symbolIndex, finds the atom
109 /// representing that symbol.
110 typedef std::function<std::error_code (uint32_t symbolIndex,
111 const lld::Atom **)> FindAtomBySymbolIndex;
112
113 /// Analyzes a relocation from a .o file and returns the info
114 /// (kind, target, addend) needed to instantiate a Reference.
115 /// Two helper functions are passed as parameters to find the target atom
116 /// given a symbol index or address.
117 virtual std::error_code
118 getReferenceInfo(const normalized::Relocation &reloc,
119 const DefinedAtom *inAtom,
120 uint32_t offsetInAtom,
121 uint64_t fixupAddress, bool swap,
122 FindAtomBySectionAndAddress atomFromAddress,
123 FindAtomBySymbolIndex atomFromSymbolIndex,
124 Reference::KindValue *kind,
125 const lld::Atom **target,
126 Reference::Addend *addend) = 0;
127
128 /// Analyzes a pair of relocations from a .o file and returns the info
129 /// (kind, target, addend) needed to instantiate a Reference.
130 /// Two helper functions are passed as parameters to find the target atom
131 /// given a symbol index or address.
132 virtual std::error_code
133 getPairReferenceInfo(const normalized::Relocation &reloc1,
134 const normalized::Relocation &reloc2,
135 const DefinedAtom *inAtom,
136 uint32_t offsetInAtom,
137 uint64_t fixupAddress, bool swap,
138 FindAtomBySectionAndAddress atomFromAddress,
139 FindAtomBySymbolIndex atomFromSymbolIndex,
140 Reference::KindValue *kind,
141 const lld::Atom **target,
142 Reference::Addend *addend) = 0;
143
Nick Kledzik2d432352014-07-17 23:16:21 +0000144 /// Prototype for a helper function. Given an atom, finds the symbol table
145 /// index for it in the output file.
146 typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
147
148 /// Prototype for a helper function. Given an atom, finds the index
149 /// of the section that will contain the atom.
150 typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
151
152 /// Prototype for a helper function. Given an atom, finds the address
153 /// assigned to it in the output file.
154 typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
155
156 /// Some architectures require local symbols on anonymous atoms.
157 virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
158 return false;
159 }
160
161 /// Copy raw content then apply all fixup References on an Atom.
162 virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
163 FindAddressForAtom findAddress,
Tim Northover1cc4fb72014-10-15 19:32:21 +0000164 FindAddressForAtom findSectionAddress,
Tim Northovercf78d372014-09-30 21:29:54 +0000165 uint64_t imageBaseAddress,
Nick Kledzik2d432352014-07-17 23:16:21 +0000166 uint8_t *atomContentBuffer) = 0;
167
168 /// Used in -r mode to convert a Reference to a mach-o relocation.
169 virtual void appendSectionRelocations(const DefinedAtom &atom,
170 uint64_t atomSectionOffset,
171 const Reference &ref,
172 FindSymbolIndexForAtom,
173 FindSectionIndexForAtom,
174 FindAddressForAtom,
175 normalized::Relocations&) = 0;
176
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000177 /// Add arch-specific References.
178 virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
179
Nick Kledzik21921372014-07-24 23:06:56 +0000180 // Add Reference for data-in-code marker.
181 virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
182 uint16_t length, uint16_t kind) { }
183
184 /// Returns true if the specificed Reference value marks the start or end
185 /// of a data-in-code range in an atom.
186 virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
187 return false;
188 }
189
190 /// Returns the Reference value for a Reference that marks that start of
191 /// a data-in-code range.
192 virtual Reference::KindValue dataInCodeTransitionStart(
193 const MachODefinedAtom &atom) {
194 return 0;
195 }
196
197 /// Returns the Reference value for a Reference that marks that end of
198 /// a data-in-code range.
199 virtual Reference::KindValue dataInCodeTransitionEnd(
200 const MachODefinedAtom &atom) {
201 return 0;
202 }
203
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000204 /// Only relevant for 32-bit arm archs.
205 virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000206
Nick Kledzik4121bce2014-10-14 01:51:42 +0000207 /// Only relevant for 32-bit arm archs.
208 virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
209 const DefinedAtom &) {
210 llvm_unreachable("shims only support on arm");
211 }
212
Tim Northover1cc4fb72014-10-15 19:32:21 +0000213 /// Does a given unwind-cfi atom represent a CIE (as opposed to an FDE).
214 static bool isDwarfCIE(bool swap, const DefinedAtom *atom);
215
Nick Kledzik2458bec2014-07-16 19:49:02 +0000216 struct ReferenceInfo {
217 Reference::KindArch arch;
218 uint16_t kind;
219 uint32_t offset;
220 int32_t addend;
221 };
222
Nick Kledzik1bebb282014-09-09 23:52:59 +0000223 struct OptionalRefInfo {
224 bool used;
225 uint16_t kind;
226 uint32_t offset;
227 int32_t addend;
228 };
229
Nick Kledzik2458bec2014-07-16 19:49:02 +0000230 /// Table of architecture specific information for creating stubs.
231 struct StubInfo {
232 const char* binderSymbolName;
233 ReferenceInfo lazyPointerReferenceToHelper;
234 ReferenceInfo lazyPointerReferenceToFinal;
235 ReferenceInfo nonLazyPointerReferenceToBinder;
236 uint8_t codeAlignment;
237
238 uint32_t stubSize;
239 uint8_t stubBytes[16];
240 ReferenceInfo stubReferenceToLP;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000241 OptionalRefInfo optStubReferenceToLP;
242
Nick Kledzik2458bec2014-07-16 19:49:02 +0000243 uint32_t stubHelperSize;
244 uint8_t stubHelperBytes[16];
245 ReferenceInfo stubHelperReferenceToImm;
246 ReferenceInfo stubHelperReferenceToHelperCommon;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000247
Nick Kledzik2458bec2014-07-16 19:49:02 +0000248 uint32_t stubHelperCommonSize;
249 uint8_t stubHelperCommonBytes[36];
250 ReferenceInfo stubHelperCommonReferenceToCache;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000251 OptionalRefInfo optStubHelperCommonReferenceToCache;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000252 ReferenceInfo stubHelperCommonReferenceToBinder;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000253 OptionalRefInfo optStubHelperCommonReferenceToBinder;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000254 };
255
256 virtual const StubInfo &stubInfo() = 0;
257
258protected:
259 ArchHandler();
260
261 static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
262 static std::unique_ptr<mach_o::ArchHandler> create_x86();
263 static std::unique_ptr<mach_o::ArchHandler> create_arm();
Nick Kledzik1bebb282014-09-09 23:52:59 +0000264 static std::unique_ptr<mach_o::ArchHandler> create_arm64();
Nick Kledzik2458bec2014-07-16 19:49:02 +0000265
266 // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
267 typedef uint16_t RelocPattern;
268 enum {
269 rScattered = 0x8000,
270 rPcRel = 0x4000,
271 rExtern = 0x2000,
272 rLength1 = 0x0000,
273 rLength2 = 0x0100,
274 rLength4 = 0x0200,
Nick Kledzikb78ad892014-07-22 23:07:49 +0000275 rLength8 = 0x0300,
276 rLenArmLo = rLength1,
277 rLenArmHi = rLength2,
278 rLenThmbLo = rLength4,
279 rLenThmbHi = rLength8
Nick Kledzik2458bec2014-07-16 19:49:02 +0000280 };
Nick Kledzik2d432352014-07-17 23:16:21 +0000281 /// Extract RelocPattern from normalized mach-o relocation.
Nick Kledzik2458bec2014-07-16 19:49:02 +0000282 static RelocPattern relocPattern(const normalized::Relocation &reloc);
Nick Kledzik2d432352014-07-17 23:16:21 +0000283 /// Create normalized Relocation initialized from pattern.
284 static normalized::Relocation relocFromPattern(RelocPattern pattern);
285 /// One liner to add a relocation.
286 static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
287 uint32_t symbol, uint32_t value,
288 RelocPattern pattern);
289
Nick Kledzik2458bec2014-07-16 19:49:02 +0000290
291 static int16_t readS16(bool swap, const uint8_t *addr);
292 static int32_t readS32(bool swap, const uint8_t *addr);
293 static uint32_t readU32(bool swap, const uint8_t *addr);
294 static int64_t readS64(bool swap, const uint8_t *addr);
295};
296
297} // namespace mach_o
298} // namespace lld
299
300#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H