void perform(std::unique_ptr<MutableFile> &mergedFile) override { // Scan all references in all atoms. for (const DefinedAtom *atom : mergedFile->defined()) { for (const Reference *ref : *atom) { // Look at instructions accessing the GOT. bool canBypassGOT; if (!_archHandler.isGOTAccess(*ref, canBypassGOT)) continue; const Atom *target = ref->target(); assert(target != nullptr); if (!shouldReplaceTargetWithGOTAtom(target, canBypassGOT)) { // Update reference kind to reflect that target is a direct accesss. _archHandler.updateReferenceToGOT(ref, false); } else { // Replace the target with a reference to a GOT entry. const DefinedAtom *gotEntry = makeGOTEntry(target); const_cast<Reference *>(ref)->setTarget(gotEntry); // Update reference kind to reflect that target is now a GOT entry. _archHandler.updateReferenceToGOT(ref, true); } } } // add all created GOT Atoms to master file for (auto &it : _targetToGOT) mergedFile->addAtom(*it.second); }
llvm::Error perform(SimpleFile &mergedFile) override { // Scan all references in all atoms. for (const DefinedAtom *atom : mergedFile.defined()) { for (const Reference *ref : *atom) { // Look at instructions accessing the GOT. bool canBypassGOT; if (!_archHandler.isGOTAccess(*ref, canBypassGOT)) continue; const Atom *target = ref->target(); assert(target != nullptr); if (!shouldReplaceTargetWithGOTAtom(target, canBypassGOT)) { // Update reference kind to reflect that target is a direct accesss. _archHandler.updateReferenceToGOT(ref, false); } else { // Replace the target with a reference to a GOT entry. const DefinedAtom *gotEntry = makeGOTEntry(target); const_cast<Reference *>(ref)->setTarget(gotEntry); // Update reference kind to reflect that target is now a GOT entry. _archHandler.updateReferenceToGOT(ref, true); } } } // Sort and add all created GOT Atoms to master file std::vector<const GOTEntryAtom *> entries; entries.reserve(_targetToGOT.size()); for (auto &it : _targetToGOT) entries.push_back(it.second); std::sort(entries.begin(), entries.end(), [](const GOTEntryAtom *left, const GOTEntryAtom *right) { return (left->slotName().compare(right->slotName()) < 0); }); for (const GOTEntryAtom *slot : entries) mergedFile.addAtom(*slot); return llvm::Error::success(); }
void GOTPass::perform(MutableFile &mergedFile) { // Use map so all pointers to same symbol use same GOT entry. llvm::DenseMap<const Atom*, const DefinedAtom*> targetToGOT; // Scan all references in all atoms. for(const DefinedAtom *atom : mergedFile.defined()) { for (const Reference *ref : *atom) { // Look at instructions accessing the GOT. bool canBypassGOT; if (!isGOTAccess(ref->kind(), canBypassGOT)) continue; const Atom *target = ref->target(); assert(target != nullptr); if (!shouldReplaceTargetWithGOTAtom(target, canBypassGOT)) { // Update reference kind to reflect that target is a direct accesss. updateReferenceToGOT(ref, false); continue; } // Replace the target with a reference to a GOT entry. const DefinedAtom *gotEntry = findGOTAtom(target, targetToGOT); if (!gotEntry) { gotEntry = makeGOTEntry(*target); assert(gotEntry != nullptr); assert(gotEntry->contentType() == DefinedAtom::typeGOT); targetToGOT[target] = gotEntry; } const_cast<Reference *>(ref)->setTarget(gotEntry); // Update reference kind to reflect that target is now a GOT entry. updateReferenceToGOT(ref, true); } } // add all created GOT Atoms to master file for (auto &it : targetToGOT) { mergedFile.addAtom(*it.second); } }