diff options
-rw-r--r-- | lld/include/lld/Core/Atom.h | 145 | ||||
-rw-r--r-- | lld/include/lld/Core/UndefinedAtom.h | 3 | ||||
-rw-r--r-- | lld/lib/Core/Atom.cpp | 4 | ||||
-rw-r--r-- | lld/lib/Core/SymbolTable.cpp | 28 | ||||
-rw-r--r-- | lld/lib/Core/YamlReader.cpp | 23 | ||||
-rw-r--r-- | lld/lib/Core/YamlWriter.cpp | 2 |
6 files changed, 133 insertions, 72 deletions
diff --git a/lld/include/lld/Core/Atom.h b/lld/include/lld/Core/Atom.h index b8008e471c6..50f39ec7fea 100644 --- a/lld/include/lld/Core/Atom.h +++ b/lld/include/lld/Core/Atom.h @@ -37,19 +37,13 @@ public: enum Definition { definitionRegular, // usual C/C++ function or global variable + definitionWeak, // can be silently overridden by regular definition definitionTentative, // C-only pre-ANSI support aka common definitionAbsolute, // asm-only (foo = 10) not tied to any content definitionUndefined, // Only in .o files to model reference to undef definitionSharedLibrary // Only in shared libraries to model export }; - enum Combine { - combineNever, // most symbols - combineByName, // weak-definition symbol - combineByTypeContent, // simple constant that can be coalesced - combineByTypeContentDeep // complex coalescable constants - }; - enum ContentType { typeUnknown, // for use with definitionUndefined typeCode, // executable code @@ -104,6 +98,12 @@ public: sectionCustomRequired // linker must place in specific section }; + enum DeadStripKind { + deadStripNormal, // linker may dead strip this atom + deadStripNever, // linker must never dead strip this atom + deadStripAlways // linker must remove this atom if unused + }; + struct Alignment { Alignment(int p2, int m = 0) : powerOf2(p2) @@ -121,54 +121,114 @@ public: typedef UnwindInfo *iterator; }; - // link-once (throw away if not used)?? - // dll import/export + /// name - The name of the atom. For a function atom, it is the (mangled) + /// name of the function. + virtual llvm::StringRef name() const = 0; + + /// internalName - If the name is just a temporary label that should + /// not show up in the final linked image. + bool internalName() const { + return _internalName; + } + + /// size - the number of bytes of space this atom's content will occupy + /// in the final linked image. For a function atom, it is the number + /// of bytes of code in the function. + virtual uint64_t size() const = 0; + + /// scope - The visibility of this atom to other atoms. C static functions + /// have scope scopeTranslationUnit. Regular C functions have scope + /// scopeGlobal. Functions compiled with visibility=hidden have scope + /// scopeLinkageUnit so they can be see by other atoms being linked but not + /// by the OS loader. + Scope scope() const { + return _scope; + } + + /// definition - Whether this atom is a definition or represents an undefined + /// or tentative symbol. + Definition definition() const { + return _definition; + } + + /// mergeDuplicates - For definitionRegular atoms, this means the + /// atom can be silently coalesced with another atom that has the + /// same name or content. + bool mergeDuplicates() const { + return _mergeDuplicates; + } + + /// contentType - The type of this atom, such as code or data. + ContentType contentType() const { + return _contentType; + } + + /// alignment - The alignment constraints on how this atom must be laid out + /// in the final linked image (e.g. 16-byte aligned). + Alignment alignment() const { + return Alignment(_alignmentPowerOf2, _alignmentModulus); + } + + /// sectionChoice - Whether this atom must be in a specially named section + /// in the final linked image, or if the linker can infer the section + /// based on the contentType(). + SectionChoice sectionChoice() const { + return _sectionChoice; + } + + /// customSectionName - If sectionChoice() != sectionBasedOnContent, then + /// this return the name of the section the atom should be placed into. + virtual llvm::StringRef customSectionName() const; + + /// deadStrip - constraints on whether the linker may dead strip away + /// this atom. + DeadStripKind deadStrip() const { + return _deadStrip; + } + + /// autoHide - Whether it is ok for the linker to change the scope of this + /// atom to hidden as long as all other duplicates are also autoHide. + bool autoHide() const { + return _autoHide; + } + + /// permissions - Returns the OS memory protections required for this atom's + /// content at runtime. A function atom is R_X and a global variable is RW_. + virtual ContentPermissions permissions() const; + + /// + virtual void copyRawContent(uint8_t buffer[]) const = 0; + virtual llvm::ArrayRef<uint8_t> rawContent() const; + - Scope scope() const { return _scope; } - Definition definition() const { return _definition; } - Combine combine() const { return _combine; } - ContentType contentType() const { return _contentType; } - Alignment alignment() const; - SectionChoice sectionChoice() const { return _sectionChoice; } - bool deadStrip() const { return _DeadStrip; } bool isThumb() const { return _thumb; } bool isAlias() const { return _alias; } - bool userVisibleName() const { return _userVisibleName; } - bool autoHide() const; + void setLive(bool l) { _live = l; } bool live() const { return _live; } - void setOverridesDylibsWeakDef(); virtual const class File *file() const = 0; virtual bool translationUnitSource(llvm::StringRef &path) const; - virtual llvm::StringRef name() const; virtual uint64_t objectAddress() const = 0; - virtual llvm::StringRef customSectionName() const; - virtual uint64_t size() const = 0; - virtual ContentPermissions permissions() const { return perm___; } - virtual void copyRawContent(uint8_t buffer[]) const = 0; - virtual llvm::ArrayRef<uint8_t> rawContent() const; virtual Reference::iterator referencesBegin() const; virtual Reference::iterator referencesEnd() const; virtual UnwindInfo::iterator beginUnwind() const; virtual UnwindInfo::iterator endUnwind() const; Atom( Definition d - , Combine c , Scope s , ContentType ct , SectionChoice sc - , bool UserVisibleName - , bool DeadStrip + , bool internalName + , DeadStripKind ds , bool IsThumb , bool IsAlias , Alignment a) : _alignmentModulus(a.modulus) , _alignmentPowerOf2(a.powerOf2) , _definition(d) - , _combine(c) - , _userVisibleName(UserVisibleName) - , _DeadStrip(DeadStrip) + , _internalName(internalName) + , _deadStrip(ds) , _thumb(IsThumb) , _alias(IsAlias) , _contentType(ct) @@ -178,18 +238,19 @@ public: virtual ~Atom(); protected: - uint16_t _alignmentModulus; - uint8_t _alignmentPowerOf2; - Definition _definition : 3; - Combine _combine : 2; - bool _userVisibleName : 1; - bool _DeadStrip : 1; - bool _thumb : 1; - bool _alias : 1; - bool _live : 1; - ContentType _contentType : 8; - Scope _scope : 2; + uint16_t _alignmentModulus; + uint8_t _alignmentPowerOf2; + ContentType _contentType : 8; + Definition _definition : 3; + Scope _scope : 2; SectionChoice _sectionChoice: 2; + bool _internalName : 1; + DeadStripKind _deadStrip : 2; + bool _mergeDuplicates : 1; + bool _thumb : 1; + bool _autoHide : 1; + bool _alias : 1; + bool _live : 1; }; } // namespace lld diff --git a/lld/include/lld/Core/UndefinedAtom.h b/lld/include/lld/Core/UndefinedAtom.h index 815ea8d1cc4..36463acb8bb 100644 --- a/lld/include/lld/Core/UndefinedAtom.h +++ b/lld/include/lld/Core/UndefinedAtom.h @@ -22,12 +22,11 @@ class UndefinedAtom : public Atom { public: UndefinedAtom(llvm::StringRef nm) : Atom( Atom::definitionUndefined - , Atom::combineNever , Atom::scopeLinkageUnit , Atom::typeUnknown , Atom::sectionBasedOnContent - , true , false + , deadStripNormal , false , false , Atom::Alignment(0)) diff --git a/lld/lib/Core/Atom.cpp b/lld/lib/Core/Atom.cpp index 482a21fe17e..889ec096e32 100644 --- a/lld/lib/Core/Atom.cpp +++ b/lld/lib/Core/Atom.cpp @@ -32,6 +32,10 @@ namespace lld { return llvm::ArrayRef<uint8_t>(); } + Atom::ContentPermissions Atom::permissions() const { + return perm___; + } + Reference::iterator Atom::referencesBegin() const { return 0; } diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp index 3b770626f6b..ebd4c0bde50 100644 --- a/lld/lib/Core/SymbolTable.cpp +++ b/lld/lib/Core/SymbolTable.cpp @@ -26,15 +26,11 @@ namespace lld { void SymbolTable::add(const Atom &atom) { assert(atom.scope() != Atom::scopeTranslationUnit); - switch (atom.combine()) { - case Atom::combineNever: - case Atom::combineByName: + if ( !atom.internalName() ) { this->addByName(atom); - break; - case Atom::combineByTypeContent: - case Atom::combineByTypeContentDeep: + } + else if ( atom.mergeDuplicates() ) { // TO DO: support constants merging - break; } } @@ -46,27 +42,31 @@ enum NameCollisionResolution { NCR_Error }; -static NameCollisionResolution cases[5][5] = { - //regular tentative absolute undef sharedLib +static NameCollisionResolution cases[6][6] = { + //regular weak tentative absolute undef sharedLib { // first is regular - NCR_Error, NCR_First, NCR_Error, NCR_First, NCR_First + NCR_Error, NCR_First, NCR_First, NCR_Error, NCR_First, NCR_First + }, + { + // first is weak + NCR_Second, NCR_Weak, NCR_Larger, NCR_Error, NCR_First, NCR_First }, { // first is tentative - NCR_Second, NCR_Larger, NCR_Error, NCR_First, NCR_First + NCR_Second, NCR_Second, NCR_Larger, NCR_Error, NCR_First, NCR_First }, { // first is absolute - NCR_Error, NCR_Error, NCR_Error, NCR_First, NCR_First + NCR_Error, NCR_Error, NCR_Error, NCR_Error, NCR_First, NCR_First }, { // first is undef - NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_Second + NCR_Second, NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_Second }, { // first is sharedLib - NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_First + NCR_Second, NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_First } }; diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp index 9b093e42c64..c95e061931c 100644 --- a/lld/lib/Core/YamlReader.cpp +++ b/lld/lib/Core/YamlReader.cpp @@ -239,18 +239,17 @@ bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name, class YAMLAtom : public Atom { public: YAMLAtom( Definition d - , Combine c , Scope s , ContentType ct , SectionChoice sc - , bool uvn - , bool dds + , bool intn + , DeadStripKind dsk , bool tb , bool al , Alignment a , YAMLFile *f , const char *n) - : Atom(d, c, s, ct, sc, uvn, dds, tb, al, a) + : Atom(d, s, ct, sc, intn, dsk, tb, al, a) , _file(f) , _name(n) , _size(0) @@ -322,13 +321,13 @@ public: private: const char *_name; Atom::Alignment _align; - Atom::Combine _combine; Atom::ContentType _type; Atom::Scope _scope; Atom::Definition _def; Atom::SectionChoice _sectionChoice; + bool _internalName; bool _userVisibleName; - bool _dontDeadStrip; + Atom::DeadStripKind _dontDeadStrip; bool _thumb; bool _alias; Reference _ref; @@ -337,11 +336,10 @@ private: YAMLAtomState::YAMLAtomState() : _name(NULL) , _align(0, 0) - , _combine(Atom::combineNever) , _type(Atom::typeData) , _scope(Atom::scopeGlobal) , _userVisibleName(true) - , _dontDeadStrip(false) + , _dontDeadStrip(Atom::deadStripNormal) , _thumb(false) , _alias(false) { _ref.target = NULL; @@ -352,8 +350,8 @@ YAMLAtomState::YAMLAtomState() } void YAMLAtomState::makeAtom(YAMLFile *f) { - Atom *a = new YAMLAtom(_def, _combine, _scope, _type, _sectionChoice, - _userVisibleName, _dontDeadStrip, _thumb, _alias, + Atom *a = new YAMLAtom(_def, _scope, _type, _sectionChoice, + _internalName, _dontDeadStrip, _thumb, _alias, _align, f, _name); f->_atoms.push_back(a); @@ -362,13 +360,12 @@ void YAMLAtomState::makeAtom(YAMLFile *f) { _name = NULL; _align.powerOf2 = 0; _align.modulus = 0; - _combine = Atom::combineNever; _type = Atom::typeData; _scope = Atom::scopeGlobal; _def = Atom::definitionRegular; _sectionChoice = Atom::sectionBasedOnContent; - _userVisibleName = true; - _dontDeadStrip = false; + _internalName = false; + _dontDeadStrip = Atom::deadStripNormal; _thumb = false; _alias = false; _ref.target = NULL; diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/Core/YamlWriter.cpp index ae27c7e3129..711fd1ac027 100644 --- a/lld/lib/Core/YamlWriter.cpp +++ b/lld/lib/Core/YamlWriter.cpp @@ -29,8 +29,8 @@ public: virtual void doFile(const class File &) { } virtual void doAtom(const class Atom &atom) { _out << " - name: " << atom.name() << "\n"; + _out << " internal-name:" << atom.internalName() << "\n"; _out << " definition: " << definitionString(atom.definition()) <<"\n"; - _out << " user-visible:" << atom.userVisibleName() << "\n"; _out << " scope: " << scopeString(atom.scope()) << "\n"; _out << " type: " << typeString(atom.contentType()) << "\n"; if (atom.referencesBegin() != atom.referencesEnd()) { |