diff options
author | Nick Kledzik <kledzik@apple.com> | 2012-02-22 21:56:59 +0000 |
---|---|---|
committer | Nick Kledzik <kledzik@apple.com> | 2012-02-22 21:56:59 +0000 |
commit | 6bc04c6904971cbbf61cc5d01a258cdab5ba5421 (patch) | |
tree | 4099b3078ee4e30d3a39e39b519bc0abd45f13bd /lld/lib | |
parent | 1a3c3d45374a74b753373747b9a326a3360c3ac4 (diff) | |
download | bcm5719-llvm-6bc04c6904971cbbf61cc5d01a258cdab5ba5421.tar.gz bcm5719-llvm-6bc04c6904971cbbf61cc5d01a258cdab5ba5421.zip |
Add support for SharedLibraryAtoms (proxy atoms for exported symbols from a
shared library) and AbsoluteAtoms (proxy atoms for absolute address (e.g. ROM)).
Redesign weak importing as can-be-null-at-runtime and can-be-null-at-build-time.
Add lots of test cases for all the above.
llvm-svn: 151204
Diffstat (limited to 'lld/lib')
-rw-r--r-- | lld/lib/Core/NativeFileFormat.h | 35 | ||||
-rw-r--r-- | lld/lib/Core/NativeReader.cpp | 207 | ||||
-rw-r--r-- | lld/lib/Core/NativeWriter.cpp | 185 | ||||
-rw-r--r-- | lld/lib/Core/Resolver.cpp | 18 | ||||
-rw-r--r-- | lld/lib/Core/SymbolTable.cpp | 56 | ||||
-rw-r--r-- | lld/lib/Core/YamlKeyValues.cpp | 39 | ||||
-rw-r--r-- | lld/lib/Core/YamlKeyValues.h | 11 | ||||
-rw-r--r-- | lld/lib/Core/YamlReader.cpp | 183 | ||||
-rw-r--r-- | lld/lib/Core/YamlWriter.cpp | 129 |
9 files changed, 736 insertions, 127 deletions
diff --git a/lld/lib/Core/NativeFileFormat.h b/lld/lib/Core/NativeFileFormat.h index 91996983c6e..9066f471674 100644 --- a/lld/lib/Core/NativeFileFormat.h +++ b/lld/lib/Core/NativeFileFormat.h @@ -90,12 +90,14 @@ enum NativeChunkSignatures { NCS_DefinedAtomsV1 = 1, NCS_AttributesArrayV1 = 2, NCS_UndefinedAtomsV1 = 3, - NCS_Strings = 4, - NCS_ReferencesArrayV1 = 5, - NCS_ReferencesArrayV2 = 6, - NCS_TargetsTable = 7, - NCS_AddendsTable = 8, - NCS_Content = 9, + NCS_SharedLibraryAtomsV1 = 4, + NCS_AbsoluteAtomsV1 = 5, + NCS_Strings = 6, + NCS_ReferencesArrayV1 = 7, + NCS_ReferencesArrayV2 = 8, + NCS_TargetsTable = 9, + NCS_AddendsTable = 10, + NCS_Content = 11, }; // @@ -165,6 +167,27 @@ struct NativeUndefinedAtomIvarsV1 { +// +// The NCS_SharedLibraryAtomsV1 chunk contains an array of these structs +// +struct NativeSharedLibraryAtomIvarsV1 { + uint32_t nameOffset; + uint32_t loadNameOffset; + uint32_t flags; +}; + + + +// +// The NCS_AbsoluteAtomsV1 chunk contains an array of these structs +// +struct NativeAbsoluteAtomIvarsV1 { + uint32_t nameOffset; + uint32_t reserved; + uint64_t value; +}; + + // // The NCS_ReferencesArrayV1 chunk contains an array of these structs diff --git a/lld/lib/Core/NativeReader.cpp b/lld/lib/Core/NativeReader.cpp index bc86d19c13b..e85d2ff825b 100644 --- a/lld/lib/Core/NativeReader.cpp +++ b/lld/lib/Core/NativeReader.cpp @@ -77,7 +77,7 @@ public: virtual DefinedAtom::DeadStripKind deadStrip() const { return (DefinedAtom::DeadStripKind)(attributes().deadStrip); - } + } virtual DefinedAtom::ContentPermissions permissions() const { return (DefinedAtom::ContentPermissions)(attributes().permissions); @@ -117,16 +117,64 @@ public: virtual const File& file() const; virtual llvm::StringRef name() const; - virtual bool weakImport() const { - return (_ivarData->flags & 0x1); + virtual CanBeNull canBeNull() const { + return (CanBeNull)(_ivarData->flags & 0x3); } + private: const NativeFile* _file; const NativeUndefinedAtomIvarsV1* _ivarData; }; +// +// An object of this class is instantied for each NativeUndefinedAtomIvarsV1 +// struct in the NCS_SharedLibraryAtomsV1 chunk. +// +class NativeSharedLibraryAtomV1 : public SharedLibraryAtom { +public: + NativeSharedLibraryAtomV1(const NativeFile& f, + const NativeSharedLibraryAtomIvarsV1* ivarData) + : _file(&f), _ivarData(ivarData) { } + + virtual const File& file() const; + virtual llvm::StringRef name() const; + virtual llvm::StringRef loadName() const; + + virtual bool canBeNullAtRuntime() const { + return (_ivarData->flags & 0x1); + } + +private: + const NativeFile* _file; + const NativeSharedLibraryAtomIvarsV1* _ivarData; +}; + + +// +// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1 +// struct in the NCS_AbsoluteAtomsV1 chunk. +// +class NativeAbsoluteAtomV1 : public AbsoluteAtom { +public: + NativeAbsoluteAtomV1(const NativeFile& f, + const NativeAbsoluteAtomIvarsV1* ivarData) + : _file(&f), _ivarData(ivarData) { } + + virtual const File& file() const; + virtual llvm::StringRef name() const; + + virtual uint64_t value() const { + return _ivarData->value; + } + +private: + const NativeFile* _file; + const NativeAbsoluteAtomIvarsV1* _ivarData; +}; + + // // An object of this class is instantied for each NativeReferenceIvarsV1 @@ -206,6 +254,12 @@ public: case NCS_UndefinedAtomsV1: ec = file->processUndefinedAtomsV1(base, chunk); break; + case NCS_SharedLibraryAtomsV1: + ec = file->processSharedLibraryAtomsV1(base, chunk); + break; + case NCS_AbsoluteAtomsV1: + ec = file->processAbsoluteAtomsV1(base, chunk); + break; case NCS_ReferencesArrayV1: ec = file->processReferencesV1(base, chunk); break; @@ -247,23 +301,45 @@ public: // to just delete the memory. delete _definedAtoms.arrayStart; delete _undefinedAtoms.arrayStart; + delete _sharedLibraryAtoms.arrayStart; + delete _absoluteAtoms.arrayStart; delete _references.arrayStart; delete _targetsTable; } // visits each atom in the file virtual bool forEachAtom(AtomHandler& handler) const { + bool didSomething = false; for(const uint8_t* p=_definedAtoms.arrayStart; p != _definedAtoms.arrayEnd; p += _definedAtoms.elementSize) { const DefinedAtom* atom = reinterpret_cast<const DefinedAtom*>(p); handler.doDefinedAtom(*atom); + didSomething = true; } - for(const uint8_t* p=_undefinedAtoms.arrayStart; p != _undefinedAtoms.arrayEnd; - p += _undefinedAtoms.elementSize) { + for(const uint8_t* p=_undefinedAtoms.arrayStart; + p != _undefinedAtoms.arrayEnd; + p += _undefinedAtoms.elementSize) { const UndefinedAtom* atom = reinterpret_cast<const UndefinedAtom*>(p); handler.doUndefinedAtom(*atom); + didSomething = true; + } + for(const uint8_t* p=_sharedLibraryAtoms.arrayStart; + p != _sharedLibraryAtoms.arrayEnd; + p += _sharedLibraryAtoms.elementSize) { + const SharedLibraryAtom* atom + = reinterpret_cast<const SharedLibraryAtom*>(p); + handler.doSharedLibraryAtom(*atom); + didSomething = true; + } + for(const uint8_t* p=_absoluteAtoms.arrayStart; + p != _absoluteAtoms.arrayEnd; + p += _absoluteAtoms.elementSize) { + const AbsoluteAtom* atom + = reinterpret_cast<const AbsoluteAtom*>(p); + handler.doAbsoluteAtom(*atom); + didSomething = true; } - return (_definedAtoms.arrayStart != _definedAtoms.arrayEnd); + return didSomething; } // not used @@ -275,6 +351,8 @@ public: private: friend class NativeDefinedAtomV1; friend class NativeUndefinedAtomV1; + friend class NativeSharedLibraryAtomV1; + friend class NativeAbsoluteAtomV1; friend class NativeReferenceV1; // instantiate array of DefinedAtoms from v1 ivar data in file @@ -308,12 +386,14 @@ private: } // set up pointers to attributes array - llvm::error_code processAttributesV1(const uint8_t* base, const NativeChunk* chunk) { + llvm::error_code processAttributesV1(const uint8_t* base, + const NativeChunk* chunk) { this->_attributes = base + chunk->fileOffset; this->_attributesMaxOffset = chunk->fileSize; return make_error_code(native_reader_error::success); } + // instantiate array of UndefinedAtoms from v1 ivar data in file llvm::error_code processUndefinedAtomsV1(const uint8_t* base, const NativeChunk* chunk) { const size_t atomSize = sizeof(NativeUndefinedAtomV1); @@ -344,6 +424,70 @@ private: } + // instantiate array of ShareLibraryAtoms from v1 ivar data in file + llvm::error_code processSharedLibraryAtomsV1(const uint8_t* base, + const NativeChunk* chunk) { + const size_t atomSize = sizeof(NativeSharedLibraryAtomV1); + size_t atomsArraySize = chunk->elementCount * atomSize; + uint8_t* atomsStart = reinterpret_cast<uint8_t*> + (operator new(atomsArraySize, std::nothrow)); + if (atomsStart == NULL ) + return make_error_code(native_reader_error::memory_error); + const size_t ivarElementSize = chunk->fileSize + / chunk->elementCount; + if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) ) + return make_error_code(native_reader_error::file_malformed); + uint8_t* atomsEnd = atomsStart + atomsArraySize; + const NativeSharedLibraryAtomIvarsV1* ivarData = + reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*> + (base + chunk->fileOffset); + for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) { + NativeSharedLibraryAtomV1* atomAllocSpace = + reinterpret_cast<NativeSharedLibraryAtomV1*>(s); + new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData); + ++ivarData; + } + this->_sharedLibraryAtoms.arrayStart = atomsStart; + this->_sharedLibraryAtoms.arrayEnd = atomsEnd; + this->_sharedLibraryAtoms.elementSize = atomSize; + this->_sharedLibraryAtoms.elementCount = chunk->elementCount; + return make_error_code(native_reader_error::success); + } + + + // instantiate array of AbsoluteAtoms from v1 ivar data in file + llvm::error_code processAbsoluteAtomsV1(const uint8_t* base, + const NativeChunk* chunk) { + const size_t atomSize = sizeof(NativeAbsoluteAtomV1); + size_t atomsArraySize = chunk->elementCount * atomSize; + uint8_t* atomsStart = reinterpret_cast<uint8_t*> + (operator new(atomsArraySize, std::nothrow)); + if (atomsStart == NULL ) + return make_error_code(native_reader_error::memory_error); + const size_t ivarElementSize = chunk->fileSize + / chunk->elementCount; + if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) ) + return make_error_code(native_reader_error::file_malformed); + uint8_t* atomsEnd = atomsStart + atomsArraySize; + const NativeAbsoluteAtomIvarsV1* ivarData = + reinterpret_cast<const NativeAbsoluteAtomIvarsV1*> + (base + chunk->fileOffset); + for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) { + NativeAbsoluteAtomV1* atomAllocSpace = + reinterpret_cast<NativeAbsoluteAtomV1*>(s); + new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData); + ++ivarData; + } + this->_absoluteAtoms.arrayStart = atomsStart; + this->_absoluteAtoms.arrayEnd = atomsEnd; + this->_absoluteAtoms.elementSize = atomSize; + this->_absoluteAtoms.elementCount = chunk->elementCount; + return make_error_code(native_reader_error::success); + } + + + + // instantiate array of Referemces from v1 ivar data in file llvm::error_code processReferencesV1(const uint8_t* base, const NativeChunk* chunk) { @@ -398,7 +542,24 @@ private: this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p); continue; } - return make_error_code(native_reader_error::file_malformed); + const uint32_t slIndex = index - _definedAtoms.elementCount + - _undefinedAtoms.elementCount; + if ( slIndex < _sharedLibraryAtoms.elementCount ) { + const uint8_t* p = _sharedLibraryAtoms.arrayStart + + slIndex * _sharedLibraryAtoms.elementSize; + this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p); + continue; + } + const uint32_t abIndex = index - _definedAtoms.elementCount + - _undefinedAtoms.elementCount + - _sharedLibraryAtoms.elementCount; + if ( abIndex < _absoluteAtoms.elementCount ) { + const uint8_t* p = _absoluteAtoms.arrayStart + + slIndex * _absoluteAtoms.elementSize; + this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p); + continue; + } + return make_error_code(native_reader_error::file_malformed); } return make_error_code(native_reader_error::success); } @@ -491,7 +652,8 @@ private: _contentStart(NULL), _contentEnd(NULL) { - _header = reinterpret_cast<const NativeFileHeader*>(_buffer->getBufferStart()); + _header = reinterpret_cast<const NativeFileHeader*> + (_buffer->getBufferStart()); } struct IvarArray { @@ -507,6 +669,8 @@ private: const NativeFileHeader* _header; IvarArray _definedAtoms; IvarArray _undefinedAtoms; + IvarArray _sharedLibraryAtoms; + IvarArray _absoluteAtoms; const uint8_t* _attributes; uint32_t _attributesMaxOffset; IvarArray _references; @@ -567,6 +731,31 @@ inline llvm::StringRef NativeUndefinedAtomV1::name() const { } + + +inline const class File& NativeSharedLibraryAtomV1::file() const { + return *_file; +} + +inline llvm::StringRef NativeSharedLibraryAtomV1::name() const { + return _file->string(_ivarData->nameOffset); +} + +inline llvm::StringRef NativeSharedLibraryAtomV1::loadName() const { + return _file->string(_ivarData->loadNameOffset); +} + + + +inline const class File& NativeAbsoluteAtomV1::file() const { + return *_file; +} + +inline llvm::StringRef NativeAbsoluteAtomV1::name() const { + return _file->string(_ivarData->nameOffset); +} + + inline const Atom* NativeReferenceV1::target() const { return _file->target(_ivarData->targetIndex); } diff --git a/lld/lib/Core/NativeWriter.cpp b/lld/lib/Core/NativeWriter.cpp index da877fd652c..a95a5149808 100644 --- a/lld/lib/Core/NativeWriter.cpp +++ b/lld/lib/Core/NativeWriter.cpp @@ -61,7 +61,21 @@ public: out.write((char*)&_undefinedAtomIvars[0], _undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1)); } - + + if ( !_sharedLibraryAtomIvars.empty() ) { + assert( out.tell() == findChunk(NCS_SharedLibraryAtomsV1).fileOffset ); + out.write((char*)&_sharedLibraryAtomIvars[0], + _sharedLibraryAtomIvars.size() + * sizeof(NativeSharedLibraryAtomIvarsV1)); + } + + if ( !_absoluteAtomIvars.empty() ) { + assert( out.tell() == findChunk(NCS_AbsoluteAtomsV1).fileOffset ); + out.write((char*)&_absoluteAtomIvars[0], + _absoluteAtomIvars.size() + * sizeof(NativeAbsoluteAtomIvarsV1)); + } + if (!_stringPool.empty()) { assert( out.tell() == findChunk(NCS_Strings).fileOffset ); out.write(&_stringPool[0], _stringPool.size()); @@ -110,23 +124,55 @@ private: _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size(); NativeUndefinedAtomIvarsV1 ivar; ivar.nameOffset = getNameOffset(atom); - ivar.flags = (atom.weakImport() ? 1 : 0); + ivar.flags = (atom.canBeNull() & 0x03); _undefinedAtomIvars.push_back(ivar); } // visitor routine called by forEachAtom() + virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) { + _sharedLibraryAtomIndex[&atom] = _sharedLibraryAtomIvars.size(); + NativeSharedLibraryAtomIvarsV1 ivar; + ivar.nameOffset = getNameOffset(atom); + ivar.loadNameOffset = getSharedLibraryNameOffset(atom.loadName()); + ivar.flags = atom.canBeNullAtRuntime(); + _sharedLibraryAtomIvars.push_back(ivar); + } + + // visitor routine called by forEachAtom() + virtual void doAbsoluteAtom(const AbsoluteAtom& atom) { + _absoluteAtomIndex[&atom] = _absoluteAtomIvars.size(); + NativeAbsoluteAtomIvarsV1 ivar; + ivar.nameOffset = getNameOffset(atom); + ivar.reserved = 0; + ivar.value = atom.value(); + _absoluteAtomIvars.push_back(ivar); + } + + // visitor routine called by forEachAtom() virtual void doFile(const File &) { } // fill out native file header and chunk directory void makeHeader() { + const bool hasDefines = !_definedAtomIvars.empty(); const bool hasUndefines = !_undefinedAtomIvars.empty(); + const bool hasSharedLibraries = !_sharedLibraryAtomIvars.empty(); + const bool hasAbsolutes = !_absoluteAtomIvars.empty(); + const bool hasReferences = !_references.empty(); const bool hasTargetsTable = !_targetsTableIndex.empty(); const bool hasAddendTable = !_addendsTableIndex.empty(); - int chunkCount = 5; + const bool hasContent = !_contentPool.empty(); + + int chunkCount = 1; // always have string pool chunk + if ( hasDefines ) chunkCount += 2; if ( hasUndefines ) ++chunkCount; + if ( hasSharedLibraries ) ++chunkCount; + if ( hasAbsolutes ) ++chunkCount; + if ( hasReferences ) ++chunkCount; if ( hasTargetsTable ) ++chunkCount; if ( hasAddendTable ) ++chunkCount; + if ( hasContent ) ++chunkCount; + _headerBufferSize = sizeof(NativeFileHeader) + chunkCount*sizeof(NativeChunk); _headerBuffer = reinterpret_cast<NativeFileHeader*> @@ -140,23 +186,25 @@ private: _headerBuffer->fileSize = 0; _headerBuffer->chunkCount = chunkCount; - - // create chunk for atom ivar array + // create chunk for defined atom ivar array int nextIndex = 0; - NativeChunk& chd = chunks[nextIndex++]; - chd.signature = NCS_DefinedAtomsV1; - chd.fileOffset = _headerBufferSize; - chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1); - chd.elementCount = _definedAtomIvars.size(); - uint32_t nextFileOffset = chd.fileOffset + chd.fileSize; - - // create chunk for attributes - NativeChunk& cha = chunks[nextIndex++]; - cha.signature = NCS_AttributesArrayV1; - cha.fileOffset = nextFileOffset; - cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1); - cha.elementCount = _attributes.size(); - nextFileOffset = cha.fileOffset + cha.fileSize; + uint32_t nextFileOffset = _headerBufferSize; + if ( hasDefines ) { + NativeChunk& chd = chunks[nextIndex++]; + chd.signature = NCS_DefinedAtomsV1; + chd.fileOffset = nextFileOffset; + chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1); + chd.elementCount = _definedAtomIvars.size(); + nextFileOffset = chd.fileOffset + chd.fileSize; + + // create chunk for attributes + NativeChunk& cha = chunks[nextIndex++]; + cha.signature = NCS_AttributesArrayV1; + cha.fileOffset = nextFileOffset; + cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1); + cha.elementCount = _attributes.size(); + nextFileOffset = cha.fileOffset + cha.fileSize; + } // create chunk for undefined atom array if ( hasUndefines ) { @@ -169,6 +217,28 @@ private: nextFileOffset = chu.fileOffset + chu.fileSize; } + // create chunk for shared library atom array + if ( hasSharedLibraries ) { + NativeChunk& chsl = chunks[nextIndex++]; + chsl.signature = NCS_SharedLibraryAtomsV1; + chsl.fileOffset = nextFileOffset; + chsl.fileSize = _sharedLibraryAtomIvars.size() * + sizeof(NativeSharedLibraryAtomIvarsV1); + chsl.elementCount = _sharedLibraryAtomIvars.size(); + nextFileOffset = chsl.fileOffset + chsl.fileSize; + } + + // create chunk for shared library atom array + if ( hasAbsolutes ) { + NativeChunk& chsl = chunks[nextIndex++]; + chsl.signature = NCS_AbsoluteAtomsV1; + chsl.fileOffset = nextFileOffset; + chsl.fileSize = _absoluteAtomIvars.size() * + sizeof(NativeAbsoluteAtomIvarsV1); + chsl.elementCount = _absoluteAtomIvars.size(); + nextFileOffset = chsl.fileOffset + chsl.fileSize; + } + // create chunk for symbol strings // pad end of string pool to 4-bytes while ( (_stringPool.size() % 4) != 0 ) @@ -181,13 +251,15 @@ private: nextFileOffset = chs.fileOffset + chs.fileSize; // create chunk for references - NativeChunk& chr = chunks[nextIndex++]; - chr.signature = NCS_ReferencesArrayV1; - chr.fileOffset = nextFileOffset; - chr.fileSize = _references.size() * sizeof(NativeReferenceIvarsV1); - chr.elementCount = _references.size(); - nextFileOffset = chr.fileOffset + chr.fileSize; - + if ( hasReferences ) { + NativeChunk& chr = chunks[nextIndex++]; + chr.signature = NCS_ReferencesArrayV1; + chr.fileOffset = nextFileOffset; + chr.fileSize = _references.size() * sizeof(NativeReferenceIvarsV1); + chr.elementCount = _references.size(); + nextFileOffset = chr.fileOffset + chr.fileSize; + } + // create chunk for target table if ( hasTargetsTable ) { NativeChunk& cht = chunks[nextIndex++]; @@ -209,13 +281,15 @@ private: } // create chunk for content - NativeChunk& chc = chunks[nextIndex++]; - chc.signature = NCS_Content; - chc.fileOffset = nextFileOffset; - chc.fileSize = _contentPool.size(); - chc.elementCount = _contentPool.size(); - nextFileOffset = chc.fileOffset + chc.fileSize; - + if ( hasContent ) { + NativeChunk& chc = chunks[nextIndex++]; + chc.signature = NCS_Content; + chc.fileOffset = nextFileOffset; + chc.fileSize = _contentPool.size(); + chc.elementCount = _contentPool.size(); + nextFileOffset = chc.fileOffset + chc.fileSize; + } + _headerBuffer->fileSize = nextFileOffset; } @@ -237,7 +311,23 @@ private: return this->getNameOffset(atom.name()); } - // append atom name to string pool and return offset + // check if name is already in pool or append and return offset + uint32_t getSharedLibraryNameOffset(llvm::StringRef name) { + assert( ! name.empty() ); + // look to see if this library name was used by another atom + for(NameToOffsetVector::iterator it = _sharedLibraryNames.begin(); + it != _sharedLibraryNames.end(); ++it) { + if ( name.equals(it->first) ) + return it->second; + } + // first use of this library name + uint32_t result = this->getNameOffset(name); + _sharedLibraryNames.push_back( + std::make_pair<llvm::StringRef, uint32_t>(name, result)); + return result; + } + + // append atom name to string pool and return offset uint32_t getNameOffset(llvm::StringRef name) { if ( name.empty() ) return 0; @@ -356,8 +446,26 @@ private: } else { pos = _undefinedAtomIndex.find(atom); - assert(pos != _undefinedAtomIndex.end()); - atomIndex = pos->second + _definedAtomIvars.size(); + if ( pos != _undefinedAtomIndex.end() ) { + atomIndex = pos->second + _definedAtomIvars.size(); + } + else { + pos = _sharedLibraryAtomIndex.find(atom); + if ( pos != _sharedLibraryAtomIndex.end() ) { + assert(pos != _sharedLibraryAtomIndex.end()); + atomIndex = pos->second + + _definedAtomIvars.size() + + _undefinedAtomIndex.size(); + } + else { + pos = _absoluteAtomIndex.find(atom); + assert(pos != _absoluteAtomIndex.end()); + atomIndex = pos->second + + _definedAtomIvars.size() + + _undefinedAtomIndex.size() + + _sharedLibraryAtomIndex.size(); + } + } } targetIndexes[targetIndex] = atomIndex; } @@ -405,12 +513,17 @@ private: std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars; std::vector<NativeAtomAttributesV1> _attributes; std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars; + std::vector<NativeSharedLibraryAtomIvarsV1> _sharedLibraryAtomIvars; + std::vector<NativeAbsoluteAtomIvarsV1> _absoluteAtomIvars; std::vector<NativeReferenceIvarsV1> _references; TargetToIndex _targetsTableIndex; TargetToIndex _definedAtomIndex; TargetToIndex _undefinedAtomIndex; + TargetToIndex _sharedLibraryAtomIndex; + TargetToIndex _absoluteAtomIndex; AddendToIndex _addendsTableIndex; NameToOffsetVector _sectionNames; + NameToOffsetVector _sharedLibraryNames; }; diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp index 68f4ba5b4f8..92c15f0af50 100644 --- a/lld/lib/Core/Resolver.cpp +++ b/lld/lib/Core/Resolver.cpp @@ -134,6 +134,24 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) { } } +void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) { + // add to list of known atoms + _atoms.push_back(&atom); + + // tell symbol table + _symbolTable.add(atom); +} + +void Resolver::doAbsoluteAtom(const AbsoluteAtom& atom) { + // add to list of known atoms + _atoms.push_back(&atom); + + // tell symbol table + _symbolTable.add(atom); +} + + + // utility to add a vector of atoms void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) { for (std::vector<const DefinedAtom *>::const_iterator it = newAtoms.begin(); diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp index cc4c935eb89..4dc86b76250 100644 --- a/lld/lib/Core/SymbolTable.cpp +++ b/lld/lib/Core/SymbolTable.cpp @@ -11,10 +11,11 @@ #include "lld/Core/Atom.h" #include "lld/Core/DefinedAtom.h" #include "lld/Core/UndefinedAtom.h" +#include "lld/Core/SharedLibraryAtom.h" +#include "lld/Core/AbsoluteAtom.h" #include "lld/Core/File.h" #include "lld/Core/InputFiles.h" #include "lld/Core/Resolver.h" -#include "lld/Core/UndefinedAtom.h" #include "lld/Platform/Platform.h" #include "llvm/Support/ErrorHandling.h" @@ -36,6 +37,14 @@ void SymbolTable::add(const UndefinedAtom &atom) { this->addByName(atom); } +void SymbolTable::add(const SharedLibraryAtom &atom) { + this->addByName(atom); +} + +void SymbolTable::add(const AbsoluteAtom &atom) { + this->addByName(atom); +} + void SymbolTable::add(const DefinedAtom &atom) { assert(atom.scope() != DefinedAtom::scopeTranslationUnit); if ( !atom.name().empty() ) { @@ -49,7 +58,9 @@ void SymbolTable::add(const DefinedAtom &atom) { enum NameCollisionResolution { NCR_First, NCR_Second, - NCR_Dup, + NCR_DupDef, + NCR_DupUndef, + NCR_DupShLib, NCR_Error }; @@ -57,7 +68,7 @@ static NameCollisionResolution cases[4][4] = { //regular absolute undef sharedLib { // first is regular - NCR_Dup, NCR_Error, NCR_First, NCR_First + NCR_DupDef, NCR_Error, NCR_First, NCR_First }, { // first is absolute @@ -65,11 +76,11 @@ static NameCollisionResolution cases[4][4] = { }, { // first is undef - NCR_Second, NCR_Second, NCR_First, NCR_Second + NCR_Second, NCR_Second, NCR_DupUndef, NCR_Second }, { // first is sharedLib - NCR_Second, NCR_Second, NCR_First, NCR_First + NCR_Second, NCR_Second, NCR_First, NCR_DupShLib } }; @@ -129,7 +140,7 @@ void SymbolTable::addByName(const Atom & newAtom) { case NCR_Second: useNew = true; break; - case NCR_Dup: + case NCR_DupDef: assert(existing->definition() == Atom::definitionRegular); assert(newAtom.definition() == Atom::definitionRegular); switch ( mergeSelect(((DefinedAtom*)existing)->merge(), @@ -148,6 +159,39 @@ void SymbolTable::addByName(const Atom & newAtom) { break; } break; + case NCR_DupUndef: { + const UndefinedAtom* existingUndef = existing->undefinedAtom(); + const UndefinedAtom* newUndef = newAtom.undefinedAtom(); + assert(existingUndef != NULL); + assert(newUndef != NULL); + if ( existingUndef->canBeNull() == newUndef->canBeNull() ) { + useNew = false; + } + else { + useNew = (newUndef->canBeNull() < existingUndef->canBeNull()); + // give platform a change to override which to use + _platform.undefineCanBeNullMismatch(*existingUndef, + *newUndef, useNew); + } + } + break; + case NCR_DupShLib: { + const SharedLibraryAtom* existingShLib = existing->sharedLibraryAtom(); + const SharedLibraryAtom* newShLib = newAtom.sharedLibraryAtom(); + assert(existingShLib != NULL); + assert(newShLib != NULL); + if ( (existingShLib->canBeNullAtRuntime() + == newShLib->canBeNullAtRuntime()) && + existingShLib->loadName().equals(newShLib->loadName()) ) { + useNew = false; + } + else { + useNew = false; // use existing shared library by default + // give platform a change to override which to use + _platform.sharedLibrarylMismatch(*existingShLib, *newShLib, useNew); + } + } + break; default: llvm::report_fatal_error("SymbolTable::addByName(): unhandled switch clause"); } diff --git a/lld/lib/Core/YamlKeyValues.cpp b/lld/lib/Core/YamlKeyValues.cpp index bb32aa88489..6e49580ce69 100644 --- a/lld/lib/Core/YamlKeyValues.cpp +++ b/lld/lib/Core/YamlKeyValues.cpp @@ -30,10 +30,12 @@ const char* const KeyValues::isThumbKeyword = "is-thumb"; const char* const KeyValues::isAliasKeyword = "is-alias"; const char* const KeyValues::sectionNameKeyword = "section-name"; const char* const KeyValues::contentKeyword = "content"; +const char* const KeyValues::loadNameKeyword = "load-name"; const char* const KeyValues::sizeKeyword = "size"; +const char* const KeyValues::valueKeyword = "value"; const char* const KeyValues::fixupsKeyword = "fixups"; const char* const KeyValues::permissionsKeyword = "permissions"; -const char* const KeyValues::weakImportKeyword = "weak-import"; +const char* const KeyValues::canBeNullKeyword = "can-be-null"; const char* const KeyValues::fixupsKindKeyword = "kind"; const char* const KeyValues::fixupsOffsetKeyword = "offset"; const char* const KeyValues::fixupsTargetKeyword = "target"; @@ -51,7 +53,7 @@ const DefinedAtom::Merge KeyValues::mergeDefault = DefinedAtom::mer const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__; const bool KeyValues::isThumbDefault = false; const bool KeyValues::isAliasDefault = false; -const bool KeyValues::weakImportDefault = false; +const UndefinedAtom::CanBeNull KeyValues::canBeNullDefault = UndefinedAtom::canBeNullNever; @@ -389,17 +391,34 @@ const char* KeyValues::isAlias(bool b) { -bool KeyValues::weakImport(const char* s) +struct CanBeNullMapping { + const char* string; + UndefinedAtom::CanBeNull value; +}; + +static const CanBeNullMapping cbnMappings[] = { + { "never", UndefinedAtom::canBeNullNever }, + { "at-runtime", UndefinedAtom::canBeNullAtRuntime }, + { "at-buildtime", UndefinedAtom::canBeNullAtBuildtime }, + { NULL, UndefinedAtom::canBeNullNever } +}; + + +UndefinedAtom::CanBeNull KeyValues::canBeNull(const char* s) { - if ( strcmp(s, "true") == 0 ) - return true; - else if ( strcmp(s, "false") == 0 ) - return false; - llvm::report_fatal_error("bad weak-import value"); + for (const CanBeNullMapping* p = cbnMappings; p->string != NULL; ++p) { + if ( strcmp(p->string, s) == 0 ) + return p->value; + } + llvm::report_fatal_error("bad can-be-null value"); } -const char* KeyValues::weakImport(bool b) { - return b ? "true" : "false"; +const char* KeyValues::canBeNull(UndefinedAtom::CanBeNull c) { + for (const CanBeNullMapping* p = cbnMappings; p->string != NULL; ++p) { + if ( p->value == c ) + return p->string; + } + llvm::report_fatal_error("bad can-be-null value"); } diff --git a/lld/lib/Core/YamlKeyValues.h b/lld/lib/Core/YamlKeyValues.h index 6cd0908c855..c9dac2a6465 100644 --- a/lld/lib/Core/YamlKeyValues.h +++ b/lld/lib/Core/YamlKeyValues.h @@ -12,6 +12,7 @@ #include "lld/Core/Atom.h" #include "lld/Core/DefinedAtom.h" +#include "lld/Core/UndefinedAtom.h" namespace lld { @@ -24,6 +25,8 @@ public: static const char* const sectionNameKeyword; static const char* const contentKeyword; static const char* const sizeKeyword; + static const char* const loadNameKeyword; + static const char* const valueKeyword; static const char* const fixupsKeyword; static const char* const definitionKeyword; @@ -76,10 +79,10 @@ public: static bool isAlias(const char*); static const char* isAlias(bool); - static const char* const weakImportKeyword; - static const bool weakImportDefault; - static bool weakImport(const char*); - static const char* weakImport(bool); + static const char* const canBeNullKeyword; + static const UndefinedAtom::CanBeNull canBeNullDefault; + static UndefinedAtom::CanBeNull canBeNull(const char*); + static const char* canBeNull(UndefinedAtom::CanBeNull); static const char* const fixupsKindKeyword; diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp index d5e60eb2131..97642abeadf 100644 --- a/lld/lib/Core/YamlReader.cpp +++ b/lld/lib/Core/YamlReader.cpp @@ -13,6 +13,9 @@ #include "lld/Core/YamlReader.h" #include "lld/Core/Atom.h" +#include "lld/Core/UndefinedAtom.h" +#include "lld/Core/SharedLibraryAtom.h" +#include "lld/Core/AbsoluteAtom.h" #include "lld/Core/Error.h" #include "lld/Core/File.h" #include "lld/Core/Reference.h" @@ -200,9 +203,7 @@ void YAML::parse(llvm::MemoryBuffer *mb, std::vector<const Entry *> &entries) { } break; case inValue: - if (isalnum(c) || (c == '-') || (c == '_')) { - *p++ = c; - } else if (c == '\n') { + if (c == '\n') { *p = '\0'; entries.push_back(new Entry(key, value, NULL, depth, nextKeyIsStartOfDocument, @@ -212,6 +213,9 @@ void YAML::parse(llvm::MemoryBuffer *mb, std::vector<const Entry *> &entries) { state = inDocument; depth = 0; } + else { + *p++ = c; + } break; case inValueSequence: if (c == ']') { @@ -300,6 +304,8 @@ public: void bindTargetReferences(); void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName); void addUndefinedAtom(UndefinedAtom* atom); + void addSharedLibraryAtom(SharedLibraryAtom* atom); + void addAbsoluteAtom(AbsoluteAtom* atom); Atom* findAtom(const char* name); struct NameAtomPair { @@ -310,6 +316,8 @@ public: std::vector<YAMLDefinedAtom*> _definedAtoms; std::vector<UndefinedAtom*> _undefinedAtoms; + std::vector<SharedLibraryAtom*> _sharedLibraryAtoms; + std::vector<AbsoluteAtom*> _absoluteAtoms; std::vector<YAMLReference> _references; std::vector<NameAtomPair> _nameToAtomMapping; unsigned int _lastRefIndex; @@ -465,8 +473,38 @@ private: class YAMLUndefinedAtom : public UndefinedAtom { public: - YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm, bool wi) - : _file(f), _name(nm), _ordinal(ord), _weakImport(wi) { } + YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm, + UndefinedAtom::CanBeNull cbn) + : _file(f), _name(nm), _ordinal(ord), _canBeNull(cbn) { } + + virtual const class File& file() const { + return _file; + } + + virtual llvm::StringRef name() const { + return _name; + } + + virtual CanBeNull canBeNull() const { + return _canBeNull; + } + + +private: + YAMLFile& _file; + const char * _name; + uint32_t _ordinal; + UndefinedAtom::CanBeNull _canBeNull; +}; + + + +class YAMLSharedLibraryAtom : public SharedLibraryAtom { +public: + YAMLSharedLibraryAtom(YAMLFile& f, int32_t ord, const char* nm, + const char* ldnm, bool cbn) + : _file(f), _name(nm), _ordinal(ord), + _loadName(ldnm), _canBeNull(cbn) { } virtual const class File& file() const { return _file; @@ -476,18 +514,52 @@ public: return _name; } - virtual bool weakImport() const { - return _weakImport; + virtual llvm::StringRef loadName() const { + return _loadName; + } + + virtual bool canBeNullAtRuntime() const { + return _canBeNull; } + private: YAMLFile& _file; const char * _name; uint32_t _ordinal; - bool _weakImport; + const char * _loadName; + bool _canBeNull; +}; + + + +class YAMLAbsoluteAtom : public AbsoluteAtom { +public: + YAMLAbsoluteAtom(YAMLFile& f, int32_t ord, const char* nm, uint64_t v) + : _file(f), _name(nm), _ordinal(ord), _value(v) { } + + virtual const class File& file() const { + return _file; + } + + virtual llvm::StringRef name() const { + return _name; + } + + virtual uint64_t value() const { + return _value; + } + +private: + YAMLFile& _file; + const char * _name; + uint32_t _ordinal; + uint64_t _value; }; + + bool YAMLFile::forEachAtom(File::AtomHandler &handler) const { handler.doFile(*this); for (std::vector<YAMLDefinedAtom *>::const_iterator it = _definedAtoms.begin(); @@ -498,6 +570,17 @@ bool YAMLFile::forEachAtom(File::AtomHandler &handler) const { it != _undefinedAtoms.end(); ++it) { handler.doUndefinedAtom(**it); } + for (std::vector<SharedLibraryAtom *>::const_iterator + it = _sharedLibraryAtoms.begin(); + it != _sharedLibraryAtoms.end(); ++it) { + handler.doSharedLibraryAtom(**it); + } + for (std::vector<AbsoluteAtom *>::const_iterator + it = _absoluteAtoms.begin(); + it != _absoluteAtoms.end(); ++it) { + handler.doAbsoluteAtom(**it); + } + return true; } @@ -534,6 +617,16 @@ void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) { _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom)); } +void YAMLFile::addSharedLibraryAtom(SharedLibraryAtom* atom) { + _sharedLibraryAtoms.push_back(atom); + _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom)); +} + +void YAMLFile::addAbsoluteAtom(AbsoluteAtom* atom) { + _absoluteAtoms.push_back(atom); + _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom)); +} + class YAMLAtomState { public: @@ -544,9 +637,7 @@ public: void setAlign2(const char *n); void setFixupKind(const char *n); - void setFixupOffset(const char *n); void setFixupTarget(const char *n); - void setFixupAddend(const char *n); void addFixup(YAMLFile *f); void makeAtom(YAMLFile&); @@ -554,7 +645,9 @@ public: const char * _name; const char * _refName; const char * _sectionName; + const char* _loadName; unsigned long long _size; + uint64_t _value; uint32_t _ordinal; std::vector<uint8_t>* _content; DefinedAtom::Alignment _alignment; @@ -568,7 +661,7 @@ public: DefinedAtom::ContentPermissions _permissions; bool _isThumb; bool _isAlias; - bool _weakImport; + UndefinedAtom::CanBeNull _canBeNull; YAMLReference _ref; }; @@ -577,7 +670,9 @@ YAMLAtomState::YAMLAtomState() : _name(NULL) , _refName(NULL) , _sectionName(NULL) + , _loadName(NULL) , _size(0) + , _value(0) , _ordinal(0) , _content(NULL) , _alignment(0, 0) @@ -591,7 +686,7 @@ YAMLAtomState::YAMLAtomState() , _permissions(KeyValues::permissionsDefault) , _isThumb(KeyValues::isThumbDefault) , _isAlias(KeyValues::isAliasDefault) - , _weakImport(false) + , _canBeNull(KeyValues::canBeNullDefault) { } @@ -606,16 +701,30 @@ void YAMLAtomState::makeAtom(YAMLFile& f) { ++_ordinal; } else if ( _definition == Atom::definitionUndefined ) { - UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _weakImport); + UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _canBeNull); f.addUndefinedAtom(a); ++_ordinal; } - + else if ( _definition == Atom::definitionSharedLibrary ) { + bool nullable = (_canBeNull == UndefinedAtom::canBeNullAtRuntime); + SharedLibraryAtom *a = new YAMLSharedLibraryAtom(f, _ordinal, _name, + _loadName, nullable); + f.addSharedLibraryAtom(a); + ++_ordinal; + } + else if ( _definition == Atom::definitionAbsolute ) { + AbsoluteAtom *a = new YAMLAbsoluteAtom(f, _ordinal, _name, _value); + f.addAbsoluteAtom(a); + ++_ordinal; + } + // reset state for next atom _name = NULL; _refName = NULL; _sectionName = NULL; + _loadName = NULL; _size = 0; + _value = 0; _ordinal = 0; _content = NULL; _alignment.powerOf2= 0; @@ -630,7 +739,7 @@ void YAMLAtomState::makeAtom(YAMLFile& f) { _permissions = KeyValues::permissionsDefault; _isThumb = KeyValues::isThumbDefault; _isAlias = KeyValues::isAliasDefault; - _weakImport = KeyValues::weakImportDefault; + _canBeNull = KeyValues::canBeNullDefault; _ref._target = NULL; _ref._targetName = NULL; _ref._addend = 0; @@ -666,24 +775,10 @@ void YAMLAtomState::setFixupKind(const char *s) { } } -void YAMLAtomState::setFixupOffset(const char *s) { - if ((s[0] == '0') && (s[1] == 'x')) - llvm::StringRef(s).getAsInteger(16, _ref._offsetInAtom); - else - llvm::StringRef(s).getAsInteger(10, _ref._offsetInAtom); -} - void YAMLAtomState::setFixupTarget(const char *s) { _ref._targetName = s; } -void YAMLAtomState::setFixupAddend(const char *s) { - if ((s[0] == '0') && (s[1] == 'x')) - llvm::StringRef(s).getAsInteger(16, _ref._addend); - else - llvm::StringRef(s).getAsInteger(10, _ref._addend); -} - void YAMLAtomState::addFixup(YAMLFile *f) { f->_references.push_back(_ref); @@ -805,8 +900,12 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb atomState._isAlias = KeyValues::isAlias(entry->value); haveAtom = true; } - else if (strcmp(entry->key, KeyValues::weakImportKeyword) == 0) { - atomState._weakImport = KeyValues::weakImport(entry->value); + else if (strcmp(entry->key, KeyValues::canBeNullKeyword) == 0) { + atomState._canBeNull = KeyValues::canBeNull(entry->value); + if ( atomState._definition == Atom::definitionSharedLibrary ) { + if ( atomState._canBeNull == UndefinedAtom::canBeNullAtBuildtime ) + return make_error_code(yaml_reader_error::illegal_value); + } haveAtom = true; } else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) { @@ -829,7 +928,14 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb } else if (strcmp(entry->key, KeyValues::fixupsKeyword) == 0) { inFixups = true; - + } + else if (strcmp(entry->key, KeyValues::loadNameKeyword) == 0) { + atomState._loadName = entry->value; + haveAtom = true; + } + else if (strcmp(entry->key, KeyValues::valueKeyword) == 0) { + llvm::StringRef(entry->value).getAsInteger(0, atomState._value); + haveAtom = true; } else { return make_error_code(yaml_reader_error::unknown_keyword); @@ -847,7 +953,8 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb haveFixup = true; } else if (strcmp(entry->key, KeyValues::fixupsOffsetKeyword) == 0) { - atomState.setFixupOffset(entry->value); + llvm::StringRef(entry->value).getAsInteger(0, + atomState._ref._offsetInAtom); haveFixup = true; } else if (strcmp(entry->key, KeyValues::fixupsTargetKeyword) == 0) { @@ -855,7 +962,8 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb haveFixup = true; } else if (strcmp(entry->key, KeyValues::fixupsAddendKeyword) == 0) { - atomState.setFixupAddend(entry->value); + llvm::StringRef(entry->value).getAsInteger(0, + atomState._ref._addend); haveFixup = true; } } @@ -865,9 +973,10 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb if (haveAtom) { atomState.makeAtom(*file); } - - file->bindTargetReferences(); - result.push_back(file); + if ( file != NULL ) { + file->bindTargetReferences(); + result.push_back(file); + } return make_error_code(yaml_reader_error::success); } diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/Core/YamlWriter.cpp index c38e735b464..c3a7f235454 100644 --- a/lld/lib/Core/YamlWriter.cpp +++ b/lld/lib/Core/YamlWriter.cpp @@ -71,6 +71,14 @@ public: buildDuplicateNameMap(atom); } + virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) { + buildDuplicateNameMap(atom); + } + + virtual void doAbsoluteAtom(const AbsoluteAtom& atom) { + buildDuplicateNameMap(atom); + } + void buildDuplicateNameMap(const Atom& atom) { assert(!atom.name().empty()); NameToAtom::iterator pos = _nameMap.find(atom.name()); @@ -132,10 +140,14 @@ public: virtual void doFile(const class File &) { _firstAtom = true; } virtual void doDefinedAtom(const class DefinedAtom &atom) { - // add blank line between atoms for readability - if ( !_firstAtom ) + if ( _firstAtom ) { + _out << "atoms:\n"; + _firstAtom = false; + } + else { + // add blank line between atoms for readability _out << "\n"; - _firstAtom = false; + } bool hasDash = false; if ( !atom.name().empty() ) { @@ -313,35 +325,115 @@ public: virtual void doUndefinedAtom(const class UndefinedAtom &atom) { - // add blank line between atoms for readability - if ( !_firstAtom ) - _out << "\n"; + if ( _firstAtom ) { + _out << "atoms:\n"; _firstAtom = false; + } + else { + // add blank line between atoms for readability + _out << "\n"; + } - _out << " - " - << KeyValues::nameKeyword + _out << " - " + << KeyValues::nameKeyword + << ":" + << spacePadding(KeyValues::nameKeyword) + << atom.name() + << "\n"; + + _out << " " + << KeyValues::definitionKeyword + << ":" + << spacePadding(KeyValues::definitionKeyword) + << KeyValues::definition(atom.definition()) + << "\n"; + + if ( atom.canBeNull() != KeyValues::canBeNullDefault ) { + _out << " " + << KeyValues::canBeNullKeyword << ":" - << spacePadding(KeyValues::nameKeyword) - << atom.name() + << spacePadding(KeyValues::canBeNullKeyword) + << KeyValues::canBeNull(atom.canBeNull()) << "\n"; + } + } + + virtual void doSharedLibraryAtom(const SharedLibraryAtom& atom) { + if ( _firstAtom ) { + _out << "atoms:\n"; + _firstAtom = false; + } + else { + // add blank line between atoms for readability + _out << "\n"; + } + + _out << " - " + << KeyValues::nameKeyword + << ":" + << spacePadding(KeyValues::nameKeyword) + << atom.name() + << "\n"; + + _out << " " + << KeyValues::definitionKeyword + << ":" + << spacePadding(KeyValues::definitionKeyword) + << KeyValues::definition(atom.definition()) + << "\n"; + if ( !atom.loadName().empty() ) { _out << " " - << KeyValues::definitionKeyword + << KeyValues::loadNameKeyword << ":" - << spacePadding(KeyValues::definitionKeyword) - << KeyValues::definition(atom.definition()) + << spacePadding(KeyValues::loadNameKeyword) + << atom.loadName() << "\n"; + } - if ( atom.weakImport() != KeyValues::weakImportDefault ) { + if ( atom.canBeNullAtRuntime() ) { _out << " " - << KeyValues::weakImportKeyword + << KeyValues::canBeNullKeyword << ":" - << spacePadding(KeyValues::weakImportKeyword) - << KeyValues::weakImport(atom.weakImport()) + << spacePadding(KeyValues::canBeNullKeyword) + << KeyValues::canBeNull(UndefinedAtom::canBeNullAtRuntime) << "\n"; } - } + } + + virtual void doAbsoluteAtom(const AbsoluteAtom& atom) { + if ( _firstAtom ) { + _out << "atoms:\n"; + _firstAtom = false; + } + else { + // add blank line between atoms for readability + _out << "\n"; + } + + _out << " - " + << KeyValues::nameKeyword + << ":" + << spacePadding(KeyValues::nameKeyword) + << atom.name() + << "\n"; + _out << " " + << KeyValues::definitionKeyword + << ":" + << spacePadding(KeyValues::definitionKeyword) + << KeyValues::definition(atom.definition()) + << "\n"; + + _out << " " + << KeyValues::valueKeyword + << ":" + << spacePadding(KeyValues::valueKeyword) + << "0x"; + _out.write_hex(atom.value()); + _out << "\n"; + } + private: // return a string of the correct number of spaces to align value @@ -380,7 +472,6 @@ void writeObjectText(const File &file, llvm::raw_ostream &out) { // Write out all atoms AtomWriter h(rnb, out); out << "---\n"; - out << "atoms:\n"; file.forEachAtom(h); out << "...\n"; } |