blob: adca0eeb08b4e4cdac660f16549c195db0a16392 [file] [log] [blame]
Lang Hamesa5216882014-07-17 18:54:50 +00001//===----- RuntimeDyldMachOARM.h ---- MachO/ARM 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
Benjamin Kramera7c40ef2014-08-13 16:26:38 +000010#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H
11#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H
Lang Hamesa5216882014-07-17 18:54:50 +000012
13#include "../RuntimeDyldMachO.h"
Lang Hamesbc38ea92016-04-27 20:54:49 +000014#include <string>
Lang Hamesa5216882014-07-17 18:54:50 +000015
16#define DEBUG_TYPE "dyld"
17
18namespace llvm {
19
20class RuntimeDyldMachOARM
21 : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> {
Lang Hames13163652014-07-30 03:35:05 +000022private:
23 typedef RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> ParentT;
24
Lang Hamesa5216882014-07-17 18:54:50 +000025public:
Lang Hameseb195f02014-09-04 04:53:03 +000026
27 typedef uint32_t TargetPtrT;
28
Lang Hames633fe142015-03-30 03:37:06 +000029 RuntimeDyldMachOARM(RuntimeDyld::MemoryManager &MM,
Lang Hamesad4a9112016-08-01 20:49:11 +000030 JITSymbolResolver &Resolver)
Lang Hames633fe142015-03-30 03:37:06 +000031 : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
Lang Hamesa5216882014-07-17 18:54:50 +000032
33 unsigned getMaxStubSize() override { return 8; }
34
Lang Hamese5fc8262014-07-17 23:11:30 +000035 unsigned getStubAlignment() override { return 4; }
Lang Hamesa5216882014-07-17 18:54:50 +000036
Lang Hames25d93092014-08-08 23:12:22 +000037 int64_t decodeAddend(const RelocationEntry &RE) const {
38 const SectionEntry &Section = Sections[RE.SectionID];
Sanjoy Das277776a2015-11-23 21:47:41 +000039 uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
Lang Hames25d93092014-08-08 23:12:22 +000040
41 switch (RE.RelType) {
Lang Hames13163652014-07-30 03:35:05 +000042 default:
Lang Hames25d93092014-08-08 23:12:22 +000043 return memcpyAddend(RE);
Lang Hames13163652014-07-30 03:35:05 +000044 case MachO::ARM_RELOC_BR24: {
Daniel Sanders66e799f2014-11-06 09:53:05 +000045 uint32_t Temp = readBytesUnaligned(LocalAddress, 4);
Lang Hames13163652014-07-30 03:35:05 +000046 Temp &= 0x00ffffff; // Mask out the opcode.
47 // Now we've got the shifted immediate, shift by 2, sign extend and ret.
48 return SignExtend32<26>(Temp << 2);
49 }
50 }
51 }
52
Lang Hames89595312016-04-27 20:24:48 +000053 Expected<relocation_iterator>
Lang Hamesa5216882014-07-17 18:54:50 +000054 processRelocationRef(unsigned SectionID, relocation_iterator RelI,
Lang Hamesb5c7b1f2014-11-26 16:54:40 +000055 const ObjectFile &BaseObjT,
56 ObjSectionToIDMap &ObjSectionToID,
Lang Hamesa5cd9502014-11-27 05:40:13 +000057 StubMap &Stubs) override {
Lang Hamesa5216882014-07-17 18:54:50 +000058 const MachOObjectFile &Obj =
Lang Hamesb5c7b1f2014-11-26 16:54:40 +000059 static_cast<const MachOObjectFile &>(BaseObjT);
Lang Hamesa5216882014-07-17 18:54:50 +000060 MachO::any_relocation_info RelInfo =
61 Obj.getRelocation(RelI->getRawDataRefImpl());
Lang Hames6f1048f2014-09-11 19:21:14 +000062 uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
Lang Hamesa5216882014-07-17 18:54:50 +000063
Lang Hames6f1048f2014-09-11 19:21:14 +000064 if (Obj.isRelocationScattered(RelInfo)) {
65 if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF)
Lang Hamesb5c7b1f2014-11-26 16:54:40 +000066 return processHALFSECTDIFFRelocation(SectionID, RelI, Obj,
Lang Hames6f1048f2014-09-11 19:21:14 +000067 ObjSectionToID);
Lang Hamesa8183e52015-07-24 17:40:04 +000068 else if (RelType == MachO::GENERIC_RELOC_VANILLA)
69 return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID);
Lang Hames6f1048f2014-09-11 19:21:14 +000070 else
Lang Hamesa8183e52015-07-24 17:40:04 +000071 return ++RelI;
Lang Hames6f1048f2014-09-11 19:21:14 +000072 }
Lang Hamesa5216882014-07-17 18:54:50 +000073
Lang Hames89595312016-04-27 20:24:48 +000074 // Sanity check relocation type.
75 switch (RelType) {
76 UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PAIR);
77 UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_SECTDIFF);
78 UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_LOCAL_SECTDIFF);
79 UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PB_LA_PTR);
80 UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_RELOC_BR22);
81 UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_32BIT_BRANCH);
82 UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_HALF);
83 default:
84 if (RelType > MachO::ARM_RELOC_HALF_SECTDIFF)
Chaoren Lin49317f22016-04-28 00:49:37 +000085 return make_error<RuntimeDyldError>(("MachO ARM relocation type " +
86 Twine(RelType) +
87 " is out of range").str());
Lang Hames89595312016-04-27 20:24:48 +000088 break;
89 }
90
Lang Hamesb5c7b1f2014-11-26 16:54:40 +000091 RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
Lang Hames25d93092014-08-08 23:12:22 +000092 RE.Addend = decodeAddend(RE);
Lang Hames89595312016-04-27 20:24:48 +000093 RelocationValueRef Value;
94 if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
95 Value = *ValueOrErr;
96 else
97 return ValueOrErr.takeError();
Lang Hamesa5216882014-07-17 18:54:50 +000098
Lang Hames13163652014-07-30 03:35:05 +000099 if (RE.IsPCRel)
Rafael Espindola76ad2322015-07-06 14:55:37 +0000100 makeValueAddendPCRel(Value, RelI, 8);
Lang Hamesa5216882014-07-17 18:54:50 +0000101
102 if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24)
103 processBranchRelocation(RE, Value, Stubs);
104 else {
Lang Hamesca279c22014-09-07 04:03:32 +0000105 RE.Addend = Value.Offset;
Lang Hamesa5216882014-07-17 18:54:50 +0000106 if (Value.SymbolName)
107 addRelocationForSymbol(RE, Value.SymbolName);
108 else
109 addRelocationForSection(RE, Value.SectionID);
110 }
111
112 return ++RelI;
113 }
114
Benjamin Kramer8c90fd72014-09-03 11:41:21 +0000115 void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
Lang Hamesa5216882014-07-17 18:54:50 +0000116 DEBUG(dumpRelocationToResolve(RE, Value));
117 const SectionEntry &Section = Sections[RE.SectionID];
Sanjoy Das277776a2015-11-23 21:47:41 +0000118 uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
Lang Hamesa5216882014-07-17 18:54:50 +0000119
120 // If the relocation is PC-relative, the value to be encoded is the
121 // pointer difference.
122 if (RE.IsPCRel) {
Sanjoy Das277776a2015-11-23 21:47:41 +0000123 uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
Lang Hamesa5216882014-07-17 18:54:50 +0000124 Value -= FinalAddress;
125 // ARM PCRel relocations have an effective-PC offset of two instructions
126 // (four bytes in Thumb mode, 8 bytes in ARM mode).
127 // FIXME: For now, assume ARM mode.
128 Value -= 8;
129 }
130
131 switch (RE.RelType) {
Lang Hamesa5216882014-07-17 18:54:50 +0000132 case MachO::ARM_RELOC_VANILLA:
Lang Hames4669cd02014-09-11 17:27:01 +0000133 writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
Lang Hamesa5216882014-07-17 18:54:50 +0000134 break;
135 case MachO::ARM_RELOC_BR24: {
136 // Mask the value into the target address. We know instructions are
137 // 32-bit aligned, so we can do it all at once.
Lang Hames4669cd02014-09-11 17:27:01 +0000138 Value += RE.Addend;
Lang Hamesa5216882014-07-17 18:54:50 +0000139 // The low two bits of the value are not encoded.
140 Value >>= 2;
141 // Mask the value to 24 bits.
142 uint64_t FinalValue = Value & 0xffffff;
Lang Hamesa5216882014-07-17 18:54:50 +0000143 // FIXME: If the destination is a Thumb function (and the instruction
144 // is a non-predicated BL instruction), we need to change it to a BLX
145 // instruction instead.
146
147 // Insert the value into the instruction.
Daniel Sanders66e799f2014-11-06 09:53:05 +0000148 uint32_t Temp = readBytesUnaligned(LocalAddress, 4);
149 writeBytesUnaligned((Temp & ~0xffffff) | FinalValue, LocalAddress, 4);
150
Lang Hamesa5216882014-07-17 18:54:50 +0000151 break;
152 }
Lang Hames6f1048f2014-09-11 19:21:14 +0000153 case MachO::ARM_RELOC_HALF_SECTDIFF: {
Sanjoy Das277776a2015-11-23 21:47:41 +0000154 uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress();
155 uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress();
Lang Hames6f1048f2014-09-11 19:21:14 +0000156 assert((Value == SectionABase || Value == SectionBBase) &&
157 "Unexpected HALFSECTDIFF relocation value.");
158 Value = SectionABase - SectionBBase + RE.Addend;
159 if (RE.Size & 0x1) // :upper16:
160 Value = (Value >> 16);
161 Value &= 0xffff;
162
Daniel Sanders66e799f2014-11-06 09:53:05 +0000163 uint32_t Insn = readBytesUnaligned(LocalAddress, 4);
Lang Hames6f1048f2014-09-11 19:21:14 +0000164 Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff);
Daniel Sanders66e799f2014-11-06 09:53:05 +0000165 writeBytesUnaligned(Insn, LocalAddress, 4);
Lang Hames6f1048f2014-09-11 19:21:14 +0000166 break;
167 }
168
Lang Hames89595312016-04-27 20:24:48 +0000169 default:
170 llvm_unreachable("Invalid relocation type");
Lang Hamesa5216882014-07-17 18:54:50 +0000171 }
172 }
173
Lang Hames89595312016-04-27 20:24:48 +0000174 Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
Lang Hames6f1048f2014-09-11 19:21:14 +0000175 const SectionRef &Section) {
176 StringRef Name;
177 Section.getName(Name);
178
179 if (Name == "__nl_symbol_ptr")
Lang Hames89595312016-04-27 20:24:48 +0000180 return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
181 Section, SectionID);
182 return Error::success();
Lang Hames6f1048f2014-09-11 19:21:14 +0000183 }
Lang Hamesa5216882014-07-17 18:54:50 +0000184
185private:
Lang Hames6f1048f2014-09-11 19:21:14 +0000186
Lang Hamesa5216882014-07-17 18:54:50 +0000187 void processBranchRelocation(const RelocationEntry &RE,
188 const RelocationValueRef &Value,
189 StubMap &Stubs) {
190 // This is an ARM branch relocation, need to use a stub function.
191 // Look up for existing stub.
192 SectionEntry &Section = Sections[RE.SectionID];
193 RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value);
194 uint8_t *Addr;
195 if (i != Stubs.end()) {
Sanjoy Das277776a2015-11-23 21:47:41 +0000196 Addr = Section.getAddressWithOffset(i->second);
Lang Hamesa5216882014-07-17 18:54:50 +0000197 } else {
198 // Create a new stub function.
Sanjoy Das277776a2015-11-23 21:47:41 +0000199 Stubs[Value] = Section.getStubOffset();
200 uint8_t *StubTargetAddr = createStubFunction(
201 Section.getAddressWithOffset(Section.getStubOffset()));
202 RelocationEntry StubRE(
203 RE.SectionID, StubTargetAddr - Section.getAddress(),
204 MachO::GENERIC_RELOC_VANILLA, Value.Offset, false, 2);
Lang Hamesa5216882014-07-17 18:54:50 +0000205 if (Value.SymbolName)
206 addRelocationForSymbol(StubRE, Value.SymbolName);
207 else
208 addRelocationForSection(StubRE, Value.SectionID);
Sanjoy Das277776a2015-11-23 21:47:41 +0000209 Addr = Section.getAddressWithOffset(Section.getStubOffset());
210 Section.advanceStubOffset(getMaxStubSize());
Lang Hamesa5216882014-07-17 18:54:50 +0000211 }
Lang Hames13163652014-07-30 03:35:05 +0000212 RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0,
Lang Hamesa5216882014-07-17 18:54:50 +0000213 RE.IsPCRel, RE.Size);
214 resolveRelocation(TargetRE, (uint64_t)Addr);
215 }
Lang Hames6f1048f2014-09-11 19:21:14 +0000216
Lang Hames89595312016-04-27 20:24:48 +0000217 Expected<relocation_iterator>
Lang Hames6f1048f2014-09-11 19:21:14 +0000218 processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
Lang Hamesb5c7b1f2014-11-26 16:54:40 +0000219 const ObjectFile &BaseTObj,
Lang Hames6f1048f2014-09-11 19:21:14 +0000220 ObjSectionToIDMap &ObjSectionToID) {
Lang Hamesb5c7b1f2014-11-26 16:54:40 +0000221 const MachOObjectFile &MachO =
222 static_cast<const MachOObjectFile&>(BaseTObj);
Lang Hames6f1048f2014-09-11 19:21:14 +0000223 MachO::any_relocation_info RE =
Lang Hamesb5c7b1f2014-11-26 16:54:40 +0000224 MachO.getRelocation(RelI->getRawDataRefImpl());
Lang Hames6f1048f2014-09-11 19:21:14 +0000225
226
227 // For a half-diff relocation the length bits actually record whether this
228 // is a movw/movt, and whether this is arm or thumb.
229 // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1).
230 // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1).
Lang Hamesb5c7b1f2014-11-26 16:54:40 +0000231 unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE);
Lang Hames6f1048f2014-09-11 19:21:14 +0000232 if (HalfDiffKindBits & 0x2)
233 llvm_unreachable("Thumb not yet supported.");
234
235 SectionEntry &Section = Sections[SectionID];
Lang Hamesb5c7b1f2014-11-26 16:54:40 +0000236 uint32_t RelocType = MachO.getAnyRelocationType(RE);
237 bool IsPCRel = MachO.getAnyRelocationPCRel(RE);
Rafael Espindola96d071c2015-06-29 23:29:12 +0000238 uint64_t Offset = RelI->getOffset();
Sanjoy Das277776a2015-11-23 21:47:41 +0000239 uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
Daniel Sanders66e799f2014-11-06 09:53:05 +0000240 int64_t Immediate = readBytesUnaligned(LocalAddress, 4); // Copy the whole instruction out.
Lang Hames6f1048f2014-09-11 19:21:14 +0000241 Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff);
242
243 ++RelI;
244 MachO::any_relocation_info RE2 =
Lang Hamesb5c7b1f2014-11-26 16:54:40 +0000245 MachO.getRelocation(RelI->getRawDataRefImpl());
246 uint32_t AddrA = MachO.getScatteredRelocationValue(RE);
247 section_iterator SAI = getSectionByAddress(MachO, AddrA);
248 assert(SAI != MachO.section_end() && "Can't find section for address A");
Rafael Espindola80291272014-10-08 15:28:58 +0000249 uint64_t SectionABase = SAI->getAddress();
Lang Hames6f1048f2014-09-11 19:21:14 +0000250 uint64_t SectionAOffset = AddrA - SectionABase;
251 SectionRef SectionA = *SAI;
Rafael Espindola80291272014-10-08 15:28:58 +0000252 bool IsCode = SectionA.isText();
Lang Hames89595312016-04-27 20:24:48 +0000253 uint32_t SectionAID = ~0U;
254 if (auto SectionAIDOrErr =
255 findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID))
256 SectionAID = *SectionAIDOrErr;
257 else
258 return SectionAIDOrErr.takeError();
Lang Hames6f1048f2014-09-11 19:21:14 +0000259
Lang Hamesb5c7b1f2014-11-26 16:54:40 +0000260 uint32_t AddrB = MachO.getScatteredRelocationValue(RE2);
261 section_iterator SBI = getSectionByAddress(MachO, AddrB);
262 assert(SBI != MachO.section_end() && "Can't find section for address B");
Rafael Espindola80291272014-10-08 15:28:58 +0000263 uint64_t SectionBBase = SBI->getAddress();
Lang Hames6f1048f2014-09-11 19:21:14 +0000264 uint64_t SectionBOffset = AddrB - SectionBBase;
265 SectionRef SectionB = *SBI;
Lang Hames89595312016-04-27 20:24:48 +0000266 uint32_t SectionBID = ~0U;
267 if (auto SectionBIDOrErr =
268 findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID))
269 SectionBID = *SectionBIDOrErr;
270 else
271 return SectionBIDOrErr.takeError();
Lang Hames6f1048f2014-09-11 19:21:14 +0000272
Lang Hamesb5c7b1f2014-11-26 16:54:40 +0000273 uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff;
Lang Hames6f1048f2014-09-11 19:21:14 +0000274 unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0;
275 uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift));
276 int64_t Addend = FullImmVal - (AddrA - AddrB);
277
278 // addend = Encoded - Expected
279 // = Encoded - (AddrA - AddrB)
280
281 DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB
282 << ", Addend: " << Addend << ", SectionA ID: " << SectionAID
283 << ", SectionAOffset: " << SectionAOffset
284 << ", SectionB ID: " << SectionBID
285 << ", SectionBOffset: " << SectionBOffset << "\n");
286 RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID,
287 SectionAOffset, SectionBID, SectionBOffset, IsPCRel,
288 HalfDiffKindBits);
289
290 addRelocationForSection(R, SectionAID);
291 addRelocationForSection(R, SectionBID);
292
293 return ++RelI;
294 }
295
Lang Hamesa5216882014-07-17 18:54:50 +0000296};
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000297}
Lang Hamesa5216882014-07-17 18:54:50 +0000298
299#undef DEBUG_TYPE
300
Benjamin Kramera7c40ef2014-08-13 16:26:38 +0000301#endif