blob: 0646260405689c982a8f3c49d00f967abdc2fd92 [file] [log] [blame]
Sean Callanane43333a2012-04-01 06:35:00 +00001Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
2===================================================================
3--- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp (revision 152265)
4+++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp (working copy)
5@@ -24,7 +24,8 @@
6 bool RuntimeDyldMachO::
7 resolveRelocation(uint8_t *LocalAddress,
8 uint64_t FinalAddress,
9- uint64_t Value,
10+ uint64_t FinalSource1,
11+ uint64_t FinalSource2,
12 bool isPCRel,
13 unsigned Type,
14 unsigned Size,
15@@ -32,10 +33,20 @@
16 // This just dispatches to the proper target specific routine.
17 switch (CPUType) {
18 default: llvm_unreachable("Unsupported CPU type!");
19+ case mach::CTM_i386:
20+ return resolveI386Relocation(LocalAddress,
21+ FinalAddress,
22+ FinalSource1,
23+ FinalSource2,
24+ isPCRel,
25+ Type,
26+ Size,
27+ Addend);
28 case mach::CTM_x86_64:
29 return resolveX86_64Relocation(LocalAddress,
30 FinalAddress,
31- (uintptr_t)Value,
32+ FinalSource1,
33+ FinalSource2,
34 isPCRel,
35 Type,
36 Size,
37@@ -43,7 +54,8 @@
38 case mach::CTM_ARM:
39 return resolveARMRelocation(LocalAddress,
40 FinalAddress,
41- (uintptr_t)Value,
42+ FinalSource1,
43+ FinalSource2,
44 isPCRel,
45 Type,
46 Size,
47@@ -52,19 +64,52 @@
48 }
49
50 bool RuntimeDyldMachO::
51+resolveI386Relocation(uint8_t *LocalAddress,
52+ uint64_t FinalAddress,
53+ uint64_t FinalSource1,
54+ uint64_t FinalSource2,
55+ bool isPCRel,
56+ unsigned Type,
57+ unsigned Size,
58+ int64_t Addend) {
59+ int64_t ValueToWrite = Addend;
60+
61+ switch (Type) {
62+ default:
63+ llvm_unreachable("Invalid relocation type!");
64+ case macho::RIT_Vanilla:
65+ ValueToWrite += FinalSource1;
66+ break;
67+ case macho::RIT_Difference:
68+ case macho::RIT_Generic_LocalDifference:
69+ case macho::RIT_Generic_PreboundLazyPointer:
70+ ValueToWrite += FinalSource1;
71+ ValueToWrite -= FinalSource2;
72+ break;
73+ }
74+
75+ if (isPCRel)
76+ ValueToWrite -= FinalAddress + 4; // see resolveX86_64Relocation
77+
78+ uint8_t *p = LocalAddress;
79+ for (unsigned i = 0; i < Size; ++i) {
80+ *p++ = (uint8_t)(ValueToWrite & 0xff);
81+ ValueToWrite >>= 8;
82+ }
83+
84+ return false;
85+}
86+
87+bool RuntimeDyldMachO::
88 resolveX86_64Relocation(uint8_t *LocalAddress,
89 uint64_t FinalAddress,
90- uint64_t Value,
91+ uint64_t FinalSource1,
92+ uint64_t FinalSource2,
93 bool isPCRel,
94 unsigned Type,
95 unsigned Size,
96 int64_t Addend) {
97- // If the relocation is PC-relative, the value to be encoded is the
98- // pointer difference.
99- if (isPCRel)
100- // FIXME: It seems this value needs to be adjusted by 4 for an effective PC
101- // address. Is that expected? Only for branches, perhaps?
102- Value -= FinalAddress + 4;
103+ int64_t ValueToWrite = Addend;
104
105 switch(Type) {
106 default:
107@@ -74,41 +119,53 @@
108 case macho::RIT_X86_64_Signed4:
109 case macho::RIT_X86_64_Signed:
110 case macho::RIT_X86_64_Unsigned:
111- case macho::RIT_X86_64_Branch: {
112- Value += Addend;
113- // Mask in the target value a byte at a time (we don't have an alignment
114- // guarantee for the target address, so this is safest).
115- uint8_t *p = (uint8_t*)LocalAddress;
116- for (unsigned i = 0; i < Size; ++i) {
117- *p++ = (uint8_t)Value;
118- Value >>= 8;
119- }
120- return false;
121- }
122+ case macho::RIT_X86_64_Branch:
123+ ValueToWrite += FinalSource1;
124+ break;
125 case macho::RIT_X86_64_GOTLoad:
126 case macho::RIT_X86_64_GOT:
127 case macho::RIT_X86_64_Subtractor:
128 case macho::RIT_X86_64_TLV:
129 return Error("Relocation type not implemented yet!");
130 }
131+
132+ // If the relocation is PC-relative, the value to be encoded is the
133+ // pointer difference.
134+ if (isPCRel)
135+ // FIXME: It seems this value needs to be adjusted by 4 for an effective PC
136+ // address. Is that expected? Only for branches, perhaps?
137+ ValueToWrite -= FinalAddress + 4;
138+
139+ // Mask in the target value a byte at a time (we don't have an alignment
140+ // guarantee for the target address, so this is safest).
141+ uint8_t *p = (uint8_t*)LocalAddress;
142+ for (unsigned i = 0; i < Size; ++i) {
143+ *p++ = (uint8_t)(ValueToWrite & 0xff);
144+ ValueToWrite >>= 8;
145+ }
146+
147+ return false;
148 }
149
150 bool RuntimeDyldMachO::
151 resolveARMRelocation(uint8_t *LocalAddress,
152 uint64_t FinalAddress,
153- uint64_t Value,
154+ uint64_t FinalSource1,
155+ uint64_t FinalSource2,
156 bool isPCRel,
157 unsigned Type,
158 unsigned Size,
159 int64_t Addend) {
160+ int64_t ValueToWrite = Addend;
161+
162 // If the relocation is PC-relative, the value to be encoded is the
163 // pointer difference.
164 if (isPCRel) {
165- Value -= FinalAddress;
166+ ValueToWrite -= FinalAddress;
167 // ARM PCRel relocations have an effective-PC offset of two instructions
168 // (four bytes in Thumb mode, 8 bytes in ARM mode).
169 // FIXME: For now, assume ARM mode.
170- Value -= 8;
171+ ValueToWrite -= 8;
172 }
173
174 switch(Type) {
175@@ -119,8 +176,8 @@
176 // guarantee for the target address, so this is safest).
177 uint8_t *p = (uint8_t*)LocalAddress;
178 for (unsigned i = 0; i < Size; ++i) {
179- *p++ = (uint8_t)Value;
180- Value >>= 8;
181+ *p++ = (uint8_t)(ValueToWrite & 0xff);
182+ ValueToWrite >>= 8;
183 }
184 break;
185 }
186@@ -129,15 +186,15 @@
187 // 32-bit aligned, so we can do it all at once.
188 uint32_t *p = (uint32_t*)LocalAddress;
189 // The low two bits of the value are not encoded.
190- Value >>= 2;
191+ ValueToWrite >>= 2;
192 // Mask the value to 24 bits.
193- Value &= 0xffffff;
194+ ValueToWrite &= 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+ *p = (*p & ~0xffffff) | ValueToWrite;
202 break;
203 }
204 case macho::RIT_ARM_ThumbBranch22Bit:
205@@ -153,6 +210,29 @@
206 return false;
207 }
208
209+static bool
210+ResolveSectionAndOffset(const MachOObject *Obj,
211+ SmallVectorImpl<unsigned> &SectionMap,
212+ const MachOObject::LoadCommandInfo *SegmentLCI,
213+ InMemoryStruct<macho::SegmentLoadCommand> &SegmentLC,
214+ uint64_t Address,
215+ unsigned &SectionID,
216+ uint64_t &Offset)
217+{
218+ for (unsigned SI = 0, SE = SegmentLC->NumSections; SI < SE; ++SI) {
219+ InMemoryStruct<macho::Section> CandidateSection;
220+ Obj->ReadSection(*SegmentLCI, SI, CandidateSection);
221+ if (Address >= CandidateSection->Address &&
222+ Address < CandidateSection->Address + CandidateSection->Size) {
223+ SectionID = SectionMap[SI];
224+ Offset = Address - CandidateSection->Address;
225+ return true;
226+ }
227+ }
228+
229+ return false;
230+}
231+
232 bool RuntimeDyldMachO::
233 loadSegment32(const MachOObject *Obj,
234 const MachOObject::LoadCommandInfo *SegmentLCI,
235@@ -210,6 +290,7 @@
236
237 // Process the relocations for each section we're loading.
238 Relocations.grow(Relocations.size() + SegmentLC->NumSections);
239+ RelocationSources.grow(RelocationSources.size() + SegmentLC->NumSections);
240 for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) {
241 InMemoryStruct<macho::Section> Sect;
242 Obj->ReadSection(*SegmentLCI, SectNum, Sect);
243@@ -218,51 +299,135 @@
244 for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) {
245 InMemoryStruct<macho::RelocationEntry> RE;
246 Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE);
247- if (RE->Word0 & macho::RF_Scattered)
248- return Error("NOT YET IMPLEMENTED: scattered relocations.");
249- // Word0 of the relocation is the offset into the section where the
250- // relocation should be applied. We need to translate that into an
251- // offset into a function since that's our atom.
252- uint32_t Offset = RE->Word0;
253- bool isExtern = (RE->Word1 >> 27) & 1;
254-
255- // FIXME: Get the relocation addend from the target address.
256- // FIXME: VERY imporant for internal relocations.
257-
258- // Figure out the source symbol of the relocation. If isExtern is true,
259- // this relocation references the symbol table, otherwise it references
260- // a section in the same object, numbered from 1 through NumSections
261- // (SectionBases is [0, NumSections-1]).
262- uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value
263- if (!isExtern) {
264- assert(SourceNum > 0 && "Invalid relocation section number!");
265- unsigned SectionID = SectionMap[SourceNum - 1];
266+ if (RE->Word0 & macho::RF_Scattered) {
267+ // The lower 24 bits of Word0 of the scattered relocation is the offset
268+ // into the section where the relocation should be applied, i.e., the
269+ // current section.
270+ uint32_t OffsetInTarget = RE->Word0 & 0x00ffffff;
271 unsigned TargetID = SectionMap[SectNum];
272- DEBUG(dbgs() << "Internal relocation at Section #"
273- << TargetID << " + " << Offset
274- << " from Section #"
275- << SectionID << " (Word1: "
276- << format("0x%x", RE->Word1) << ")\n");
277-
278- // Store the relocation information. It will get resolved when
279- // the section addresses are assigned.
280- Relocations[SectionID].push_back(RelocationEntry(TargetID,
281- Offset,
282- RE->Word1,
283- 0 /*Addend*/));
284+ // Word1 of the scattered relocation is a file offset which needs to
285+ // be resolved into Section+Offset form. This gives the address of the
286+ // source.
287+ unsigned Source1ID;
288+ uint64_t Source1Offset;
289+ if (!ResolveSectionAndOffset(Obj,
290+ SectionMap,
291+ SegmentLCI,
292+ SegmentLC,
293+ RE->Word1,
294+ Source1ID,
295+ Source1Offset))
296+ return Error("couldn't find scattered relocation value in sections");
297+ // This relocation may have a paired relocation entry. If it does, set
298+ // the source/offset information for it correctly.
299+ unsigned Source2ID = SectionOffset::NoSectionID;
300+ uint64_t Source2Offset = 0;
301+ if (j + 1 < Sect->NumRelocationTableEntries) {
302+ InMemoryStruct<macho::RelocationEntry> PairRE;
303+ Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j+1, PairRE);
304+ if ((PairRE->Word0 & macho::RF_Scattered) &&
305+ ((PairRE->Word0 & 0x0f000000) >> 24) == macho::RIT_Pair) {
306+ if (!ResolveSectionAndOffset(Obj,
307+ SectionMap,
308+ SegmentLCI,
309+ SegmentLC,
310+ PairRE->Word1,
311+ Source2ID,
312+ Source2Offset))
313+ return Error("couldn't find scattered relocation value in sections");
314+ ++j;
315+ }
316+ }
317+ if (Source2ID == SectionOffset::NoSectionID)
318+ DEBUG(dbgs() << "Scattered relocation at Section #"
319+ << TargetID << " + " << OffsetInTarget
320+ << " from Section #" << Source1ID
321+ << "+" << Source1Offset
322+ << " (Word0: "
323+ << format("0x%x", RE->Word0) << ")\n");
324+ else
325+ DEBUG(dbgs() << "Scattered relocation at Section #"
326+ << TargetID << " + " << OffsetInTarget
327+ << " from Section #" << Source1ID
328+ << "+" << Source1Offset
329+ << " and Section #" << Source2ID
330+ << "+" << Source2Offset
331+ << " (Word0: "
332+ << format("0x%x", RE->Word0) << ")\n");
333+ uint32_t RelocationIndex = Relocations[TargetID].size();
334+ // FIXME: Get the relocation addend from the target address.
335+ // FIXME: VERY imporant for internal relocations.
336+ RelocationEntry TranslatedRE(OffsetInTarget,
337+ Source1ID,
338+ Source1Offset,
339+ Source2ID,
340+ Source2Offset,
341+ RE->Word1,
342+ 0 /*Addend*/);
343+ Relocations[TargetID].push_back(TranslatedRE);
344+ RelocationSources[Source1ID].push_back(RelocationSource(TargetID,
345+ RelocationIndex,
346+ 0));
347+ if (Source2ID != SectionOffset::NoSectionID)
348+ RelocationSources[Source2ID].push_back(RelocationSource(TargetID,
349+ RelocationIndex,
350+ 1));
351 } else {
352- StringRef SourceName = SymbolNames[SourceNum];
353-
354- // Now store the relocation information. Associate it with the source
355- // symbol. Just add it to the unresolved list and let the general
356- // path post-load resolve it if we know where the symbol is.
357- UnresolvedRelocations[SourceName].push_back(RelocationEntry(SectNum,
358- Offset,
359- RE->Word1,
360- 0 /*Addend*/));
361- DEBUG(dbgs() << "Relocation at Section #" << SectNum << " + " << Offset
362- << " from '" << SourceName << "(Word1: "
363- << format("0x%x", RE->Word1) << ")\n");
364+ // Word0 of the relocation is the offset into the section where the
365+ // relocation should be applied, i.e., the current section. We need
366+ // to translate that into an offset into a function since that's our atom.
367+ uint32_t OffsetInTarget = RE->Word0;
368+ bool isExtern = (RE->Word1 >> 27) & 1;
369+
370+ // FIXME: Get the relocation addend from the target address.
371+ // FIXME: VERY imporant for internal relocations.
372+
373+ // Figure out the source symbol of the relocation. If isExtern is true,
374+ // this relocation references the symbol table, otherwise it references
375+ // a section in the same object, numbered from 1 through NumSections
376+ // (SectionBases is [0, NumSections-1]).
377+ uint32_t SourceNum_OneBased = RE->Word1 & 0xffffff; // 24-bit value
378+ if (!isExtern) {
379+ assert(SourceNum_OneBased > 0 && "Invalid relocation section number!");
380+ unsigned SourceID = SectionMap[SourceNum_OneBased - 1];
381+ unsigned TargetID = SectionMap[SectNum];
382+ DEBUG(dbgs() << "Internal relocation at Section #"
383+ << TargetID << " + " << OffsetInTarget
384+ << " from Section #"
385+ << SourceID << " (Word1: "
386+ << format("0x%x", RE->Word1) << ")\n");
387+
388+ // Store the relocation information. It will get resolved when
389+ // the section addresses are assigned.
390+ uint32_t RelocationIndex = Relocations[TargetID].size();
391+ Relocations[TargetID].push_back(RelocationEntry(OffsetInTarget,
392+ SourceID,
393+ SectionOffset::NoSectionID,
394+ RE->Word1,
395+ 0 /*Addend*/));
396+ RelocationSources[SourceID].push_back(RelocationSource(TargetID,
397+ RelocationIndex,
398+ 0));
399+ } else {
400+ StringRef SourceName = SymbolNames[SourceNum_OneBased];
401+
402+ // Now store the relocation information. Associate it with the source
403+ // symbol. Just add it to the unresolved list and let the general
404+ // path post-load resolve it if we know where the symbol is.
405+ unsigned TargetID = SectionMap[SectNum];
406+ uint32_t RelocationIndex = Relocations[TargetID].size();
407+ Relocations[TargetID].push_back(RelocationEntry(OffsetInTarget,
408+ SectionOffset::UnresolvedSourceID,
409+ SectionOffset::NoSectionID,
410+ RE->Word1,
411+ 0 /*Addend*/));
412+ UnresolvedRelocations[SourceName].push_back(RelocationSource(TargetID,
413+ RelocationIndex,
414+ 0));
415+ DEBUG(dbgs() << "Relocation at Section #" << SectNum << " + " << OffsetInTarget
416+ << " from '" << SourceName << "' (Word1: "
417+ << format("0x%x", RE->Word1) << ")\n");
418+ }
419 }
420 }
421 }
422@@ -332,6 +497,7 @@
423
424 // Process the relocations for each section we're loading.
425 Relocations.grow(Relocations.size() + Segment64LC->NumSections);
426+ RelocationSources.grow(RelocationSources.size() + Segment64LC->NumSections);
427 for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections; ++SectNum) {
428 InMemoryStruct<macho::Section64> Sect;
429 Obj->ReadSection64(*SegmentLCI, SectNum, Sect);
430@@ -341,11 +507,11 @@
431 InMemoryStruct<macho::RelocationEntry> RE;
432 Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE);
433 if (RE->Word0 & macho::RF_Scattered)
434- return Error("NOT YET IMPLEMENTED: scattered relocations.");
435+ return Error("scattered relocations don't exist on 64-bit platforms");
436 // Word0 of the relocation is the offset into the section where the
437 // relocation should be applied. We need to translate that into an
438 // offset into a function since that's our atom.
439- uint32_t Offset = RE->Word0;
440+ uint32_t OffsetInTarget = RE->Word0;
441 bool isExtern = (RE->Word1 >> 27) & 1;
442
443 // FIXME: Get the relocation addend from the target address.
444@@ -355,34 +521,45 @@
445 // this relocation references the symbol table, otherwise it references
446 // a section in the same object, numbered from 1 through NumSections
447 // (SectionBases is [0, NumSections-1]).
448- uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value
449+ uint32_t SourceNum_OneBased = RE->Word1 & 0xffffff; // 24-bit value
450 if (!isExtern) {
451- assert(SourceNum > 0 && "Invalid relocation section number!");
452- unsigned SectionID = SectionMap[SourceNum - 1];
453+ assert(SourceNum_OneBased > 0 && "Invalid relocation section number!");
454+ unsigned SourceID = SectionMap[SourceNum_OneBased - 1];
455 unsigned TargetID = SectionMap[SectNum];
456 DEBUG(dbgs() << "Internal relocation at Section #"
457- << TargetID << " + " << Offset
458+ << TargetID << " + " << OffsetInTarget
459 << " from Section #"
460- << SectionID << " (Word1: "
461+ << SourceID << " (Word1: "
462 << format("0x%x", RE->Word1) << ")\n");
463
464 // Store the relocation information. It will get resolved when
465 // the section addresses are assigned.
466- Relocations[SectionID].push_back(RelocationEntry(TargetID,
467- Offset,
468- RE->Word1,
469- 0 /*Addend*/));
470+ uint32_t RelocationIndex = Relocations[TargetID].size();
471+ Relocations[TargetID].push_back(RelocationEntry(OffsetInTarget,
472+ SourceID,
473+ SectionOffset::NoSectionID,
474+ RE->Word1,
475+ 0 /*Addend*/));
476+ RelocationSources[SourceID].push_back(RelocationSource(TargetID,
477+ RelocationIndex,
478+ 0));
479 } else {
480- StringRef SourceName = SymbolNames[SourceNum];
481+ StringRef SourceName = SymbolNames[SourceNum_OneBased];
482
483 // Now store the relocation information. Associate it with the source
484 // symbol. Just add it to the unresolved list and let the general
485 // path post-load resolve it if we know where the symbol is.
486- UnresolvedRelocations[SourceName].push_back(RelocationEntry(SectNum,
487- Offset,
488- RE->Word1,
489- 0 /*Addend*/));
490- DEBUG(dbgs() << "Relocation at Section #" << SectNum << " + " << Offset
491+ unsigned TargetID = SectionMap[SectNum];
492+ uint32_t RelocationIndex = Relocations[TargetID].size();
493+ Relocations[TargetID].push_back(RelocationEntry(OffsetInTarget,
494+ SectionOffset::UnresolvedSourceID,
495+ SectionOffset::NoSectionID,
496+ RE->Word1,
497+ 0 /*Addend*/));
498+ UnresolvedRelocations[SourceName].push_back(RelocationSource(TargetID,
499+ RelocationIndex,
500+ 0));
501+ DEBUG(dbgs() << "Relocation at Section #" << SectNum << " + " << OffsetInTarget
502 << " from '" << SourceName << "(Word1: "
503 << format("0x%x", RE->Word1) << ")\n");
504 }
505@@ -468,18 +645,22 @@
506 if (Loc == SymbolTable.end())
507 return;
508
509- RelocationList &Relocs = UnresolvedRelocations[Name];
510+ RelocationSourceList &SourcesForSymbol = UnresolvedRelocations[Name];
511 DEBUG(dbgs() << "Resolving symbol '" << Name << "'\n");
512- for (int i = 0, e = Relocs.size(); i != e; ++i) {
513- // Change the relocation to be section relative rather than symbol
514- // relative and move it to the resolved relocation list.
515- RelocationEntry Entry = Relocs[i];
516- Entry.Addend += Loc->second.second;
517- Relocations[Loc->second.first].push_back(Entry);
518+ for (int i = 0, e = SourcesForSymbol.size(); i != e; ++i) {
519+ // Find the relocation entry corresponding to this source and fill
520+ // in its source information with the resolved information from this
521+ // symbol.
522+ RelocationSource &Source = SourcesForSymbol[i];
523+ RelocationEntry &Entry = Relocations[Source.SectionID][Source.Index];
524+ Entry.Sources[Source.SourceIdx].Offset = Loc->second.second;
525+ Entry.Sources[Source.SourceIdx].ID = Loc->second.first;
526+ // Now create a relocation source in the pointed-to section.
527+ RelocationSources[Loc->second.first].push_back(Source);
528 }
529 // FIXME: Keep a worklist of the relocations we've added so that we can
530 // resolve more selectively later.
531- Relocs.clear();
532+ SourcesForSymbol.clear();
533 }
534
535 bool RuntimeDyldMachO::loadObject(MemoryBuffer *InputBuffer) {
536@@ -575,6 +756,56 @@
537 return false;
538 }
539
540+bool RuntimeDyldMachO::resolveRelocationEntry(unsigned SectionID,
541+ RelocationEntry &RE)
542+{
543+ uint8_t *Target = (uint8_t*)Sections[SectionID].base() + RE.Offset;
544+ uint64_t FinalTarget = SectionLoadAddress[SectionID] + RE.Offset;
545+
546+ uint64_t FinalSource1 = 0;
547+ uint64_t FinalSource2 = 0;
548+
549+ if (RE.Sources[0].ID == SectionOffset::UnresolvedSourceID ||
550+ RE.Sources[1].ID == SectionOffset::UnresolvedSourceID)
551+ return false;
552+
553+ FinalSource1 = SectionLoadAddress[RE.Sources[0].ID] + RE.Sources[0].Offset;
554+ if (RE.Sources[1].ID != SectionOffset::NoSectionID)
555+ FinalSource2 = SectionLoadAddress[RE.Sources[1].ID] + RE.Sources[1].Offset;
556+
557+ bool isPCRel = RE.isPCRel();
558+ unsigned Type = RE.type();
559+ unsigned Size = RE.length();
560+
561+ if (RE.Sources[1].ID == SectionOffset::NoSectionID)
562+ DEBUG(dbgs() << "Resolving relocation at Section #" << SectionID
563+ << " + " << RE.Offset << " (" << format("%p", Target) << ")"
564+ << " from Section #" << RE.Sources[0].ID << "+" << RE.Sources[0].Offset
565+ << " (" << format("0x%llx", FinalSource1) << ")"
566+ << " (" << (isPCRel ? "pcrel" : "absolute")
567+ << ", type: " << Type << ", Size: " << Size << ", Addend: "
568+ << RE.Addend << ").\n");
569+ else
570+ DEBUG(dbgs() << "Resolving relocation at Section #" << SectionID
571+ << " + " << RE.Offset << " (" << format("%p", Target) << ")"
572+ << " from Section #" << RE.Sources[0].ID << "+" << RE.Sources[0].Offset
573+ << " (" << format("0x%llx", FinalSource1) << ")"
574+ << " and Section #" << RE.Sources[1].ID << "+" << RE.Sources[1].Offset
575+ << " (" << format("0x%llx", FinalSource2) << ")"
576+ << " (" << (isPCRel ? "pcrel" : "absolute")
577+ << ", type: " << Type << ", Size: " << Size << ", Addend: "
578+ << RE.Addend << ").\n");
579+
580+ return resolveRelocation(Target,
581+ FinalTarget,
582+ FinalSource1,
583+ FinalSource2,
584+ isPCRel,
585+ Type,
586+ Size,
587+ RE.Addend);
588+}
589+
590 // Assign an address to a symbol name and resolve all the relocations
591 // associated with it.
592 void RuntimeDyldMachO::reassignSectionAddress(unsigned SectionID,
593@@ -590,30 +821,17 @@
594
595 SectionLoadAddress[SectionID] = Addr;
596
597- RelocationList &Relocs = Relocations[SectionID];
598- for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
599- RelocationEntry &RE = Relocs[i];
600- uint8_t *Target = (uint8_t*)Sections[RE.SectionID].base() + RE.Offset;
601- uint64_t FinalTarget = (uint64_t)SectionLoadAddress[RE.SectionID] + RE.Offset;
602- bool isPCRel = (RE.Data >> 24) & 1;
603- unsigned Type = (RE.Data >> 28) & 0xf;
604- unsigned Size = 1 << ((RE.Data >> 25) & 3);
605-
606- DEBUG(dbgs() << "Resolving relocation at Section #" << RE.SectionID
607- << " + " << RE.Offset << " (" << format("%p", Target) << ")"
608- << " from Section #" << SectionID << " (" << format("%p", Addr) << ")"
609- << "(" << (isPCRel ? "pcrel" : "absolute")
610- << ", type: " << Type << ", Size: " << Size << ", Addend: "
611- << RE.Addend << ").\n");
612-
613- resolveRelocation(Target,
614- FinalTarget,
615- Addr,
616- isPCRel,
617- Type,
618- Size,
619- RE.Addend);
620+ RelocationList &RelocsForSection = Relocations[SectionID];
621+ for (unsigned i = 0, e = RelocsForSection.size(); i != e; ++i) {
622+ RelocationEntry &RE = RelocsForSection[i];
623+ resolveRelocationEntry(SectionID, RE);
624 }
625+ RelocationSourceList &SourcesForSection = RelocationSources[SectionID];
626+ for (unsigned i = 0, e = SourcesForSection.size(); i != e; ++i) {
627+ RelocationSource &R = SourcesForSection[i];
628+ RelocationEntry &RE = Relocations[R.SectionID][R.Index];
629+ resolveRelocationEntry(R.SectionID, RE);
630+ }
631 }
632
633 bool RuntimeDyldMachO::isKnownFormat(const MemoryBuffer *InputBuffer) {
634Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
635===================================================================
636--- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h (revision 152265)
637+++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h (working copy)
638@@ -26,48 +26,183 @@
639 namespace llvm {
640 class RuntimeDyldMachO : public RuntimeDyldImpl {
641
642- // For each symbol, keep a list of relocations based on it. Anytime
643- // its address is reassigned (the JIT re-compiled the function, e.g.),
644- // the relocations get re-resolved.
645- // The symbol (or section) the relocation is sourced from is the Key
646- // in the relocation list where it's stored.
647+ // For each section, keep a list of relocatable pieces of data that
648+ // reside in it. If the section moves, or the sections whose
649+ // locations the data depends on move, re-resolve the relocations
650+ // based on that movement.
651+ //
652+ // RelocationEntry structures correspond to one or two Mach-O
653+ // relocation_info or scattered_relocation_info structures --
654+ // usually one, but two iff the original has a paired structure
655+ // following it.
656+ //
657+ // To facilitate updating a relocation when its sources move, we
658+ // also keep RelocationSource structures associated with the sections
659+ // whose location the data depends on.
660+
661+ // FIXME: Use SymbolLoc for this instead. Where should the enum live?
662+ struct SectionOffset {
663+ uint64_t Offset; // Offset of the location into its section.
664+ unsigned ID; // The section the location is contained in.
665+
666+ enum {
667+ NoSectionID = 0xffff0000,
668+ UnresolvedSourceID = 0xffffffff
669+ };
670+ };
671+
672 struct RelocationEntry {
673- unsigned SectionID; // Section the relocation is contained in.
674- uint64_t Offset; // Offset into the section for the relocation.
675- uint32_t Data; // Second word of the raw macho relocation entry.
676- int64_t Addend; // Addend encoded in the instruction itself, if any,
677- // plus the offset into the source section for
678- // the symbol once the relocation is resolvable.
679+ SectionOffset Sources[2]; // The section/offset pairs this relocation
680+ // refers to.
681+ // If the original Mach-O relocation entries used
682+ // relocation_info, this data is computed from
683+ // r_symbolnum and the offsets are locked to 0.
684+ // (The only offset is determined by the addend.)
685+ // If the original Mach-O relocation entries used
686+ // scattered_relocation_info, this data, including
687+ // offsets, is computed by looking r_value up in
688+ // the section table.
689
690- RelocationEntry(unsigned id, uint64_t offset, uint32_t data, int64_t addend)
691- : SectionID(id), Offset(offset), Data(data), Addend(addend) {}
692+ uint64_t Offset; // The offset of the data to be relocated.
693+ // We don't use a SectionOffset because this
694+ // RelocationEntry is already associated with the
695+ // proper Section.
696+
697+ int64_t Addend; // Addend encoded in the instruction itself, if any,
698+ // plus the offset into the source section for
699+ // the symbol once the relocation is resolvable.
700+
701+ uint32_t Data; // If the original Mach-O relocation entry was a
702+ // relocation_info, the bitfield { r_symbolnum,
703+ // r_pcrel, r_length, r_extern, r_type }.
704+ // If the original Mach-O relocation entry was a
705+ // scattered_relocation_info, the bitfield
706+ // { r_address, r_type, r_length, r_pcrel,
707+ // r_scattered }.
708+
709+ bool Scattered; // True iff this relocation is scattered.
710+
711+ bool isPCRel()
712+ {
713+ if (Scattered)
714+ return (Data & 0x40000000) >> 30;
715+ else
716+ return (Data & 0x01000000) >> 24;
717+ }
718+
719+ uint8_t type()
720+ {
721+ if (Scattered)
722+ return (Data & 0x0f000000) >> 24;
723+ else
724+ return (Data & 0xf0000000) >> 28;
725+ }
726+
727+ // Returns the decoded version of the length field
728+ uint8_t length()
729+ {
730+ if (Scattered)
731+ return 1 << ((Data & 0x30000000) >> 28);
732+ else
733+ return 1 << ((Data & 0x0e000000) >> 25);
734+ }
735+
736+ // Used with an ordinary relocation entry, where the source_offsets are not
737+ // known yet.
738+ RelocationEntry(uint64_t offset, // See the Offset field.
739+ unsigned source_id0, // The section ID for the first source.
740+ unsigned source_id1, // The section ID for the second source.
741+ uint32_t data, // See the Data field.
742+ int64_t addend) // See the Addend field.
743+ : Offset(offset),
744+ Addend(addend),
745+ Data(data),
746+ Scattered(false) {
747+ Sources[0].ID = source_id0;
748+ Sources[0].Offset = 0;
749+ Sources[1].ID = source_id1;
750+ Sources[1].Offset = 0;
751+ }
752+
753+ // Used with a scattered relocation entry, where the source_offsets can be
754+ // derived from the value.
755+ RelocationEntry(uint64_t offset, // See the Offset field.
756+ unsigned source_id0, // The section ID for the first source.
757+ uint64_t source_off0, // The offset for the first source.
758+ unsigned source_id1, // The section ID for the second source.
759+ uint64_t source_off1, // The offset for the second source.
760+ uint32_t data, // See the Data field.
761+ int64_t addend) // See the Addend field.
762+ : Offset(offset),
763+ Addend(addend),
764+ Data(data),
765+ Scattered(true) {
766+ Sources[0].ID = source_id0;
767+ Sources[0].Offset = source_off0;
768+ Sources[1].ID = source_id1;
769+ Sources[1].Offset = source_off1;
770+ }
771 };
772 typedef SmallVector<RelocationEntry, 4> RelocationList;
773- // Relocations to sections already loaded. Indexed by SectionID which is the
774- // source of the address. The target where the address will be writen is
775- // SectionID/Offset in the relocation itself.
776+
777+ // For each section, keep a list of sources that are used by relocations in
778+ // other sections. Whenever a relocation gets created, create one or two
779+ // corresponding relocation sources. Whenever relocations are re-resolved
780+ // for a section, also re-resolve the relocations corresponding to that
781+ // section's relocation targets.
782+ struct RelocationSource {
783+ unsigned SectionID; // Section whose RelocationList contains the relocation.
784+ uint32_t Index : 24; // Index of the RelocatonEntry in that RelocationList.
785+ uint8_t SourceIdx : 1; // Index of this source in the RelocationEntry's Sources.
786+
787+ RelocationSource(unsigned id,
788+ uint32_t index,
789+ uint8_t source_idx)
790+ : SectionID(id),
791+ Index(index),
792+ SourceIdx(source_idx) {}
793+ };
794+ typedef SmallVector<RelocationSource, 4> RelocationSourceList;
795+
796+ // Relocations which refer to already-loaded section. Indexed by SectionID
797+ // which is the section containing the relocatable data.
798 IndexedMap<RelocationList> Relocations;
799+ // Targets corresponding to Relocations.
800+ IndexedMap<RelocationSourceList> RelocationSources;
801 // Relocations to symbols that are not yet resolved. Must be external
802 // relocations by definition. Indexed by symbol name.
803- StringMap<RelocationList> UnresolvedRelocations;
804+ StringMap<RelocationSourceList> UnresolvedRelocations;
805
806+ bool resolveRelocationEntry(unsigned SectionID,
807+ RelocationEntry &RE);
808 bool resolveRelocation(uint8_t *LocalAddress,
809 uint64_t FinalAddress,
810- uint64_t Value,
811+ uint64_t FinalSource1,
812+ uint64_t FinalSource2,
813 bool isPCRel,
814 unsigned Type,
815 unsigned Size,
816 int64_t Addend);
817+ bool resolveI386Relocation(uint8_t *LocalAddress,
818+ uint64_t FinalAddress,
819+ uint64_t FinalSource1,
820+ uint64_t FinalSource2,
821+ bool isPCRel,
822+ unsigned Type,
823+ unsigned Size,
824+ int64_t Addend);
825 bool resolveX86_64Relocation(uint8_t *LocalAddress,
826 uint64_t FinalAddress,
827- uint64_t Value,
828+ uint64_t FinalSource1,
829+ uint64_t FinalSource2,
830 bool isPCRel,
831 unsigned Type,
832 unsigned Size,
833 int64_t Addend);
834 bool resolveARMRelocation(uint8_t *LocalAddress,
835 uint64_t FinalAddress,
836- uint64_t Value,
837+ uint64_t FinalSource1,
838+ uint64_t FinalSource2,
839 bool isPCRel,
840 unsigned Type,
841 unsigned Size,