blob: 9118535085c19a82dde614b25119570e638b750f [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
56 /// Used by normalizedFromAtoms() to know where to generated rebasing and
57 /// binding info in final executables.
58 virtual bool isPointer(const Reference &) = 0;
59
60 /// Used by normalizedFromAtoms() to know where to generated lazy binding
61 /// info in final executables.
62 virtual bool isLazyPointer(const Reference &);
63
64 /// Returns true if the specified relocation is paired to the next relocation.
65 virtual bool isPairedReloc(const normalized::Relocation &) = 0;
66
67 /// Prototype for a helper function. Given a sectionIndex and address,
68 /// finds the atom and offset with that atom of that address.
69 typedef std::function<std::error_code (uint32_t sectionIndex, uint64_t addr,
70 const lld::Atom **, Reference::Addend *)>
71 FindAtomBySectionAndAddress;
72
73 /// Prototype for a helper function. Given a symbolIndex, finds the atom
74 /// representing that symbol.
75 typedef std::function<std::error_code (uint32_t symbolIndex,
76 const lld::Atom **)> FindAtomBySymbolIndex;
77
78 /// Analyzes a relocation from a .o file and returns the info
79 /// (kind, target, addend) needed to instantiate a Reference.
80 /// Two helper functions are passed as parameters to find the target atom
81 /// given a symbol index or address.
82 virtual std::error_code
83 getReferenceInfo(const normalized::Relocation &reloc,
84 const DefinedAtom *inAtom,
85 uint32_t offsetInAtom,
86 uint64_t fixupAddress, bool swap,
87 FindAtomBySectionAndAddress atomFromAddress,
88 FindAtomBySymbolIndex atomFromSymbolIndex,
89 Reference::KindValue *kind,
90 const lld::Atom **target,
91 Reference::Addend *addend) = 0;
92
93 /// Analyzes a pair of relocations from a .o file and returns the info
94 /// (kind, target, addend) needed to instantiate a Reference.
95 /// Two helper functions are passed as parameters to find the target atom
96 /// given a symbol index or address.
97 virtual std::error_code
98 getPairReferenceInfo(const normalized::Relocation &reloc1,
99 const normalized::Relocation &reloc2,
100 const DefinedAtom *inAtom,
101 uint32_t offsetInAtom,
102 uint64_t fixupAddress, bool swap,
103 FindAtomBySectionAndAddress atomFromAddress,
104 FindAtomBySymbolIndex atomFromSymbolIndex,
105 Reference::KindValue *kind,
106 const lld::Atom **target,
107 Reference::Addend *addend) = 0;
108
Nick Kledzik2d432352014-07-17 23:16:21 +0000109 /// Prototype for a helper function. Given an atom, finds the symbol table
110 /// index for it in the output file.
111 typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
112
113 /// Prototype for a helper function. Given an atom, finds the index
114 /// of the section that will contain the atom.
115 typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
116
117 /// Prototype for a helper function. Given an atom, finds the address
118 /// assigned to it in the output file.
119 typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
120
121 /// Some architectures require local symbols on anonymous atoms.
122 virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
123 return false;
124 }
125
126 /// Copy raw content then apply all fixup References on an Atom.
127 virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
128 FindAddressForAtom findAddress,
129 uint8_t *atomContentBuffer) = 0;
130
131 /// Used in -r mode to convert a Reference to a mach-o relocation.
132 virtual void appendSectionRelocations(const DefinedAtom &atom,
133 uint64_t atomSectionOffset,
134 const Reference &ref,
135 FindSymbolIndexForAtom,
136 FindSectionIndexForAtom,
137 FindAddressForAtom,
138 normalized::Relocations&) = 0;
139
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000140 /// Add arch-specific References.
141 virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
142
Nick Kledzik21921372014-07-24 23:06:56 +0000143 // Add Reference for data-in-code marker.
144 virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
145 uint16_t length, uint16_t kind) { }
146
147 /// Returns true if the specificed Reference value marks the start or end
148 /// of a data-in-code range in an atom.
149 virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
150 return false;
151 }
152
153 /// Returns the Reference value for a Reference that marks that start of
154 /// a data-in-code range.
155 virtual Reference::KindValue dataInCodeTransitionStart(
156 const MachODefinedAtom &atom) {
157 return 0;
158 }
159
160 /// Returns the Reference value for a Reference that marks that end of
161 /// a data-in-code range.
162 virtual Reference::KindValue dataInCodeTransitionEnd(
163 const MachODefinedAtom &atom) {
164 return 0;
165 }
166
Nick Kledzik7e9808f2014-07-23 00:51:37 +0000167 /// Only relevant for 32-bit arm archs.
168 virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
Nick Kledzik2458bec2014-07-16 19:49:02 +0000169
170 struct ReferenceInfo {
171 Reference::KindArch arch;
172 uint16_t kind;
173 uint32_t offset;
174 int32_t addend;
175 };
176
Nick Kledzik1bebb282014-09-09 23:52:59 +0000177 struct OptionalRefInfo {
178 bool used;
179 uint16_t kind;
180 uint32_t offset;
181 int32_t addend;
182 };
183
Nick Kledzik2458bec2014-07-16 19:49:02 +0000184 /// Table of architecture specific information for creating stubs.
185 struct StubInfo {
186 const char* binderSymbolName;
187 ReferenceInfo lazyPointerReferenceToHelper;
188 ReferenceInfo lazyPointerReferenceToFinal;
189 ReferenceInfo nonLazyPointerReferenceToBinder;
190 uint8_t codeAlignment;
191
192 uint32_t stubSize;
193 uint8_t stubBytes[16];
194 ReferenceInfo stubReferenceToLP;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000195 OptionalRefInfo optStubReferenceToLP;
196
Nick Kledzik2458bec2014-07-16 19:49:02 +0000197 uint32_t stubHelperSize;
198 uint8_t stubHelperBytes[16];
199 ReferenceInfo stubHelperReferenceToImm;
200 ReferenceInfo stubHelperReferenceToHelperCommon;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000201
Nick Kledzik2458bec2014-07-16 19:49:02 +0000202 uint32_t stubHelperCommonSize;
203 uint8_t stubHelperCommonBytes[36];
204 ReferenceInfo stubHelperCommonReferenceToCache;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000205 OptionalRefInfo optStubHelperCommonReferenceToCache;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000206 ReferenceInfo stubHelperCommonReferenceToBinder;
Nick Kledzik1bebb282014-09-09 23:52:59 +0000207 OptionalRefInfo optStubHelperCommonReferenceToBinder;
Nick Kledzik2458bec2014-07-16 19:49:02 +0000208 };
209
210 virtual const StubInfo &stubInfo() = 0;
211
212protected:
213 ArchHandler();
214
215 static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
216 static std::unique_ptr<mach_o::ArchHandler> create_x86();
217 static std::unique_ptr<mach_o::ArchHandler> create_arm();
Nick Kledzik1bebb282014-09-09 23:52:59 +0000218 static std::unique_ptr<mach_o::ArchHandler> create_arm64();
Nick Kledzik2458bec2014-07-16 19:49:02 +0000219
220 // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
221 typedef uint16_t RelocPattern;
222 enum {
223 rScattered = 0x8000,
224 rPcRel = 0x4000,
225 rExtern = 0x2000,
226 rLength1 = 0x0000,
227 rLength2 = 0x0100,
228 rLength4 = 0x0200,
Nick Kledzikb78ad892014-07-22 23:07:49 +0000229 rLength8 = 0x0300,
230 rLenArmLo = rLength1,
231 rLenArmHi = rLength2,
232 rLenThmbLo = rLength4,
233 rLenThmbHi = rLength8
Nick Kledzik2458bec2014-07-16 19:49:02 +0000234 };
Nick Kledzik2d432352014-07-17 23:16:21 +0000235 /// Extract RelocPattern from normalized mach-o relocation.
Nick Kledzik2458bec2014-07-16 19:49:02 +0000236 static RelocPattern relocPattern(const normalized::Relocation &reloc);
Nick Kledzik2d432352014-07-17 23:16:21 +0000237 /// Create normalized Relocation initialized from pattern.
238 static normalized::Relocation relocFromPattern(RelocPattern pattern);
239 /// One liner to add a relocation.
240 static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
241 uint32_t symbol, uint32_t value,
242 RelocPattern pattern);
243
Nick Kledzik2458bec2014-07-16 19:49:02 +0000244
245 static int16_t readS16(bool swap, const uint8_t *addr);
246 static int32_t readS32(bool swap, const uint8_t *addr);
247 static uint32_t readU32(bool swap, const uint8_t *addr);
248 static int64_t readS64(bool swap, const uint8_t *addr);
249};
250
251} // namespace mach_o
252} // namespace lld
253
254#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H