diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index e96a68925a0..0b72b567c30 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 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 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. @@ -599,6 +607,31 @@ void RuntimeDyldMachO::reassignSectionAddress(unsigned SectionID, 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); + } + 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) << ")" diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index 09803cff748..6721703565b 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 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 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 Relocations; + // Referrers corresponding to Relocations. + IndexedMap Referrers; // Relocations to symbols that are not yet resolved. Must be external // relocations by definition. Indexed by symbol name. StringMap UnresolvedRelocations;