summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/Core/Atom.h145
-rw-r--r--lld/include/lld/Core/UndefinedAtom.h3
-rw-r--r--lld/lib/Core/Atom.cpp4
-rw-r--r--lld/lib/Core/SymbolTable.cpp28
-rw-r--r--lld/lib/Core/YamlReader.cpp23
-rw-r--r--lld/lib/Core/YamlWriter.cpp2
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()) {
OpenPOWER on IntegriCloud