blob: cf479c83a00ec2db4ed37f30e01138ff75dc10af [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"
11
12#include "lld/Core/LLVM.h"
13#include "lld/Core/Reference.h"
14#include "lld/Core/Simple.h"
15#include "lld/ReaderWriter/MachOLinkingContext.h"
16
17#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
52 /// Used by GOTPass to update GOT References
53 virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
54
55 /// Used by normalizedFromAtoms() to know where to generated rebasing and
56 /// binding info in final executables.
57 virtual bool isPointer(const Reference &) = 0;
58
59 /// Used by normalizedFromAtoms() to know where to generated lazy binding
60 /// info in final executables.
61 virtual bool isLazyPointer(const Reference &);
62
63 /// Returns true if the specified relocation is paired to the next relocation.
64 virtual bool isPairedReloc(const normalized::Relocation &) = 0;
65
66 /// Prototype for a helper function. Given a sectionIndex and address,
67 /// finds the atom and offset with that atom of that address.
68 typedef std::function<std::error_code (uint32_t sectionIndex, uint64_t addr,
69 const lld::Atom **, Reference::Addend *)>
70 FindAtomBySectionAndAddress;
71
72 /// Prototype for a helper function. Given a symbolIndex, finds the atom
73 /// representing that symbol.
74 typedef std::function<std::error_code (uint32_t symbolIndex,
75 const lld::Atom **)> FindAtomBySymbolIndex;
76
77 /// Analyzes a relocation from a .o file and returns the info
78 /// (kind, target, addend) needed to instantiate a Reference.
79 /// Two helper functions are passed as parameters to find the target atom
80 /// given a symbol index or address.
81 virtual std::error_code
82 getReferenceInfo(const normalized::Relocation &reloc,
83 const DefinedAtom *inAtom,
84 uint32_t offsetInAtom,
85 uint64_t fixupAddress, bool swap,
86 FindAtomBySectionAndAddress atomFromAddress,
87 FindAtomBySymbolIndex atomFromSymbolIndex,
88 Reference::KindValue *kind,
89 const lld::Atom **target,
90 Reference::Addend *addend) = 0;
91
92 /// Analyzes a pair of relocations 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 getPairReferenceInfo(const normalized::Relocation &reloc1,
98 const normalized::Relocation &reloc2,
99 const DefinedAtom *inAtom,
100 uint32_t offsetInAtom,
101 uint64_t fixupAddress, bool swap,
102 FindAtomBySectionAndAddress atomFromAddress,
103 FindAtomBySymbolIndex atomFromSymbolIndex,
104 Reference::KindValue *kind,
105 const lld::Atom **target,
106 Reference::Addend *addend) = 0;
107
Nick Kledzik2d432352014-07-17 23:16:21 +0000108 /// Prototype for a helper function. Given an atom, finds the symbol table
109 /// index for it in the output file.
110 typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
111
112 /// Prototype for a helper function. Given an atom, finds the index
113 /// of the section that will contain the atom.
114 typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
115
116 /// Prototype for a helper function. Given an atom, finds the address
117 /// assigned to it in the output file.
118 typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
119
120 /// Some architectures require local symbols on anonymous atoms.
121 virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
122 return false;
123 }
124
125 /// Copy raw content then apply all fixup References on an Atom.
126 virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
127 FindAddressForAtom findAddress,
128 uint8_t *atomContentBuffer) = 0;
129
130 /// Used in -r mode to convert a Reference to a mach-o relocation.
131 virtual void appendSectionRelocations(const DefinedAtom &atom,
132 uint64_t atomSectionOffset,
133 const Reference &ref,
134 FindSymbolIndexForAtom,
135 FindSectionIndexForAtom,
136 FindAddressForAtom,
137 normalized::Relocations&) = 0;
138
Nick Kledzik2458bec2014-07-16 19:49:02 +0000139
140 struct ReferenceInfo {
141 Reference::KindArch arch;
142 uint16_t kind;
143 uint32_t offset;
144 int32_t addend;
145 };
146
147 /// Table of architecture specific information for creating stubs.
148 struct StubInfo {
149 const char* binderSymbolName;
150 ReferenceInfo lazyPointerReferenceToHelper;
151 ReferenceInfo lazyPointerReferenceToFinal;
152 ReferenceInfo nonLazyPointerReferenceToBinder;
153 uint8_t codeAlignment;
154
155 uint32_t stubSize;
156 uint8_t stubBytes[16];
157 ReferenceInfo stubReferenceToLP;
158
159 uint32_t stubHelperSize;
160 uint8_t stubHelperBytes[16];
161 ReferenceInfo stubHelperReferenceToImm;
162 ReferenceInfo stubHelperReferenceToHelperCommon;
163
164 uint32_t stubHelperCommonSize;
165 uint8_t stubHelperCommonBytes[36];
166 ReferenceInfo stubHelperCommonReferenceToCache;
167 ReferenceInfo stubHelperCommonReferenceToBinder;
168 };
169
170 virtual const StubInfo &stubInfo() = 0;
171
172protected:
173 ArchHandler();
174
175 static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
176 static std::unique_ptr<mach_o::ArchHandler> create_x86();
177 static std::unique_ptr<mach_o::ArchHandler> create_arm();
178
179 // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
180 typedef uint16_t RelocPattern;
181 enum {
182 rScattered = 0x8000,
183 rPcRel = 0x4000,
184 rExtern = 0x2000,
185 rLength1 = 0x0000,
186 rLength2 = 0x0100,
187 rLength4 = 0x0200,
188 rLength8 = 0x0300
189 };
Nick Kledzik2d432352014-07-17 23:16:21 +0000190 /// Extract RelocPattern from normalized mach-o relocation.
Nick Kledzik2458bec2014-07-16 19:49:02 +0000191 static RelocPattern relocPattern(const normalized::Relocation &reloc);
Nick Kledzik2d432352014-07-17 23:16:21 +0000192 /// Create normalized Relocation initialized from pattern.
193 static normalized::Relocation relocFromPattern(RelocPattern pattern);
194 /// One liner to add a relocation.
195 static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
196 uint32_t symbol, uint32_t value,
197 RelocPattern pattern);
198
Nick Kledzik2458bec2014-07-16 19:49:02 +0000199
200 static int16_t readS16(bool swap, const uint8_t *addr);
201 static int32_t readS32(bool swap, const uint8_t *addr);
202 static uint32_t readU32(bool swap, const uint8_t *addr);
203 static int64_t readS64(bool swap, const uint8_t *addr);
204};
205
206} // namespace mach_o
207} // namespace lld
208
209#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H