forked from OSchip/llvm-project
				
			
							parent
							
								
									51e318737a
								
							
						
					
					
						commit
						b495562b5d
					
				| 
						 | 
				
			
			@ -18,21 +18,15 @@ namespace lld {
 | 
			
		|||
/// It exists to represent content at fixed addresses in memory.
 | 
			
		||||
class AbsoluteAtom : public Atom {
 | 
			
		||||
public:
 | 
			
		||||
  virtual Definition definition() const {
 | 
			
		||||
    return Atom::definitionAbsolute;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// like dynamic_cast, if atom is definitionAbsolute
 | 
			
		||||
  /// returns atom cast to AbsoluteAtom*, else returns nullptr
 | 
			
		||||
  virtual const AbsoluteAtom* absoluteAtom() const { 
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  virtual uint64_t value() const = 0;
 | 
			
		||||
  
 | 
			
		||||
  static inline bool classof(const Atom *a) {
 | 
			
		||||
    return a->definition() == definitionAbsolute;
 | 
			
		||||
  }
 | 
			
		||||
  static inline bool classof(const AbsoluteAtom *) { return true; }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
           AbsoluteAtom() {}
 | 
			
		||||
  AbsoluteAtom() : Atom(definitionAbsolute) {}
 | 
			
		||||
  virtual ~AbsoluteAtom() {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,10 +21,6 @@ namespace llvm {
 | 
			
		|||
namespace lld {
 | 
			
		||||
 | 
			
		||||
class File;
 | 
			
		||||
class DefinedAtom;
 | 
			
		||||
class UndefinedAtom;
 | 
			
		||||
class SharedLibraryAtom;
 | 
			
		||||
class AbsoluteAtom;
 | 
			
		||||
 | 
			
		||||
///
 | 
			
		||||
/// The linker has a Graph Theory model of linking. An object file is seen
 | 
			
		||||
| 
						 | 
				
			
			@ -52,33 +48,22 @@ public:
 | 
			
		|||
  
 | 
			
		||||
  /// definition - Whether this atom is a definition or represents an undefined
 | 
			
		||||
  /// symbol.
 | 
			
		||||
  virtual Definition definition() const = 0;
 | 
			
		||||
  Definition definition() const { return _definition; };
 | 
			
		||||
 | 
			
		||||
  /// definedAtom - like dynamic_cast, if atom is definitionRegular
 | 
			
		||||
  /// returns atom cast to DefinedAtom*, else returns nullptr;
 | 
			
		||||
  virtual const DefinedAtom* definedAtom() const { return nullptr; }
 | 
			
		||||
 | 
			
		||||
  /// undefinedAtom - like dynamic_cast, if atom is definitionUndefined
 | 
			
		||||
  /// returns atom cast to UndefinedAtom*, else returns nullptr;
 | 
			
		||||
  virtual const UndefinedAtom* undefinedAtom() const { return nullptr; }
 | 
			
		||||
  
 | 
			
		||||
  /// sharedLibraryAtom - like dynamic_cast, if atom is definitionSharedLibrary
 | 
			
		||||
  /// returns atom cast to SharedLibraryAtom*, else returns nullptr;
 | 
			
		||||
  virtual const SharedLibraryAtom* sharedLibraryAtom() const { return nullptr; }
 | 
			
		||||
  
 | 
			
		||||
  /// absoluteAtom - like dynamic_cast, if atom is definitionAbsolute
 | 
			
		||||
  /// returns atom cast to AbsoluteAtom*, else returns nullptr;
 | 
			
		||||
  virtual const AbsoluteAtom* absoluteAtom() const { return nullptr; }
 | 
			
		||||
  static inline bool classof(const Atom *a) { return true; }
 | 
			
		||||
  
 | 
			
		||||
protected:
 | 
			
		||||
  /// Atom is an abstract base class.  Only subclasses can access constructor.
 | 
			
		||||
  Atom() {}
 | 
			
		||||
  Atom(Definition def) : _definition(def) {}
 | 
			
		||||
  
 | 
			
		||||
  /// The memory for Atom objects is always managed by the owning File
 | 
			
		||||
  /// object.  Therefore, no one but the owning File object should call
 | 
			
		||||
  /// delete on an Atom.  In fact, some File objects may bulk allocate
 | 
			
		||||
  /// an array of Atoms, so they cannot be individually deleted by anyone.
 | 
			
		||||
  virtual ~Atom() {}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  Definition _definition;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace lld
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,15 +88,6 @@ class File;
 | 
			
		|||
///
 | 
			
		||||
class DefinedAtom : public Atom {
 | 
			
		||||
public:
 | 
			
		||||
  /// Whether this atom is defined or a proxy for an undefined symbol
 | 
			
		||||
  virtual Definition definition() const {
 | 
			
		||||
    return Atom::definitionRegular;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  virtual const DefinedAtom* definedAtom() const { 
 | 
			
		||||
    return this; 
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// The scope in which this atom is acessible to other atoms.
 | 
			
		||||
  enum Scope {
 | 
			
		||||
    scopeTranslationUnit,  ///< Accessible only to atoms in the same translation
 | 
			
		||||
| 
						 | 
				
			
			@ -293,11 +284,15 @@ public:
 | 
			
		|||
  /// Returns an iterator to the end of this Atom's References
 | 
			
		||||
  virtual reference_iterator referencesEnd() const = 0;
 | 
			
		||||
 
 | 
			
		||||
  static inline bool classof(const Atom *a) {
 | 
			
		||||
    return a->definition() == definitionRegular;
 | 
			
		||||
  }
 | 
			
		||||
  static inline bool classof(const DefinedAtom *) { return true; }
 | 
			
		||||
 
 | 
			
		||||
protected:
 | 
			
		||||
  /// DefinedAtom is an abstract base class.  
 | 
			
		||||
  /// Only subclasses can access constructor.
 | 
			
		||||
  DefinedAtom() { }
 | 
			
		||||
  DefinedAtom() : Atom(definitionRegular) { }
 | 
			
		||||
  
 | 
			
		||||
  /// The memory for DefinedAtom objects is always managed by the owning File
 | 
			
		||||
  /// object.  Therefore, no one but the owning File object should call
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,16 +22,6 @@ namespace lld {
 | 
			
		|||
/// It exists to represent a symbol which will be bound at runtime.
 | 
			
		||||
class SharedLibraryAtom : public Atom {
 | 
			
		||||
public:
 | 
			
		||||
  virtual Definition definition() const {
 | 
			
		||||
    return Atom::definitionSharedLibrary;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// like dynamic_cast, if atom is definitionSharedLibrary
 | 
			
		||||
  /// returns atom cast to SharedLibraryAtom*, else returns nullptr
 | 
			
		||||
  virtual const SharedLibraryAtom* sharedLibraryAtom() const { 
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Returns shared library name used to load it at runtime.
 | 
			
		||||
  /// On linux that is the DT_NEEDED name.
 | 
			
		||||
  /// On Darwin it is the LC_DYLIB_LOAD dylib name.
 | 
			
		||||
| 
						 | 
				
			
			@ -41,8 +31,13 @@ public:
 | 
			
		|||
  /// so the loader should silently resolve address of symbol to be nullptr.
 | 
			
		||||
  virtual bool canBeNullAtRuntime() const = 0;
 | 
			
		||||
 | 
			
		||||
  static inline bool classof(const Atom *a) {
 | 
			
		||||
    return a->definition() == definitionSharedLibrary;
 | 
			
		||||
  }
 | 
			
		||||
  static inline bool classof(const SharedLibraryAtom *) { return true; }
 | 
			
		||||
  
 | 
			
		||||
protected:
 | 
			
		||||
           SharedLibraryAtom() {}
 | 
			
		||||
  SharedLibraryAtom() : Atom(definitionSharedLibrary) {}
 | 
			
		||||
  virtual ~SharedLibraryAtom() {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,16 +18,6 @@ namespace lld {
 | 
			
		|||
/// It exists as a place holder for a future atom.
 | 
			
		||||
class UndefinedAtom : public Atom {
 | 
			
		||||
public:
 | 
			
		||||
  virtual Definition definition() const {
 | 
			
		||||
    return Atom::definitionUndefined;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// like dynamic_cast, if atom is definitionUndefined
 | 
			
		||||
  /// returns atom cast to UndefinedAtom*, else returns nullptr
 | 
			
		||||
  virtual const UndefinedAtom* undefinedAtom() const { 
 | 
			
		||||
    return this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Whether this undefined symbol needs to be resolved,
 | 
			
		||||
  /// or whether it can just evaluate to nullptr.
 | 
			
		||||
  /// This concept is often called "weak", but that term
 | 
			
		||||
| 
						 | 
				
			
			@ -61,9 +51,13 @@ public:
 | 
			
		|||
  
 | 
			
		||||
  virtual CanBeNull canBeNull() const = 0;
 | 
			
		||||
  
 | 
			
		||||
  static inline bool classof(const Atom *a) {
 | 
			
		||||
    return a->definition() == definitionUndefined;
 | 
			
		||||
  }
 | 
			
		||||
  static inline bool classof(const UndefinedAtom *) { return true; }
 | 
			
		||||
   
 | 
			
		||||
protected:
 | 
			
		||||
           UndefinedAtom() {}
 | 
			
		||||
  UndefinedAtom() : Atom(definitionUndefined) {}
 | 
			
		||||
  virtual ~UndefinedAtom() {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@
 | 
			
		|||
#include "lld/Core/SymbolTable.h"
 | 
			
		||||
#include "lld/Core/UndefinedAtom.h"
 | 
			
		||||
 | 
			
		||||
#include "llvm/Support/Casting.h"
 | 
			
		||||
#include "llvm/Support/raw_ostream.h"
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +34,7 @@ public:
 | 
			
		|||
    if ( _liveAtoms.count(atom) )
 | 
			
		||||
      return false;
 | 
			
		||||
   // don't remove if marked never-dead-strip
 | 
			
		||||
    if ( const DefinedAtom* defAtom = atom->definedAtom() ) {
 | 
			
		||||
    if (const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(atom)) {
 | 
			
		||||
      if ( defAtom->deadStrip() == DefinedAtom::deadStripNever )
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -194,7 +195,7 @@ void Resolver::resolveUndefines() {
 | 
			
		|||
      std::vector<const Atom *> tents;
 | 
			
		||||
      for (std::vector<const Atom *>::iterator ait = _atoms.begin();
 | 
			
		||||
           ait != _atoms.end(); ++ait) {
 | 
			
		||||
        if ( const DefinedAtom* defAtom = (*ait)->definedAtom() ) {
 | 
			
		||||
        if (const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(*ait)) {
 | 
			
		||||
          if ( defAtom->merge() == DefinedAtom::mergeAsTentative )
 | 
			
		||||
            tents.push_back(defAtom);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -206,7 +207,8 @@ void Resolver::resolveUndefines() {
 | 
			
		|||
        llvm::StringRef tentName = (*dit)->name();
 | 
			
		||||
        const Atom *curAtom = _symbolTable.findByName(tentName);
 | 
			
		||||
        assert(curAtom != nullptr);
 | 
			
		||||
        if ( const DefinedAtom* curDefAtom = curAtom->definedAtom() ) {
 | 
			
		||||
        if (const DefinedAtom* curDefAtom =
 | 
			
		||||
              llvm::dyn_cast<DefinedAtom>(curAtom)) {
 | 
			
		||||
          if (curDefAtom->merge() == DefinedAtom::mergeAsTentative )
 | 
			
		||||
            _inputFiles.searchLibraries(tentName, searchDylibs, 
 | 
			
		||||
                                        true, true, *this);
 | 
			
		||||
| 
						 | 
				
			
			@ -221,7 +223,7 @@ void Resolver::resolveUndefines() {
 | 
			
		|||
// to the new defined atom
 | 
			
		||||
void Resolver::updateReferences() {
 | 
			
		||||
  for (auto ait = _atoms.begin(); ait != _atoms.end(); ++ait) {
 | 
			
		||||
    if ( const DefinedAtom* defAtom = (*ait)->definedAtom() ) {
 | 
			
		||||
    if (const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(*ait)) {
 | 
			
		||||
      for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd();
 | 
			
		||||
                                                        rit != end; ++rit) {
 | 
			
		||||
        const Reference* ref = *rit;
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +261,7 @@ void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
 | 
			
		|||
  WhyLiveBackChain thisChain;
 | 
			
		||||
  thisChain.previous = previous;
 | 
			
		||||
  thisChain.referer = &atom;
 | 
			
		||||
  if ( const DefinedAtom* defAtom = atom.definedAtom() ) {
 | 
			
		||||
  if ( const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(&atom)) {
 | 
			
		||||
    for (auto rit=defAtom->referencesBegin(), end=defAtom->referencesEnd();
 | 
			
		||||
                                                        rit != end; ++rit) {
 | 
			
		||||
      const Reference* ref = *rit;
 | 
			
		||||
| 
						 | 
				
			
			@ -342,7 +344,7 @@ void Resolver::removeCoalescedAwayAtoms() {
 | 
			
		|||
void Resolver::checkDylibSymbolCollisions() {
 | 
			
		||||
  for (std::vector<const Atom *>::const_iterator it = _atoms.begin();
 | 
			
		||||
       it != _atoms.end(); ++it) {
 | 
			
		||||
    const DefinedAtom* defAtom = (*it)->definedAtom();
 | 
			
		||||
    const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(*it);
 | 
			
		||||
    if (defAtom == nullptr)
 | 
			
		||||
      continue;
 | 
			
		||||
    if ( defAtom->merge() != DefinedAtom::mergeAsTentative ) 
 | 
			
		||||
| 
						 | 
				
			
			@ -389,19 +391,17 @@ void Resolver::resolve() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void Resolver::MergedFile::addAtom(const Atom& atom) {
 | 
			
		||||
  if ( const DefinedAtom* defAtom = atom.definedAtom() ) {
 | 
			
		||||
  if (const DefinedAtom* defAtom = llvm::dyn_cast<DefinedAtom>(&atom)) {
 | 
			
		||||
    _definedAtoms._atoms.push_back(defAtom);
 | 
			
		||||
  }
 | 
			
		||||
  else if ( const UndefinedAtom* undefAtom = atom.undefinedAtom() ) {
 | 
			
		||||
  } else if (const UndefinedAtom* undefAtom =
 | 
			
		||||
               llvm::dyn_cast<UndefinedAtom>(&atom)) {
 | 
			
		||||
    _undefinedAtoms._atoms.push_back(undefAtom);
 | 
			
		||||
  }
 | 
			
		||||
  else if ( const SharedLibraryAtom* slAtom = atom.sharedLibraryAtom() ) {
 | 
			
		||||
  } else if (const SharedLibraryAtom* slAtom =
 | 
			
		||||
               llvm::dyn_cast<SharedLibraryAtom>(&atom)) {
 | 
			
		||||
    _sharedLibraryAtoms._atoms.push_back(slAtom);
 | 
			
		||||
  }
 | 
			
		||||
  else if ( const AbsoluteAtom* abAtom = atom.absoluteAtom() ) {
 | 
			
		||||
  } else if (const AbsoluteAtom* abAtom = llvm::dyn_cast<AbsoluteAtom>(&atom)) {
 | 
			
		||||
    _absoluteAtoms._atoms.push_back(abAtom);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
  } else {
 | 
			
		||||
    assert(0 && "atom has unknown definition kind");
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
 | 
			
		||||
#include "llvm/ADT/ArrayRef.h"
 | 
			
		||||
#include "llvm/ADT/DenseMapInfo.h"
 | 
			
		||||
#include "llvm/Support/Casting.h"
 | 
			
		||||
#include "llvm/Support/ErrorHandling.h"
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
| 
						 | 
				
			
			@ -160,8 +161,10 @@ void SymbolTable::addByName(const Atom & newAtom) {
 | 
			
		|||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case NCR_DupUndef: {
 | 
			
		||||
          const UndefinedAtom* existingUndef = existing->undefinedAtom();
 | 
			
		||||
          const UndefinedAtom* newUndef = newAtom.undefinedAtom();
 | 
			
		||||
          const UndefinedAtom* existingUndef =
 | 
			
		||||
            llvm::dyn_cast<UndefinedAtom>(existing);
 | 
			
		||||
          const UndefinedAtom* newUndef =
 | 
			
		||||
            llvm::dyn_cast<UndefinedAtom>(&newAtom);
 | 
			
		||||
          assert(existingUndef != nullptr);
 | 
			
		||||
          assert(newUndef != nullptr);
 | 
			
		||||
          if ( existingUndef->canBeNull() == newUndef->canBeNull() ) {
 | 
			
		||||
| 
						 | 
				
			
			@ -176,8 +179,10 @@ void SymbolTable::addByName(const Atom & newAtom) {
 | 
			
		|||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case NCR_DupShLib: {
 | 
			
		||||
          const SharedLibraryAtom* existingShLib = existing->sharedLibraryAtom();
 | 
			
		||||
          const SharedLibraryAtom* newShLib = newAtom.sharedLibraryAtom();
 | 
			
		||||
          const SharedLibraryAtom* existingShLib =
 | 
			
		||||
            llvm::dyn_cast<SharedLibraryAtom>(existing);
 | 
			
		||||
          const SharedLibraryAtom* newShLib =
 | 
			
		||||
            llvm::dyn_cast<SharedLibraryAtom>(&newAtom);
 | 
			
		||||
          assert(existingShLib != nullptr);
 | 
			
		||||
          assert(newShLib != nullptr);
 | 
			
		||||
          if ( (existingShLib->canBeNullAtRuntime() 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,7 @@
 | 
			
		|||
#include "lld/Core/Reference.h"
 | 
			
		||||
 | 
			
		||||
#include "llvm/ADT/DenseMap.h"
 | 
			
		||||
#include "llvm/Support/Casting.h"
 | 
			
		||||
 | 
			
		||||
namespace lld {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +58,7 @@ void GOTPass::perform() {
 | 
			
		|||
      if ( _platform.isGOTAccess(ref->kind(), canBypassGOT) ) {
 | 
			
		||||
        const Atom* target = ref->target();
 | 
			
		||||
        assert(target != nullptr);
 | 
			
		||||
        const DefinedAtom* defTarget = target->definedAtom();
 | 
			
		||||
        const DefinedAtom* defTarget = llvm::dyn_cast<DefinedAtom>(target);
 | 
			
		||||
        bool replaceTargetWithGOTAtom = false;
 | 
			
		||||
        if ( target->definition() == Atom::definitionSharedLibrary ) {
 | 
			
		||||
          // Accesses to shared library symbols must go through GOT.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@
 | 
			
		|||
#include "lld/Core/Reference.h"
 | 
			
		||||
 | 
			
		||||
#include "llvm/ADT/DenseMap.h"
 | 
			
		||||
#include "llvm/Support/Casting.h"
 | 
			
		||||
 | 
			
		||||
namespace lld {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -47,8 +48,8 @@ void StubsPass::perform() {
 | 
			
		|||
        if ( target->definition() == Atom::definitionSharedLibrary ) {
 | 
			
		||||
          // Calls to shared libraries go through stubs.
 | 
			
		||||
          replaceCalleeWithStub = true;
 | 
			
		||||
        }
 | 
			
		||||
        else if ( const DefinedAtom* defTarget = target->definedAtom() ) {
 | 
			
		||||
        } else if (const DefinedAtom* defTarget =
 | 
			
		||||
                     llvm::dyn_cast<DefinedAtom>(target)) {
 | 
			
		||||
          if ( defTarget->interposable() != DefinedAtom::interposeNo ) {
 | 
			
		||||
            // Calls to interposable functions in same linkage unit 
 | 
			
		||||
            // must also go through a stub.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue