summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Callanan <scallanan@apple.com>2012-03-20 22:25:39 +0000
committerSean Callanan <scallanan@apple.com>2012-03-20 22:25:39 +0000
commit5069b21b45d8ec99a1b34b6483d800ba5c2ea598 (patch)
tree3cf1b418721fc326d8e42f0db32e6e8d23ee5593
parent768b4e8cb4dabc14b8e16806d1defb79f83a7d72 (diff)
downloadllvm-5069b21b45d8ec99a1b34b6483d800ba5c2ea598.tar.gz
llvm-5069b21b45d8ec99a1b34b6483d800ba5c2ea598.tar.bz2
llvm-5069b21b45d8ec99a1b34b6483d800ba5c2ea598.tar.xz
RuntimeDyldMachO has the ability to keep track of
relocations (i.e., pieces of data whose addresses are referred to elsewhere in the binary image) and update the references when the section containing the relocations moves. The way this works is that there is a map from section IDs to lists of relocations. Because the relocations are associated with the section containing the data being referred to, they are updated only when the target moves. However, many data references are relative and also depend on the location of the referrer. To solve this problem, I introduced a new data structure, Referrer, which simply contains the section being referred to and the index of the relocation in that section. These referrers are associated with the source containing the reference that needs to be updated, so now regardless of which end of the relocation moves, the relocation will now be updated correctly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153147 91177308-0d34-0410-b5e6-96231b3b80d8
-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;