blob: df7f04cdf8b6007f052e31e3b9057388aeb82681 [file] [log] [blame]
Jim Grosbach06594e12012-01-16 23:50:58 +00001//===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=//
Danil Malyshev72510f22011-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
Eli Bendersky058d6472012-01-22 07:05:02 +000014#include "RuntimeDyldMachO.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000015#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/StringRef.h"
Danil Malyshev72510f22011-07-13 07:57:58 +000017using namespace llvm;
18using namespace llvm::object;
19
Chandler Carruthf58e3762014-04-22 03:04:17 +000020#define DEBUG_TYPE "dyld"
21
Danil Malyshev72510f22011-07-13 07:57:58 +000022namespace llvm {
23
Juergen Ributzka7608dc02014-03-21 20:28:42 +000024static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText,
25 intptr_t DeltaForEH) {
Lang Hames36072da2014-05-12 21:39:59 +000026 DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText
27 << ", Delta for EH: " << DeltaForEH << "\n");
Juergen Ributzka7608dc02014-03-21 20:28:42 +000028 uint32_t Length = *((uint32_t *)P);
Rafael Espindolafa5942b2013-05-05 20:43:10 +000029 P += 4;
30 unsigned char *Ret = P + Length;
Juergen Ributzka7608dc02014-03-21 20:28:42 +000031 uint32_t Offset = *((uint32_t *)P);
Rafael Espindolafa5942b2013-05-05 20:43:10 +000032 if (Offset == 0) // is a CIE
33 return Ret;
34
35 P += 4;
Juergen Ributzka7608dc02014-03-21 20:28:42 +000036 intptr_t FDELocation = *((intptr_t *)P);
Rafael Espindolafa5942b2013-05-05 20:43:10 +000037 intptr_t NewLocation = FDELocation - DeltaForText;
Juergen Ributzka7608dc02014-03-21 20:28:42 +000038 *((intptr_t *)P) = NewLocation;
Rafael Espindolafa5942b2013-05-05 20:43:10 +000039 P += sizeof(intptr_t);
40
41 // Skip the FDE address range
42 P += sizeof(intptr_t);
43
44 uint8_t Augmentationsize = *P;
45 P += 1;
46 if (Augmentationsize != 0) {
Juergen Ributzka7608dc02014-03-21 20:28:42 +000047 intptr_t LSDA = *((intptr_t *)P);
Rafael Espindolafa5942b2013-05-05 20:43:10 +000048 intptr_t NewLSDA = LSDA - DeltaForEH;
Juergen Ributzka7608dc02014-03-21 20:28:42 +000049 *((intptr_t *)P) = NewLSDA;
Rafael Espindolafa5942b2013-05-05 20:43:10 +000050 }
51
52 return Ret;
53}
54
55static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) {
Juergen Ributzka7608dc02014-03-21 20:28:42 +000056 intptr_t ObjDistance = A->ObjAddress - B->ObjAddress;
Rafael Espindolafa5942b2013-05-05 20:43:10 +000057 intptr_t MemDistance = A->LoadAddress - B->LoadAddress;
58 return ObjDistance - MemDistance;
59}
60
Andrew Kaylor7bb13442013-10-11 21:25:48 +000061void RuntimeDyldMachO::registerEHFrames() {
62
63 if (!MemMgr)
64 return;
65 for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) {
66 EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i];
67 if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID ||
68 SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID)
69 continue;
70 SectionEntry *Text = &Sections[SectionInfo.TextSID];
71 SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID];
Craig Topper353eda42014-04-24 06:44:33 +000072 SectionEntry *ExceptTab = nullptr;
Andrew Kaylor7bb13442013-10-11 21:25:48 +000073 if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID)
74 ExceptTab = &Sections[SectionInfo.ExceptTabSID];
75
76 intptr_t DeltaForText = computeDelta(Text, EHFrame);
77 intptr_t DeltaForEH = 0;
78 if (ExceptTab)
79 DeltaForEH = computeDelta(ExceptTab, EHFrame);
80
81 unsigned char *P = EHFrame->Address;
82 unsigned char *End = P + EHFrame->Size;
Juergen Ributzka7608dc02014-03-21 20:28:42 +000083 do {
Andrew Kaylor7bb13442013-10-11 21:25:48 +000084 P = processFDE(P, DeltaForText, DeltaForEH);
Juergen Ributzka7608dc02014-03-21 20:28:42 +000085 } while (P != End);
Andrew Kaylor7bb13442013-10-11 21:25:48 +000086
Juergen Ributzka7608dc02014-03-21 20:28:42 +000087 MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress,
Andrew Kaylor7bb13442013-10-11 21:25:48 +000088 EHFrame->Size);
Rafael Espindolafa5942b2013-05-05 20:43:10 +000089 }
Andrew Kaylor7bb13442013-10-11 21:25:48 +000090 UnregisteredEHFrameSections.clear();
91}
Rafael Espindolafa5942b2013-05-05 20:43:10 +000092
Lang Hames36072da2014-05-12 21:39:59 +000093void RuntimeDyldMachO::finalizeLoad(ObjectImage &ObjImg,
94 ObjSectionToIDMap &SectionMap) {
Andrew Kaylor7bb13442013-10-11 21:25:48 +000095 unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID;
96 unsigned TextSID = RTDYLD_INVALID_SECTION_ID;
97 unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID;
98 ObjSectionToIDMap::iterator i, e;
99 for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) {
100 const SectionRef &Section = i->first;
101 StringRef Name;
102 Section.getName(Name);
103 if (Name == "__eh_frame")
104 EHFrameSID = i->second;
105 else if (Name == "__text")
106 TextSID = i->second;
107 else if (Name == "__gcc_except_tab")
108 ExceptTabSID = i->second;
Lang Hames36072da2014-05-12 21:39:59 +0000109 else if (Name == "__jump_table")
110 populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()),
111 Section, i->second);
112 else if (Name == "__pointers")
113 populatePointersSection(cast<MachOObjectFile>(*ObjImg.getObjectFile()),
114 Section, i->second);
Andrew Kaylor7bb13442013-10-11 21:25:48 +0000115 }
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000116 UnregisteredEHFrameSections.push_back(
117 EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID));
Rafael Espindolafa5942b2013-05-05 20:43:10 +0000118}
119
Andrew Kaylor5f3a9982013-08-19 19:38:06 +0000120// The target location for the relocation is described by RE.SectionID and
121// RE.Offset. RE.SectionID can be used to find the SectionEntry. Each
122// SectionEntry has three members describing its location.
123// SectionEntry::Address is the address at which the section has been loaded
124// into memory in the current (host) process. SectionEntry::LoadAddress is the
125// address that the section will have in the target process.
126// SectionEntry::ObjAddress is the address of the bits for this section in the
127// original emitted object image (also in the current address space).
128//
129// Relocations will be applied as if the section were loaded at
130// SectionEntry::LoadAddress, but they will be applied at an address based
131// on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to
132// Target memory contents if they are required for value calculations.
133//
134// The Value parameter here is the load address of the symbol for the
135// relocation to be applied. For relocations which refer to symbols in the
136// current object Value will be the LoadAddress of the section in which
137// the symbol resides (RE.Addend provides additional information about the
138// symbol location). For external symbols, Value will be the address of the
139// symbol in the target address space.
Rafael Espindolaf1f1c622013-04-29 17:24:34 +0000140void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE,
141 uint64_t Value) {
Lang Hamesf35553e2014-05-09 00:11:18 +0000142 DEBUG (
143 const SectionEntry &Section = Sections[RE.SectionID];
144 uint8_t* LocalAddress = Section.Address + RE.Offset;
145 uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
Rafael Espindolaf1f1c622013-04-29 17:24:34 +0000146
Lang Hamesf35553e2014-05-09 00:11:18 +0000147 dbgs() << "resolveRelocation Section: " << RE.SectionID
148 << " LocalAddress: " << format("%p", LocalAddress)
149 << " FinalAddress: " << format("%p", FinalAddress)
150 << " Value: " << format("%p", Value)
151 << " Addend: " << RE.Addend
152 << " isPCRel: " << RE.IsPCRel
153 << " MachoType: " << RE.RelType
154 << " Size: " << (1 << RE.Size) << "\n";
155 );
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000156
Danil Malyshev72510f22011-07-13 07:57:58 +0000157 // This just dispatches to the proper target specific routine.
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000158 switch (Arch) {
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000159 default:
160 llvm_unreachable("Unsupported CPU type!");
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000161 case Triple::x86_64:
Lang Hamesf35553e2014-05-09 00:11:18 +0000162 resolveX86_64Relocation(RE, Value);
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000163 break;
164 case Triple::x86:
Lang Hamesf35553e2014-05-09 00:11:18 +0000165 resolveI386Relocation(RE, Value);
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000166 break;
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000167 case Triple::arm: // Fall through.
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000168 case Triple::thumb:
Lang Hamesf35553e2014-05-09 00:11:18 +0000169 resolveARMRelocation(RE, Value);
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000170 break;
Tim Northover00ed9962014-03-29 10:18:08 +0000171 case Triple::arm64:
Lang Hamesf35553e2014-05-09 00:11:18 +0000172 resolveARM64Relocation(RE, Value);
Tim Northover00ed9962014-03-29 10:18:08 +0000173 break;
Danil Malyshev72510f22011-07-13 07:57:58 +0000174 }
Danil Malyshev72510f22011-07-13 07:57:58 +0000175}
176
Lang Hamesf35553e2014-05-09 00:11:18 +0000177bool RuntimeDyldMachO::resolveI386Relocation(const RelocationEntry &RE,
178 uint64_t Value) {
179 const SectionEntry &Section = Sections[RE.SectionID];
180 uint8_t* LocalAddress = Section.Address + RE.Offset;
Sean Callanana3759432012-03-26 20:45:52 +0000181
Lang Hamesf35553e2014-05-09 00:11:18 +0000182 if (RE.IsPCRel) {
183 uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
184 Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation.
Sean Callanana3759432012-03-26 20:45:52 +0000185 }
Lang Hamesf35553e2014-05-09 00:11:18 +0000186
187 switch (RE.RelType) {
188 default:
189 llvm_unreachable("Invalid relocation type!");
190 case MachO::GENERIC_RELOC_VANILLA:
191 return applyRelocationValue(LocalAddress, Value + RE.Addend,
192 1 << RE.Size);
193 case MachO::GENERIC_RELOC_SECTDIFF:
Lang Hames36072da2014-05-12 21:39:59 +0000194 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
195 uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress;
196 uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress;
197 assert((Value == SectionABase || Value == SectionBBase) &&
198 "Unexpected SECTDIFF relocation value.");
199 Value = SectionABase - SectionBBase + RE.Addend;
200 return applyRelocationValue(LocalAddress, Value, 1 << RE.Size);
201 }
Lang Hamesf35553e2014-05-09 00:11:18 +0000202 case MachO::GENERIC_RELOC_PB_LA_PTR:
203 return Error("Relocation type not implemented yet!");
Sean Callanana3759432012-03-26 20:45:52 +0000204 }
205}
206
Lang Hamesf35553e2014-05-09 00:11:18 +0000207bool RuntimeDyldMachO::resolveX86_64Relocation(const RelocationEntry &RE,
208 uint64_t Value) {
209 const SectionEntry &Section = Sections[RE.SectionID];
210 uint8_t* LocalAddress = Section.Address + RE.Offset;
211
Danil Malyshev72510f22011-07-13 07:57:58 +0000212 // If the relocation is PC-relative, the value to be encoded is the
213 // pointer difference.
Lang Hamesf35553e2014-05-09 00:11:18 +0000214 if (RE.IsPCRel) {
Danil Malyshev72510f22011-07-13 07:57:58 +0000215 // FIXME: It seems this value needs to be adjusted by 4 for an effective PC
216 // address. Is that expected? Only for branches, perhaps?
Lang Hamesf35553e2014-05-09 00:11:18 +0000217 uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
218 Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation.
219 }
Danil Malyshev72510f22011-07-13 07:57:58 +0000220
Lang Hamesf35553e2014-05-09 00:11:18 +0000221 switch (RE.RelType) {
Danil Malyshev72510f22011-07-13 07:57:58 +0000222 default:
223 llvm_unreachable("Invalid relocation type!");
Charles Davis8bdfafd2013-09-01 04:28:48 +0000224 case MachO::X86_64_RELOC_SIGNED_1:
225 case MachO::X86_64_RELOC_SIGNED_2:
226 case MachO::X86_64_RELOC_SIGNED_4:
227 case MachO::X86_64_RELOC_SIGNED:
228 case MachO::X86_64_RELOC_UNSIGNED:
Lang Hamesf35553e2014-05-09 00:11:18 +0000229 case MachO::X86_64_RELOC_BRANCH:
230 return applyRelocationValue(LocalAddress, Value + RE.Addend, 1 << RE.Size);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000231 case MachO::X86_64_RELOC_GOT_LOAD:
232 case MachO::X86_64_RELOC_GOT:
233 case MachO::X86_64_RELOC_SUBTRACTOR:
234 case MachO::X86_64_RELOC_TLV:
Danil Malyshev72510f22011-07-13 07:57:58 +0000235 return Error("Relocation type not implemented yet!");
236 }
Danil Malyshev72510f22011-07-13 07:57:58 +0000237}
238
Lang Hamesf35553e2014-05-09 00:11:18 +0000239bool RuntimeDyldMachO::resolveARMRelocation(const RelocationEntry &RE,
240 uint64_t Value) {
241 const SectionEntry &Section = Sections[RE.SectionID];
242 uint8_t* LocalAddress = Section.Address + RE.Offset;
243
Danil Malyshev72510f22011-07-13 07:57:58 +0000244 // If the relocation is PC-relative, the value to be encoded is the
245 // pointer difference.
Lang Hamesf35553e2014-05-09 00:11:18 +0000246 if (RE.IsPCRel) {
247 uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
Sean Callananca92a3d2012-03-07 23:05:25 +0000248 Value -= FinalAddress;
Danil Malyshev72510f22011-07-13 07:57:58 +0000249 // ARM PCRel relocations have an effective-PC offset of two instructions
250 // (four bytes in Thumb mode, 8 bytes in ARM mode).
251 // FIXME: For now, assume ARM mode.
252 Value -= 8;
253 }
254
Lang Hamesf35553e2014-05-09 00:11:18 +0000255 switch (RE.RelType) {
Danil Malyshev72510f22011-07-13 07:57:58 +0000256 default:
257 llvm_unreachable("Invalid relocation type!");
Lang Hamesf35553e2014-05-09 00:11:18 +0000258 case MachO::ARM_RELOC_VANILLA:
259 return applyRelocationValue(LocalAddress, Value, 1 << RE.Size);
Charles Davis8bdfafd2013-09-01 04:28:48 +0000260 case MachO::ARM_RELOC_BR24: {
Danil Malyshev72510f22011-07-13 07:57:58 +0000261 // Mask the value into the target address. We know instructions are
262 // 32-bit aligned, so we can do it all at once.
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000263 uint32_t *p = (uint32_t *)LocalAddress;
Danil Malyshev72510f22011-07-13 07:57:58 +0000264 // The low two bits of the value are not encoded.
265 Value >>= 2;
266 // Mask the value to 24 bits.
Lang Hamesf35553e2014-05-09 00:11:18 +0000267 uint64_t FinalValue = Value & 0xffffff;
268 // Check for overflow.
269 if (Value != FinalValue)
270 return Error("ARM BR24 relocation out of range.");
Danil Malyshev72510f22011-07-13 07:57:58 +0000271 // FIXME: If the destination is a Thumb function (and the instruction
272 // is a non-predicated BL instruction), we need to change it to a BLX
273 // instruction instead.
274
275 // Insert the value into the instruction.
Lang Hamesf35553e2014-05-09 00:11:18 +0000276 *p = (*p & ~0xffffff) | FinalValue;
Danil Malyshev72510f22011-07-13 07:57:58 +0000277 break;
278 }
Charles Davis8bdfafd2013-09-01 04:28:48 +0000279 case MachO::ARM_THUMB_RELOC_BR22:
280 case MachO::ARM_THUMB_32BIT_BRANCH:
281 case MachO::ARM_RELOC_HALF:
282 case MachO::ARM_RELOC_HALF_SECTDIFF:
283 case MachO::ARM_RELOC_PAIR:
284 case MachO::ARM_RELOC_SECTDIFF:
285 case MachO::ARM_RELOC_LOCAL_SECTDIFF:
286 case MachO::ARM_RELOC_PB_LA_PTR:
Danil Malyshev72510f22011-07-13 07:57:58 +0000287 return Error("Relocation type not implemented yet!");
288 }
289 return false;
290}
291
Lang Hamesf35553e2014-05-09 00:11:18 +0000292bool RuntimeDyldMachO::resolveARM64Relocation(const RelocationEntry &RE,
293 uint64_t Value) {
294 const SectionEntry &Section = Sections[RE.SectionID];
295 uint8_t* LocalAddress = Section.Address + RE.Offset;
296
Tim Northover00ed9962014-03-29 10:18:08 +0000297 // If the relocation is PC-relative, the value to be encoded is the
298 // pointer difference.
Lang Hamesf35553e2014-05-09 00:11:18 +0000299 if (RE.IsPCRel) {
300 uint64_t FinalAddress = Section.LoadAddress + RE.Offset;
Tim Northover00ed9962014-03-29 10:18:08 +0000301 Value -= FinalAddress;
Lang Hamesf35553e2014-05-09 00:11:18 +0000302 }
Tim Northover00ed9962014-03-29 10:18:08 +0000303
Lang Hamesf35553e2014-05-09 00:11:18 +0000304 switch (RE.RelType) {
Tim Northover00ed9962014-03-29 10:18:08 +0000305 default:
306 llvm_unreachable("Invalid relocation type!");
Lang Hamesf35553e2014-05-09 00:11:18 +0000307 case MachO::ARM64_RELOC_UNSIGNED:
308 return applyRelocationValue(LocalAddress, Value, 1 << RE.Size);
Tim Northover00ed9962014-03-29 10:18:08 +0000309 case MachO::ARM64_RELOC_BRANCH26: {
310 // Mask the value into the target address. We know instructions are
311 // 32-bit aligned, so we can do it all at once.
312 uint32_t *p = (uint32_t *)LocalAddress;
313 // The low two bits of the value are not encoded.
314 Value >>= 2;
315 // Mask the value to 26 bits.
Lang Hamesf35553e2014-05-09 00:11:18 +0000316 uint64_t FinalValue = Value & 0x3ffffff;
317 // Check for overflow.
318 if (FinalValue != Value)
319 return Error("ARM64 BRANCH26 relocation out of range.");
Tim Northover00ed9962014-03-29 10:18:08 +0000320 // Insert the value into the instruction.
Lang Hamesf35553e2014-05-09 00:11:18 +0000321 *p = (*p & ~0x3ffffff) | FinalValue;
Tim Northover00ed9962014-03-29 10:18:08 +0000322 break;
323 }
324 case MachO::ARM64_RELOC_SUBTRACTOR:
325 case MachO::ARM64_RELOC_PAGE21:
326 case MachO::ARM64_RELOC_PAGEOFF12:
327 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
328 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
329 case MachO::ARM64_RELOC_POINTER_TO_GOT:
330 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
331 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
332 case MachO::ARM64_RELOC_ADDEND:
333 return Error("Relocation type not implemented yet!");
334 }
335 return false;
336}
337
Lang Hames36072da2014-05-12 21:39:59 +0000338void RuntimeDyldMachO::populateJumpTable(MachOObjectFile &Obj,
339 const SectionRef &JTSection,
340 unsigned JTSectionID) {
341 assert(!Obj.is64Bit() &&
342 "__jump_table section not supported in 64-bit MachO.");
343
344 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
345 MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl());
346 uint32_t JTSectionSize = Sec32.size;
347 unsigned FirstIndirectSymbol = Sec32.reserved1;
348 unsigned JTEntrySize = Sec32.reserved2;
349 unsigned NumJTEntries = JTSectionSize / JTEntrySize;
350 uint8_t* JTSectionAddr = getSectionAddress(JTSectionID);
351 unsigned JTEntryOffset = 0;
352
353 assert((JTSectionSize % JTEntrySize) == 0 &&
354 "Jump-table section does not contain a whole number of stubs?");
355
356 for (unsigned i = 0; i < NumJTEntries; ++i) {
357 unsigned SymbolIndex =
358 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
359 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
360 StringRef IndirectSymbolName;
361 SI->getName(IndirectSymbolName);
362 uint8_t* JTEntryAddr = JTSectionAddr + JTEntryOffset;
363 createStubFunction(JTEntryAddr);
364 RelocationEntry RE(JTSectionID, JTEntryOffset + 1,
365 MachO::GENERIC_RELOC_VANILLA, 0, true, 2);
366 addRelocationForSymbol(RE, IndirectSymbolName);
367 JTEntryOffset += JTEntrySize;
368 }
369}
370
371void RuntimeDyldMachO::populatePointersSection(MachOObjectFile &Obj,
372 const SectionRef &PTSection,
373 unsigned PTSectionID) {
374 assert(!Obj.is64Bit() &&
375 "__pointers section not supported in 64-bit MachO.");
376
377 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
378 MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl());
379 uint32_t PTSectionSize = Sec32.size;
380 unsigned FirstIndirectSymbol = Sec32.reserved1;
381 const unsigned PTEntrySize = 4;
382 unsigned NumPTEntries = PTSectionSize / PTEntrySize;
383 unsigned PTEntryOffset = 0;
384
385 assert((PTSectionSize % PTEntrySize) == 0 &&
386 "Pointers section does not contain a whole number of stubs?");
387
388 DEBUG(dbgs() << "Populating __pointers, Section ID " << PTSectionID
389 << ", " << NumPTEntries << " entries, "
390 << PTEntrySize << " bytes each:\n");
391
392 for (unsigned i = 0; i < NumPTEntries; ++i) {
393 unsigned SymbolIndex =
394 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
395 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
396 StringRef IndirectSymbolName;
397 SI->getName(IndirectSymbolName);
398 DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex
399 << ", PT offset: " << PTEntryOffset << "\n");
400 RelocationEntry RE(PTSectionID, PTEntryOffset,
401 MachO::GENERIC_RELOC_VANILLA, 0, false, 2);
402 addRelocationForSymbol(RE, IndirectSymbolName);
403 PTEntryOffset += PTEntrySize;
404 }
405}
406
407
408section_iterator getSectionByAddress(const MachOObjectFile &Obj,
409 uint64_t Addr) {
410 section_iterator SI = Obj.section_begin();
411 section_iterator SE = Obj.section_end();
412
413 for (; SI != SE; ++SI) {
414 uint64_t SAddr, SSize;
415 SI->getAddress(SAddr);
416 SI->getSize(SSize);
417 if ((Addr >= SAddr) && (Addr < SAddr + SSize))
418 return SI;
419 }
420
421 return SE;
422}
423
424relocation_iterator RuntimeDyldMachO::processSECTDIFFRelocation(
425 unsigned SectionID,
426 relocation_iterator RelI,
427 ObjectImage &Obj,
428 ObjSectionToIDMap &ObjSectionToID) {
429 const MachOObjectFile *MachO =
430 static_cast<const MachOObjectFile*>(Obj.getObjectFile());
431 MachO::any_relocation_info RE =
432 MachO->getRelocation(RelI->getRawDataRefImpl());
433
434 SectionEntry &Section = Sections[SectionID];
435 uint32_t RelocType = MachO->getAnyRelocationType(RE);
436 bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
437 unsigned Size = MachO->getAnyRelocationLength(RE);
438 uint64_t Offset;
439 RelI->getOffset(Offset);
440 uint8_t *LocalAddress = Section.Address + Offset;
441 unsigned NumBytes = 1 << Size;
442 int64_t Addend = 0;
443 memcpy(&Addend, LocalAddress, NumBytes);
444
445 ++RelI;
446 MachO::any_relocation_info RE2 =
447 MachO->getRelocation(RelI->getRawDataRefImpl());
448
449 uint32_t AddrA = MachO->getScatteredRelocationValue(RE);
450 section_iterator SAI = getSectionByAddress(*MachO, AddrA);
451 assert(SAI != MachO->section_end() && "Can't find section for address A");
452 uint64_t SectionABase;
453 SAI->getAddress(SectionABase);
454 uint64_t SectionAOffset = AddrA - SectionABase;
455 SectionRef SectionA = *SAI;
456 bool IsCode;
457 SectionA.isText(IsCode);
458 uint32_t SectionAID = findOrEmitSection(Obj, SectionA, IsCode,
459 ObjSectionToID);
460
461 uint32_t AddrB = MachO->getScatteredRelocationValue(RE2);
462 section_iterator SBI = getSectionByAddress(*MachO, AddrB);
463 assert(SBI != MachO->section_end() && "Can't find seciton for address B");
464 uint64_t SectionBBase;
465 SBI->getAddress(SectionBBase);
466 uint64_t SectionBOffset = AddrB - SectionBBase;
467 SectionRef SectionB = *SBI;
468 uint32_t SectionBID = findOrEmitSection(Obj, SectionB, IsCode,
469 ObjSectionToID);
470
471 if (Addend != AddrA - AddrB)
472 Error("Unexpected SECTDIFF relocation addend.");
473
474 DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB
475 << ", Addend: " << Addend << ", SectionA ID: "
476 << SectionAID << ", SectionAOffset: " << SectionAOffset
477 << ", SectionB ID: " << SectionBID << ", SectionBOffset: "
478 << SectionBOffset << "\n");
479 RelocationEntry R(SectionID, Offset, RelocType, 0,
480 SectionAID, SectionAOffset, SectionBID, SectionBOffset,
481 IsPCRel, Size);
482
483 addRelocationForSection(R, SectionAID);
484 addRelocationForSection(R, SectionBID);
485
486 return RelI;
487}
488
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000489relocation_iterator RuntimeDyldMachO::processRelocationRef(
490 unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj,
491 ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols,
492 StubMap &Stubs) {
Rafael Espindola4d4a48d2013-04-29 14:44:23 +0000493 const ObjectFile *OF = Obj.getObjectFile();
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000494 const MachOObjectFile *MachO = static_cast<const MachOObjectFile *>(OF);
Juergen Ributzka046709f2014-03-21 07:26:41 +0000495 MachO::any_relocation_info RE =
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000496 MachO->getRelocation(RelI->getRawDataRefImpl());
Danil Malyshev72510f22011-07-13 07:57:58 +0000497
Rafael Espindola4d4a48d2013-04-29 14:44:23 +0000498 uint32_t RelType = MachO->getAnyRelocationType(RE);
Lang Hamesfe2833b2013-08-09 00:57:01 +0000499
500 // FIXME: Properly handle scattered relocations.
501 // For now, optimistically skip these: they can often be ignored, as
502 // the static linker will already have applied the relocation, and it
503 // only needs to be reapplied if symbols move relative to one another.
504 // Note: This will fail horribly where the relocations *do* need to be
505 // applied, but that was already the case.
Lang Hames36072da2014-05-12 21:39:59 +0000506 if (MachO->isRelocationScattered(RE)) {
507 if (RelType == MachO::GENERIC_RELOC_SECTDIFF ||
508 RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)
509 return processSECTDIFFRelocation(SectionID, RelI, Obj, ObjSectionToID);
510
Juergen Ributzka046709f2014-03-21 07:26:41 +0000511 return ++RelI;
Lang Hames36072da2014-05-12 21:39:59 +0000512 }
Lang Hamesfe2833b2013-08-09 00:57:01 +0000513
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000514 RelocationValueRef Value;
Rafael Espindola4d4a48d2013-04-29 14:44:23 +0000515 SectionEntry &Section = Sections[SectionID];
Jim Grosbacheff0a402012-01-16 22:26:39 +0000516
Lang Hamesf35553e2014-05-09 00:11:18 +0000517 bool IsExtern = MachO->getPlainRelocationExternal(RE);
Rafael Espindolaf1f1c622013-04-29 17:24:34 +0000518 bool IsPCRel = MachO->getAnyRelocationPCRel(RE);
519 unsigned Size = MachO->getAnyRelocationLength(RE);
Rafael Espindolad00c2762013-04-30 01:29:57 +0000520 uint64_t Offset;
Juergen Ributzka046709f2014-03-21 07:26:41 +0000521 RelI->getOffset(Offset);
Rafael Espindola52501032013-04-30 15:40:54 +0000522 uint8_t *LocalAddress = Section.Address + Offset;
523 unsigned NumBytes = 1 << Size;
524 uint64_t Addend = 0;
525 memcpy(&Addend, LocalAddress, NumBytes);
Rafael Espindolad00c2762013-04-30 01:29:57 +0000526
Lang Hamesf35553e2014-05-09 00:11:18 +0000527 if (IsExtern) {
Eli Bendersky667b8792012-05-01 10:41:12 +0000528 // Obtain the symbol name which is referenced in the relocation
Juergen Ributzka046709f2014-03-21 07:26:41 +0000529 symbol_iterator Symbol = RelI->getSymbol();
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000530 StringRef TargetName;
Rafael Espindola806f0062013-06-05 01:33:53 +0000531 Symbol->getName(TargetName);
Eli Bendersky667b8792012-05-01 10:41:12 +0000532 // First search for the symbol in the local symbol table
Eli Benderskyfc079082012-05-01 06:58:59 +0000533 SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data());
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000534 if (lsi != Symbols.end()) {
535 Value.SectionID = lsi->second.first;
Rafael Espindolad00c2762013-04-30 01:29:57 +0000536 Value.Addend = lsi->second.second + Addend;
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000537 } else {
Eli Bendersky667b8792012-05-01 10:41:12 +0000538 // Search for the symbol in the global symbol table
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000539 SymbolTableMap::const_iterator gsi =
540 GlobalSymbolTable.find(TargetName.data());
Eli Benderskyfc079082012-05-01 06:58:59 +0000541 if (gsi != GlobalSymbolTable.end()) {
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000542 Value.SectionID = gsi->second.first;
Rafael Espindolad00c2762013-04-30 01:29:57 +0000543 Value.Addend = gsi->second.second + Addend;
544 } else {
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000545 Value.SymbolName = TargetName.data();
Rafael Espindolad00c2762013-04-30 01:29:57 +0000546 Value.Addend = Addend;
547 }
Danil Malyshev3548eaf2012-03-29 21:46:18 +0000548 }
Bill Wendling76fdc4b2012-03-29 23:23:59 +0000549 } else {
Rafael Espindola52501032013-04-30 15:40:54 +0000550 SectionRef Sec = MachO->getRelocationSection(RE);
Lang Hames9b2dc932014-02-18 21:46:39 +0000551 bool IsCode = false;
552 Sec.isText(IsCode);
553 Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID);
Rafael Espindola52501032013-04-30 15:40:54 +0000554 uint64_t Addr;
555 Sec.getAddress(Addr);
556 Value.Addend = Addend - Addr;
Lang Hames2cbbdf42014-01-29 18:31:35 +0000557 if (IsPCRel)
558 Value.Addend += Offset + NumBytes;
Bill Wendling76fdc4b2012-03-29 23:23:59 +0000559 }
560
Charles Davis8bdfafd2013-09-01 04:28:48 +0000561 if (Arch == Triple::x86_64 && (RelType == MachO::X86_64_RELOC_GOT ||
562 RelType == MachO::X86_64_RELOC_GOT_LOAD)) {
Rafael Espindolafa5942b2013-05-05 20:43:10 +0000563 assert(IsPCRel);
564 assert(Size == 2);
565 StubMap::const_iterator i = Stubs.find(Value);
566 uint8_t *Addr;
567 if (i != Stubs.end()) {
568 Addr = Section.Address + i->second;
569 } else {
570 Stubs[Value] = Section.StubOffset;
571 uint8_t *GOTEntry = Section.Address + Section.StubOffset;
Lang Hamesf35553e2014-05-09 00:11:18 +0000572 RelocationEntry GOTRE(SectionID, Section.StubOffset,
573 MachO::X86_64_RELOC_UNSIGNED, 0, false, 3);
Rafael Espindolafa5942b2013-05-05 20:43:10 +0000574 if (Value.SymbolName)
Lang Hamesf35553e2014-05-09 00:11:18 +0000575 addRelocationForSymbol(GOTRE, Value.SymbolName);
Rafael Espindolafa5942b2013-05-05 20:43:10 +0000576 else
Lang Hamesf35553e2014-05-09 00:11:18 +0000577 addRelocationForSection(GOTRE, Value.SectionID);
Rafael Espindolafa5942b2013-05-05 20:43:10 +0000578 Section.StubOffset += 8;
579 Addr = GOTEntry;
580 }
Lang Hamesf35553e2014-05-09 00:11:18 +0000581 RelocationEntry TargetRE(SectionID, Offset,
582 MachO::X86_64_RELOC_UNSIGNED, Value.Addend, true,
583 2);
584 resolveRelocation(TargetRE, (uint64_t)Addr);
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000585 } else if (Arch == Triple::arm && (RelType & 0xf) == MachO::ARM_RELOC_BR24) {
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000586 // This is an ARM branch relocation, need to use a stub function.
Bill Wendling76fdc4b2012-03-29 23:23:59 +0000587
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000588 // Look up for existing stub.
589 StubMap::const_iterator i = Stubs.find(Value);
Lang Hamesf35553e2014-05-09 00:11:18 +0000590 uint8_t *Addr;
591 if (i != Stubs.end()) {
592 Addr = Section.Address + i->second;
593 } else {
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000594 // Create a new stub function.
595 Stubs[Value] = Section.StubOffset;
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000596 uint8_t *StubTargetAddr =
597 createStubFunction(Section.Address + Section.StubOffset);
Lang Hamesf35553e2014-05-09 00:11:18 +0000598 RelocationEntry StubRE(SectionID, StubTargetAddr - Section.Address,
599 MachO::GENERIC_RELOC_VANILLA, Value.Addend);
Eli Bendersky667b8792012-05-01 10:41:12 +0000600 if (Value.SymbolName)
Lang Hamesf35553e2014-05-09 00:11:18 +0000601 addRelocationForSymbol(StubRE, Value.SymbolName);
Eli Bendersky667b8792012-05-01 10:41:12 +0000602 else
Lang Hamesf35553e2014-05-09 00:11:18 +0000603 addRelocationForSection(StubRE, Value.SectionID);
604 Addr = Section.Address + Section.StubOffset;
Danil Malyshev70d22cc2012-03-30 16:45:19 +0000605 Section.StubOffset += getMaxStubSize();
606 }
Lang Hamesf35553e2014-05-09 00:11:18 +0000607 RelocationEntry TargetRE(Value.SectionID, Offset, RelType, 0, IsPCRel,
608 Size);
609 resolveRelocation(TargetRE, (uint64_t)Addr);
Eli Bendersky667b8792012-05-01 10:41:12 +0000610 } else {
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000611 RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, IsPCRel, Size);
Eli Bendersky667b8792012-05-01 10:41:12 +0000612 if (Value.SymbolName)
613 addRelocationForSymbol(RE, Value.SymbolName);
614 else
615 addRelocationForSection(RE, Value.SectionID);
616 }
Juergen Ributzka046709f2014-03-21 07:26:41 +0000617 return ++RelI;
Bill Wendling76fdc4b2012-03-29 23:23:59 +0000618}
619
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000620bool
621RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const {
Andrew Kayloradc70562012-10-02 21:18:39 +0000622 if (InputBuffer->getBufferSize() < 4)
623 return false;
624 StringRef Magic(InputBuffer->getBufferStart(), 4);
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000625 if (Magic == "\xFE\xED\xFA\xCE")
626 return true;
627 if (Magic == "\xCE\xFA\xED\xFE")
628 return true;
629 if (Magic == "\xFE\xED\xFA\xCF")
630 return true;
631 if (Magic == "\xCF\xFA\xED\xFE")
632 return true;
Danil Malyshev72510f22011-07-13 07:57:58 +0000633 return false;
634}
635
Juergen Ributzka7608dc02014-03-21 20:28:42 +0000636bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const {
Lang Hames173c69f2014-01-08 04:09:09 +0000637 return Obj->isMachO();
638}
639
Danil Malyshev72510f22011-07-13 07:57:58 +0000640} // end namespace llvm