summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/lld/lib/Core/Resolver.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
commitb64793999546ed8adebaeebd9d8345d18db8927d (patch)
tree4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/lld/lib/Core/Resolver.cpp
parentAdd support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff)
downloadwireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz
wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/lld/lib/Core/Resolver.cpp')
-rw-r--r--gnu/llvm/tools/lld/lib/Core/Resolver.cpp505
1 files changed, 0 insertions, 505 deletions
diff --git a/gnu/llvm/tools/lld/lib/Core/Resolver.cpp b/gnu/llvm/tools/lld/lib/Core/Resolver.cpp
deleted file mode 100644
index 9c51c6cdb19..00000000000
--- a/gnu/llvm/tools/lld/lib/Core/Resolver.cpp
+++ /dev/null
@@ -1,505 +0,0 @@
-//===- Core/Resolver.cpp - Resolves Atom References -----------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Resolver.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/Core/SymbolTable.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <utility>
-#include <vector>
-
-namespace lld {
-
-llvm::Expected<bool> Resolver::handleFile(File &file) {
- if (auto ec = _ctx.handleLoadedFile(file))
- return std::move(ec);
- bool undefAdded = false;
- for (auto &atom : file.defined().owning_ptrs())
- doDefinedAtom(std::move(atom));
- for (auto &atom : file.undefined().owning_ptrs()) {
- if (doUndefinedAtom(std::move(atom)))
- undefAdded = true;
- }
- for (auto &atom : file.sharedLibrary().owning_ptrs())
- doSharedLibraryAtom(std::move(atom));
- for (auto &atom : file.absolute().owning_ptrs())
- doAbsoluteAtom(std::move(atom));
- return undefAdded;
-}
-
-llvm::Expected<bool> Resolver::forEachUndefines(File &file,
- UndefCallback callback) {
- size_t i = _undefineIndex[&file];
- bool undefAdded = false;
- do {
- for (; i < _undefines.size(); ++i) {
- StringRef undefName = _undefines[i];
- if (undefName.empty())
- continue;
- const Atom *atom = _symbolTable.findByName(undefName);
- if (!isa<UndefinedAtom>(atom) || _symbolTable.isCoalescedAway(atom)) {
- // The symbol was resolved by some other file. Cache the result.
- _undefines[i] = "";
- continue;
- }
- auto undefAddedOrError = callback(undefName);
- if (auto ec = undefAddedOrError.takeError())
- return std::move(ec);
- undefAdded |= undefAddedOrError.get();
- }
- } while (i < _undefines.size());
- _undefineIndex[&file] = i;
- return undefAdded;
-}
-
-llvm::Expected<bool> Resolver::handleArchiveFile(File &file) {
- ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&file);
- return forEachUndefines(file,
- [&](StringRef undefName) -> llvm::Expected<bool> {
- if (File *member = archiveFile->find(undefName)) {
- member->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- return handleFile(*member);
- }
- return false;
- });
-}
-
-llvm::Error Resolver::handleSharedLibrary(File &file) {
- // Add all the atoms from the shared library
- SharedLibraryFile *sharedLibrary = cast<SharedLibraryFile>(&file);
- auto undefAddedOrError = handleFile(*sharedLibrary);
- if (auto ec = undefAddedOrError.takeError())
- return ec;
- undefAddedOrError =
- forEachUndefines(file, [&](StringRef undefName) -> llvm::Expected<bool> {
- auto atom = sharedLibrary->exports(undefName);
- if (atom.get())
- doSharedLibraryAtom(std::move(atom));
- return false;
- });
-
- if (auto ec = undefAddedOrError.takeError())
- return ec;
- return llvm::Error::success();
-}
-
-bool Resolver::doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << " UndefinedAtom: "
- << llvm::format("0x%09lX", atom.get())
- << ", name=" << atom.get()->name() << "\n");
-
- // tell symbol table
- bool newUndefAdded = _symbolTable.add(*atom.get());
- if (newUndefAdded)
- _undefines.push_back(atom.get()->name());
-
- // add to list of known atoms
- _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-
- return newUndefAdded;
-}
-
-// Called on each atom when a file is added. Returns true if a given
-// atom is added to the symbol table.
-void Resolver::doDefinedAtom(OwningAtomPtr<DefinedAtom> atom) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << " DefinedAtom: "
- << llvm::format("0x%09lX", atom.get())
- << ", file=#"
- << atom.get()->file().ordinal()
- << ", atom=#"
- << atom.get()->ordinal()
- << ", name="
- << atom.get()->name()
- << ", type="
- << atom.get()->contentType()
- << "\n");
-
- // An atom that should never be dead-stripped is a dead-strip root.
- if (_ctx.deadStrip() &&
- atom.get()->deadStrip() == DefinedAtom::deadStripNever) {
- _deadStripRoots.insert(atom.get());
- }
-
- // add to list of known atoms
- _symbolTable.add(*atom.get());
- _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-}
-
-void Resolver::doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << " SharedLibraryAtom: "
- << llvm::format("0x%09lX", atom.get())
- << ", name="
- << atom.get()->name()
- << "\n");
-
- // tell symbol table
- _symbolTable.add(*atom.get());
-
- // add to list of known atoms
- _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-}
-
-void Resolver::doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << " AbsoluteAtom: "
- << llvm::format("0x%09lX", atom.get())
- << ", name="
- << atom.get()->name()
- << "\n");
-
- // tell symbol table
- if (atom.get()->scope() != Atom::scopeTranslationUnit)
- _symbolTable.add(*atom.get());
-
- // add to list of known atoms
- _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-}
-
-// Returns true if at least one of N previous files has created an
-// undefined symbol.
-bool Resolver::undefinesAdded(int begin, int end) {
- std::vector<std::unique_ptr<Node>> &inputs = _ctx.getNodes();
- for (int i = begin; i < end; ++i)
- if (FileNode *node = dyn_cast<FileNode>(inputs[i].get()))
- if (_newUndefinesAdded[node->getFile()])
- return true;
- return false;
-}
-
-File *Resolver::getFile(int &index) {
- std::vector<std::unique_ptr<Node>> &inputs = _ctx.getNodes();
- if ((size_t)index >= inputs.size())
- return nullptr;
- if (GroupEnd *group = dyn_cast<GroupEnd>(inputs[index].get())) {
- // We are at the end of the current group. If one or more new
- // undefined atom has been added in the last groupSize files, we
- // reiterate over the files.
- int size = group->getSize();
- if (undefinesAdded(index - size, index)) {
- index -= size;
- return getFile(index);
- }
- ++index;
- return getFile(index);
- }
- return cast<FileNode>(inputs[index++].get())->getFile();
-}
-
-// Keep adding atoms until _ctx.getNextFile() returns an error. This
-// function is where undefined atoms are resolved.
-bool Resolver::resolveUndefines() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Resolving undefines:\n");
- ScopedTask task(getDefaultDomain(), "resolveUndefines");
- int index = 0;
- std::set<File *> seen;
- for (;;) {
- bool undefAdded = false;
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "Loading file #" << index << "\n");
- File *file = getFile(index);
- if (!file)
- return true;
- if (std::error_code ec = file->parse()) {
- llvm::errs() << "Cannot open " + file->path()
- << ": " << ec.message() << "\n";
- return false;
- }
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "Loaded file: " << file->path() << "\n");
- switch (file->kind()) {
- case File::kindErrorObject:
- case File::kindNormalizedObject:
- case File::kindMachObject:
- case File::kindCEntryObject:
- case File::kindHeaderObject:
- case File::kindEntryObject:
- case File::kindUndefinedSymsObject:
- case File::kindStubHelperObject:
- case File::kindResolverMergedObject:
- case File::kindSectCreateObject: {
- // The same file may be visited more than once if the file is
- // in --start-group and --end-group. Only library files should
- // be processed more than once.
- if (seen.count(file))
- break;
- seen.insert(file);
- assert(!file->hasOrdinal());
- file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- auto undefAddedOrError = handleFile(*file);
- if (auto EC = undefAddedOrError.takeError()) {
- // FIXME: This should be passed to logAllUnhandledErrors but it needs
- // to be passed a Twine instead of a string.
- llvm::errs() << "Error in " + file->path() << ": ";
- logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
- return false;
- }
- undefAdded = undefAddedOrError.get();
- break;
- }
- case File::kindArchiveLibrary: {
- if (!file->hasOrdinal())
- file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- auto undefAddedOrError = handleArchiveFile(*file);
- if (auto EC = undefAddedOrError.takeError()) {
- // FIXME: This should be passed to logAllUnhandledErrors but it needs
- // to be passed a Twine instead of a string.
- llvm::errs() << "Error in " + file->path() << ": ";
- logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
- return false;
- }
- undefAdded = undefAddedOrError.get();
- break;
- }
- case File::kindSharedLibrary:
- if (!file->hasOrdinal())
- file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- if (auto EC = handleSharedLibrary(*file)) {
- // FIXME: This should be passed to logAllUnhandledErrors but it needs
- // to be passed a Twine instead of a string.
- llvm::errs() << "Error in " + file->path() << ": ";
- logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
- return false;
- }
- break;
- }
- _newUndefinesAdded[file] = undefAdded;
- }
-}
-
-// switch all references to undefined or coalesced away atoms
-// to the new defined atom
-void Resolver::updateReferences() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Updating references:\n");
- ScopedTask task(getDefaultDomain(), "updateReferences");
- for (const OwningAtomPtr<Atom> &atom : _atoms) {
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get())) {
- for (const Reference *ref : *defAtom) {
- // A reference of type kindAssociate should't be updated.
- // Instead, an atom having such reference will be removed
- // if the target atom is coalesced away, so that they will
- // go away as a group.
- if (ref->kindNamespace() == lld::Reference::KindNamespace::all &&
- ref->kindValue() == lld::Reference::kindAssociate) {
- if (_symbolTable.isCoalescedAway(atom.get()))
- _deadAtoms.insert(ref->target());
- continue;
- }
- const Atom *newTarget = _symbolTable.replacement(ref->target());
- const_cast<Reference *>(ref)->setTarget(newTarget);
- }
- }
- }
-}
-
-// For dead code stripping, recursively mark atoms "live"
-void Resolver::markLive(const Atom *atom) {
- // Mark the atom is live. If it's already marked live, then stop recursion.
- auto exists = _liveAtoms.insert(atom);
- if (!exists.second)
- return;
-
- // Mark all atoms it references as live
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
- for (const Reference *ref : *defAtom)
- markLive(ref->target());
- for (auto &p : llvm::make_range(_reverseRef.equal_range(defAtom))) {
- const Atom *target = p.second;
- markLive(target);
- }
- }
-}
-
-static bool isBackref(const Reference *ref) {
- if (ref->kindNamespace() != lld::Reference::KindNamespace::all)
- return false;
- return (ref->kindValue() == lld::Reference::kindLayoutAfter);
-}
-
-// remove all atoms not actually used
-void Resolver::deadStripOptimize() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Dead stripping unused atoms:\n");
- ScopedTask task(getDefaultDomain(), "deadStripOptimize");
- // only do this optimization with -dead_strip
- if (!_ctx.deadStrip())
- return;
-
- // Some type of references prevent referring atoms to be dead-striped.
- // Make a reverse map of such references before traversing the graph.
- // While traversing the list of atoms, mark AbsoluteAtoms as live
- // in order to avoid reclaim.
- for (const OwningAtomPtr<Atom> &atom : _atoms) {
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
- for (const Reference *ref : *defAtom)
- if (isBackref(ref))
- _reverseRef.insert(std::make_pair(ref->target(), atom.get()));
- if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom.get()))
- markLive(absAtom);
- }
-
- // By default, shared libraries are built with all globals as dead strip roots
- if (_ctx.globalsAreDeadStripRoots())
- for (const OwningAtomPtr<Atom> &atom : _atoms)
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
- if (defAtom->scope() == DefinedAtom::scopeGlobal)
- _deadStripRoots.insert(defAtom);
-
- // Or, use list of names that are dead strip roots.
- for (const StringRef &name : _ctx.deadStripRoots()) {
- const Atom *symAtom = _symbolTable.findByName(name);
- assert(symAtom);
- _deadStripRoots.insert(symAtom);
- }
-
- // mark all roots as live, and recursively all atoms they reference
- for (const Atom *dsrAtom : _deadStripRoots)
- markLive(dsrAtom);
-
- // now remove all non-live atoms from _atoms
- _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
- [&](OwningAtomPtr<Atom> &a) {
- return _liveAtoms.count(a.get()) == 0;
- }),
- _atoms.end());
-}
-
-// error out if some undefines remain
-bool Resolver::checkUndefines() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Checking for undefines:\n");
-
- // build vector of remaining undefined symbols
- std::vector<const UndefinedAtom *> undefinedAtoms = _symbolTable.undefines();
- if (_ctx.deadStrip()) {
- // When dead code stripping, we don't care if dead atoms are undefined.
- undefinedAtoms.erase(
- std::remove_if(undefinedAtoms.begin(), undefinedAtoms.end(),
- [&](const Atom *a) { return _liveAtoms.count(a) == 0; }),
- undefinedAtoms.end());
- }
-
- if (undefinedAtoms.empty())
- return false;
-
- // Warn about unresolved symbols.
- bool foundUndefines = false;
- for (const UndefinedAtom *undef : undefinedAtoms) {
- // Skip over a weak symbol.
- if (undef->canBeNull() != UndefinedAtom::canBeNullNever)
- continue;
-
- // If this is a library and undefined symbols are allowed on the
- // target platform, skip over it.
- if (isa<SharedLibraryFile>(undef->file()) && _ctx.allowShlibUndefines())
- continue;
-
- // If the undefine is coalesced away, skip over it.
- if (_symbolTable.isCoalescedAway(undef))
- continue;
-
- // Seems like this symbol is undefined. Warn that.
- foundUndefines = true;
- if (_ctx.printRemainingUndefines()) {
- llvm::errs() << "Undefined symbol: " << undef->file().path()
- << ": " << _ctx.demangle(undef->name())
- << "\n";
- }
- }
- if (!foundUndefines)
- return false;
- if (_ctx.printRemainingUndefines())
- llvm::errs() << "symbol(s) not found\n";
- return true;
-}
-
-// remove from _atoms all coaleseced away atoms
-void Resolver::removeCoalescedAwayAtoms() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Removing coalesced away atoms:\n");
- ScopedTask task(getDefaultDomain(), "removeCoalescedAwayAtoms");
- _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
- [&](OwningAtomPtr<Atom> &a) {
- return _symbolTable.isCoalescedAway(a.get()) ||
- _deadAtoms.count(a.get());
- }),
- _atoms.end());
-}
-
-bool Resolver::resolve() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Resolving atom references:\n");
- if (!resolveUndefines())
- return false;
- updateReferences();
- deadStripOptimize();
- if (checkUndefines()) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Found undefines... ");
- if (!_ctx.allowRemainingUndefines()) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "which we don't allow\n");
- return false;
- }
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "which we are ok with\n");
- }
- removeCoalescedAwayAtoms();
- _result->addAtoms(_atoms);
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "******** Finished resolver\n");
- return true;
-}
-
-void Resolver::MergedFile::addAtoms(
- llvm::MutableArrayRef<OwningAtomPtr<Atom>> all) {
- ScopedTask task(getDefaultDomain(), "addAtoms");
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
-
- for (OwningAtomPtr<Atom> &atom : all) {
-#ifndef NDEBUG
- if (auto *definedAtom = dyn_cast<DefinedAtom>(atom.get())) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << llvm::format(" 0x%09lX", definedAtom)
- << ", file=#"
- << definedAtom->file().ordinal()
- << ", atom=#"
- << definedAtom->ordinal()
- << ", name="
- << definedAtom->name()
- << ", type="
- << definedAtom->contentType()
- << "\n");
- } else {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << llvm::format(" 0x%09lX", atom.get())
- << ", name="
- << atom.get()->name()
- << "\n");
- }
-#endif
- addAtom(*atom.release());
- }
-}
-
-} // namespace lld