summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp33
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h16
2 files changed, 49 insertions, 0 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
index e96a68925a..0b72b567c3 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
@@ -210,6 +210,7 @@ loadSegment32(const MachOObject *Obj,
// Process the relocations for each section we're loading.
Relocations.grow(Relocations.size() + SegmentLC->NumSections);
+ Referrers.grow(Referrers.size() + SegmentLC->NumSections);
for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) {
InMemoryStruct<macho::Section> Sect;
Obj->ReadSection(*SegmentLCI, SectNum, Sect);
@@ -246,10 +247,12 @@ loadSegment32(const MachOObject *Obj,
// Store the relocation information. It will get resolved when
// the section addresses are assigned.
+ uint32_t RelocationIndex = Relocations[SectionID].size();
Relocations[SectionID].push_back(RelocationEntry(TargetID,
Offset,
RE->Word1,
0 /*Addend*/));
+ Referrers[TargetID].push_back(Referrer(SectionID, RelocationIndex));
} else {
StringRef SourceName = SymbolNames[SourceNum];
@@ -332,6 +335,7 @@ loadSegment64(const MachOObject *Obj,
// Process the relocations for each section we're loading.
Relocations.grow(Relocations.size() + Segment64LC->NumSections);
+ Referrers.grow(Referrers.size() + Segment64LC->NumSections);
for (unsigned SectNum = 0; SectNum != Segment64LC->NumSections; ++SectNum) {
InMemoryStruct<macho::Section64> Sect;
Obj->ReadSection64(*SegmentLCI, SectNum, Sect);
@@ -368,10 +372,12 @@ loadSegment64(const MachOObject *Obj,
// Store the relocation information. It will get resolved when
// the section addresses are assigned.
+ uint32_t RelocationIndex = Relocations[SectionID].size();
Relocations[SectionID].push_back(RelocationEntry(TargetID,
Offset,
RE->Word1,
0 /*Addend*/));
+ Referrers[TargetID].push_back(Referrer(SectionID, RelocationIndex));
} else {
StringRef SourceName = SymbolNames[SourceNum];
@@ -475,7 +481,9 @@ void RuntimeDyldMachO::resolveSymbol(StringRef Name) {
// relative and move it to the resolved relocation list.
RelocationEntry Entry = Relocs[i];
Entry.Addend += Loc->second.second;
+ uint32_t RelocationIndex = Relocations[Loc->second.first].size();
Relocations[Loc->second.first].push_back(Entry);
+ Referrers[Entry.SectionID].push_back(Referrer(Loc->second.first, RelocationIndex));
}
// FIXME: Keep a worklist of the relocations we've added so that we can
// resolve more selectively later.
@@ -614,6 +622,31 @@ void RuntimeDyldMachO::reassignSectionAddress(unsigned SectionID,
Size,
RE.Addend);
}
+ ReferrerList &Refers = Referrers[SectionID];
+ for (unsigned i = 0, e = Refers.size(); i != e; ++i) {
+ Referrer &R = Refers[i];
+ RelocationEntry &RE = Relocations[R.SectionID][R.Index];
+ uint8_t *Target = (uint8_t*)Sections[RE.SectionID].base() + RE.Offset;
+ uint64_t FinalTarget = (uint64_t)SectionLoadAddress[RE.SectionID] + RE.Offset;
+ bool isPCRel = (RE.Data >> 24) & 1;
+ unsigned Type = (RE.Data >> 28) & 0xf;
+ unsigned Size = 1 << ((RE.Data >> 25) & 3);
+
+ DEBUG(dbgs() << "Resolving relocation at Section #" << RE.SectionID
+ << " + " << RE.Offset << " (" << format("%p", Target) << ")"
+ << " from Section #" << SectionID << " (" << format("%p", Addr) << ")"
+ << "(" << (isPCRel ? "pcrel" : "absolute")
+ << ", type: " << Type << ", Size: " << Size << ", Addend: "
+ << RE.Addend << ").\n");
+
+ resolveRelocation(Target,
+ FinalTarget,
+ Addr,
+ isPCRel,
+ Type,
+ Size,
+ RE.Addend);
+ }
}
bool RuntimeDyldMachO::isKnownFormat(const MemoryBuffer *InputBuffer) {
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
index 09803cff74..6721703565 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
@@ -43,10 +43,26 @@ class RuntimeDyldMachO : public RuntimeDyldImpl {
: SectionID(id), Offset(offset), Data(data), Addend(addend) {}
};
typedef SmallVector<RelocationEntry, 4> RelocationList;
+
+ // For each section, keep a list of referrers in that section that are clients
+ // of relocations in other sections. Whenever a relocation gets created,
+ // create a corresponding referrer. Whenever relocations are re-resolved,
+ // re-resolve the referrers' relocations as well.
+ struct Referrer {
+ unsigned SectionID; // Section whose RelocationList contains the relocation.
+ uint32_t Index; // Index of the RelocatonEntry in that RelocationList.
+
+ Referrer(unsigned id, uint32_t index)
+ : SectionID(id), Index(index) {}
+ };
+ typedef SmallVector<Referrer, 4> ReferrerList;
+
// Relocations to sections already loaded. Indexed by SectionID which is the
// source of the address. The target where the address will be writen is
// SectionID/Offset in the relocation itself.
IndexedMap<RelocationList> Relocations;
+ // Referrers corresponding to Relocations.
+ IndexedMap<ReferrerList> Referrers;
// Relocations to symbols that are not yet resolved. Must be external
// relocations by definition. Indexed by symbol name.
StringMap<RelocationList> UnresolvedRelocations;