Ejemplo n.º 1
0
void StubsPass::perform(MutableFile &mergedFile) {
  // Skip this pass if output format uses text relocations instead of stubs.
  if ( ! this->noTextRelocs() )
    return;

  // Scan all references in all atoms.
  for(const DefinedAtom *atom : mergedFile.defined()) {
    for (const Reference *ref : *atom) {
      // Look at call-sites.
      if (this->isCallSite(ref->kind()) ) {
        const Atom* target = ref->target();
        assert(target != nullptr);
        bool replaceCalleeWithStub = false;
        if ( target->definition() == Atom::definitionSharedLibrary ) {
          // Calls to shared libraries go through stubs.
          replaceCalleeWithStub = true;
        }
        else if (const DefinedAtom* defTarget =
                     dyn_cast<DefinedAtom>(target)) {
          if ( defTarget->interposable() != DefinedAtom::interposeNo ) {
            // Calls to interposable functions in same linkage unit
            // must also go through a stub.
            assert(defTarget->scope() != DefinedAtom::scopeTranslationUnit);
            replaceCalleeWithStub = true;
          }
        }
        if ( replaceCalleeWithStub ) {
          // Make file-format specific stub and other support atoms.
          const DefinedAtom* stub = this->getStub(*target);
          assert(stub != nullptr);
          // Switch call site to reference stub atom instead.
          (const_cast<Reference*>(ref))->setTarget(stub);
         }
      }
    }
  }

  // Add all created stubs and support Atoms.
 this->addStubAtoms(mergedFile);
}
Ejemplo n.º 2
0
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);
  }
}