mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 01:58:44 +08:00
Revert "Use owning pointers instead of raw pointers for Atom's to fix leaks."
This reverts commit r264022. This breaks the Window's bots which don't like that i'm calling ~Atom when the this pointer is a sublcass of Atom. Reverting for now until I try find a better fix. I tried using std::unique_ptr with a custom deleter as a quick fix, but it didn't work well in the YAML parser. llvm-svn: 264023
This commit is contained in:
@@ -16,9 +16,6 @@ namespace lld {
|
||||
|
||||
class File;
|
||||
|
||||
template<typename T>
|
||||
class OwningAtomPtr;
|
||||
|
||||
///
|
||||
/// The linker has a Graph Theory model of linking. An object file is seen
|
||||
/// as a set of Atoms with References to other Atoms. Each Atom is a node
|
||||
@@ -27,7 +24,6 @@ class OwningAtomPtr;
|
||||
/// undefined symbol (extern declaration).
|
||||
///
|
||||
class Atom {
|
||||
template<typename T> friend class OwningAtomPtr;
|
||||
public:
|
||||
/// Whether this atom is defined or a proxy for an undefined symbol
|
||||
enum Definition {
|
||||
@@ -75,49 +71,6 @@ private:
|
||||
Definition _definition;
|
||||
};
|
||||
|
||||
/// Class which owns an atom pointer and runs the atom destructor when the
|
||||
/// owning pointer goes out of scope.
|
||||
template<typename T>
|
||||
class OwningAtomPtr {
|
||||
private:
|
||||
OwningAtomPtr(const OwningAtomPtr &) = delete;
|
||||
void operator=(const OwningAtomPtr&) = delete;
|
||||
public:
|
||||
OwningAtomPtr() : atom(nullptr) { }
|
||||
OwningAtomPtr(T *atom) : atom(atom) { }
|
||||
|
||||
~OwningAtomPtr() {
|
||||
if (atom)
|
||||
atom->~Atom();
|
||||
}
|
||||
|
||||
OwningAtomPtr(OwningAtomPtr &&ptr) : atom(ptr.atom) {
|
||||
ptr.atom = nullptr;
|
||||
}
|
||||
|
||||
void operator=(OwningAtomPtr&& ptr) {
|
||||
atom = ptr.atom;
|
||||
ptr.atom = nullptr;
|
||||
}
|
||||
|
||||
T *const &get() const {
|
||||
return atom;
|
||||
}
|
||||
|
||||
T *&get() {
|
||||
return atom;
|
||||
}
|
||||
|
||||
T *release() {
|
||||
auto *v = atom;
|
||||
atom = nullptr;
|
||||
return v;
|
||||
}
|
||||
|
||||
private:
|
||||
T *atom;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
#endif // LLD_CORE_ATOM_H
|
||||
|
||||
@@ -363,8 +363,6 @@ protected:
|
||||
// constructor.
|
||||
DefinedAtom() : Atom(definitionRegular) { }
|
||||
|
||||
~DefinedAtom() override = default;
|
||||
|
||||
/// \brief Returns a pointer to the Reference object that the abstract
|
||||
/// iterator "points" to.
|
||||
virtual const Reference *derefIterator(const void *iter) const = 0;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "lld/Core/SharedLibraryAtom.h"
|
||||
#include "lld/Core/UndefinedAtom.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <functional>
|
||||
@@ -40,10 +39,6 @@ class LinkingContext;
|
||||
/// The Atom objects in a File are owned by the File object. The Atom objects
|
||||
/// are destroyed when the File object is destroyed.
|
||||
class File {
|
||||
protected:
|
||||
/// The type of atom mutable container.
|
||||
template <typename T> using AtomVector = std::vector<OwningAtomPtr<T>>;
|
||||
|
||||
public:
|
||||
virtual ~File();
|
||||
|
||||
@@ -109,67 +104,18 @@ public:
|
||||
return _allocator;
|
||||
}
|
||||
|
||||
/// The range type for the atoms.
|
||||
/// The type of atom mutable container.
|
||||
template <typename T> using AtomVector = std::vector<const T *>;
|
||||
|
||||
/// The range type for the atoms. It's backed by a std::vector, but hides
|
||||
/// its member functions so that you can only call begin or end.
|
||||
template <typename T> class AtomRange {
|
||||
public:
|
||||
AtomRange(AtomVector<T> &v) : _v(v) {}
|
||||
AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
|
||||
|
||||
typedef std::pointer_to_unary_function<const OwningAtomPtr<T>&,
|
||||
const T*> ConstDerefFn;
|
||||
|
||||
typedef std::pointer_to_unary_function<OwningAtomPtr<T>&, T*> DerefFn;
|
||||
|
||||
typedef llvm::mapped_iterator<typename AtomVector<T>::const_iterator,
|
||||
ConstDerefFn> ConstItTy;
|
||||
typedef llvm::mapped_iterator<typename AtomVector<T>::iterator,
|
||||
DerefFn> ItTy;
|
||||
|
||||
static const T* DerefConst(const OwningAtomPtr<T> &p) {
|
||||
return p.get();
|
||||
}
|
||||
|
||||
static T* Deref(OwningAtomPtr<T> &p) {
|
||||
return p.get();
|
||||
}
|
||||
|
||||
ConstItTy begin() const {
|
||||
return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
|
||||
}
|
||||
ConstItTy end() const {
|
||||
return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
|
||||
}
|
||||
|
||||
ItTy begin() {
|
||||
return ItTy(_v.begin(), DerefFn(Deref));
|
||||
}
|
||||
ItTy end() {
|
||||
return ItTy(_v.end(), DerefFn(Deref));
|
||||
}
|
||||
|
||||
llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() {
|
||||
return llvm::make_range(_v.begin(), _v.end());
|
||||
}
|
||||
|
||||
llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
|
||||
return llvm::make_range(_v.begin(), _v.end());
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return _v.empty();
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return _v.size();
|
||||
}
|
||||
|
||||
const OwningAtomPtr<T> &operator[](size_t idx) const {
|
||||
return _v[idx];
|
||||
}
|
||||
|
||||
OwningAtomPtr<T> &operator[](size_t idx) {
|
||||
return _v[idx];
|
||||
}
|
||||
AtomRange(AtomVector<T> v) : _v(v) {}
|
||||
typename AtomVector<T>::const_iterator begin() const { return _v.begin(); }
|
||||
typename AtomVector<T>::const_iterator end() const { return _v.end(); }
|
||||
typename AtomVector<T>::iterator begin() { return _v.begin(); }
|
||||
typename AtomVector<T>::iterator end() { return _v.end(); }
|
||||
|
||||
private:
|
||||
AtomVector<T> &_v;
|
||||
@@ -177,25 +123,19 @@ public:
|
||||
|
||||
/// \brief Must be implemented to return the AtomVector object for
|
||||
/// all DefinedAtoms in this File.
|
||||
virtual const AtomRange<DefinedAtom> defined() const = 0;
|
||||
virtual const AtomVector<DefinedAtom> &defined() const = 0;
|
||||
|
||||
/// \brief Must be implemented to return the AtomVector object for
|
||||
/// all UndefinedAtomw in this File.
|
||||
virtual const AtomRange<UndefinedAtom> undefined() const = 0;
|
||||
virtual const AtomVector<UndefinedAtom> &undefined() const = 0;
|
||||
|
||||
/// \brief Must be implemented to return the AtomVector object for
|
||||
/// all SharedLibraryAtoms in this File.
|
||||
virtual const AtomRange<SharedLibraryAtom> sharedLibrary() const = 0;
|
||||
virtual const AtomVector<SharedLibraryAtom> &sharedLibrary() const = 0;
|
||||
|
||||
/// \brief Must be implemented to return the AtomVector object for
|
||||
/// all AbsoluteAtoms in this File.
|
||||
virtual const AtomRange<AbsoluteAtom> absolute() const = 0;
|
||||
|
||||
/// Drop all of the atoms owned by this file. This will result in all of
|
||||
/// the atoms running their destructors.
|
||||
/// This is required because atoms may be allocated on a BumpPtrAllocator
|
||||
/// of a different file. We need to destruct all atoms before any files.
|
||||
virtual void clearAtoms() = 0;
|
||||
virtual const AtomVector<AbsoluteAtom> &absolute() const = 0;
|
||||
|
||||
/// \brief If a file is parsed using a different method than doParse(),
|
||||
/// one must use this method to set the last error status, so that
|
||||
@@ -254,22 +194,19 @@ public:
|
||||
|
||||
std::error_code doParse() override { return _ec; }
|
||||
|
||||
const AtomRange<DefinedAtom> defined() const override {
|
||||
const AtomVector<DefinedAtom> &defined() const override {
|
||||
llvm_unreachable("internal error");
|
||||
}
|
||||
const AtomRange<UndefinedAtom> undefined() const override {
|
||||
const AtomVector<UndefinedAtom> &undefined() const override {
|
||||
llvm_unreachable("internal error");
|
||||
}
|
||||
const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
|
||||
const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
|
||||
llvm_unreachable("internal error");
|
||||
}
|
||||
const AtomRange<AbsoluteAtom> absolute() const override {
|
||||
const AtomVector<AbsoluteAtom> &absolute() const override {
|
||||
llvm_unreachable("internal error");
|
||||
}
|
||||
|
||||
void clearAtoms() override {
|
||||
}
|
||||
|
||||
private:
|
||||
std::error_code _ec;
|
||||
};
|
||||
|
||||
@@ -35,10 +35,10 @@ public:
|
||||
Resolver(LinkingContext &ctx) : _ctx(ctx), _result(new MergedFile()) {}
|
||||
|
||||
// InputFiles::Handler methods
|
||||
void doDefinedAtom(OwningAtomPtr<DefinedAtom> atom);
|
||||
bool doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom);
|
||||
void doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom);
|
||||
void doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom);
|
||||
void doDefinedAtom(const DefinedAtom&);
|
||||
bool doUndefinedAtom(const UndefinedAtom &);
|
||||
void doSharedLibraryAtom(const SharedLibraryAtom &);
|
||||
void doAbsoluteAtom(const AbsoluteAtom &);
|
||||
|
||||
// Handle files, this adds atoms from the current file thats
|
||||
// being processed by the resolver
|
||||
@@ -71,16 +71,17 @@ private:
|
||||
UndefCallback callback);
|
||||
|
||||
void markLive(const Atom *atom);
|
||||
void addAtoms(const std::vector<const DefinedAtom *>&);
|
||||
|
||||
class MergedFile : public SimpleFile {
|
||||
public:
|
||||
MergedFile() : SimpleFile("<linker-internal>", kindResolverMergedObject) {}
|
||||
void addAtoms(llvm::MutableArrayRef<OwningAtomPtr<Atom>> atoms);
|
||||
void addAtoms(std::vector<const Atom*>& atoms);
|
||||
};
|
||||
|
||||
LinkingContext &_ctx;
|
||||
SymbolTable _symbolTable;
|
||||
std::vector<OwningAtomPtr<Atom>> _atoms;
|
||||
std::vector<const Atom *> _atoms;
|
||||
std::set<const Atom *> _deadStripRoots;
|
||||
llvm::DenseSet<const Atom *> _liveAtoms;
|
||||
llvm::DenseSet<const Atom *> _deadAtoms;
|
||||
|
||||
@@ -44,8 +44,6 @@ public:
|
||||
|
||||
protected:
|
||||
SharedLibraryAtom() : Atom(definitionSharedLibrary) {}
|
||||
|
||||
~SharedLibraryAtom() override = default;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
@@ -27,35 +27,28 @@ public:
|
||||
/// Check if the shared library exports a symbol with the specified name.
|
||||
/// If so, return a SharedLibraryAtom which represents that exported
|
||||
/// symbol. Otherwise return nullptr.
|
||||
virtual OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
|
||||
virtual const SharedLibraryAtom *exports(StringRef name,
|
||||
bool dataSymbolOnly) const = 0;
|
||||
|
||||
// Returns the install name.
|
||||
virtual StringRef getDSOName() const = 0;
|
||||
|
||||
const AtomRange<DefinedAtom> defined() const override {
|
||||
const AtomVector<DefinedAtom> &defined() const override {
|
||||
return _definedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<UndefinedAtom> undefined() const override {
|
||||
const AtomVector<UndefinedAtom> &undefined() const override {
|
||||
return _undefinedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
|
||||
const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
|
||||
return _sharedLibraryAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<AbsoluteAtom> absolute() const override {
|
||||
const AtomVector<AbsoluteAtom> &absolute() const override {
|
||||
return _absoluteAtoms;
|
||||
}
|
||||
|
||||
void clearAtoms() override {
|
||||
_definedAtoms.clear();
|
||||
_undefinedAtoms.clear();
|
||||
_sharedLibraryAtoms.clear();
|
||||
_absoluteAtoms.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// only subclasses of SharedLibraryFile can be instantiated
|
||||
explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {}
|
||||
|
||||
@@ -31,35 +31,20 @@ public:
|
||||
SimpleFile(StringRef path, File::Kind kind)
|
||||
: File(path, kind) {}
|
||||
|
||||
~SimpleFile() override {
|
||||
_defined.clear();
|
||||
_undefined.clear();
|
||||
_shared.clear();
|
||||
_absolute.clear();
|
||||
}
|
||||
|
||||
void addAtom(DefinedAtom &a) {
|
||||
_defined.push_back(OwningAtomPtr<DefinedAtom>(&a));
|
||||
}
|
||||
void addAtom(UndefinedAtom &a) {
|
||||
_undefined.push_back(OwningAtomPtr<UndefinedAtom>(&a));
|
||||
}
|
||||
void addAtom(SharedLibraryAtom &a) {
|
||||
_shared.push_back(OwningAtomPtr<SharedLibraryAtom>(&a));
|
||||
}
|
||||
void addAtom(AbsoluteAtom &a) {
|
||||
_absolute.push_back(OwningAtomPtr<AbsoluteAtom>(&a));
|
||||
}
|
||||
void addAtom(const DefinedAtom &a) { _defined.push_back(&a); }
|
||||
void addAtom(const UndefinedAtom &a) { _undefined.push_back(&a); }
|
||||
void addAtom(const SharedLibraryAtom &a) { _shared.push_back(&a); }
|
||||
void addAtom(const AbsoluteAtom &a) { _absolute.push_back(&a); }
|
||||
|
||||
void addAtom(const Atom &atom) {
|
||||
if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
|
||||
addAtom(const_cast<DefinedAtom &>(*p));
|
||||
_defined.push_back(p);
|
||||
} else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
|
||||
addAtom(const_cast<UndefinedAtom &>(*p));
|
||||
_undefined.push_back(p);
|
||||
} else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
|
||||
addAtom(const_cast<SharedLibraryAtom &>(*p));
|
||||
_shared.push_back(p);
|
||||
} else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
|
||||
addAtom(const_cast<AbsoluteAtom &>(*p));
|
||||
_absolute.push_back(p);
|
||||
} else {
|
||||
llvm_unreachable("atom has unknown definition kind");
|
||||
}
|
||||
@@ -67,35 +52,25 @@ public:
|
||||
|
||||
void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
|
||||
auto &atoms = _defined;
|
||||
auto newEnd = std::remove_if(atoms.begin(), atoms.end(),
|
||||
[&pred](OwningAtomPtr<DefinedAtom> &p) {
|
||||
return pred(p.get());
|
||||
});
|
||||
auto newEnd = std::remove_if(atoms.begin(), atoms.end(), pred);
|
||||
atoms.erase(newEnd, atoms.end());
|
||||
}
|
||||
|
||||
const AtomRange<DefinedAtom> defined() const override { return _defined; }
|
||||
const AtomVector<DefinedAtom> &defined() const override { return _defined; }
|
||||
|
||||
const AtomRange<UndefinedAtom> undefined() const override {
|
||||
const AtomVector<UndefinedAtom> &undefined() const override {
|
||||
return _undefined;
|
||||
}
|
||||
|
||||
const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
|
||||
const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
|
||||
return _shared;
|
||||
}
|
||||
|
||||
const AtomRange<AbsoluteAtom> absolute() const override {
|
||||
const AtomVector<AbsoluteAtom> &absolute() const override {
|
||||
return _absolute;
|
||||
}
|
||||
|
||||
void clearAtoms() override {
|
||||
_defined.clear();
|
||||
_undefined.clear();
|
||||
_shared.clear();
|
||||
_absolute.clear();
|
||||
}
|
||||
|
||||
typedef AtomRange<DefinedAtom> DefinedAtomRange;
|
||||
typedef llvm::MutableArrayRef<const DefinedAtom *> DefinedAtomRange;
|
||||
DefinedAtomRange definedAtoms() { return _defined; }
|
||||
|
||||
private:
|
||||
@@ -194,10 +169,6 @@ public:
|
||||
_references.setAllocator(&f.allocator());
|
||||
}
|
||||
|
||||
~SimpleDefinedAtom() {
|
||||
_references.clearAndLeakNodesUnsafely();
|
||||
}
|
||||
|
||||
const File &file() const override { return _file; }
|
||||
|
||||
StringRef name() const override { return StringRef(); }
|
||||
@@ -294,8 +265,6 @@ public:
|
||||
assert(!name.empty() && "UndefinedAtoms must have a name");
|
||||
}
|
||||
|
||||
~SimpleUndefinedAtom() override = default;
|
||||
|
||||
/// file - returns the File that produced/owns this Atom
|
||||
const File &file() const override { return _file; }
|
||||
|
||||
|
||||
@@ -59,8 +59,6 @@ public:
|
||||
|
||||
protected:
|
||||
UndefinedAtom() : Atom(definitionUndefined) {}
|
||||
|
||||
~UndefinedAtom() override = default;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
namespace lld {
|
||||
|
||||
File::~File() { }
|
||||
File::~File() {}
|
||||
|
||||
File::AtomVector<DefinedAtom> File::_noDefinedAtoms;
|
||||
File::AtomVector<UndefinedAtom> File::_noUndefinedAtoms;
|
||||
|
||||
@@ -33,16 +33,16 @@ ErrorOr<bool> Resolver::handleFile(File &file) {
|
||||
if (auto ec = _ctx.handleLoadedFile(file))
|
||||
return 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)))
|
||||
for (const DefinedAtom *atom : file.defined())
|
||||
doDefinedAtom(*atom);
|
||||
for (const UndefinedAtom *atom : file.undefined()) {
|
||||
if (doUndefinedAtom(*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));
|
||||
for (const SharedLibraryAtom *atom : file.sharedLibrary())
|
||||
doSharedLibraryAtom(*atom);
|
||||
for (const AbsoluteAtom *atom : file.absolute())
|
||||
doAbsoluteAtom(*atom);
|
||||
return undefAdded;
|
||||
}
|
||||
|
||||
@@ -113,9 +113,9 @@ std::error_code Resolver::handleSharedLibrary(File &file) {
|
||||
undefAddedOrError = forEachUndefines(file, searchForOverrides,
|
||||
[&](StringRef undefName,
|
||||
bool dataSymbolOnly)->ErrorOr<bool> {
|
||||
auto atom = sharedLibrary->exports(undefName, dataSymbolOnly);
|
||||
if (atom.get())
|
||||
doSharedLibraryAtom(std::move(atom));
|
||||
if (const SharedLibraryAtom *atom =
|
||||
sharedLibrary->exports(undefName, dataSymbolOnly))
|
||||
doSharedLibraryAtom(*atom);
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -124,79 +124,84 @@ std::error_code Resolver::handleSharedLibrary(File &file) {
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
bool Resolver::doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom) {
|
||||
bool Resolver::doUndefinedAtom(const 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());
|
||||
<< llvm::format("0x%09lX", &atom)
|
||||
<< ", name=" << atom.name() << "\n");
|
||||
|
||||
// add to list of known atoms
|
||||
_atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
|
||||
_atoms.push_back(&atom);
|
||||
|
||||
// tell symbol table
|
||||
bool newUndefAdded = _symbolTable.add(atom);
|
||||
if (newUndefAdded)
|
||||
_undefines.push_back(atom.name());
|
||||
|
||||
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) {
|
||||
void Resolver::doDefinedAtom(const DefinedAtom &atom) {
|
||||
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
|
||||
<< " DefinedAtom: "
|
||||
<< llvm::format("0x%09lX", atom.get())
|
||||
<< llvm::format("0x%09lX", &atom)
|
||||
<< ", file=#"
|
||||
<< atom.get()->file().ordinal()
|
||||
<< atom.file().ordinal()
|
||||
<< ", atom=#"
|
||||
<< atom.get()->ordinal()
|
||||
<< atom.ordinal()
|
||||
<< ", name="
|
||||
<< atom.get()->name()
|
||||
<< atom.name()
|
||||
<< ", type="
|
||||
<< atom.get()->contentType()
|
||||
<< atom.contentType()
|
||||
<< "\n");
|
||||
|
||||
// add to list of known atoms
|
||||
_atoms.push_back(&atom);
|
||||
_symbolTable.add(atom);
|
||||
|
||||
// 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());
|
||||
if (_ctx.deadStrip() && atom.deadStrip() == DefinedAtom::deadStripNever) {
|
||||
_deadStripRoots.insert(&atom);
|
||||
}
|
||||
|
||||
// add to list of known atoms
|
||||
_symbolTable.add(*atom.get());
|
||||
_atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
|
||||
}
|
||||
|
||||
void Resolver::doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom) {
|
||||
void Resolver::doSharedLibraryAtom(const SharedLibraryAtom &atom) {
|
||||
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
|
||||
<< " SharedLibraryAtom: "
|
||||
<< llvm::format("0x%09lX", atom.get())
|
||||
<< llvm::format("0x%09lX", &atom)
|
||||
<< ", name="
|
||||
<< atom.get()->name()
|
||||
<< atom.name()
|
||||
<< "\n");
|
||||
|
||||
// tell symbol table
|
||||
_symbolTable.add(*atom.get());
|
||||
|
||||
// add to list of known atoms
|
||||
_atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
|
||||
_atoms.push_back(&atom);
|
||||
|
||||
// tell symbol table
|
||||
_symbolTable.add(atom);
|
||||
}
|
||||
|
||||
void Resolver::doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom) {
|
||||
void Resolver::doAbsoluteAtom(const AbsoluteAtom &atom) {
|
||||
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
|
||||
<< " AbsoluteAtom: "
|
||||
<< llvm::format("0x%09lX", atom.get())
|
||||
<< llvm::format("0x%09lX", &atom)
|
||||
<< ", name="
|
||||
<< atom.get()->name()
|
||||
<< atom.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()));
|
||||
_atoms.push_back(&atom);
|
||||
|
||||
// tell symbol table
|
||||
if (atom.scope() != Atom::scopeTranslationUnit)
|
||||
_symbolTable.add(atom);
|
||||
}
|
||||
|
||||
// utility to add a vector of atoms
|
||||
void Resolver::addAtoms(const std::vector<const DefinedAtom *> &newAtoms) {
|
||||
for (const DefinedAtom *newAtom : newAtoms)
|
||||
doDefinedAtom(*newAtom);
|
||||
}
|
||||
|
||||
// Returns true if at least one of N previous files has created an
|
||||
@@ -311,8 +316,8 @@ 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 Atom *atom : _atoms) {
|
||||
if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
|
||||
for (const Reference *ref : *defAtom) {
|
||||
// A reference of type kindAssociate should't be updated.
|
||||
// Instead, an atom having such reference will be removed
|
||||
@@ -320,7 +325,7 @@ void Resolver::updateReferences() {
|
||||
// go away as a group.
|
||||
if (ref->kindNamespace() == lld::Reference::KindNamespace::all &&
|
||||
ref->kindValue() == lld::Reference::kindAssociate) {
|
||||
if (_symbolTable.isCoalescedAway(atom.get()))
|
||||
if (_symbolTable.isCoalescedAway(atom))
|
||||
_deadAtoms.insert(ref->target());
|
||||
continue;
|
||||
}
|
||||
@@ -368,19 +373,19 @@ void Resolver::deadStripOptimize() {
|
||||
// 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 Atom *atom : _atoms) {
|
||||
if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
|
||||
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()))
|
||||
_reverseRef.insert(std::make_pair(ref->target(), atom));
|
||||
if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom))
|
||||
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()))
|
||||
for (const Atom *atom : _atoms)
|
||||
if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
|
||||
if (defAtom->scope() == DefinedAtom::scopeGlobal)
|
||||
_deadStripRoots.insert(defAtom);
|
||||
|
||||
@@ -396,9 +401,8 @@ void Resolver::deadStripOptimize() {
|
||||
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.erase(std::remove_if(_atoms.begin(), _atoms.end(), [&](const Atom *a) {
|
||||
return _liveAtoms.count(a) == 0;
|
||||
}),
|
||||
_atoms.end());
|
||||
}
|
||||
@@ -457,10 +461,8 @@ 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.erase(std::remove_if(_atoms.begin(), _atoms.end(), [&](const Atom *a) {
|
||||
return _symbolTable.isCoalescedAway(a) || _deadAtoms.count(a);
|
||||
}),
|
||||
_atoms.end());
|
||||
}
|
||||
@@ -486,16 +488,15 @@ bool Resolver::resolve() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Resolver::MergedFile::addAtoms(
|
||||
llvm::MutableArrayRef<OwningAtomPtr<Atom>> all) {
|
||||
void Resolver::MergedFile::addAtoms(std::vector<const Atom *> &all) {
|
||||
ScopedTask task(getDefaultDomain(), "addAtoms");
|
||||
DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
|
||||
|
||||
for (OwningAtomPtr<Atom> &atom : all) {
|
||||
for (const Atom *atom : all) {
|
||||
#ifndef NDEBUG
|
||||
if (auto *definedAtom = dyn_cast<DefinedAtom>(atom.get())) {
|
||||
if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) {
|
||||
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
|
||||
<< llvm::format(" 0x%09lX", definedAtom)
|
||||
<< llvm::format(" 0x%09lX", atom)
|
||||
<< ", file=#"
|
||||
<< definedAtom->file().ordinal()
|
||||
<< ", atom=#"
|
||||
@@ -507,13 +508,13 @@ void Resolver::MergedFile::addAtoms(
|
||||
<< "\n");
|
||||
} else {
|
||||
DEBUG_WITH_TYPE("resolver", llvm::dbgs()
|
||||
<< llvm::format(" 0x%09lX", atom.get())
|
||||
<< llvm::format(" 0x%09lX", atom)
|
||||
<< ", name="
|
||||
<< atom.get()->name()
|
||||
<< atom->name()
|
||||
<< "\n");
|
||||
}
|
||||
#endif
|
||||
addAtom(*atom.release());
|
||||
addAtom(*atom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1169,14 +1169,7 @@ bool link(llvm::ArrayRef<const char *> args, raw_ostream &diagnostics) {
|
||||
Resolver resolver(ctx);
|
||||
if (!resolver.resolve())
|
||||
return false;
|
||||
SimpleFile *merged = nullptr;
|
||||
{
|
||||
std::unique_ptr<SimpleFile> mergedFile = resolver.resultFile();
|
||||
merged = mergedFile.get();
|
||||
auto &members = ctx.getNodes();
|
||||
members.insert(members.begin(),
|
||||
llvm::make_unique<FileNode>(std::move(mergedFile)));
|
||||
}
|
||||
std::unique_ptr<SimpleFile> merged = resolver.resultFile();
|
||||
resolveTask.end();
|
||||
|
||||
// Run passes on linked atoms.
|
||||
|
||||
@@ -88,29 +88,22 @@ public:
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
const AtomRange<DefinedAtom> defined() const override {
|
||||
const AtomVector<DefinedAtom> &defined() const override {
|
||||
return _noDefinedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<UndefinedAtom> undefined() const override {
|
||||
const AtomVector<UndefinedAtom> &undefined() const override {
|
||||
return _noUndefinedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
|
||||
const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
|
||||
return _noSharedLibraryAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<AbsoluteAtom> absolute() const override {
|
||||
const AtomVector<AbsoluteAtom> &absolute() const override {
|
||||
return _noAbsoluteAtoms;
|
||||
}
|
||||
|
||||
void clearAtoms() override {
|
||||
_noDefinedAtoms.clear();
|
||||
_noUndefinedAtoms.clear();
|
||||
_noSharedLibraryAtoms.clear();
|
||||
_noAbsoluteAtoms.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::error_code doParse() override {
|
||||
// Make Archive object which will be owned by FileArchive object.
|
||||
|
||||
@@ -1429,8 +1429,6 @@ public:
|
||||
_name = tmp.copy(file.allocator());
|
||||
}
|
||||
|
||||
~Thumb2ToArmShimAtom() override = default;
|
||||
|
||||
StringRef name() const override {
|
||||
return _name;
|
||||
}
|
||||
@@ -1474,8 +1472,6 @@ public:
|
||||
_name = tmp.copy(file.allocator());
|
||||
}
|
||||
|
||||
~ArmToThumbShimAtom() override = default;
|
||||
|
||||
StringRef name() const override {
|
||||
return _name;
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@ public:
|
||||
_contentType(type), _scope(scope), _merge(mergeNo), _thumb(false),
|
||||
_noDeadStrip(noDeadStrip) {}
|
||||
|
||||
~MachODefinedAtom() override = default;
|
||||
|
||||
uint64_t size() const override { return _content.size(); }
|
||||
|
||||
ContentType contentType() const override { return _contentType; }
|
||||
@@ -85,8 +83,6 @@ public:
|
||||
content, align),
|
||||
_sectionName(sectionName) {}
|
||||
|
||||
~MachODefinedCustomSectionAtom() override = default;
|
||||
|
||||
SectionChoice sectionChoice() const override {
|
||||
return DefinedAtom::sectionCustomRequired;
|
||||
}
|
||||
@@ -105,8 +101,6 @@ public:
|
||||
: SimpleDefinedAtom(f), _name(name), _scope(scope), _size(size),
|
||||
_align(align) {}
|
||||
|
||||
~MachOTentativeDefAtom() override = default;
|
||||
|
||||
uint64_t size() const override { return _size; }
|
||||
|
||||
Merge merge() const override { return DefinedAtom::mergeAsTentative; }
|
||||
|
||||
@@ -88,8 +88,6 @@ public:
|
||||
addSecondLevelPages(pages);
|
||||
}
|
||||
|
||||
~UnwindInfoAtom() override = default;
|
||||
|
||||
ContentType contentType() const override {
|
||||
return DefinedAtom::typeProcessedUnwindInfo;
|
||||
}
|
||||
|
||||
@@ -122,28 +122,21 @@ public:
|
||||
ArrayRef<uint8_t>(), DefinedAtom::Alignment(1)));
|
||||
}
|
||||
|
||||
const AtomRange<DefinedAtom> defined() const override {
|
||||
const AtomVector<DefinedAtom> &defined() const override {
|
||||
return _definedAtoms;
|
||||
}
|
||||
const AtomRange<UndefinedAtom> undefined() const override {
|
||||
const AtomVector<UndefinedAtom> &undefined() const override {
|
||||
return _noUndefinedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
|
||||
const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
|
||||
return _noSharedLibraryAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<AbsoluteAtom> absolute() const override {
|
||||
const AtomVector<AbsoluteAtom> &absolute() const override {
|
||||
return _noAbsoluteAtoms;
|
||||
}
|
||||
|
||||
void clearAtoms() override {
|
||||
_definedAtoms.clear();
|
||||
_noUndefinedAtoms.clear();
|
||||
_noSharedLibraryAtoms.clear();
|
||||
_noAbsoluteAtoms.clear();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
mutable AtomVector<DefinedAtom> _definedAtoms;
|
||||
|
||||
@@ -275,8 +275,7 @@ public:
|
||||
|
||||
MachODylibFile(StringRef path) : SharedLibraryFile(path) {}
|
||||
|
||||
OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
|
||||
bool isData) const override {
|
||||
const SharedLibraryAtom *exports(StringRef name, bool isData) const override {
|
||||
// Pass down _installName so that if this requested symbol
|
||||
// is re-exported through this dylib, the SharedLibraryAtom's loadName()
|
||||
// is this dylib installName and not the implementation dylib's.
|
||||
@@ -329,30 +328,25 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
|
||||
const SharedLibraryAtom *exports(StringRef name,
|
||||
StringRef installName) const {
|
||||
// First, check if requested symbol is directly implemented by this dylib.
|
||||
auto entry = _nameToAtom.find(name);
|
||||
if (entry != _nameToAtom.end()) {
|
||||
// FIXME: Make this map a set and only used in assert builds.
|
||||
// Note, its safe to assert here as the resolver is the only client of
|
||||
// this API and it only requests exports for undefined symbols.
|
||||
// If we return from here we are no longer undefined so we should never
|
||||
// get here again.
|
||||
assert(!entry->second.atom && "Duplicate shared library export");
|
||||
bool weakDef = entry->second.weakDef;
|
||||
auto *atom = new (allocator()) MachOSharedLibraryAtom(*this, name,
|
||||
installName,
|
||||
weakDef);
|
||||
entry->second.atom = atom;
|
||||
return atom;
|
||||
if (!entry->second.atom) {
|
||||
// Lazily create SharedLibraryAtom.
|
||||
entry->second.atom =
|
||||
new (allocator()) MachOSharedLibraryAtom(*this, name, installName,
|
||||
entry->second.weakDef);
|
||||
}
|
||||
return entry->second.atom;
|
||||
}
|
||||
|
||||
// Next, check if symbol is implemented in some re-exported dylib.
|
||||
for (const ReExportedDylib &dylib : _reExportedDylibs) {
|
||||
assert(dylib.file);
|
||||
auto atom = dylib.file->exports(name, installName);
|
||||
if (atom.get())
|
||||
if (atom)
|
||||
return atom;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,35 +25,34 @@ public:
|
||||
FlatNamespaceFile(const MachOLinkingContext &context)
|
||||
: SharedLibraryFile("flat namespace") { }
|
||||
|
||||
OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
|
||||
const SharedLibraryAtom *exports(StringRef name,
|
||||
bool dataSymbolOnly) const override {
|
||||
return new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
|
||||
false);
|
||||
_sharedLibraryAtoms.push_back(
|
||||
new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
|
||||
false));
|
||||
|
||||
return _sharedLibraryAtoms.back();
|
||||
}
|
||||
|
||||
StringRef getDSOName() const override { return "flat-namespace"; }
|
||||
|
||||
const AtomRange<DefinedAtom> defined() const override {
|
||||
const AtomVector<DefinedAtom> &defined() const override {
|
||||
return _noDefinedAtoms;
|
||||
}
|
||||
const AtomRange<UndefinedAtom> undefined() const override {
|
||||
const AtomVector<UndefinedAtom> &undefined() const override {
|
||||
return _noUndefinedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
|
||||
return _noSharedLibraryAtoms;
|
||||
const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
|
||||
return _sharedLibraryAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<AbsoluteAtom> absolute() const override {
|
||||
const AtomVector<AbsoluteAtom> &absolute() const override {
|
||||
return _noAbsoluteAtoms;
|
||||
}
|
||||
|
||||
void clearAtoms() override {
|
||||
_noDefinedAtoms.clear();
|
||||
_noUndefinedAtoms.clear();
|
||||
_noSharedLibraryAtoms.clear();
|
||||
_noAbsoluteAtoms.clear();
|
||||
}
|
||||
private:
|
||||
mutable AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
};
|
||||
|
||||
} // namespace mach_o
|
||||
|
||||
@@ -54,8 +54,6 @@ public:
|
||||
GOTEntryAtom(const File &file, bool is64, StringRef name)
|
||||
: SimpleDefinedAtom(file), _is64(is64), _name(name) { }
|
||||
|
||||
~GOTEntryAtom() override = default;
|
||||
|
||||
ContentType contentType() const override {
|
||||
return DefinedAtom::typeGOT;
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ static void printDefinedAtoms(const SimpleFile::DefinedAtomRange &atomRange) {
|
||||
|
||||
/// Verify that the followon chain is sane. Should not be called in
|
||||
/// release binary.
|
||||
void LayoutPass::checkFollowonChain(const SimpleFile::DefinedAtomRange &range) {
|
||||
void LayoutPass::checkFollowonChain(SimpleFile::DefinedAtomRange &range) {
|
||||
ScopedTask task(getDefaultDomain(), "LayoutPass::checkFollowonChain");
|
||||
|
||||
// Verify that there's no cycle in follow-on chain.
|
||||
@@ -176,8 +176,8 @@ static bool compareAtomsSub(const LayoutPass::SortKey &lc,
|
||||
const LayoutPass::SortKey &rc,
|
||||
LayoutPass::SortOverride customSorter,
|
||||
std::string &reason) {
|
||||
const DefinedAtom *left = lc._atom.get();
|
||||
const DefinedAtom *right = rc._atom.get();
|
||||
const DefinedAtom *left = lc._atom;
|
||||
const DefinedAtom *right = rc._atom;
|
||||
if (left == right) {
|
||||
reason = "same";
|
||||
return false;
|
||||
@@ -252,9 +252,8 @@ static bool compareAtoms(const LayoutPass::SortKey &lc,
|
||||
bool result = compareAtomsSub(lc, rc, customSorter, reason);
|
||||
DEBUG({
|
||||
StringRef comp = result ? "<" : ">=";
|
||||
llvm::dbgs() << "Layout: '" << lc._atom.get()->name()
|
||||
<< "' " << comp << " '"
|
||||
<< rc._atom.get()->name() << "' (" << reason << ")\n";
|
||||
llvm::dbgs() << "Layout: '" << lc._atom->name() << "' " << comp << " '"
|
||||
<< rc._atom->name() << "' (" << reason << ")\n";
|
||||
});
|
||||
return result;
|
||||
}
|
||||
@@ -330,7 +329,7 @@ void LayoutPass::setChainRoot(const DefinedAtom *targetAtom,
|
||||
/// d) If the targetAtom is part of a different chain and the root of the
|
||||
/// targetAtom until the targetAtom has all atoms of size 0, then chain the
|
||||
/// targetAtoms and its tree to the current chain
|
||||
void LayoutPass::buildFollowOnTable(const SimpleFile::DefinedAtomRange &range) {
|
||||
void LayoutPass::buildFollowOnTable(SimpleFile::DefinedAtomRange &range) {
|
||||
ScopedTask task(getDefaultDomain(), "LayoutPass::buildFollowOnTable");
|
||||
// Set the initial size of the followon and the followonNext hash to the
|
||||
// number of atoms that we have.
|
||||
@@ -398,8 +397,7 @@ void LayoutPass::buildFollowOnTable(const SimpleFile::DefinedAtomRange &range) {
|
||||
/// assigning ordinals to each atom, if the atoms have their ordinals
|
||||
/// already assigned skip the atom and move to the next. This is the
|
||||
/// main map thats used to sort the atoms while comparing two atoms together
|
||||
void
|
||||
LayoutPass::buildOrdinalOverrideMap(const SimpleFile::DefinedAtomRange &range) {
|
||||
void LayoutPass::buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range) {
|
||||
ScopedTask task(getDefaultDomain(), "LayoutPass::buildOrdinalOverrideMap");
|
||||
uint64_t index = 0;
|
||||
for (const DefinedAtom *ai : range) {
|
||||
@@ -421,12 +419,12 @@ LayoutPass::buildOrdinalOverrideMap(const SimpleFile::DefinedAtomRange &range) {
|
||||
std::vector<LayoutPass::SortKey>
|
||||
LayoutPass::decorate(SimpleFile::DefinedAtomRange &atomRange) const {
|
||||
std::vector<SortKey> ret;
|
||||
for (OwningAtomPtr<DefinedAtom> &atom : atomRange.owning_ptrs()) {
|
||||
auto ri = _followOnRoots.find(atom.get());
|
||||
auto oi = _ordinalOverrideMap.find(atom.get());
|
||||
const auto *root = (ri == _followOnRoots.end()) ? atom.get() : ri->second;
|
||||
for (const DefinedAtom *atom : atomRange) {
|
||||
auto ri = _followOnRoots.find(atom);
|
||||
auto oi = _ordinalOverrideMap.find(atom);
|
||||
const DefinedAtom *root = (ri == _followOnRoots.end()) ? atom : ri->second;
|
||||
uint64_t override = (oi == _ordinalOverrideMap.end()) ? 0 : oi->second;
|
||||
ret.push_back(SortKey(std::move(atom), root, override));
|
||||
ret.push_back(SortKey(atom, root, override));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -435,7 +433,7 @@ void LayoutPass::undecorate(SimpleFile::DefinedAtomRange &atomRange,
|
||||
std::vector<SortKey> &keys) const {
|
||||
size_t i = 0;
|
||||
for (SortKey &k : keys)
|
||||
atomRange[i++] = std::move(k._atom);
|
||||
atomRange[i++] = k._atom;
|
||||
}
|
||||
|
||||
/// Perform the actual pass
|
||||
|
||||
@@ -33,10 +33,9 @@ namespace mach_o {
|
||||
class LayoutPass : public Pass {
|
||||
public:
|
||||
struct SortKey {
|
||||
SortKey(OwningAtomPtr<DefinedAtom> &&atom,
|
||||
const DefinedAtom *root, uint64_t override)
|
||||
: _atom(std::move(atom)), _root(root), _override(override) {}
|
||||
OwningAtomPtr<DefinedAtom> _atom;
|
||||
SortKey(const DefinedAtom *atom, const DefinedAtom *root, uint64_t override)
|
||||
: _atom(atom), _root(root), _override(override) {}
|
||||
const DefinedAtom *_atom;
|
||||
const DefinedAtom *_root;
|
||||
uint64_t _override;
|
||||
};
|
||||
@@ -54,10 +53,10 @@ public:
|
||||
private:
|
||||
// Build the followOn atoms chain as specified by the kindLayoutAfter
|
||||
// reference type
|
||||
void buildFollowOnTable(const SimpleFile::DefinedAtomRange &range);
|
||||
void buildFollowOnTable(SimpleFile::DefinedAtomRange &range);
|
||||
|
||||
// Build a map of Atoms to ordinals for sorting the atoms
|
||||
void buildOrdinalOverrideMap(const SimpleFile::DefinedAtomRange &range);
|
||||
void buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range);
|
||||
|
||||
const Registry &_registry;
|
||||
SortOverride _customSorter;
|
||||
@@ -86,12 +85,11 @@ private:
|
||||
void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);
|
||||
|
||||
std::vector<SortKey> decorate(SimpleFile::DefinedAtomRange &atomRange) const;
|
||||
|
||||
void undecorate(SimpleFile::DefinedAtomRange &atomRange,
|
||||
std::vector<SortKey> &keys) const;
|
||||
|
||||
// Check if the follow-on graph is a correct structure. For debugging only.
|
||||
void checkFollowonChain(const SimpleFile::DefinedAtomRange &range);
|
||||
void checkFollowonChain(SimpleFile::DefinedAtomRange &range);
|
||||
};
|
||||
|
||||
} // namespace mach_o
|
||||
|
||||
@@ -171,19 +171,7 @@ bool MachOLinkingContext::sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset,
|
||||
|
||||
MachOLinkingContext::MachOLinkingContext() {}
|
||||
|
||||
MachOLinkingContext::~MachOLinkingContext() {
|
||||
// Atoms are allocated on BumpPtrAllocator's on File's.
|
||||
// As we transfer atoms from one file to another, we need to clear all of the
|
||||
// atoms before we remove any of the BumpPtrAllocator's.
|
||||
auto &nodes = getNodes();
|
||||
for (unsigned i = 0, e = nodes.size(); i != e; ++i) {
|
||||
FileNode *node = dyn_cast<FileNode>(nodes[i].get());
|
||||
if (!node)
|
||||
continue;
|
||||
File *file = node->getFile();
|
||||
file->clearAtoms();
|
||||
}
|
||||
}
|
||||
MachOLinkingContext::~MachOLinkingContext() {}
|
||||
|
||||
void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
|
||||
uint32_t minOSVersion,
|
||||
|
||||
@@ -56,8 +56,6 @@ public:
|
||||
Data.info.flags |= (swiftVersion << 8);
|
||||
}
|
||||
|
||||
~ObjCImageInfoAtom() override = default;
|
||||
|
||||
ContentType contentType() const override {
|
||||
return DefinedAtom::typeObjCImageInfo;
|
||||
}
|
||||
|
||||
@@ -31,8 +31,6 @@ public:
|
||||
_combinedName((segName + "/" + sectName).str()),
|
||||
_content(std::move(content)) {}
|
||||
|
||||
~SectCreateAtom() override = default;
|
||||
|
||||
uint64_t size() const override { return _content->getBufferSize(); }
|
||||
|
||||
Scope scope() const override { return scopeGlobal; }
|
||||
@@ -69,29 +67,22 @@ public:
|
||||
new (allocator()) SectCreateAtom(*this, seg, sect, std::move(content)));
|
||||
}
|
||||
|
||||
const AtomRange<DefinedAtom> defined() const override {
|
||||
const AtomVector<DefinedAtom> &defined() const override {
|
||||
return _definedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<UndefinedAtom> undefined() const override {
|
||||
const AtomVector<UndefinedAtom> &undefined() const override {
|
||||
return _noUndefinedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
|
||||
const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
|
||||
return _noSharedLibraryAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<AbsoluteAtom> absolute() const override {
|
||||
const AtomVector<AbsoluteAtom> &absolute() const override {
|
||||
return _noAbsoluteAtoms;
|
||||
}
|
||||
|
||||
void clearAtoms() override {
|
||||
_definedAtoms.clear();
|
||||
_noUndefinedAtoms.clear();
|
||||
_noSharedLibraryAtoms.clear();
|
||||
_noAbsoluteAtoms.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
AtomVector<DefinedAtom> _definedAtoms;
|
||||
};
|
||||
|
||||
@@ -37,8 +37,6 @@ public:
|
||||
LazyPointerAtom(const File &file, bool is64)
|
||||
: SimpleDefinedAtom(file), _is64(is64) { }
|
||||
|
||||
~LazyPointerAtom() override = default;
|
||||
|
||||
ContentType contentType() const override {
|
||||
return DefinedAtom::typeLazyPointer;
|
||||
}
|
||||
@@ -73,8 +71,6 @@ public:
|
||||
NonLazyPointerAtom(const File &file, bool is64, ContentType contentType)
|
||||
: SimpleDefinedAtom(file), _is64(is64), _contentType(contentType) { }
|
||||
|
||||
~NonLazyPointerAtom() override = default;
|
||||
|
||||
ContentType contentType() const override {
|
||||
return _contentType;
|
||||
}
|
||||
@@ -110,8 +106,6 @@ public:
|
||||
StubAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
|
||||
: SimpleDefinedAtom(file), _stubInfo(stubInfo){ }
|
||||
|
||||
~StubAtom() override = default;
|
||||
|
||||
ContentType contentType() const override {
|
||||
return DefinedAtom::typeStub;
|
||||
}
|
||||
@@ -144,8 +138,6 @@ public:
|
||||
StubHelperAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
|
||||
: SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
|
||||
|
||||
~StubHelperAtom() override = default;
|
||||
|
||||
ContentType contentType() const override {
|
||||
return DefinedAtom::typeStubHelper;
|
||||
}
|
||||
@@ -179,8 +171,6 @@ public:
|
||||
StubHelperCommonAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
|
||||
: SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
|
||||
|
||||
~StubHelperCommonAtom() override = default;
|
||||
|
||||
ContentType contentType() const override {
|
||||
return DefinedAtom::typeStubHelper;
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ public:
|
||||
TLVPEntryAtom(const File &file, bool is64, StringRef name)
|
||||
: SimpleDefinedAtom(file), _is64(is64), _name(name) {}
|
||||
|
||||
~TLVPEntryAtom() override = default;
|
||||
|
||||
ContentType contentType() const override {
|
||||
return DefinedAtom::typeTLVInitializerPtr;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ private:
|
||||
|
||||
/// Mapping of Atoms.
|
||||
template <typename T> class AtomList {
|
||||
using Ty = std::vector<OwningAtomPtr<T>>;
|
||||
typedef lld::File::AtomVector<T> Ty;
|
||||
|
||||
public:
|
||||
typename Ty::iterator begin() { return _atoms.begin(); }
|
||||
@@ -503,20 +503,10 @@ template <> struct MappingTraits<ArchMember> {
|
||||
// Declare that an AtomList is a yaml sequence.
|
||||
template <typename T> struct SequenceTraits<AtomList<T> > {
|
||||
static size_t size(IO &io, AtomList<T> &seq) { return seq._atoms.size(); }
|
||||
static T *&element(IO &io, AtomList<T> &seq, size_t index) {
|
||||
static const T *&element(IO &io, AtomList<T> &seq, size_t index) {
|
||||
if (index >= seq._atoms.size())
|
||||
seq._atoms.resize(index + 1);
|
||||
return seq._atoms[index].get();
|
||||
}
|
||||
};
|
||||
|
||||
// Declare that an AtomRange is a yaml sequence.
|
||||
template <typename T> struct SequenceTraits<File::AtomRange<T> > {
|
||||
static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
|
||||
static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
|
||||
assert(io.outputting() && "AtomRange only used when outputting");
|
||||
assert(index < seq.size() && "Out of range access");
|
||||
return seq[index].get();
|
||||
return seq._atoms[index];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -568,29 +558,23 @@ template <> struct MappingTraits<const lld::File *> {
|
||||
|
||||
const lld::File *denormalize(IO &io) { return this; }
|
||||
|
||||
const AtomRange<lld::DefinedAtom> defined() const override {
|
||||
const AtomVector<lld::DefinedAtom> &defined() const override {
|
||||
return _noDefinedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<lld::UndefinedAtom> undefined() const override {
|
||||
const AtomVector<lld::UndefinedAtom> &undefined() const override {
|
||||
return _noUndefinedAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
|
||||
const AtomVector<lld::SharedLibraryAtom> &
|
||||
sharedLibrary() const override {
|
||||
return _noSharedLibraryAtoms;
|
||||
}
|
||||
|
||||
const AtomRange<lld::AbsoluteAtom> absolute() const override {
|
||||
const AtomVector<lld::AbsoluteAtom> &absolute() const override {
|
||||
return _noAbsoluteAtoms;
|
||||
}
|
||||
|
||||
void clearAtoms() override {
|
||||
_noDefinedAtoms.clear();
|
||||
_noUndefinedAtoms.clear();
|
||||
_noSharedLibraryAtoms.clear();
|
||||
_noAbsoluteAtoms.clear();
|
||||
}
|
||||
|
||||
File *find(StringRef name, bool dataSymbolOnly) override {
|
||||
for (const ArchMember &member : _members) {
|
||||
for (const lld::DefinedAtom *atom : member._content->defined()) {
|
||||
@@ -622,46 +606,36 @@ template <> struct MappingTraits<const lld::File *> {
|
||||
class NormalizedFile : public lld::File {
|
||||
public:
|
||||
NormalizedFile(IO &io)
|
||||
: File("", kindNormalizedObject), _io(io), _rnb(nullptr),
|
||||
_definedAtomsRef(_definedAtoms._atoms),
|
||||
_undefinedAtomsRef(_undefinedAtoms._atoms),
|
||||
_sharedLibraryAtomsRef(_sharedLibraryAtoms._atoms),
|
||||
_absoluteAtomsRef(_absoluteAtoms._atoms) {}
|
||||
: File("", kindNormalizedObject), _io(io), _rnb(nullptr) {}
|
||||
NormalizedFile(IO &io, const lld::File *file)
|
||||
: File(file->path(), kindNormalizedObject), _io(io),
|
||||
_rnb(new RefNameBuilder(*file)), _path(file->path()),
|
||||
_definedAtomsRef(file->defined()),
|
||||
_undefinedAtomsRef(file->undefined()),
|
||||
_sharedLibraryAtomsRef(file->sharedLibrary()),
|
||||
_absoluteAtomsRef(file->absolute()) {
|
||||
_rnb(new RefNameBuilder(*file)), _path(file->path()) {
|
||||
for (const lld::DefinedAtom *a : file->defined())
|
||||
_definedAtoms._atoms.push_back(a);
|
||||
for (const lld::UndefinedAtom *a : file->undefined())
|
||||
_undefinedAtoms._atoms.push_back(a);
|
||||
for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
|
||||
_sharedLibraryAtoms._atoms.push_back(a);
|
||||
for (const lld::AbsoluteAtom *a : file->absolute())
|
||||
_absoluteAtoms._atoms.push_back(a);
|
||||
}
|
||||
|
||||
~NormalizedFile() override {
|
||||
}
|
||||
|
||||
const lld::File *denormalize(IO &io);
|
||||
|
||||
const AtomRange<lld::DefinedAtom> defined() const override {
|
||||
return _definedAtomsRef;
|
||||
const AtomVector<lld::DefinedAtom> &defined() const override {
|
||||
return _definedAtoms._atoms;
|
||||
}
|
||||
|
||||
const AtomRange<lld::UndefinedAtom> undefined() const override {
|
||||
return _undefinedAtomsRef;
|
||||
const AtomVector<lld::UndefinedAtom> &undefined() const override {
|
||||
return _undefinedAtoms._atoms;
|
||||
}
|
||||
|
||||
const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
|
||||
return _sharedLibraryAtomsRef;
|
||||
const AtomVector<lld::SharedLibraryAtom> &
|
||||
sharedLibrary() const override {
|
||||
return _sharedLibraryAtoms._atoms;
|
||||
}
|
||||
|
||||
const AtomRange<lld::AbsoluteAtom> absolute() const override {
|
||||
return _absoluteAtomsRef;
|
||||
}
|
||||
|
||||
void clearAtoms() override {
|
||||
_definedAtoms._atoms.clear();
|
||||
_undefinedAtoms._atoms.clear();
|
||||
_sharedLibraryAtoms._atoms.clear();
|
||||
_absoluteAtoms._atoms.clear();
|
||||
const AtomVector<lld::AbsoluteAtom> &absolute() const override {
|
||||
return _absoluteAtoms._atoms;
|
||||
}
|
||||
|
||||
// Allocate a new copy of this string in _storage, so the strings
|
||||
@@ -679,10 +653,6 @@ template <> struct MappingTraits<const lld::File *> {
|
||||
AtomList<lld::UndefinedAtom> _undefinedAtoms;
|
||||
AtomList<lld::SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
AtomList<lld::AbsoluteAtom> _absoluteAtoms;
|
||||
AtomRange<lld::DefinedAtom> _definedAtomsRef;
|
||||
AtomRange<lld::UndefinedAtom> _undefinedAtomsRef;
|
||||
AtomRange<lld::SharedLibraryAtom> _sharedLibraryAtomsRef;
|
||||
AtomRange<lld::AbsoluteAtom> _absoluteAtomsRef;
|
||||
llvm::BumpPtrAllocator _storage;
|
||||
};
|
||||
|
||||
@@ -706,18 +676,10 @@ template <> struct MappingTraits<const lld::File *> {
|
||||
info->_file = keys.operator->();
|
||||
|
||||
io.mapOptional("path", keys->_path);
|
||||
|
||||
if (io.outputting()) {
|
||||
io.mapOptional("defined-atoms", keys->_definedAtomsRef);
|
||||
io.mapOptional("undefined-atoms", keys->_undefinedAtomsRef);
|
||||
io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtomsRef);
|
||||
io.mapOptional("absolute-atoms", keys->_absoluteAtomsRef);
|
||||
} else {
|
||||
io.mapOptional("defined-atoms", keys->_definedAtoms);
|
||||
io.mapOptional("undefined-atoms", keys->_undefinedAtoms);
|
||||
io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
|
||||
io.mapOptional("absolute-atoms", keys->_absoluteAtoms);
|
||||
}
|
||||
io.mapOptional("defined-atoms", keys->_definedAtoms);
|
||||
io.mapOptional("undefined-atoms", keys->_undefinedAtoms);
|
||||
io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
|
||||
io.mapOptional("absolute-atoms", keys->_absoluteAtoms);
|
||||
}
|
||||
|
||||
static void mappingArchive(IO &io, const lld::File *&file) {
|
||||
@@ -828,9 +790,6 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
|
||||
for (uint8_t x : cont)
|
||||
_content.push_back(x);
|
||||
}
|
||||
|
||||
~NormalizedAtom() override = default;
|
||||
|
||||
const lld::DefinedAtom *denormalize(IO &io) {
|
||||
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
|
||||
assert(info != nullptr);
|
||||
@@ -979,14 +938,6 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<lld::DefinedAtom *> {
|
||||
static void mapping(IO &io, lld::DefinedAtom *&atom) {
|
||||
const lld::DefinedAtom *atomPtr = atom;
|
||||
MappingTraits<const lld::DefinedAtom *>::mapping(io, atomPtr);
|
||||
atom = const_cast<lld::DefinedAtom *>(atomPtr);
|
||||
}
|
||||
};
|
||||
|
||||
// YAML conversion for const lld::UndefinedAtom*
|
||||
template <> struct MappingTraits<const lld::UndefinedAtom *> {
|
||||
|
||||
@@ -999,8 +950,6 @@ template <> struct MappingTraits<const lld::UndefinedAtom *> {
|
||||
: _file(fileFromContext(io)), _name(atom->name()),
|
||||
_canBeNull(atom->canBeNull()) {}
|
||||
|
||||
~NormalizedAtom() override = default;
|
||||
|
||||
const lld::UndefinedAtom *denormalize(IO &io) {
|
||||
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
|
||||
assert(info != nullptr);
|
||||
@@ -1044,14 +993,6 @@ template <> struct MappingTraits<const lld::UndefinedAtom *> {
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<lld::UndefinedAtom *> {
|
||||
static void mapping(IO &io, lld::UndefinedAtom *&atom) {
|
||||
const lld::UndefinedAtom *atomPtr = atom;
|
||||
MappingTraits<const lld::UndefinedAtom *>::mapping(io, atomPtr);
|
||||
atom = const_cast<lld::UndefinedAtom *>(atomPtr);
|
||||
}
|
||||
};
|
||||
|
||||
// YAML conversion for const lld::SharedLibraryAtom*
|
||||
template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
|
||||
|
||||
@@ -1065,8 +1006,6 @@ template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
|
||||
_loadName(atom->loadName()), _canBeNull(atom->canBeNullAtRuntime()),
|
||||
_type(atom->type()), _size(atom->size()) {}
|
||||
|
||||
~NormalizedAtom() override = default;
|
||||
|
||||
const lld::SharedLibraryAtom *denormalize(IO &io) {
|
||||
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
|
||||
assert(info != nullptr);
|
||||
@@ -1122,14 +1061,6 @@ template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<lld::SharedLibraryAtom *> {
|
||||
static void mapping(IO &io, lld::SharedLibraryAtom *&atom) {
|
||||
const lld::SharedLibraryAtom *atomPtr = atom;
|
||||
MappingTraits<const lld::SharedLibraryAtom *>::mapping(io, atomPtr);
|
||||
atom = const_cast<lld::SharedLibraryAtom *>(atomPtr);
|
||||
}
|
||||
};
|
||||
|
||||
// YAML conversion for const lld::AbsoluteAtom*
|
||||
template <> struct MappingTraits<const lld::AbsoluteAtom *> {
|
||||
|
||||
@@ -1140,9 +1071,6 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> {
|
||||
NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom)
|
||||
: _file(fileFromContext(io)), _name(atom->name()),
|
||||
_scope(atom->scope()), _value(atom->value()) {}
|
||||
|
||||
~NormalizedAtom() override = default;
|
||||
|
||||
const lld::AbsoluteAtom *denormalize(IO &io) {
|
||||
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
|
||||
assert(info != nullptr);
|
||||
@@ -1201,14 +1129,6 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> {
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<lld::AbsoluteAtom *> {
|
||||
static void mapping(IO &io, lld::AbsoluteAtom *&atom) {
|
||||
const lld::AbsoluteAtom *atomPtr = atom;
|
||||
MappingTraits<const lld::AbsoluteAtom *>::mapping(io, atomPtr);
|
||||
atom = const_cast<lld::AbsoluteAtom *>(atomPtr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
} // namespace yaml
|
||||
|
||||
|
||||
Reference in New Issue
Block a user