blob: b3467a9ab38bb4620c20457266c11b67dda5f8a0 [file] [log] [blame]
Jim Grosbache0934be2012-01-16 23:50:58 +00001//===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=//
Danil Malyshevcf852dc2011-07-13 07:57:58 +00002//
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// Implementation of the MC-JIT runtime dynamic linker.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "dyld"
Eli Bendersky76463fd2012-01-22 07:05:02 +000015#include "RuntimeDyldMachO.h"
Chandler Carruthd04a8d42012-12-03 16:50:05 +000016#include "llvm/ADT/OwningPtr.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/StringRef.h"
Danil Malyshevcf852dc2011-07-13 07:57:58 +000019using namespace llvm;
20using namespace llvm::object;
21
22namespace llvm {
23
Rafael Espindola87b50172013-04-29 17:24:34 +000024void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE,
25 uint64_t Value) {
26 const SectionEntry &Section = Sections[RE.SectionID];
27 return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
28 RE.IsPCRel, RE.Size);
29}
30
Andrew Kaylora307a1c2012-11-02 19:45:23 +000031void RuntimeDyldMachO::resolveRelocation(const SectionEntry &Section,
32 uint64_t Offset,
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +000033 uint64_t Value,
34 uint32_t Type,
Rafael Espindola87b50172013-04-29 17:24:34 +000035 int64_t Addend,
36 bool isPCRel,
37 unsigned LogSize) {
Andrew Kaylora307a1c2012-11-02 19:45:23 +000038 uint8_t *LocalAddress = Section.Address + Offset;
39 uint64_t FinalAddress = Section.LoadAddress + Offset;
Rafael Espindola87b50172013-04-29 17:24:34 +000040 unsigned MachoType = Type;
41 unsigned Size = 1 << LogSize;
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +000042
Eli Bendersky6d15e872012-04-30 10:06:27 +000043 DEBUG(dbgs() << "resolveRelocation LocalAddress: "
44 << format("%p", LocalAddress)
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +000045 << " FinalAddress: " << format("%p", FinalAddress)
46 << " Value: " << format("%p", Value)
47 << " Addend: " << Addend
48 << " isPCRel: " << isPCRel
49 << " MachoType: " << MachoType
50 << " Size: " << Size
51 << "\n");
52
Danil Malyshevcf852dc2011-07-13 07:57:58 +000053 // This just dispatches to the proper target specific routine.
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +000054 switch (Arch) {
Craig Topper85814382012-02-07 05:05:23 +000055 default: llvm_unreachable("Unsupported CPU type!");
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +000056 case Triple::x86_64:
57 resolveX86_64Relocation(LocalAddress,
58 FinalAddress,
59 (uintptr_t)Value,
60 isPCRel,
61 MachoType,
62 Size,
63 Addend);
64 break;
65 case Triple::x86:
66 resolveI386Relocation(LocalAddress,
Eli Bendersky6d15e872012-04-30 10:06:27 +000067 FinalAddress,
68 (uintptr_t)Value,
69 isPCRel,
Jim Grosbachba9ba9f2012-09-13 01:24:32 +000070 MachoType,
Eli Bendersky6d15e872012-04-30 10:06:27 +000071 Size,
72 Addend);
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +000073 break;
74 case Triple::arm: // Fall through.
75 case Triple::thumb:
76 resolveARMRelocation(LocalAddress,
77 FinalAddress,
78 (uintptr_t)Value,
79 isPCRel,
80 MachoType,
81 Size,
82 Addend);
83 break;
Danil Malyshevcf852dc2011-07-13 07:57:58 +000084 }
Danil Malyshevcf852dc2011-07-13 07:57:58 +000085}
86
Eli Bendersky6d15e872012-04-30 10:06:27 +000087bool RuntimeDyldMachO::resolveI386Relocation(uint8_t *LocalAddress,
88 uint64_t FinalAddress,
89 uint64_t Value,
90 bool isPCRel,
91 unsigned Type,
92 unsigned Size,
93 int64_t Addend) {
Sean Callananb38aae42012-03-26 20:45:52 +000094 if (isPCRel)
95 Value -= FinalAddress + 4; // see resolveX86_64Relocation
96
97 switch (Type) {
98 default:
99 llvm_unreachable("Invalid relocation type!");
100 case macho::RIT_Vanilla: {
101 uint8_t *p = LocalAddress;
102 uint64_t ValueToWrite = Value + Addend;
103 for (unsigned i = 0; i < Size; ++i) {
104 *p++ = (uint8_t)(ValueToWrite & 0xff);
105 ValueToWrite >>= 8;
106 }
Jim Grosbach6f6f1712013-01-31 19:46:28 +0000107 return false;
Sean Callananb38aae42012-03-26 20:45:52 +0000108 }
109 case macho::RIT_Difference:
110 case macho::RIT_Generic_LocalDifference:
111 case macho::RIT_Generic_PreboundLazyPointer:
112 return Error("Relocation type not implemented yet!");
113 }
114}
115
Eli Bendersky6d15e872012-04-30 10:06:27 +0000116bool RuntimeDyldMachO::resolveX86_64Relocation(uint8_t *LocalAddress,
117 uint64_t FinalAddress,
118 uint64_t Value,
119 bool isPCRel,
120 unsigned Type,
121 unsigned Size,
122 int64_t Addend) {
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000123 // If the relocation is PC-relative, the value to be encoded is the
124 // pointer difference.
125 if (isPCRel)
126 // FIXME: It seems this value needs to be adjusted by 4 for an effective PC
127 // address. Is that expected? Only for branches, perhaps?
Sean Callanan61dfa772012-03-07 23:05:25 +0000128 Value -= FinalAddress + 4;
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000129
130 switch(Type) {
131 default:
132 llvm_unreachable("Invalid relocation type!");
Jim Grosbach652ca2f2012-01-16 23:50:49 +0000133 case macho::RIT_X86_64_Signed1:
134 case macho::RIT_X86_64_Signed2:
135 case macho::RIT_X86_64_Signed4:
136 case macho::RIT_X86_64_Signed:
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000137 case macho::RIT_X86_64_Unsigned:
138 case macho::RIT_X86_64_Branch: {
Jim Grosbach652ca2f2012-01-16 23:50:49 +0000139 Value += Addend;
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000140 // Mask in the target value a byte at a time (we don't have an alignment
141 // guarantee for the target address, so this is safest).
Sean Callanan61dfa772012-03-07 23:05:25 +0000142 uint8_t *p = (uint8_t*)LocalAddress;
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000143 for (unsigned i = 0; i < Size; ++i) {
144 *p++ = (uint8_t)Value;
145 Value >>= 8;
146 }
147 return false;
148 }
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000149 case macho::RIT_X86_64_GOTLoad:
150 case macho::RIT_X86_64_GOT:
151 case macho::RIT_X86_64_Subtractor:
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000152 case macho::RIT_X86_64_TLV:
153 return Error("Relocation type not implemented yet!");
154 }
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000155}
156
Eli Bendersky6d15e872012-04-30 10:06:27 +0000157bool RuntimeDyldMachO::resolveARMRelocation(uint8_t *LocalAddress,
158 uint64_t FinalAddress,
159 uint64_t Value,
160 bool isPCRel,
161 unsigned Type,
162 unsigned Size,
163 int64_t Addend) {
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000164 // If the relocation is PC-relative, the value to be encoded is the
165 // pointer difference.
166 if (isPCRel) {
Sean Callanan61dfa772012-03-07 23:05:25 +0000167 Value -= FinalAddress;
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000168 // ARM PCRel relocations have an effective-PC offset of two instructions
169 // (four bytes in Thumb mode, 8 bytes in ARM mode).
170 // FIXME: For now, assume ARM mode.
171 Value -= 8;
172 }
173
174 switch(Type) {
175 default:
176 llvm_unreachable("Invalid relocation type!");
177 case macho::RIT_Vanilla: {
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000178 // Mask in the target value a byte at a time (we don't have an alignment
179 // guarantee for the target address, so this is safest).
Sean Callanan61dfa772012-03-07 23:05:25 +0000180 uint8_t *p = (uint8_t*)LocalAddress;
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000181 for (unsigned i = 0; i < Size; ++i) {
182 *p++ = (uint8_t)Value;
183 Value >>= 8;
184 }
185 break;
186 }
187 case macho::RIT_ARM_Branch24Bit: {
188 // Mask the value into the target address. We know instructions are
189 // 32-bit aligned, so we can do it all at once.
Sean Callanan61dfa772012-03-07 23:05:25 +0000190 uint32_t *p = (uint32_t*)LocalAddress;
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000191 // The low two bits of the value are not encoded.
192 Value >>= 2;
193 // Mask the value to 24 bits.
194 Value &= 0xffffff;
195 // FIXME: If the destination is a Thumb function (and the instruction
196 // is a non-predicated BL instruction), we need to change it to a BLX
197 // instruction instead.
198
199 // Insert the value into the instruction.
200 *p = (*p & ~0xffffff) | Value;
201 break;
202 }
203 case macho::RIT_ARM_ThumbBranch22Bit:
204 case macho::RIT_ARM_ThumbBranch32Bit:
205 case macho::RIT_ARM_Half:
206 case macho::RIT_ARM_HalfDifference:
207 case macho::RIT_Pair:
208 case macho::RIT_Difference:
209 case macho::RIT_ARM_LocalDifference:
210 case macho::RIT_ARM_PreboundLazyPointer:
211 return Error("Relocation type not implemented yet!");
212 }
213 return false;
214}
215
Rafael Espindolaefa91f62013-04-29 14:44:23 +0000216void RuntimeDyldMachO::processRelocationRef(unsigned SectionID,
Rafael Espindolaca0e7362013-04-29 19:03:21 +0000217 RelocationRef RelI,
Preston Gurd689ff9c2012-04-16 22:12:58 +0000218 ObjectImage &Obj,
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000219 ObjSectionToIDMap &ObjSectionToID,
Eli Benderskyd98c9e92012-05-01 06:58:59 +0000220 const SymbolTableMap &Symbols,
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000221 StubMap &Stubs) {
Rafael Espindolaefa91f62013-04-29 14:44:23 +0000222 const ObjectFile *OF = Obj.getObjectFile();
223 const MachOObjectFile *MachO = static_cast<const MachOObjectFile*>(OF);
Rafael Espindolaca0e7362013-04-29 19:03:21 +0000224 macho::RelocationEntry RE = MachO->getRelocation(RelI.getRawDataRefImpl());
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000225
Rafael Espindolaefa91f62013-04-29 14:44:23 +0000226 uint32_t RelType = MachO->getAnyRelocationType(RE);
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000227 RelocationValueRef Value;
Rafael Espindolaefa91f62013-04-29 14:44:23 +0000228 SectionEntry &Section = Sections[SectionID];
Jim Grosbach61425c02012-01-16 22:26:39 +0000229
Rafael Espindolaefa91f62013-04-29 14:44:23 +0000230 bool isExtern = MachO->getPlainRelocationExternal(RE);
Rafael Espindola87b50172013-04-29 17:24:34 +0000231 bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
232 unsigned Size = MachO->getAnyRelocationLength(RE);
Rafael Espindola8e6e02a2013-04-30 01:29:57 +0000233 uint64_t Offset;
234 RelI.getOffset(Offset);
Rafael Espindolae87dadc2013-04-30 15:40:54 +0000235 uint8_t *LocalAddress = Section.Address + Offset;
236 unsigned NumBytes = 1 << Size;
237 uint64_t Addend = 0;
238 memcpy(&Addend, LocalAddress, NumBytes);
Rafael Espindola8e6e02a2013-04-30 01:29:57 +0000239
Rafael Espindolae87dadc2013-04-30 15:40:54 +0000240 if (isExtern) {
Eli Benderskyc201e6e2012-05-01 10:41:12 +0000241 // Obtain the symbol name which is referenced in the relocation
Rafael Espindolaefa91f62013-04-29 14:44:23 +0000242 SymbolRef Symbol;
Rafael Espindolaca0e7362013-04-29 19:03:21 +0000243 RelI.getSymbol(Symbol);
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000244 StringRef TargetName;
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000245 Symbol.getName(TargetName);
Eli Benderskyc201e6e2012-05-01 10:41:12 +0000246 // First search for the symbol in the local symbol table
Eli Benderskyd98c9e92012-05-01 06:58:59 +0000247 SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000248 if (lsi != Symbols.end()) {
249 Value.SectionID = lsi->second.first;
Rafael Espindola8e6e02a2013-04-30 01:29:57 +0000250 Value.Addend = lsi->second.second + Addend;
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000251 } else {
Eli Benderskyc201e6e2012-05-01 10:41:12 +0000252 // Search for the symbol in the global symbol table
Eli Benderskyd98c9e92012-05-01 06:58:59 +0000253 SymbolTableMap::const_iterator gsi = GlobalSymbolTable.find(TargetName.data());
254 if (gsi != GlobalSymbolTable.end()) {
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000255 Value.SectionID = gsi->second.first;
Rafael Espindola8e6e02a2013-04-30 01:29:57 +0000256 Value.Addend = gsi->second.second + Addend;
257 } else {
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000258 Value.SymbolName = TargetName.data();
Rafael Espindola8e6e02a2013-04-30 01:29:57 +0000259 Value.Addend = Addend;
260 }
Danil Malyshev4b0b8ef2012-03-29 21:46:18 +0000261 }
Bill Wendling288967d2012-03-29 23:23:59 +0000262 } else {
Rafael Espindolae87dadc2013-04-30 15:40:54 +0000263 SectionRef Sec = MachO->getRelocationSection(RE);
264 Value.SectionID = findOrEmitSection(Obj, Sec, true, ObjSectionToID);
265 uint64_t Addr;
266 Sec.getAddress(Addr);
267 Value.Addend = Addend - Addr;
Bill Wendling288967d2012-03-29 23:23:59 +0000268 }
269
Jim Grosbach01e1a972012-09-13 01:24:35 +0000270 if (Arch == Triple::arm && (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) {
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000271 // This is an ARM branch relocation, need to use a stub function.
Bill Wendling288967d2012-03-29 23:23:59 +0000272
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000273 // Look up for existing stub.
274 StubMap::const_iterator i = Stubs.find(Value);
275 if (i != Stubs.end())
Rafael Espindolaefa91f62013-04-29 14:44:23 +0000276 resolveRelocation(Section, Offset,
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000277 (uint64_t)Section.Address + i->second,
Rafael Espindola87b50172013-04-29 17:24:34 +0000278 RelType, 0, IsPCRel, Size);
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000279 else {
280 // Create a new stub function.
281 Stubs[Value] = Section.StubOffset;
282 uint8_t *StubTargetAddr = createStubFunction(Section.Address +
283 Section.StubOffset);
Rafael Espindolaefa91f62013-04-29 14:44:23 +0000284 RelocationEntry RE(SectionID, StubTargetAddr - Section.Address,
Eli Benderskyc201e6e2012-05-01 10:41:12 +0000285 macho::RIT_Vanilla, Value.Addend);
286 if (Value.SymbolName)
287 addRelocationForSymbol(RE, Value.SymbolName);
288 else
289 addRelocationForSection(RE, Value.SectionID);
Rafael Espindolaefa91f62013-04-29 14:44:23 +0000290 resolveRelocation(Section, Offset,
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000291 (uint64_t)Section.Address + Section.StubOffset,
Rafael Espindola87b50172013-04-29 17:24:34 +0000292 RelType, 0, IsPCRel, Size);
Danil Malyshev0e4fa5f2012-03-30 16:45:19 +0000293 Section.StubOffset += getMaxStubSize();
294 }
Eli Benderskyc201e6e2012-05-01 10:41:12 +0000295 } else {
Rafael Espindola87b50172013-04-29 17:24:34 +0000296 RelocationEntry RE(SectionID, Offset, RelType, Value.Addend,
297 IsPCRel, Size);
Eli Benderskyc201e6e2012-05-01 10:41:12 +0000298 if (Value.SymbolName)
299 addRelocationForSymbol(RE, Value.SymbolName);
300 else
301 addRelocationForSection(RE, Value.SectionID);
302 }
Bill Wendling288967d2012-03-29 23:23:59 +0000303}
304
Bill Wendling288967d2012-03-29 23:23:59 +0000305
Eli Bendersky6d15e872012-04-30 10:06:27 +0000306bool RuntimeDyldMachO::isCompatibleFormat(
Andrew Kaylor3f23cef2012-10-02 21:18:39 +0000307 const ObjectBuffer *InputBuffer) const {
308 if (InputBuffer->getBufferSize() < 4)
309 return false;
310 StringRef Magic(InputBuffer->getBufferStart(), 4);
Danil Malyshevcf852dc2011-07-13 07:57:58 +0000311 if (Magic == "\xFE\xED\xFA\xCE") return true;
312 if (Magic == "\xCE\xFA\xED\xFE") return true;
313 if (Magic == "\xFE\xED\xFA\xCF") return true;
314 if (Magic == "\xCF\xFA\xED\xFE") return true;
315 return false;
316}
317
318} // end namespace llvm