Esempio n. 1
0
std::map<StringRef, std::vector<COFFSharedLibraryAtom *> >
IdataPass::groupByLoadName(MutableFile &file) {
  std::map<StringRef, COFFSharedLibraryAtom *> uniqueAtoms;
  for (const SharedLibraryAtom *atom : file.sharedLibrary())
    uniqueAtoms[atom->name()] = (COFFSharedLibraryAtom *)atom;

  std::map<StringRef, std::vector<COFFSharedLibraryAtom *> > ret;
  for (auto i : uniqueAtoms) {
    COFFSharedLibraryAtom *atom = i.second;
    ret[atom->loadName()].push_back(atom);
  }
  return ret;
}
Esempio 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);
  }
}
Esempio n. 3
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);
}
Esempio n. 4
0
/// Perform the actual pass
void LayoutPass::perform(MutableFile &mergedFile) {
  ScopedTask task(getDefaultDomain(), "LayoutPass");
  MutableFile::DefinedAtomRange atomRange = mergedFile.definedAtoms();

  // Build follow on tables
  buildFollowOnTable(atomRange);

  // Build Ingroup reference table
  buildInGroupTable(atomRange);

  // Build preceded by tables
  buildPrecededByTable(atomRange);

  // Check the structure of followon graph if running in debug mode.
  DEBUG(checkFollowonChain(atomRange));

  // Build override maps
  buildOrdinalOverrideMap(atomRange);

  DEBUG({
    llvm::dbgs() << "unsorted atoms:\n";
    printDefinedAtoms(atomRange);
  });
Esempio n. 5
0
nsresult
FileService::Enqueue(FileHandle* aFileHandle, FileHelper* aFileHelper)
{
  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
  MOZ_ASSERT(aFileHandle, "Null pointer!");

  MutableFile* mutableFile = aFileHandle->mMutableFile;

  if (mutableFile->IsInvalid()) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  const nsACString& storageId = mutableFile->mStorageId;
  const nsAString& fileName = mutableFile->mFileName;
  bool modeIsWrite = aFileHandle->mMode == FileMode::Readwrite;

  StorageInfo* storageInfo;
  if (!mStorageInfos.Get(storageId, &storageInfo)) {
    nsAutoPtr<StorageInfo> newStorageInfo(new StorageInfo());

    mStorageInfos.Put(storageId, newStorageInfo);

    storageInfo = newStorageInfo.forget();
  }

  FileHandleQueue* existingFileHandleQueue =
    storageInfo->GetFileHandleQueue(aFileHandle);

  if (existingFileHandleQueue) {
    existingFileHandleQueue->Enqueue(aFileHelper);
    return NS_OK;
  }

  bool lockedForReading = storageInfo->IsFileLockedForReading(fileName);
  bool lockedForWriting = storageInfo->IsFileLockedForWriting(fileName);

  if (modeIsWrite) {
    if (!lockedForWriting) {
      storageInfo->LockFileForWriting(fileName);
    }
  }
  else {
    if (!lockedForReading) {
      storageInfo->LockFileForReading(fileName);
    }
  }

  if (lockedForWriting || (lockedForReading && modeIsWrite)) {
    storageInfo->CreateDelayedEnqueueInfo(aFileHandle, aFileHelper);
  }
  else {
    FileHandleQueue* fileHandleQueue =
      storageInfo->CreateFileHandleQueue(aFileHandle);

    if (aFileHelper) {
      // Enqueue() will queue the file helper if there's already something
      // running. That can't fail, so no need to eventually remove
      // storageInfo from the hash table.
      //
      // If the file helper is free to run then AsyncRun() is called on the
      // file helper. AsyncRun() is responsible for calling all necessary
      // callbacks when something fails. We're propagating the error here,
      // however there's no need to eventually remove storageInfo from
      // the hash table. Code behind AsyncRun() will take care of it. The last
      // item in the code path is NotifyFileHandleCompleted() which removes
      // storageInfo from the hash table if there are no file handles for
      // the file storage.
      nsresult rv = fileHandleQueue->Enqueue(aFileHelper);
      NS_ENSURE_SUCCESS(rv, rv);
    }
  }

  return NS_OK;
}