diff options
| author | Nick Kledzik <kledzik@apple.com> | 2012-02-07 02:59:54 +0000 |
|---|---|---|
| committer | Nick Kledzik <kledzik@apple.com> | 2012-02-07 02:59:54 +0000 |
| commit | 23384e84afd9e7a53cf2c802829f505cef2754c2 (patch) | |
| tree | 363052290c18a83f3bb54871e9533d7f21aaeb14 /lld/lib | |
| parent | e55c556a247a9c0decb4e256d9e897dfc9cf841d (diff) | |
| download | bcm5719-llvm-23384e84afd9e7a53cf2c802829f505cef2754c2.tar.gz bcm5719-llvm-23384e84afd9e7a53cf2c802829f505cef2754c2.zip | |
Add support for UndefinedAtom in yaml and native format. Add test cases with undefined atoms
llvm-svn: 149962
Diffstat (limited to 'lld/lib')
| -rw-r--r-- | lld/lib/Core/NativeFileFormat.h | 15 | ||||
| -rw-r--r-- | lld/lib/Core/NativeReader.cpp | 115 | ||||
| -rw-r--r-- | lld/lib/Core/NativeWriter.cpp | 105 | ||||
| -rw-r--r-- | lld/lib/Core/Resolver.cpp | 2 | ||||
| -rw-r--r-- | lld/lib/Core/YamlKeyValues.cpp | 183 | ||||
| -rw-r--r-- | lld/lib/Core/YamlKeyValues.h | 5 | ||||
| -rw-r--r-- | lld/lib/Core/YamlReader.cpp | 43 | ||||
| -rw-r--r-- | lld/lib/Core/YamlWriter.cpp | 37 |
8 files changed, 362 insertions, 143 deletions
diff --git a/lld/lib/Core/NativeFileFormat.h b/lld/lib/Core/NativeFileFormat.h index 4e4bfb4e1f9..9fb6d5fe62c 100644 --- a/lld/lib/Core/NativeFileFormat.h +++ b/lld/lib/Core/NativeFileFormat.h @@ -88,9 +88,10 @@ struct NativeFileHeader { enum NativeChunkSignatures { NCS_DefinedAtomsV1 = 1, NCS_AttributesArrayV1 = 2, - NCS_Content = 3, + NCS_UndefinedAtomsV1 = 3, NCS_Strings = 4, - NCS_ReferencesArray = 5, + NCS_Content = 5, + NCS_ReferencesArray = 6, }; // @@ -152,6 +153,16 @@ struct NativeAtomAttributesV1 { +// +// The NCS_UndefinedAtomsV1 chunk contains an array of these structs +// +struct NativeUndefinedAtomIvarsV1 { + uint32_t nameOffset; + uint32_t flags; +}; + + + diff --git a/lld/lib/Core/NativeReader.cpp b/lld/lib/Core/NativeReader.cpp index 845d6bf45ac..033cf9890f6 100644 --- a/lld/lib/Core/NativeReader.cpp +++ b/lld/lib/Core/NativeReader.cpp @@ -65,7 +65,8 @@ public: } virtual DefinedAtom::ContentType contentType() const { - return (DefinedAtom::ContentType)(attributes().contentType); + const NativeAtomAttributesV1& attr = attributes(); + return (DefinedAtom::ContentType)(attr.contentType); } virtual DefinedAtom::Alignment alignment() const { @@ -113,6 +114,29 @@ private: +// +// An object of this class is instantied for each NativeUndefinedAtomIvarsV1 +// struct in the NCS_UndefinedAtomsV1 chunk. +// +class NativeUndefinedAtomV1 : public UndefinedAtom { +public: + NativeUndefinedAtomV1(const NativeFile& f, + const NativeUndefinedAtomIvarsV1* ivarData) + : _file(&f), _ivarData(ivarData) { } + + virtual const File& file() const; + virtual llvm::StringRef name() const; + + virtual bool weakImport() const { + return (_ivarData->flags & 0x1); + } + +private: + const NativeFile* _file; + const NativeUndefinedAtomIvarsV1* _ivarData; +}; + + // // lld::File object for native llvm object file @@ -122,8 +146,9 @@ public: /// Instantiates a File object from a native object file. Ownership /// of the MemoryBuffer is transfered to the resulting File object. - static llvm::error_code make(llvm::MemoryBuffer* mb, llvm::StringRef path, - File*& result) { + static llvm::error_code make(llvm::OwningPtr<llvm::MemoryBuffer>& mb, + llvm::StringRef path, + llvm::OwningPtr<File>& result) { const uint8_t* const base = reinterpret_cast<const uint8_t*>(mb->getBufferStart()); const NativeFileHeader* const header = @@ -159,6 +184,9 @@ public: case NCS_AttributesArrayV1: ec = file->processAttributesV1(base, chunk); break; + case NCS_UndefinedAtomsV1: + ec = file->processUndefinedAtomsV1(base, chunk); + break; case NCS_Content: ec = file->processContent(base, chunk); break; @@ -175,7 +203,7 @@ public: // TO DO: validate enough chunks were used - result = file; + result.reset(file); } @@ -183,13 +211,14 @@ public: } virtual ~NativeFile() { - // The NativeFile owns the MemoryBuffer and must not delete it. - delete _buffer; + // _buffer is automatically deleted because of OwningPtr<> + // All other ivar pointers are pointers into the MemoryBuffer, except // the _definedAtoms array which was allocated to contain an array // of Atom objects. The atoms have empty destructors, so it is ok // to just delete the memory. delete _definedAtoms.arrayStart; + delete _undefinedAtoms.arrayStart; } // visits each atom in the file @@ -199,6 +228,11 @@ public: const DefinedAtom* atom = reinterpret_cast<const DefinedAtom*>(p); handler.doDefinedAtom(*atom); } + for(const uint8_t* p=_undefinedAtoms.arrayStart; p != _undefinedAtoms.arrayEnd; + p += _undefinedAtoms.elementSize) { + const UndefinedAtom* atom = reinterpret_cast<const UndefinedAtom*>(p); + handler.doUndefinedAtom(*atom); + } return (_definedAtoms.arrayStart != _definedAtoms.arrayEnd); } @@ -210,6 +244,7 @@ public: private: friend class NativeDefinedAtomV1; + friend class NativeUndefinedAtomV1; // instantiate array of DefinedAtoms from v1 ivar data in file llvm::error_code processDefinedAtomsV1(const uint8_t* base, @@ -247,6 +282,34 @@ private: return make_error_code(native_reader_error::success); } + llvm::error_code processUndefinedAtomsV1(const uint8_t* base, + const NativeChunk* chunk) { + const size_t atomSize = sizeof(NativeUndefinedAtomV1); + 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(NativeUndefinedAtomIvarsV1) ) + return make_error_code(native_reader_error::file_malformed); + uint8_t* atomsEnd = atomsStart + atomsArraySize; + const NativeUndefinedAtomIvarsV1* ivarData = + reinterpret_cast<const NativeUndefinedAtomIvarsV1*> + (base + chunk->fileOffset); + for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) { + NativeUndefinedAtomV1* atomAllocSpace = + reinterpret_cast<NativeUndefinedAtomV1*>(s); + new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData); + ++ivarData; + } + this->_undefinedAtoms.arrayStart = atomsStart; + this->_undefinedAtoms.arrayEnd = atomsEnd; + this->_undefinedAtoms.elementSize = atomSize; + return make_error_code(native_reader_error::success); + } + // set up pointers to string pool in file llvm::error_code processStrings(const uint8_t* base, const NativeChunk* chunk) { @@ -281,12 +344,18 @@ private: // private constructor, only called by make() - NativeFile(llvm::MemoryBuffer* mb, llvm::StringRef path) : - lld::File(path), _buffer(mb), _header(NULL), - _strings(NULL), _stringsMaxOffset(0), - _contentStart(NULL), _contentEnd(NULL) + NativeFile(llvm::OwningPtr<llvm::MemoryBuffer>& mb, llvm::StringRef path) : + lld::File(path), + _buffer(mb.take()), // NativeFile now takes ownership of buffer + _header(NULL), + _strings(NULL), + _stringsMaxOffset(0), + _contentStart(NULL), + _contentEnd(NULL) { - _header = reinterpret_cast<const NativeFileHeader*>(mb->getBufferStart()); + _header = reinterpret_cast<const NativeFileHeader*>(_buffer->getBufferStart()); + _definedAtoms.arrayStart = NULL; + _undefinedAtoms.arrayStart = NULL; } struct AtomArray { @@ -297,9 +366,10 @@ private: uint32_t elementSize; }; - llvm::MemoryBuffer* _buffer; + llvm::OwningPtr<llvm::MemoryBuffer> _buffer; const NativeFileHeader* _header; AtomArray _definedAtoms; + AtomArray _undefinedAtoms; const uint8_t* _attributes; uint32_t _attributesMaxOffset; const char* _strings; @@ -342,11 +412,24 @@ inline llvm::StringRef NativeDefinedAtomV1::customSectionName() const { + +inline const class File& NativeUndefinedAtomV1::file() const { + return *_file; +} + +inline llvm::StringRef NativeUndefinedAtomV1::name() const { + return _file->string(_ivarData->nameOffset); +} + + + + // // Instantiate an lld::File from the given native object file buffer // -llvm::error_code parseNativeObjectFile(llvm::MemoryBuffer* mb, - llvm::StringRef path, File*& result) { +llvm::error_code parseNativeObjectFile(llvm::OwningPtr<llvm::MemoryBuffer>& mb, + llvm::StringRef path, + llvm::OwningPtr<File>& result) { return NativeFile::make(mb, path, result); } @@ -356,13 +439,13 @@ llvm::error_code parseNativeObjectFile(llvm::MemoryBuffer* mb, // Instantiate an lld::File from the given native object file path // llvm::error_code parseNativeObjectFileOrSTDIN(llvm::StringRef path, - File*& result) { + llvm::OwningPtr<File>& result) { llvm::OwningPtr<llvm::MemoryBuffer> mb; llvm::error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb); if ( ec ) return ec; - return parseNativeObjectFile(mb.take(), path, result); + return parseNativeObjectFile(mb, path, result); } diff --git a/lld/lib/Core/NativeWriter.cpp b/lld/lib/Core/NativeWriter.cpp index e9533be636c..09fdd9cdd17 100644 --- a/lld/lib/Core/NativeWriter.cpp +++ b/lld/lib/Core/NativeWriter.cpp @@ -44,10 +44,13 @@ public: if (!_attributes.empty()) out.write((char*)&_attributes[0], _attributes.size()*sizeof(NativeAtomAttributesV1)); - if (!_contentPool.empty()) - out.write((char*)&_contentPool[0], _contentPool.size()); + if ( !_undefinedAtomIvars.empty() ) + out.write((char*)&_undefinedAtomIvars[0], + _undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1)); if (!_stringPool.empty()) out.write(&_stringPool[0], _stringPool.size()); + if (!_contentPool.empty()) + out.write((char*)&_contentPool[0], _contentPool.size()); } private: @@ -64,15 +67,22 @@ private: // visitor routine called by forEachAtom() virtual void doUndefinedAtom(const class UndefinedAtom& atom) { + NativeUndefinedAtomIvarsV1 ivar; + ivar.nameOffset = getNameOffset(atom); + ivar.flags = (atom.weakImport() ? 1 : 0); + _undefinedAtomIvars.push_back(ivar); } // visitor routine called by forEachAtom() virtual void doFile(const class File &) { } - + // fill out native file header and chunk directory void makeHeader() { - _headerBufferSize = sizeof(NativeFileHeader) + 4*sizeof(NativeChunk); + const bool hasUndefines = !_undefinedAtomIvars.empty(); + const int chunkCount = hasUndefines ? 5 : 4; + _headerBufferSize = sizeof(NativeFileHeader) + + chunkCount*sizeof(NativeChunk); _headerBuffer = reinterpret_cast<NativeFileHeader*> (operator new(_headerBufferSize, std::nothrow)); NativeChunk *chunks = @@ -82,39 +92,59 @@ private: _headerBuffer->endian = NFH_LittleEndian; _headerBuffer->architecture = 0; _headerBuffer->fileSize = 0; - _headerBuffer->chunkCount = 4; + _headerBuffer->chunkCount = chunkCount; + // create chunk for atom ivar array - NativeChunk& ch0 = chunks[0]; - ch0.signature = NCS_DefinedAtomsV1; - ch0.fileOffset = _headerBufferSize; - ch0.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1); - ch0.elementCount = _definedAtomIvars.size(); - // create chunk for attributes - NativeChunk& ch1 = chunks[1]; - ch1.signature = NCS_AttributesArrayV1; - ch1.fileOffset = ch0.fileOffset + ch0.fileSize; - ch1.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1); - ch1.elementCount = _attributes.size(); - // create chunk for content - NativeChunk& ch2 = chunks[2]; - ch2.signature = NCS_Content; - ch2.fileOffset = ch1.fileOffset + ch1.fileSize; - ch2.fileSize = _contentPool.size(); - ch2.elementCount = _contentPool.size(); + 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; + + // create chunk for undefined atom array + if ( hasUndefines ) { + NativeChunk& chu = chunks[nextIndex++]; + chu.signature = NCS_UndefinedAtomsV1; + chu.fileOffset = nextFileOffset; + chu.fileSize = _undefinedAtomIvars.size() * + sizeof(NativeUndefinedAtomIvarsV1); + chu.elementCount = _undefinedAtomIvars.size(); + nextFileOffset = chu.fileOffset + chu.fileSize; + } + // create chunk for symbol strings - NativeChunk& ch3 = chunks[3]; - ch3.signature = NCS_Strings; - ch3.fileOffset = ch2.fileOffset + ch2.fileSize; - ch3.fileSize = _stringPool.size(); - ch3.elementCount = _stringPool.size(); + NativeChunk& chs = chunks[nextIndex++]; + chs.signature = NCS_Strings; + chs.fileOffset = nextFileOffset; + chs.fileSize = _stringPool.size(); + chs.elementCount = _stringPool.size(); + nextFileOffset = chs.fileOffset + chs.fileSize; - _headerBuffer->fileSize = ch3.fileOffset + ch3.fileSize; + // 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; + + _headerBuffer->fileSize = nextFileOffset; } // append atom name to string pool and return offset - uint32_t getNameOffset(const class DefinedAtom& atom) { + uint32_t getNameOffset(const Atom& atom) { return this->getNameOffset(atom.name()); } @@ -190,14 +220,15 @@ private: typedef std::vector<std::pair<llvm::StringRef, uint32_t> > NameToOffsetVector; - const lld::File& _file; - NativeFileHeader* _headerBuffer; - size_t _headerBufferSize; - std::vector<char> _stringPool; - std::vector<uint8_t> _contentPool; - std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars; - std::vector<NativeAtomAttributesV1> _attributes; - NameToOffsetVector _sectionNames; + const lld::File& _file; + NativeFileHeader* _headerBuffer; + size_t _headerBufferSize; + std::vector<char> _stringPool; + std::vector<uint8_t> _contentPool; + std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars; + std::vector<NativeAtomAttributesV1> _attributes; + std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars; + NameToOffsetVector _sectionNames; }; diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp index 51f6a481a65..cebf3f7d10c 100644 --- a/lld/lib/Core/Resolver.cpp +++ b/lld/lib/Core/Resolver.cpp @@ -33,7 +33,7 @@ public: // don't remove if live if ( _liveAtoms.count(atom) ) return false; - // don't remove if marked never-dead-strip + // don't remove if marked never-dead-strip if ( const DefinedAtom* defAtom = atom->definedAtom() ) { if ( defAtom->deadStrip() == DefinedAtom::deadStripNever ) return false; diff --git a/lld/lib/Core/YamlKeyValues.cpp b/lld/lib/Core/YamlKeyValues.cpp index 4158e6d4e51..9401aae949a 100644 --- a/lld/lib/Core/YamlKeyValues.cpp +++ b/lld/lib/Core/YamlKeyValues.cpp @@ -31,7 +31,8 @@ const char* const KeyValues::isAliasKeyword = "is-alias"; const char* const KeyValues::sectionNameKeyword = "section-name"; const char* const KeyValues::contentKeyword = "content"; const char* const KeyValues::sizeKeyword = "size"; -const char* const KeyValues::permissionsKeyword = "permissions"; +const char* const KeyValues::permissionsKeyword = "permissions"; +const char* const KeyValues::weakImportKeyword = "weak-import"; const DefinedAtom::Definition KeyValues::definitionDefault = Atom::definitionRegular; @@ -45,27 +46,28 @@ const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAto const bool KeyValues::internalNameDefault = false; const bool KeyValues::isThumbDefault = false; const bool KeyValues::isAliasDefault = false; +const bool KeyValues::weakImportDefault = false; struct DefinitionMapping { - const char* string; - Atom::Definition value; + const char* string; + Atom::Definition value; }; static const DefinitionMapping defMappings[] = { - { "regular", Atom::definitionRegular }, - { "absolute", Atom::definitionAbsolute }, - { "undefined", Atom::definitionUndefined }, - { "shared-library", Atom::definitionSharedLibrary }, + { "regular", Atom::definitionRegular }, + { "absolute", Atom::definitionAbsolute }, + { "undefined", Atom::definitionUndefined }, + { "shared-library", Atom::definitionSharedLibrary }, { NULL, Atom::definitionRegular } }; Atom::Definition KeyValues::definition(const char* s) { - for (const DefinitionMapping* p = defMappings; p->string != NULL; ++p) { + for (const DefinitionMapping* p = defMappings; p->string != NULL; ++p) { if ( strcmp(p->string, s) == 0 ) return p->value; } @@ -73,7 +75,7 @@ Atom::Definition KeyValues::definition(const char* s) } const char* KeyValues::definition(Atom::Definition s) { - for (const DefinitionMapping* p = defMappings; p->string != NULL; ++p) { + for (const DefinitionMapping* p = defMappings; p->string != NULL; ++p) { if ( p->value == s ) return p->string; } @@ -85,20 +87,20 @@ const char* KeyValues::definition(Atom::Definition s) { struct ScopeMapping { - const char* string; - DefinedAtom::Scope value; + const char* string; + DefinedAtom::Scope value; }; static const ScopeMapping scopeMappings[] = { - { "global", DefinedAtom::scopeGlobal }, - { "hidden", DefinedAtom::scopeLinkageUnit }, - { "static", DefinedAtom::scopeTranslationUnit }, + { "global", DefinedAtom::scopeGlobal }, + { "hidden", DefinedAtom::scopeLinkageUnit }, + { "static", DefinedAtom::scopeTranslationUnit }, { NULL, DefinedAtom::scopeGlobal } }; DefinedAtom::Scope KeyValues::scope(const char* s) { - for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) { + for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) { if ( strcmp(p->string, s) == 0 ) return p->value; } @@ -106,7 +108,7 @@ DefinedAtom::Scope KeyValues::scope(const char* s) } const char* KeyValues::scope(DefinedAtom::Scope s) { - for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) { + for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) { if ( p->value == s ) return p->string; } @@ -121,41 +123,41 @@ const char* KeyValues::scope(DefinedAtom::Scope s) { struct ContentTypeMapping { - const char* string; - DefinedAtom::ContentType value; + const char* string; + DefinedAtom::ContentType value; }; static const ContentTypeMapping typeMappings[] = { - { "unknown", DefinedAtom::typeUnknown }, - { "code", DefinedAtom::typeCode }, - { "resolver", DefinedAtom::typeResolver }, - { "constant", DefinedAtom::typeConstant }, - { "c-string", DefinedAtom::typeCString }, - { "utf16-string", DefinedAtom::typeUTF16String }, - { "CFI", DefinedAtom::typeCFI }, - { "LSDA", DefinedAtom::typeLSDA }, - { "literal-4", DefinedAtom::typeLiteral4 }, - { "literal-8", DefinedAtom::typeLiteral8 }, - { "literal-16", DefinedAtom::typeLiteral16 }, - { "data", DefinedAtom::typeData }, - { "zero-fill", DefinedAtom::typeZeroFill }, - { "cf-string", DefinedAtom::typeCFString }, - { "initializer-ptr",DefinedAtom::typeInitializerPtr }, - { "terminator-ptr", DefinedAtom::typeTerminatorPtr }, - { "c-string-ptr", DefinedAtom::typeCStringPtr }, - { "objc1-class", DefinedAtom::typeObjC1Class }, - { "objc1-class-ptr",DefinedAtom::typeObjCClassPtr }, - { "objc2-cat-ptr", DefinedAtom::typeObjC2CategoryList }, - { "tlv-thunk", DefinedAtom::typeThunkTLV }, - { "tlv-data", DefinedAtom::typeTLVInitialData }, - { "tlv-zero-fill", DefinedAtom::typeTLVInitialZeroFill }, - { "tlv-init-ptr", DefinedAtom::typeTLVInitializerPtr }, + { "unknown", DefinedAtom::typeUnknown }, + { "code", DefinedAtom::typeCode }, + { "resolver", DefinedAtom::typeResolver }, + { "constant", DefinedAtom::typeConstant }, + { "c-string", DefinedAtom::typeCString }, + { "utf16-string", DefinedAtom::typeUTF16String }, + { "CFI", DefinedAtom::typeCFI }, + { "LSDA", DefinedAtom::typeLSDA }, + { "literal-4", DefinedAtom::typeLiteral4 }, + { "literal-8", DefinedAtom::typeLiteral8 }, + { "literal-16", DefinedAtom::typeLiteral16 }, + { "data", DefinedAtom::typeData }, + { "zero-fill", DefinedAtom::typeZeroFill }, + { "cf-string", DefinedAtom::typeCFString }, + { "initializer-ptr",DefinedAtom::typeInitializerPtr }, + { "terminator-ptr", DefinedAtom::typeTerminatorPtr }, + { "c-string-ptr", DefinedAtom::typeCStringPtr }, + { "objc1-class", DefinedAtom::typeObjC1Class }, + { "objc1-class-ptr",DefinedAtom::typeObjCClassPtr }, + { "objc2-cat-ptr", DefinedAtom::typeObjC2CategoryList }, + { "tlv-thunk", DefinedAtom::typeThunkTLV }, + { "tlv-data", DefinedAtom::typeTLVInitialData }, + { "tlv-zero-fill", DefinedAtom::typeTLVInitialZeroFill }, + { "tlv-init-ptr", DefinedAtom::typeTLVInitializerPtr }, { NULL, DefinedAtom::typeUnknown } }; DefinedAtom::ContentType KeyValues::contentType(const char* s) { - for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) { + for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) { if ( strcmp(p->string, s) == 0 ) return p->value; } @@ -163,7 +165,7 @@ DefinedAtom::ContentType KeyValues::contentType(const char* s) } const char* KeyValues::contentType(DefinedAtom::ContentType s) { - for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) { + for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) { if ( p->value == s ) return p->string; } @@ -177,20 +179,20 @@ const char* KeyValues::contentType(DefinedAtom::ContentType s) { struct DeadStripMapping { - const char* string; - DefinedAtom::DeadStripKind value; + const char* string; + DefinedAtom::DeadStripKind value; }; static const DeadStripMapping deadStripMappings[] = { - { "normal", DefinedAtom::deadStripNormal }, - { "never", DefinedAtom::deadStripNever }, - { "always", DefinedAtom::deadStripAlways }, + { "normal", DefinedAtom::deadStripNormal }, + { "never", DefinedAtom::deadStripNever }, + { "always", DefinedAtom::deadStripAlways }, { NULL, DefinedAtom::deadStripNormal } }; DefinedAtom::DeadStripKind KeyValues::deadStripKind(const char* s) { - for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) { + for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) { if ( strcmp(p->string, s) == 0 ) return p->value; } @@ -198,7 +200,7 @@ DefinedAtom::DeadStripKind KeyValues::deadStripKind(const char* s) } const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) { - for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) { + for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) { if ( p->value == dsk ) return p->string; } @@ -210,20 +212,20 @@ const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) { struct InterposableMapping { - const char* string; - DefinedAtom::Interposable value; + const char* string; + DefinedAtom::Interposable value; }; static const InterposableMapping interMappings[] = { - { "no", DefinedAtom::interposeNo }, - { "yes", DefinedAtom::interposeYes }, - { "yesAndWeak", DefinedAtom::interposeYesAndRuntimeWeak }, + { "no", DefinedAtom::interposeNo }, + { "yes", DefinedAtom::interposeYes }, + { "yesAndWeak", DefinedAtom::interposeYesAndRuntimeWeak }, { NULL, DefinedAtom::interposeNo } }; DefinedAtom::Interposable KeyValues::interposable(const char* s) { - for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) { + for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) { if ( strcmp(p->string, s) == 0 ) return p->value; } @@ -231,7 +233,7 @@ DefinedAtom::Interposable KeyValues::interposable(const char* s) } const char* KeyValues::interposable(DefinedAtom::Interposable in) { - for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) { + for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) { if ( p->value == in ) return p->string; } @@ -244,21 +246,21 @@ const char* KeyValues::interposable(DefinedAtom::Interposable in) { struct MergeMapping { - const char* string; - DefinedAtom::Merge value; + const char* string; + DefinedAtom::Merge value; }; static const MergeMapping mergeMappings[] = { - { "no", DefinedAtom::mergeNo }, - { "asTentative", DefinedAtom::mergeAsTentative }, - { "asWeak", DefinedAtom::mergeAsWeak }, - { "asAddressedWeak",DefinedAtom::mergeAsWeakAndAddressUsed }, + { "no", DefinedAtom::mergeNo }, + { "asTentative", DefinedAtom::mergeAsTentative }, + { "asWeak", DefinedAtom::mergeAsWeak }, + { "asAddressedWeak",DefinedAtom::mergeAsWeakAndAddressUsed }, { NULL, DefinedAtom::mergeNo } }; DefinedAtom::Merge KeyValues::merge(const char* s) { - for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) { + for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) { if ( strcmp(p->string, s) == 0 ) return p->value; } @@ -266,7 +268,7 @@ DefinedAtom::Merge KeyValues::merge(const char* s) } const char* KeyValues::merge(DefinedAtom::Merge in) { - for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) { + for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) { if ( p->value == in ) return p->string; } @@ -279,20 +281,20 @@ const char* KeyValues::merge(DefinedAtom::Merge in) { struct SectionChoiceMapping { - const char* string; - DefinedAtom::SectionChoice value; + const char* string; + DefinedAtom::SectionChoice value; }; static const SectionChoiceMapping sectMappings[] = { - { "content", DefinedAtom::sectionBasedOnContent }, - { "custom", DefinedAtom::sectionCustomPreferred }, - { "custom-required", DefinedAtom::sectionCustomRequired }, + { "content", DefinedAtom::sectionBasedOnContent }, + { "custom", DefinedAtom::sectionCustomPreferred }, + { "custom-required", DefinedAtom::sectionCustomRequired }, { NULL, DefinedAtom::sectionBasedOnContent } }; DefinedAtom::SectionChoice KeyValues::sectionChoice(const char* s) { - for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) { + for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) { if ( strcmp(p->string, s) == 0 ) return p->value; } @@ -300,7 +302,7 @@ DefinedAtom::SectionChoice KeyValues::sectionChoice(const char* s) } const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) { - for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) { + for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) { if ( p->value == s ) return p->string; } @@ -314,22 +316,22 @@ const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) { struct PermissionsMapping { - const char* string; - DefinedAtom::ContentPermissions value; + const char* string; + DefinedAtom::ContentPermissions value; }; static const PermissionsMapping permMappings[] = { - { "content", DefinedAtom::perm___ }, - { "custom", DefinedAtom::permR__ }, - { "custom-required", DefinedAtom::permR_X }, - { "custom-required", DefinedAtom::permRW_ }, - { "custom-required", DefinedAtom::permRW_L }, + { "content", DefinedAtom::perm___ }, + { "custom", DefinedAtom::permR__ }, + { "custom-required", DefinedAtom::permR_X }, + { "custom-required", DefinedAtom::permRW_ }, + { "custom-required", DefinedAtom::permRW_L }, { NULL, DefinedAtom::perm___ } }; DefinedAtom::ContentPermissions KeyValues::permissions(const char* s) { - for (const PermissionsMapping* p = permMappings; p->string != NULL; ++p) { + for (const PermissionsMapping* p = permMappings; p->string != NULL; ++p) { if ( strcmp(p->string, s) == 0 ) return p->value; } @@ -337,7 +339,7 @@ DefinedAtom::ContentPermissions KeyValues::permissions(const char* s) } const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) { - for (const PermissionsMapping* p = permMappings; p->string != NULL; ++p) { + for (const PermissionsMapping* p = permMappings; p->string != NULL; ++p) { if ( p->value == s ) return p->string; } @@ -398,6 +400,23 @@ const char* KeyValues::isAlias(bool b) { +bool KeyValues::weakImport(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"); +} + +const char* KeyValues::weakImport(bool b) { + return b ? "true" : "false"; +} + + + + + } // namespace yaml diff --git a/lld/lib/Core/YamlKeyValues.h b/lld/lib/Core/YamlKeyValues.h index b38a26cfaf3..2a15ed25639 100644 --- a/lld/lib/Core/YamlKeyValues.h +++ b/lld/lib/Core/YamlKeyValues.h @@ -79,6 +79,11 @@ 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); + }; } // namespace yaml diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp index 39c06432f39..37c6382fc52 100644 --- a/lld/lib/Core/YamlReader.cpp +++ b/lld/lib/Core/YamlReader.cpp @@ -267,6 +267,10 @@ bool YAMLFile::forEachAtom(File::AtomHandler &handler) const { it != _definedAtoms.end(); ++it) { handler.doDefinedAtom(**it); } + for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin(); + it != _undefinedAtoms.end(); ++it) { + handler.doUndefinedAtom(**it); + } return true; } @@ -424,6 +428,32 @@ 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) { } + + virtual const class File& file() const { + return _file; + } + + virtual llvm::StringRef name() const { + return _name; + } + + virtual bool weakImport() const { + return _weakImport; + } + +private: + YAMLFile& _file; + const char * _name; + uint32_t _ordinal; + bool _weakImport; +}; + + + class YAMLAtomState { public: YAMLAtomState(); @@ -455,6 +485,7 @@ public: bool _internalName; bool _isThumb; bool _isAlias; + bool _weakImport; Reference _ref; }; @@ -477,6 +508,7 @@ YAMLAtomState::YAMLAtomState() , _internalName(KeyValues::internalNameDefault) , _isThumb(KeyValues::isThumbDefault) , _isAlias(KeyValues::isAliasDefault) + , _weakImport(false) { _ref.target = NULL; _ref.addend = 0; @@ -496,6 +528,12 @@ void YAMLAtomState::makeAtom(YAMLFile& f) { f._definedAtoms.push_back(a); ++_ordinal; } + else if ( _definition == Atom::definitionUndefined ) { + UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _weakImport); + + f._undefinedAtoms.push_back(a); + ++_ordinal; + } // reset state for next atom _name = NULL; @@ -515,6 +553,7 @@ void YAMLAtomState::makeAtom(YAMLFile& f) { _permissions = KeyValues::permissionsDefault; _isThumb = KeyValues::isThumbDefault; _isAlias = KeyValues::isAliasDefault; + _weakImport = KeyValues::weakImportDefault; _ref.target = NULL; _ref.addend = 0; _ref.offsetInAtom = 0; @@ -664,6 +703,10 @@ 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); + haveAtom = true; + } else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) { atomState._sectionName = entry->value; haveAtom = true; diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/Core/YamlWriter.cpp index e5f0b1c44c3..db46b5a12d7 100644 --- a/lld/lib/Core/YamlWriter.cpp +++ b/lld/lib/Core/YamlWriter.cpp @@ -81,7 +81,7 @@ public: << "\n"; } - if ( atom.merge() != KeyValues::mergeDefault ) { + if ( atom.merge() != KeyValues::mergeDefault ) { _out << " " << KeyValues::mergeKeyword << ":" @@ -124,7 +124,7 @@ public: << "\n"; } - if ( atom.isThumb() != KeyValues::isThumbDefault ) { + if ( atom.isThumb() != KeyValues::isThumbDefault ) { _out << " " << KeyValues::isThumbKeyword << ":" @@ -142,7 +142,8 @@ public: << "\n"; } - if ( atom.contentType() != DefinedAtom::typeZeroFill ) { + if ( (atom.contentType() != DefinedAtom::typeZeroFill) + && (atom.size() != 0) ) { _out << " " << KeyValues::contentKeyword << ":" @@ -171,9 +172,35 @@ public: } - virtual void doUndefinedAtom(const class UndefinedAtom &atom) { + virtual void doUndefinedAtom(const class UndefinedAtom &atom) { + // add blank line between atoms for readability + if ( !_firstAtom ) + _out << "\n"; + _firstAtom = false; + + _out << " - " + << KeyValues::nameKeyword + << ":" + << spacePadding(KeyValues::nameKeyword) + << atom.name() + << "\n"; - } + _out << " " + << KeyValues::definitionKeyword + << ":" + << spacePadding(KeyValues::definitionKeyword) + << KeyValues::definition(atom.definition()) + << "\n"; + + if ( atom.weakImport() != KeyValues::weakImportDefault ) { + _out << " " + << KeyValues::weakImportKeyword + << ":" + << spacePadding(KeyValues::weakImportKeyword) + << KeyValues::weakImport(atom.weakImport()) + << "\n"; + } + } private: |

