Line data Source code
1 : //===-- RuntimeDyldMachOAArch64.h -- MachO/AArch64 specific code. -*- C++ -*-=//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H
11 : #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H
12 :
13 : #include "../RuntimeDyldMachO.h"
14 : #include "llvm/Support/Endian.h"
15 :
16 : #define DEBUG_TYPE "dyld"
17 :
18 : namespace llvm {
19 :
20 : class RuntimeDyldMachOAArch64
21 : : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOAArch64> {
22 : public:
23 :
24 : typedef uint64_t TargetPtrT;
25 :
26 : RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM,
27 : JITSymbolResolver &Resolver)
28 1 : : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
29 :
30 4 : unsigned getMaxStubSize() override { return 8; }
31 :
32 7 : unsigned getStubAlignment() override { return 8; }
33 :
34 : /// Extract the addend encoded in the instruction / memory location.
35 10 : Expected<int64_t> decodeAddend(const RelocationEntry &RE) const {
36 10 : const SectionEntry &Section = Sections[RE.SectionID];
37 10 : uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
38 10 : unsigned NumBytes = 1 << RE.Size;
39 : int64_t Addend = 0;
40 : // Verify that the relocation has the correct size and alignment.
41 10 : switch (RE.RelType) {
42 : default: {
43 : std::string ErrMsg;
44 : {
45 0 : raw_string_ostream ErrStream(ErrMsg);
46 0 : ErrStream << "Unsupported relocation type: "
47 0 : << getRelocName(RE.RelType);
48 : }
49 0 : return make_error<StringError>(std::move(ErrMsg),
50 0 : inconvertibleErrorCode());
51 : }
52 3 : case MachO::ARM64_RELOC_POINTER_TO_GOT:
53 : case MachO::ARM64_RELOC_UNSIGNED: {
54 3 : if (NumBytes != 4 && NumBytes != 8) {
55 : std::string ErrMsg;
56 : {
57 0 : raw_string_ostream ErrStream(ErrMsg);
58 0 : ErrStream << "Invalid relocation size for relocation "
59 0 : << getRelocName(RE.RelType);
60 : }
61 0 : return make_error<StringError>(std::move(ErrMsg),
62 0 : inconvertibleErrorCode());
63 : }
64 : break;
65 : }
66 : case MachO::ARM64_RELOC_BRANCH26:
67 : case MachO::ARM64_RELOC_PAGE21:
68 : case MachO::ARM64_RELOC_PAGEOFF12:
69 : case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
70 : case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
71 : assert(NumBytes == 4 && "Invalid relocation size.");
72 : assert((((uintptr_t)LocalAddress & 0x3) == 0) &&
73 : "Instruction address is not aligned to 4 bytes.");
74 : break;
75 : }
76 :
77 10 : switch (RE.RelType) {
78 0 : default:
79 0 : llvm_unreachable("Unsupported relocation type!");
80 3 : case MachO::ARM64_RELOC_POINTER_TO_GOT:
81 : case MachO::ARM64_RELOC_UNSIGNED:
82 : // This could be an unaligned memory location.
83 3 : if (NumBytes == 4)
84 1 : Addend = *reinterpret_cast<support::ulittle32_t *>(LocalAddress);
85 : else
86 2 : Addend = *reinterpret_cast<support::ulittle64_t *>(LocalAddress);
87 : break;
88 2 : case MachO::ARM64_RELOC_BRANCH26: {
89 : // Verify that the relocation points to a B/BL instruction.
90 : auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
91 : assert(((*p & 0xFC000000) == 0x14000000 ||
92 : (*p & 0xFC000000) == 0x94000000) &&
93 : "Expected branch instruction.");
94 :
95 : // Get the 26 bit addend encoded in the branch instruction and sign-extend
96 : // to 64 bit. The lower 2 bits are always zeros and are therefore implicit
97 : // (<< 2).
98 2 : Addend = (*p & 0x03FFFFFF) << 2;
99 2 : Addend = SignExtend64(Addend, 28);
100 2 : break;
101 : }
102 2 : case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
103 : case MachO::ARM64_RELOC_PAGE21: {
104 : // Verify that the relocation points to the expected adrp instruction.
105 : auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
106 : assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction.");
107 :
108 : // Get the 21 bit addend encoded in the adrp instruction and sign-extend
109 : // to 64 bit. The lower 12 bits (4096 byte page) are always zeros and are
110 : // therefore implicit (<< 12).
111 2 : Addend = ((*p & 0x60000000) >> 29) | ((*p & 0x01FFFFE0) >> 3) << 12;
112 2 : Addend = SignExtend64(Addend, 33);
113 2 : break;
114 : }
115 : case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
116 : // Verify that the relocation points to one of the expected load / store
117 : // instructions.
118 : auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
119 : (void)p;
120 : assert((*p & 0x3B000000) == 0x39000000 &&
121 : "Only expected load / store instructions.");
122 : LLVM_FALLTHROUGH;
123 : }
124 3 : case MachO::ARM64_RELOC_PAGEOFF12: {
125 : // Verify that the relocation points to one of the expected load / store
126 : // or add / sub instructions.
127 : auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
128 : assert((((*p & 0x3B000000) == 0x39000000) ||
129 : ((*p & 0x11C00000) == 0x11000000) ) &&
130 : "Expected load / store or add/sub instruction.");
131 :
132 : // Get the 12 bit addend encoded in the instruction.
133 3 : Addend = (*p & 0x003FFC00) >> 10;
134 :
135 : // Check which instruction we are decoding to obtain the implicit shift
136 : // factor of the instruction.
137 : int ImplicitShift = 0;
138 3 : if ((*p & 0x3B000000) == 0x39000000) { // << load / store
139 : // For load / store instructions the size is encoded in bits 31:30.
140 2 : ImplicitShift = ((*p >> 30) & 0x3);
141 2 : if (ImplicitShift == 0) {
142 : // Check if this a vector op to get the correct shift value.
143 0 : if ((*p & 0x04800000) == 0x04800000)
144 : ImplicitShift = 4;
145 : }
146 : }
147 : // Compensate for implicit shift.
148 3 : Addend <<= ImplicitShift;
149 3 : break;
150 : }
151 : }
152 : return Addend;
153 : }
154 :
155 : /// Extract the addend encoded in the instruction.
156 12 : void encodeAddend(uint8_t *LocalAddress, unsigned NumBytes,
157 : MachO::RelocationInfoType RelType, int64_t Addend) const {
158 : // Verify that the relocation has the correct alignment.
159 : switch (RelType) {
160 0 : default:
161 0 : llvm_unreachable("Unsupported relocation type!");
162 : case MachO::ARM64_RELOC_POINTER_TO_GOT:
163 : case MachO::ARM64_RELOC_UNSIGNED:
164 : assert((NumBytes == 4 || NumBytes == 8) && "Invalid relocation size.");
165 : break;
166 : case MachO::ARM64_RELOC_BRANCH26:
167 : case MachO::ARM64_RELOC_PAGE21:
168 : case MachO::ARM64_RELOC_PAGEOFF12:
169 : case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
170 : case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
171 : assert(NumBytes == 4 && "Invalid relocation size.");
172 : assert((((uintptr_t)LocalAddress & 0x3) == 0) &&
173 : "Instruction address is not aligned to 4 bytes.");
174 : break;
175 : }
176 :
177 12 : switch (RelType) {
178 0 : default:
179 0 : llvm_unreachable("Unsupported relocation type!");
180 5 : case MachO::ARM64_RELOC_POINTER_TO_GOT:
181 : case MachO::ARM64_RELOC_UNSIGNED:
182 : // This could be an unaligned memory location.
183 5 : if (NumBytes == 4)
184 1 : *reinterpret_cast<support::ulittle32_t *>(LocalAddress) = Addend;
185 : else
186 4 : *reinterpret_cast<support::ulittle64_t *>(LocalAddress) = Addend;
187 : break;
188 2 : case MachO::ARM64_RELOC_BRANCH26: {
189 : auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
190 : // Verify that the relocation points to the expected branch instruction.
191 : assert(((*p & 0xFC000000) == 0x14000000 ||
192 : (*p & 0xFC000000) == 0x94000000) &&
193 : "Expected branch instruction.");
194 :
195 : // Verify addend value.
196 : assert((Addend & 0x3) == 0 && "Branch target is not aligned");
197 : assert(isInt<28>(Addend) && "Branch target is out of range.");
198 :
199 : // Encode the addend as 26 bit immediate in the branch instruction.
200 2 : *p = (*p & 0xFC000000) | ((uint32_t)(Addend >> 2) & 0x03FFFFFF);
201 : break;
202 : }
203 2 : case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
204 : case MachO::ARM64_RELOC_PAGE21: {
205 : // Verify that the relocation points to the expected adrp instruction.
206 : auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
207 : assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction.");
208 :
209 : // Check that the addend fits into 21 bits (+ 12 lower bits).
210 : assert((Addend & 0xFFF) == 0 && "ADRP target is not page aligned.");
211 : assert(isInt<33>(Addend) && "Invalid page reloc value.");
212 :
213 : // Encode the addend into the instruction.
214 2 : uint32_t ImmLoValue = ((uint64_t)Addend << 17) & 0x60000000;
215 2 : uint32_t ImmHiValue = ((uint64_t)Addend >> 9) & 0x00FFFFE0;
216 2 : *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue;
217 : break;
218 : }
219 : case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
220 : // Verify that the relocation points to one of the expected load / store
221 : // instructions.
222 : auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
223 : assert((*p & 0x3B000000) == 0x39000000 &&
224 : "Only expected load / store instructions.");
225 : (void)p;
226 : LLVM_FALLTHROUGH;
227 : }
228 3 : case MachO::ARM64_RELOC_PAGEOFF12: {
229 : // Verify that the relocation points to one of the expected load / store
230 : // or add / sub instructions.
231 : auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress);
232 : assert((((*p & 0x3B000000) == 0x39000000) ||
233 : ((*p & 0x11C00000) == 0x11000000) ) &&
234 : "Expected load / store or add/sub instruction.");
235 :
236 : // Check which instruction we are decoding to obtain the implicit shift
237 : // factor of the instruction and verify alignment.
238 : int ImplicitShift = 0;
239 3 : if ((*p & 0x3B000000) == 0x39000000) { // << load / store
240 : // For load / store instructions the size is encoded in bits 31:30.
241 2 : ImplicitShift = ((*p >> 30) & 0x3);
242 : switch (ImplicitShift) {
243 : case 0:
244 : // Check if this a vector op to get the correct shift value.
245 0 : if ((*p & 0x04800000) == 0x04800000) {
246 : ImplicitShift = 4;
247 : assert(((Addend & 0xF) == 0) &&
248 : "128-bit LDR/STR not 16-byte aligned.");
249 : }
250 : break;
251 : case 1:
252 : assert(((Addend & 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned.");
253 : break;
254 : case 2:
255 : assert(((Addend & 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned.");
256 : break;
257 : case 3:
258 : assert(((Addend & 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned.");
259 : break;
260 : }
261 : }
262 : // Compensate for implicit shift.
263 3 : Addend >>= ImplicitShift;
264 : assert(isUInt<12>(Addend) && "Addend cannot be encoded.");
265 :
266 : // Encode the addend into the instruction.
267 3 : *p = (*p & 0xFFC003FF) | ((uint32_t)(Addend << 10) & 0x003FFC00);
268 : break;
269 : }
270 : }
271 12 : }
272 :
273 : Expected<relocation_iterator>
274 11 : processRelocationRef(unsigned SectionID, relocation_iterator RelI,
275 : const ObjectFile &BaseObjT,
276 : ObjSectionToIDMap &ObjSectionToID,
277 : StubMap &Stubs) override {
278 : const MachOObjectFile &Obj =
279 : static_cast<const MachOObjectFile &>(BaseObjT);
280 : MachO::any_relocation_info RelInfo =
281 11 : Obj.getRelocation(RelI->getRawDataRefImpl());
282 :
283 11 : if (Obj.isRelocationScattered(RelInfo))
284 : return make_error<RuntimeDyldError>("Scattered relocations not supported "
285 : "for MachO AArch64");
286 :
287 : // ARM64 has an ARM64_RELOC_ADDEND relocation type that carries an explicit
288 : // addend for the following relocation. If found: (1) store the associated
289 : // addend, (2) consume the next relocation, and (3) use the stored addend to
290 : // override the addend.
291 : int64_t ExplicitAddend = 0;
292 11 : if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_ADDEND) {
293 : assert(!Obj.getPlainRelocationExternal(RelInfo));
294 : assert(!Obj.getAnyRelocationPCRel(RelInfo));
295 : assert(Obj.getAnyRelocationLength(RelInfo) == 2);
296 1 : int64_t RawAddend = Obj.getPlainRelocationSymbolNum(RelInfo);
297 : // Sign-extend the 24-bit to 64-bit.
298 1 : ExplicitAddend = SignExtend64(RawAddend, 24);
299 : ++RelI;
300 1 : RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl());
301 : }
302 :
303 11 : if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_SUBTRACTOR)
304 1 : return processSubtractRelocation(SectionID, RelI, Obj, ObjSectionToID);
305 :
306 10 : RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
307 :
308 10 : if (RE.RelType == MachO::ARM64_RELOC_POINTER_TO_GOT) {
309 : bool Valid =
310 2 : (RE.Size == 2 && RE.IsPCRel) || (RE.Size == 3 && !RE.IsPCRel);
311 : if (!Valid)
312 0 : return make_error<StringError>("ARM64_RELOC_POINTER_TO_GOT supports "
313 : "32-bit pc-rel or 64-bit absolute only",
314 0 : inconvertibleErrorCode());
315 : }
316 :
317 10 : if (auto Addend = decodeAddend(RE))
318 10 : RE.Addend = *Addend;
319 : else
320 : return Addend.takeError();
321 :
322 : assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\
323 : "ARM64_RELOC_ADDEND and embedded addend in the instruction.");
324 10 : if (ExplicitAddend)
325 1 : RE.Addend = ExplicitAddend;
326 :
327 : RelocationValueRef Value;
328 10 : if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
329 10 : Value = *ValueOrErr;
330 : else
331 : return ValueOrErr.takeError();
332 :
333 10 : bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
334 10 : if (RE.RelType == MachO::ARM64_RELOC_POINTER_TO_GOT) {
335 : // We'll take care of the offset in processGOTRelocation.
336 2 : Value.Offset = 0;
337 8 : } else if (!IsExtern && RE.IsPCRel)
338 0 : makeValueAddendPCRel(Value, RelI, 1 << RE.Size);
339 :
340 10 : RE.Addend = Value.Offset;
341 :
342 20 : if (RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGE21 ||
343 10 : RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12 ||
344 : RE.RelType == MachO::ARM64_RELOC_POINTER_TO_GOT)
345 4 : processGOTRelocation(RE, Value, Stubs);
346 : else {
347 6 : if (Value.SymbolName)
348 0 : addRelocationForSymbol(RE, Value.SymbolName);
349 : else
350 6 : addRelocationForSection(RE, Value.SectionID);
351 : }
352 :
353 : return ++RelI;
354 : }
355 :
356 13 : void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
357 : LLVM_DEBUG(dumpRelocationToResolve(RE, Value));
358 :
359 13 : const SectionEntry &Section = Sections[RE.SectionID];
360 13 : uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
361 13 : MachO::RelocationInfoType RelType =
362 : static_cast<MachO::RelocationInfoType>(RE.RelType);
363 :
364 13 : switch (RelType) {
365 0 : default:
366 0 : llvm_unreachable("Invalid relocation type!");
367 3 : case MachO::ARM64_RELOC_UNSIGNED: {
368 : assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_UNSIGNED not supported");
369 : // Mask in the target value a byte at a time (we don't have an alignment
370 : // guarantee for the target address, so this is safest).
371 3 : if (RE.Size < 2)
372 0 : llvm_unreachable("Invalid size for ARM64_RELOC_UNSIGNED");
373 :
374 3 : encodeAddend(LocalAddress, 1 << RE.Size, RelType, Value + RE.Addend);
375 3 : break;
376 : }
377 :
378 2 : case MachO::ARM64_RELOC_POINTER_TO_GOT: {
379 : assert(((RE.Size == 2 && RE.IsPCRel) || (RE.Size == 3 && !RE.IsPCRel)) &&
380 : "ARM64_RELOC_POINTER_TO_GOT only supports 32-bit pc-rel or 64-bit "
381 : "absolute");
382 : // Addend is the GOT entry address and RE.Offset the target of the
383 : // relocation.
384 : uint64_t Result =
385 2 : RE.IsPCRel ? (RE.Addend - RE.Offset) : (Value + RE.Addend);
386 2 : encodeAddend(LocalAddress, 1 << RE.Size, RelType, Result);
387 2 : break;
388 : }
389 :
390 2 : case MachO::ARM64_RELOC_BRANCH26: {
391 : assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_BRANCH26 not supported");
392 : // Check if branch is in range.
393 2 : uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
394 2 : int64_t PCRelVal = Value - FinalAddress + RE.Addend;
395 2 : encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal);
396 2 : break;
397 : }
398 2 : case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
399 : case MachO::ARM64_RELOC_PAGE21: {
400 : assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_PAGE21 not supported");
401 : // Adjust for PC-relative relocation and offset.
402 2 : uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
403 2 : int64_t PCRelVal =
404 2 : ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096));
405 2 : encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal);
406 2 : break;
407 : }
408 3 : case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
409 : case MachO::ARM64_RELOC_PAGEOFF12: {
410 : assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_PAGEOFF21 not supported");
411 : // Add the offset from the symbol.
412 3 : Value += RE.Addend;
413 : // Mask out the page address and only use the lower 12 bits.
414 3 : Value &= 0xFFF;
415 3 : encodeAddend(LocalAddress, /*Size=*/4, RelType, Value);
416 3 : break;
417 : }
418 1 : case MachO::ARM64_RELOC_SUBTRACTOR: {
419 1 : uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress();
420 1 : uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress();
421 : assert((Value == SectionABase || Value == SectionBBase) &&
422 : "Unexpected SUBTRACTOR relocation value.");
423 1 : Value = SectionABase - SectionBBase + RE.Addend;
424 1 : writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
425 1 : break;
426 : }
427 :
428 : case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
429 : case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
430 : llvm_unreachable("Relocation type not yet implemented!");
431 : case MachO::ARM64_RELOC_ADDEND:
432 : llvm_unreachable("ARM64_RELOC_ADDEND should have been handeled by "
433 : "processRelocationRef!");
434 : }
435 13 : }
436 :
437 0 : Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
438 : const SectionRef &Section) {
439 0 : return Error::success();
440 : }
441 :
442 : private:
443 4 : void processGOTRelocation(const RelocationEntry &RE,
444 : RelocationValueRef &Value, StubMap &Stubs) {
445 : assert((RE.RelType == MachO::ARM64_RELOC_POINTER_TO_GOT &&
446 : (RE.Size == 2 || RE.Size == 3)) ||
447 : RE.Size == 2);
448 4 : SectionEntry &Section = Sections[RE.SectionID];
449 : StubMap::const_iterator i = Stubs.find(Value);
450 : int64_t Offset;
451 4 : if (i != Stubs.end())
452 2 : Offset = static_cast<int64_t>(i->second);
453 : else {
454 : // FIXME: There must be a better way to do this then to check and fix the
455 : // alignment every time!!!
456 2 : uintptr_t BaseAddress = uintptr_t(Section.getAddress());
457 2 : uintptr_t StubAlignment = getStubAlignment();
458 : uintptr_t StubAddress =
459 2 : (BaseAddress + Section.getStubOffset() + StubAlignment - 1) &
460 2 : -StubAlignment;
461 2 : unsigned StubOffset = StubAddress - BaseAddress;
462 2 : Stubs[Value] = StubOffset;
463 : assert(((StubAddress % getStubAlignment()) == 0) &&
464 : "GOT entry not aligned");
465 2 : RelocationEntry GOTRE(RE.SectionID, StubOffset,
466 2 : MachO::ARM64_RELOC_UNSIGNED, Value.Offset,
467 2 : /*IsPCRel=*/false, /*Size=*/3);
468 2 : if (Value.SymbolName)
469 2 : addRelocationForSymbol(GOTRE, Value.SymbolName);
470 : else
471 1 : addRelocationForSection(GOTRE, Value.SectionID);
472 2 : Section.advanceStubOffset(getMaxStubSize());
473 2 : Offset = static_cast<int64_t>(StubOffset);
474 : }
475 4 : RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, Offset,
476 4 : RE.IsPCRel, RE.Size);
477 4 : addRelocationForSection(TargetRE, RE.SectionID);
478 4 : }
479 :
480 : Expected<relocation_iterator>
481 1 : processSubtractRelocation(unsigned SectionID, relocation_iterator RelI,
482 : const ObjectFile &BaseObjT,
483 : ObjSectionToIDMap &ObjSectionToID) {
484 : const MachOObjectFile &Obj =
485 : static_cast<const MachOObjectFile&>(BaseObjT);
486 : MachO::any_relocation_info RE =
487 1 : Obj.getRelocation(RelI->getRawDataRefImpl());
488 :
489 1 : unsigned Size = Obj.getAnyRelocationLength(RE);
490 1 : uint64_t Offset = RelI->getOffset();
491 2 : uint8_t *LocalAddress = Sections[SectionID].getAddressWithOffset(Offset);
492 1 : unsigned NumBytes = 1 << Size;
493 :
494 1 : Expected<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName();
495 1 : if (!SubtrahendNameOrErr)
496 : return SubtrahendNameOrErr.takeError();
497 1 : auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr);
498 1 : unsigned SectionBID = SubtrahendI->second.getSectionID();
499 1 : uint64_t SectionBOffset = SubtrahendI->second.getOffset();
500 : int64_t Addend =
501 1 : SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8);
502 :
503 : ++RelI;
504 1 : Expected<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName();
505 1 : if (!MinuendNameOrErr)
506 : return MinuendNameOrErr.takeError();
507 1 : auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr);
508 1 : unsigned SectionAID = MinuendI->second.getSectionID();
509 1 : uint64_t SectionAOffset = MinuendI->second.getOffset();
510 :
511 : RelocationEntry R(SectionID, Offset, MachO::ARM64_RELOC_SUBTRACTOR, (uint64_t)Addend,
512 : SectionAID, SectionAOffset, SectionBID, SectionBOffset,
513 : false, Size);
514 :
515 1 : addRelocationForSection(R, SectionAID);
516 :
517 : return ++RelI;
518 : }
519 :
520 0 : static const char *getRelocName(uint32_t RelocType) {
521 0 : switch (RelocType) {
522 : case MachO::ARM64_RELOC_UNSIGNED: return "ARM64_RELOC_UNSIGNED";
523 0 : case MachO::ARM64_RELOC_SUBTRACTOR: return "ARM64_RELOC_SUBTRACTOR";
524 0 : case MachO::ARM64_RELOC_BRANCH26: return "ARM64_RELOC_BRANCH26";
525 0 : case MachO::ARM64_RELOC_PAGE21: return "ARM64_RELOC_PAGE21";
526 0 : case MachO::ARM64_RELOC_PAGEOFF12: return "ARM64_RELOC_PAGEOFF12";
527 0 : case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: return "ARM64_RELOC_GOT_LOAD_PAGE21";
528 0 : case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: return "ARM64_RELOC_GOT_LOAD_PAGEOFF12";
529 0 : case MachO::ARM64_RELOC_POINTER_TO_GOT: return "ARM64_RELOC_POINTER_TO_GOT";
530 0 : case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: return "ARM64_RELOC_TLVP_LOAD_PAGE21";
531 0 : case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: return "ARM64_RELOC_TLVP_LOAD_PAGEOFF12";
532 0 : case MachO::ARM64_RELOC_ADDEND: return "ARM64_RELOC_ADDEND";
533 : }
534 0 : return "Unrecognized arm64 addend";
535 : }
536 :
537 : };
538 : }
539 :
540 : #undef DEBUG_TYPE
541 :
542 : #endif
|