From 2a59024ff8735cfffada708ecbc8abd8cde874e3 Mon Sep 17 00:00:00 2001 From: Sid Manning Date: Thu, 18 Oct 2012 17:16:19 +0000 Subject: [PATCH] This update does the following: * Moves enum Scope from DefinedAtom.h to Atom.h * Adds scope method to AbsoluteAtom class * Updates YAML to print scope of AbsoluteAtoms * Update Native Reader/Writer to handle this new, "attribute" * Adds testcase Reviewed and approved by Nick Kledzik llvm-svn: 166189 --- lld/include/lld/Core/AbsoluteAtom.h | 8 ++++ lld/include/lld/Core/Atom.h | 11 ++++++ lld/include/lld/Core/DefinedAtom.h | 10 ----- lld/lib/ReaderWriter/ELF/ReaderELF.cpp | 22 ++++++++--- lld/lib/ReaderWriter/ELF/WriterELF.cpp | 24 +++++++++--- lld/lib/ReaderWriter/Native/NativeFileFormat.h | 2 + lld/lib/ReaderWriter/Native/ReaderNative.cpp | 32 +++++++++++++++- lld/lib/ReaderWriter/Native/WriterNative.cpp | 49 +++++++++++++++++++++---- lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp | 4 ++ lld/lib/ReaderWriter/YAML/ReaderYAML.cpp | 4 ++ lld/lib/ReaderWriter/YAML/WriterYAML.cpp | 8 ++++ lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp | 11 +++--- lld/lib/ReaderWriter/YAML/YamlKeyValues.h | 2 +- lld/test/elf/Inputs/abs-test.i386 | Bin 0 -> 504 bytes lld/test/elf/abs.objtxt | 21 +++++++++++ 15 files changed, 173 insertions(+), 35 deletions(-) create mode 100644 lld/test/elf/Inputs/abs-test.i386 create mode 100644 lld/test/elf/abs.objtxt diff --git a/lld/include/lld/Core/AbsoluteAtom.h b/lld/include/lld/Core/AbsoluteAtom.h index 6496c41..22eabcc 100644 --- a/lld/include/lld/Core/AbsoluteAtom.h +++ b/lld/include/lld/Core/AbsoluteAtom.h @@ -18,8 +18,16 @@ namespace lld { /// It exists to represent content at fixed addresses in memory. class AbsoluteAtom : public Atom { public: + virtual uint64_t value() 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. + virtual Scope scope() const = 0; + static inline bool classof(const Atom *a) { return a->definition() == definitionAbsolute; } diff --git a/lld/include/lld/Core/Atom.h b/lld/include/lld/Core/Atom.h index ecc66b4..fbda9b1 100644 --- a/lld/include/lld/Core/Atom.h +++ b/lld/include/lld/Core/Atom.h @@ -41,6 +41,17 @@ public: definitionSharedLibrary ///< Only in shared libraries to model export. }; + /// The scope in which this atom is acessible to other atoms. + enum Scope { + scopeTranslationUnit, ///< Accessible only to atoms in the same translation + /// unit (e.g. a C static). + scopeLinkageUnit, ///< Accessible to atoms being linked but not visible + /// to runtime loader (e.g. visibility=hidden). + scopeGlobal ///< Accessible to all atoms and visible to runtime + /// loader (e.g. visibility=default). + }; + + /// file - returns the File that produced/owns this Atom virtual const class File& file() const = 0; diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h index b7e269f..c70b6c9 100644 --- a/lld/include/lld/Core/DefinedAtom.h +++ b/lld/include/lld/Core/DefinedAtom.h @@ -88,16 +88,6 @@ class File; /// class DefinedAtom : public Atom { public: - /// The scope in which this atom is acessible to other atoms. - enum Scope { - scopeTranslationUnit, ///< Accessible only to atoms in the same translation - /// unit (e.g. a C static). - scopeLinkageUnit, ///< Accessible to atoms being linked but not visible - /// to runtime loader (e.g. visibility=hidden). - scopeGlobal ///< Accessible to all atoms and visible to runtime - /// loader (e.g. visibility=default). - }; - enum Interposable { interposeNo, // linker can directly bind uses of this atom interposeYes, // linker must indirect (through GOT) uses diff --git a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp index 45b5702..6fa3025 100644 --- a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp +++ b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp @@ -11,7 +11,6 @@ // to consume an ELF file and produces atoms out of it. // //===----------------------------------------------------------------------===// - #include "lld/ReaderWriter/ReaderELF.h" #include "lld/Core/File.h" #include "lld/Core/Reference.h" @@ -115,14 +114,18 @@ private: /// particular address. This atom has no content its address will be used by /// the writer to fixup references that point to it. template -class ELFAbsoluteAtom final: public AbsoluteAtom { +class ELFAbsoluteAtom final : public AbsoluteAtom { + + typedef llvm::object::Elf_Sym_Impl Elf_Sym; public: ELFAbsoluteAtom(const File &file, llvm::StringRef name, + const Elf_Sym *symbol, uint64_t value) : _owningFile(file) , _name(name) + , _symbol(symbol) , _value(value) {} @@ -130,6 +133,15 @@ public: return _owningFile; } + virtual Scope scope() const { + if (_symbol->st_other == llvm::ELF::STV_HIDDEN) + return scopeLinkageUnit; + if (_symbol->getBinding() == llvm::ELF::STB_LOCAL) + return scopeTranslationUnit; + else + return scopeGlobal; + } + virtual llvm::StringRef name() const { return _name; } @@ -141,6 +153,7 @@ public: private: const File &_owningFile; llvm::StringRef _name; + const Elf_Sym *_symbol; uint64_t _value; }; @@ -308,6 +321,7 @@ public: ret = typeZeroFill; break; } + return ret; } @@ -319,7 +333,6 @@ public: || _symbol->st_shndx == llvm::ELF::SHN_COMMON) { return Alignment(llvm::Log2_64(_symbol->st_value)); } - return Alignment(llvm::Log2_64(_section->sh_addralign)); } @@ -422,7 +435,6 @@ private: llvm::StringRef _sectionName; const Elf_Sym *_symbol; const Elf_Shdr *_section; - // _contentData will hold the bits that make up the atom. llvm::ArrayRef _contentData; @@ -543,7 +555,7 @@ public: auto *newAtom = new (_readerStorage.Allocate > ()) ELFAbsoluteAtom - (*this, symbolName, symbol->st_value); + (*this, symbolName, symbol, symbol->st_value); _absoluteAtoms._atoms.push_back(newAtom); _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom)); diff --git a/lld/lib/ReaderWriter/ELF/WriterELF.cpp b/lld/lib/ReaderWriter/ELF/WriterELF.cpp index 974e829..13453b7 100644 --- a/lld/lib/ReaderWriter/ELF/WriterELF.cpp +++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp @@ -601,14 +601,28 @@ void ELFSymbolTableChunk b = ELF::STB_WEAK; else b = ELF::STB_GLOBAL; - } else if (const AbsoluteAtom *aa = llvm::dyn_cast(a)){ + } else if (const AbsoluteAtom *aa = llvm::dyn_cast(a)){ //FIXME: Absolute atoms need more properties to differentiate each other // based on binding and type of symbol - symbol->st_value = aa->value(); + t = ELF::STT_OBJECT; + + switch (aa->scope()) { + case AbsoluteAtom::scopeLinkageUnit: + symbol->st_other = ELF::STV_HIDDEN; + b = ELF::STB_LOCAL; + break; + case AbsoluteAtom::scopeTranslationUnit: + b = ELF::STB_LOCAL; + break; + case AbsoluteAtom::scopeGlobal: + b = ELF::STB_GLOBAL; + break; + } + symbol->st_value = aa->value(); } else { - symbol->st_value = 0; - t = ELF::STT_NOTYPE; - b = ELF::STB_LOCAL; + symbol->st_value = 0; + t = ELF::STT_NOTYPE; + b = ELF::STB_LOCAL; } symbol->setBindingAndType(b, t); diff --git a/lld/lib/ReaderWriter/Native/NativeFileFormat.h b/lld/lib/ReaderWriter/Native/NativeFileFormat.h index 43731f1..d43236f 100644 --- a/lld/lib/ReaderWriter/Native/NativeFileFormat.h +++ b/lld/lib/ReaderWriter/Native/NativeFileFormat.h @@ -89,6 +89,7 @@ struct NativeFileHeader { enum NativeChunkSignatures { NCS_DefinedAtomsV1 = 1, NCS_AttributesArrayV1 = 2, + NCS_AbsoluteAttributesV1 = 12, NCS_UndefinedAtomsV1 = 3, NCS_SharedLibraryAtomsV1 = 4, NCS_AbsoluteAtomsV1 = 5, @@ -183,6 +184,7 @@ struct NativeSharedLibraryAtomIvarsV1 { // struct NativeAbsoluteAtomIvarsV1 { uint32_t nameOffset; + uint32_t attributesOffset; uint32_t reserved; uint64_t value; }; diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp index bd0c17a..1ad37c7 100644 --- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp +++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp @@ -175,12 +175,16 @@ public: virtual const lld::File& file() const; virtual StringRef name() const; - + virtual Scope scope() const { + const NativeAtomAttributesV1& attr = absAttributes(); + return (Scope)(attr.scope); + } virtual uint64_t value() const { return _ivarData->value; } private: + const NativeAtomAttributesV1& absAttributes() const; const File *_file; const NativeAbsoluteAtomIvarsV1 *_ivarData; }; @@ -289,6 +293,9 @@ public: case NCS_AbsoluteAtomsV1: ec = file->processAbsoluteAtomsV1(base, chunk); break; + case NCS_AbsoluteAttributesV1: + ec = file->processAbsoluteAttributesV1(base, chunk); + break; case NCS_ReferencesArrayV1: ec = file->processReferencesV1(base, chunk); break; @@ -425,6 +432,19 @@ private: return make_error_code(native_reader_error::success); } + // set up pointers to attributes array + error_code processAbsoluteAttributesV1(const uint8_t *base, + const NativeChunk *chunk) { + this->_absAttributes = base + chunk->fileOffset; + this->_absAbsoluteMaxOffset = chunk->fileSize; + DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs() + << " chunk AbsoluteAttributesV1: " + << " count=" << chunk->elementCount + << " chunkSize=" << chunk->fileSize + << "\n"); + return make_error_code(native_reader_error::success); + } + // instantiate array of UndefinedAtoms from v1 ivar data in file error_code processUndefinedAtomsV1(const uint8_t *base, const NativeChunk *chunk) { @@ -677,6 +697,11 @@ private: return *reinterpret_cast(_attributes + off); } + const NativeAtomAttributesV1& absAttribute(uint32_t off) const { + assert(off < _absAbsoluteMaxOffset); + return *reinterpret_cast(_absAttributes + off); + } + const uint8_t* content(uint32_t offset, uint32_t size) const { const uint8_t* result = _contentStart + offset; assert((result+size) <= _contentEnd); @@ -768,6 +793,8 @@ private: AtomArray _undefinedAtoms; AtomArray _sharedLibraryAtoms; AtomArray _absoluteAtoms; + const uint8_t* _absAttributes; + uint32_t _absAbsoluteMaxOffset; const uint8_t* _attributes; uint32_t _attributesMaxOffset; IvarArray _references; @@ -868,6 +895,9 @@ inline StringRef NativeAbsoluteAtomV1::name() const { return _file->string(_ivarData->nameOffset); } +inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const { + return _file->absAttribute(_ivarData->attributesOffset); +} inline const Atom* NativeReferenceV1::target() const { return _file->target(_ivarData->targetIndex); diff --git a/lld/lib/ReaderWriter/Native/WriterNative.cpp b/lld/lib/ReaderWriter/Native/WriterNative.cpp index 50969a6..615dfac 100644 --- a/lld/lib/ReaderWriter/Native/WriterNative.cpp +++ b/lld/lib/ReaderWriter/Native/WriterNative.cpp @@ -102,6 +102,11 @@ private: _absoluteAtomIvars.size() * sizeof(NativeAbsoluteAtomIvarsV1)); } + if (!_absAttributes.empty()) { + assert( out.tell() == findChunk(NCS_AbsoluteAttributesV1).fileOffset ); + out.write((char*)&_absAttributes[0], + _absAttributes.size()*sizeof(NativeAtomAttributesV1)); + } if (!_stringPool.empty()) { assert( out.tell() == findChunk(NCS_Strings).fileOffset ); @@ -164,6 +169,7 @@ private: _absoluteAtomIndex[&atom] = _absoluteAtomIvars.size(); NativeAbsoluteAtomIvarsV1 ivar; ivar.nameOffset = getNameOffset(atom); + ivar.attributesOffset = getAttributeOffset(atom); ivar.reserved = 0; ivar.value = atom.value(); _absoluteAtomIvars.push_back(ivar); @@ -184,7 +190,7 @@ private: if ( hasDefines ) chunkCount += 2; if ( hasUndefines ) ++chunkCount; if ( hasSharedLibraries ) ++chunkCount; - if ( hasAbsolutes ) ++chunkCount; + if ( hasAbsolutes ) chunkCount += 2; if ( hasReferences ) ++chunkCount; if ( hasTargetsTable ) ++chunkCount; if ( hasAddendTable ) ++chunkCount; @@ -247,13 +253,21 @@ private: // create chunk for shared library atom array if ( hasAbsolutes ) { - NativeChunk& chsl = chunks[nextIndex++]; - chsl.signature = NCS_AbsoluteAtomsV1; - chsl.fileOffset = nextFileOffset; - chsl.fileSize = _absoluteAtomIvars.size() * + NativeChunk& chabs = chunks[nextIndex++]; + chabs.signature = NCS_AbsoluteAtomsV1; + chabs.fileOffset = nextFileOffset; + chabs.fileSize = _absoluteAtomIvars.size() * sizeof(NativeAbsoluteAtomIvarsV1); - chsl.elementCount = _absoluteAtomIvars.size(); - nextFileOffset = chsl.fileOffset + chsl.fileSize; + chabs.elementCount = _absoluteAtomIvars.size(); + nextFileOffset = chabs.fileOffset + chabs.fileSize; + + // create chunk for attributes + NativeChunk& cha = chunks[nextIndex++]; + cha.signature = NCS_AbsoluteAttributesV1; + cha.fileOffset = nextFileOffset; + cha.fileSize = _absAttributes.size()*sizeof(NativeAtomAttributesV1); + cha.elementCount = _absAttributes.size(); + nextFileOffset = cha.fileOffset + cha.fileSize; } // create chunk for symbol strings @@ -380,6 +394,21 @@ private: return result; } + uint32_t getAttributeOffset(const class AbsoluteAtom& atom) { + NativeAtomAttributesV1 attrs; + computeAbsoluteAttributes(atom, attrs); + for(unsigned int i=0; i < _absAttributes.size(); ++i) { + if ( !memcmp(&_absAttributes[i], &attrs, sizeof(NativeAtomAttributesV1)) ) { + // found that this set of attributes already used, so re-use + return i * sizeof(NativeAtomAttributesV1); + } + } + // append new attribute set to end + uint32_t result = _absAttributes.size() * sizeof(NativeAtomAttributesV1); + _absAttributes.push_back(attrs); + return result; + } + uint32_t sectionNameOffset(const class DefinedAtom& atom) { // if section based on content, then no custom section name available if ( atom.sectionChoice() == DefinedAtom::sectionBasedOnContent ) @@ -414,6 +443,11 @@ private: attrs.alias = atom.isAlias(); } + void computeAbsoluteAttributes(const class AbsoluteAtom& atom, + NativeAtomAttributesV1& attrs) { + attrs.scope = atom.scope(); + } + // add references for this atom in a contiguous block in NCS_ReferencesArrayV1 uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& count) { count = 0; @@ -528,6 +562,7 @@ private: std::vector _contentPool; std::vector _definedAtomIvars; std::vector _attributes; + std::vector _absAttributes; std::vector _undefinedAtomIvars; std::vector _sharedLibraryAtomIvars; std::vector _absoluteAtomIvars; diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp index 89ec2ff..4b1fd68 100644 --- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp @@ -39,6 +39,10 @@ public: return OwningFile; } + virtual Scope scope() const { + return scopeGlobal; + } + virtual llvm::StringRef name() const { return Name; } diff --git a/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp index 72536a4..bf8e70c 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp @@ -429,6 +429,10 @@ public: return _file; } + virtual Scope scope() const { + return scopeGlobal; + } + virtual StringRef name() const { return _name; } diff --git a/lld/lib/ReaderWriter/YAML/WriterYAML.cpp b/lld/lib/ReaderWriter/YAML/WriterYAML.cpp index 24582c6..76773b7 100644 --- a/lld/lib/ReaderWriter/YAML/WriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/WriterYAML.cpp @@ -412,6 +412,14 @@ public: << KeyValues::definition(atom.definition()) << "\n"; + if ( atom.scope() != KeyValues::scopeDefault ) { + out << " " + << "scope:" + << spacePadding(strlen("scope")) + << KeyValues::scope(atom.scope()) + << "\n"; + } + out << " " << "value:" << spacePadding(strlen("value")) diff --git a/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp b/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp index 46120ad..d464f92 100644 --- a/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp +++ b/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp @@ -75,10 +75,10 @@ struct ScopeMapping { }; static const ScopeMapping scopeMappings[] = { - { "global", DefinedAtom::scopeGlobal }, - { "hidden", DefinedAtom::scopeLinkageUnit }, - { "static", DefinedAtom::scopeTranslationUnit }, - { nullptr, DefinedAtom::scopeGlobal } + { "global", Atom::scopeGlobal }, + { "hidden", Atom::scopeLinkageUnit }, + { "static", Atom::scopeTranslationUnit }, + { nullptr, Atom::scopeGlobal } }; bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out) @@ -92,7 +92,7 @@ bool KeyValues::scope(StringRef s, DefinedAtom::Scope &out) return true; } -const char* KeyValues::scope(DefinedAtom::Scope s) { +const char* KeyValues::scope(Atom::Scope s) { for (const ScopeMapping* p = scopeMappings; p->string != nullptr; ++p) { if ( p->value == s ) return p->string; @@ -106,7 +106,6 @@ const char* KeyValues::scope(DefinedAtom::Scope s) { - struct ContentTypeMapping { const char* string; DefinedAtom::ContentType value; diff --git a/lld/lib/ReaderWriter/YAML/YamlKeyValues.h b/lld/lib/ReaderWriter/YAML/YamlKeyValues.h index 9f0e964..3d099da 100644 --- a/lld/lib/ReaderWriter/YAML/YamlKeyValues.h +++ b/lld/lib/ReaderWriter/YAML/YamlKeyValues.h @@ -29,7 +29,7 @@ public: static const char* const scopeKeyword; static const DefinedAtom::Scope scopeDefault; static bool scope(StringRef, DefinedAtom::Scope&); - static const char* scope(DefinedAtom::Scope); + static const char* scope(Atom::Scope); static const char* const contentTypeKeyword; static const DefinedAtom::ContentType contentTypeDefault; diff --git a/lld/test/elf/Inputs/abs-test.i386 b/lld/test/elf/Inputs/abs-test.i386 new file mode 100644 index 0000000000000000000000000000000000000000..8556c24da551a11bc720dc92f1634e29f33b05c0 GIT binary patch literal 504 zcma)3I}XAy41J+|C6MUM0uv0V6ITG1Zd{-VMPg`GiDYOeuE{kx0oZ9m%Ycd{=lLZs z&sK8Z#|I$QA z-LJVuU2UvrWnEBH{L-!IeEf$lY-!k%{kB}V@NdD`^P7YvZ6t&|?|_o$n^R6G{cKd? xLAoUuF4(6lzJGxI+MStu#nf5}JYU=!nAtTX4yklpoMm>Za#dtZk6EEU{0+3?Bf