diff options
author | Nick Kledzik <kledzik@apple.com> | 2014-09-03 19:52:50 +0000 |
---|---|---|
committer | Nick Kledzik <kledzik@apple.com> | 2014-09-03 19:52:50 +0000 |
commit | 141330aef62f4a753622441d11a756cfc72bde94 (patch) | |
tree | 151ebf036f9dcb9928fd0af08167f4a6fbb4b92f /lld | |
parent | ed9709d928ff3684bc1d646badcf068689ce232d (diff) | |
download | bcm5719-llvm-141330aef62f4a753622441d11a756cfc72bde94.tar.gz bcm5719-llvm-141330aef62f4a753622441d11a756cfc72bde94.zip |
[mach-o] Add support for using export tries
On Darwin at runtime, dyld will prefer to use the export trie of a dylib instead
of the traditional symbol table (which is large and requires a binary search).
This change enables the linker to generate an export trie and to prefer it if
found in a dylib being linked against. This also simples the yaml for dylibs
because the yaml form of the trie can be reduced to just a sequence of names.
llvm-svn: 217066
Diffstat (limited to 'lld')
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp | 30 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp | 240 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp | 31 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp | 19 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp | 11 | ||||
-rw-r--r-- | lld/test/mach-o/dylib-exports.yaml | 41 | ||||
-rw-r--r-- | lld/test/mach-o/hello-world-armv6.yaml | 20 | ||||
-rw-r--r-- | lld/test/mach-o/hello-world-armv7.yaml | 20 | ||||
-rw-r--r-- | lld/test/mach-o/hello-world-x86.yaml | 19 | ||||
-rw-r--r-- | lld/test/mach-o/hello-world-x86_64.yaml | 23 |
10 files changed, 362 insertions, 92 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp index fc43141ca24..6fcee3bf059 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp @@ -33,6 +33,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/Object/MachO.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" @@ -45,6 +46,8 @@ #include <system_error> using namespace llvm::MachO; +using llvm::object::ExportEntry; +using llvm::object::MachOObjectFile; namespace lld { namespace mach_o { @@ -231,6 +234,7 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb, // Walk load commands looking for segments/sections and the symbol table. const data_in_code_entry *dataInCode = nullptr; + const dyld_info_command *dyldInfo = nullptr; uint32_t dataInCodeSize = 0; ec = forEachLoadCommand(lcRange, lcCount, swap, is64, [&] (uint32_t cmd, uint32_t size, const char* lc) -> bool { @@ -406,6 +410,7 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb, start + read32(swap, ldc->dataoff)); dataInCodeSize = read32(swap, ldc->datasize); } + break; case LC_LOAD_DYLIB: case LC_LOAD_WEAK_DYLIB: case LC_REEXPORT_DYLIB: @@ -417,6 +422,10 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb, f->dependentDylibs.push_back(entry); } break; + case LC_DYLD_INFO: + case LC_DYLD_INFO_ONLY: + dyldInfo = reinterpret_cast<const dyld_info_command*>(lc); + break; } return false; }); @@ -434,11 +443,30 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb, } } + if (dyldInfo) { + // If any exports, extract and add to normalized exportInfo vector. + if (dyldInfo->export_size) { + const uint8_t *trieStart = reinterpret_cast<const uint8_t*>(start + + dyldInfo->export_off); + ArrayRef<uint8_t> trie(trieStart, dyldInfo->export_size); + for (const ExportEntry &trieExport : MachOObjectFile::exports(trie)) { + Export normExport; + normExport.name = trieExport.name().copy(f->ownedAllocations); + normExport.offset = trieExport.address(); + normExport.kind = ExportSymbolKind(trieExport.flags() & EXPORT_SYMBOL_FLAGS_KIND_MASK); + normExport.flags = trieExport.flags() & ~EXPORT_SYMBOL_FLAGS_KIND_MASK; + normExport.otherOffset = trieExport.other(); + if (!trieExport.otherName().empty()) + normExport.otherName = trieExport.otherName().copy(f->ownedAllocations); + f->exportInfo.push_back(normExport); + } + } + } + return std::move(f); } - class MachOReader : public Reader { public: MachOReader(MachOLinkingContext &ctx) : _ctx(ctx) {} diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp index 5d9f46dd582..3f1ed9ac2bf 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/Format.h" #include "llvm/Support/Host.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/MachO.h" @@ -77,12 +78,14 @@ private: void writeRebaseInfo(); void writeBindingInfo(); void writeLazyBindingInfo(); + void writeExportInfo(); void writeDataInCodeInfo(); void writeLinkEditContent(); void buildLinkEditInfo(); void buildRebaseInfo(); void buildBindInfo(); void buildLazyBindInfo(); + void buildExportTrie(); void computeDataInCodeSize(); void computeSymbolTableSizes(); void buildSectionRelocations(); @@ -115,6 +118,7 @@ private: class ByteBuffer { public: ByteBuffer() : _ostream(_bytes) { } + void append_byte(uint8_t b) { _ostream << b; } @@ -144,6 +148,37 @@ private: llvm::raw_svector_ostream _ostream; }; + struct TrieNode; // Forward declaration. + + struct TrieEdge { + TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {} + ~TrieEdge() {} + + StringRef _subString; + struct TrieNode *_child; + }; + + struct TrieNode { + TrieNode(StringRef s) + : _cummulativeString(s), _address(0), _flags(0), _other(0), + _trieOffset(0), _hasExportInfo(false) {} + ~TrieNode() {} + + void addSymbol(const Export &entry, BumpPtrAllocator &allocator, + std::vector<TrieNode *> &allNodes); + bool updateOffset(uint32_t &offset); + void appendToByteBuffer(ByteBuffer &out); + +private: + StringRef _cummulativeString; + SmallVector<TrieEdge, 8> _children; + uint64_t _address; + uint64_t _flags; + uint64_t _other; + StringRef _importedName; + uint32_t _trieOffset; + bool _hasExportInfo; + }; struct SegExtraInfo { uint32_t fileOffset; @@ -190,6 +225,8 @@ private: uint32_t _endOfBindingInfo; uint32_t _startOfLazyBindingInfo; uint32_t _endOfLazyBindingInfo; + uint32_t _startOfExportTrie; + uint32_t _endOfExportTrie; uint32_t _endOfLinkEdit; uint64_t _addressOfLinkEdit; SegMap _segInfo; @@ -198,7 +235,7 @@ private: ByteBuffer _bindingInfo; ByteBuffer _lazyBindingInfo; ByteBuffer _weakBindingInfo; - ByteBuffer _exportInfo; + ByteBuffer _exportTrie; }; size_t headerAndLoadCommandsSize(const NormalizedFile &file) { @@ -295,7 +332,9 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file) _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size(); _startOfLazyBindingInfo = _endOfBindingInfo; _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size(); - _startOfDataInCode = _endOfLazyBindingInfo; + _startOfExportTrie = _endOfLazyBindingInfo; + _endOfExportTrie = _startOfExportTrie + _exportTrie.size(); + _startOfDataInCode = _endOfExportTrie; _startOfSymbols = _startOfDataInCode + _dataInCodeSize; _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize; _startOfSymbolStrings = _startOfIndirectSymbols @@ -315,6 +354,8 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file) << " endOfBindingInfo=" << _endOfBindingInfo << "\n" << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n" << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n" + << " startOfExportTrie=" << _startOfExportTrie << "\n" + << " endOfExportTrie=" << _endOfExportTrie << "\n" << " startOfDataInCode=" << _startOfDataInCode << "\n" << " startOfSymbols=" << _startOfSymbols << "\n" << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n" @@ -685,8 +726,8 @@ std::error_code MachOFileLayout::writeLoadCommands() { di->weak_bind_size = 0; di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0; di->lazy_bind_size = _lazyBindingInfo.size(); - di->export_off = 0; - di->export_size = 0; + di->export_off = _exportTrie.size() ? _startOfExportTrie : 0; + di->export_size = _exportTrie.size(); if (_swap) swapStruct(*di); lc += sizeof(dyld_info_command); @@ -897,10 +938,15 @@ void MachOFileLayout::writeLazyBindingInfo() { _lazyBindingInfo.bytes(), _lazyBindingInfo.size()); } +void MachOFileLayout::writeExportInfo() { + memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size()); +} + void MachOFileLayout::buildLinkEditInfo() { buildRebaseInfo(); buildBindInfo(); buildLazyBindInfo(); + buildExportTrie(); computeSymbolTableSizes(); computeDataInCodeSize(); } @@ -957,6 +1003,191 @@ void MachOFileLayout::buildLazyBindInfo() { _lazyBindingInfo.align(_is64 ? 8 : 4); } +void MachOFileLayout::TrieNode::addSymbol(const Export& entry, + BumpPtrAllocator &allocator, + std::vector<TrieNode*> &allNodes) { + StringRef partialStr = entry.name.drop_front(_cummulativeString.size()); + for (TrieEdge &edge : _children) { + StringRef edgeStr = edge._subString; + if (partialStr.startswith(edgeStr)) { + // Already have matching edge, go down that path. + edge._child->addSymbol(entry, allocator, allNodes); + return; + } + // See if string has commmon prefix with existing edge. + for (int n=edgeStr.size()-1; n > 0; --n) { + if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) { + // Splice in new node: was A -> C, now A -> B -> C + StringRef bNodeStr = edge._child->_cummulativeString; + bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator); + TrieNode* bNode = new (allocator) TrieNode(bNodeStr); + allNodes.push_back(bNode); + TrieNode* cNode = edge._child; + StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator); + StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator); + DEBUG_WITH_TYPE("trie-builder", llvm::dbgs() + << "splice in TrieNode('" << bNodeStr + << "') between edge '" + << abEdgeStr << "' and edge='" + << bcEdgeStr<< "'\n"); + TrieEdge& abEdge = edge; + abEdge._subString = abEdgeStr; + abEdge._child = bNode; + TrieEdge bcEdge(bcEdgeStr, cNode); + bNode->_children.push_back(bcEdge); + bNode->addSymbol(entry, allocator, allNodes); + return; + } + } + } + if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) { + assert(entry.otherOffset != 0); + } + if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) { + assert(entry.otherOffset != 0); + } + // No commonality with any existing child, make a new edge. + TrieNode* newNode = new (allocator) TrieNode(entry.name.copy(allocator)); + TrieEdge newEdge(partialStr, newNode); + _children.push_back(newEdge); + DEBUG_WITH_TYPE("trie-builder", llvm::dbgs() + << "new TrieNode('" << entry.name << "') with edge '" + << partialStr << "' from node='" + << _cummulativeString << "'\n"); + newNode->_address = entry.offset; + newNode->_flags = entry.flags | entry.kind; + newNode->_other = entry.otherOffset; + if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty()) + newNode->_importedName = entry.otherName.copy(allocator); + newNode->_hasExportInfo = true; + allNodes.push_back(newNode); +} + +bool MachOFileLayout::TrieNode::updateOffset(uint32_t& offset) { + uint32_t nodeSize = 1; // Length when no export info + if (_hasExportInfo) { + if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) { + nodeSize = llvm::getULEB128Size(_flags); + nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal. + nodeSize += _importedName.size(); + ++nodeSize; // Trailing zero in imported name. + } else { + nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address); + if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) + nodeSize += llvm::getULEB128Size(_other); + } + // Overall node size so far is uleb128 of export info + actual export info. + nodeSize += llvm::getULEB128Size(nodeSize); + } + // Compute size of all child edges. + ++nodeSize; // Byte for number of chidren. + for (TrieEdge &edge : _children) { + nodeSize += edge._subString.size() + 1 // String length. + + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len. + } + // On input, 'offset' is new prefered location for this node. + bool result = (_trieOffset != offset); + // Store new location in node object for use by parents. + _trieOffset = offset; + // Update offset for next iteration. + offset += nodeSize; + // Return true if _trieOffset was changed. + return result; +} + +void MachOFileLayout::TrieNode::appendToByteBuffer(ByteBuffer &out) { + if (_hasExportInfo) { + if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) { + if (!_importedName.empty()) { + // nodes with re-export info: size, flags, ordinal, import-name + uint32_t nodeSize = llvm::getULEB128Size(_flags) + + llvm::getULEB128Size(_other) + + _importedName.size() + 1; + assert(nodeSize < 256); + out.append_byte(nodeSize); + out.append_uleb128(_flags); + out.append_uleb128(_other); + out.append_string(_importedName); + } else { + // nodes without re-export info: size, flags, ordinal, empty-string + uint32_t nodeSize = llvm::getULEB128Size(_flags) + + llvm::getULEB128Size(_other) + 1; + assert(nodeSize < 256); + out.append_byte(nodeSize); + out.append_uleb128(_flags); + out.append_uleb128(_other); + out.append_byte(0); + } + } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) { + // Nodes with export info: size, flags, address, other + uint32_t nodeSize = llvm::getULEB128Size(_flags) + + llvm::getULEB128Size(_address) + + llvm::getULEB128Size(_other); + assert(nodeSize < 256); + out.append_byte(nodeSize); + out.append_uleb128(_flags); + out.append_uleb128(_address); + out.append_uleb128(_other); + } else { + // Nodes with export info: size, flags, address + uint32_t nodeSize = llvm::getULEB128Size(_flags) + + llvm::getULEB128Size(_address); + assert(nodeSize < 256); + out.append_byte(nodeSize); + out.append_uleb128(_flags); + out.append_uleb128(_address); + } + } else { + // Node with no export info. + uint32_t nodeSize = 0; + out.append_byte(nodeSize); + } + // Add number of children. + assert(_children.size() < 256); + out.append_byte(_children.size()); + // Append each child edge substring and node offset. + for (TrieEdge &edge : _children) { + out.append_string(edge._subString); + out.append_uleb128(edge._child->_trieOffset); + } +} + +void MachOFileLayout::buildExportTrie() { + if (_file.exportInfo.empty()) + return; + + // For all temporary strings and objects used building trie. + BumpPtrAllocator allocator; + + // Build trie of all exported symbols. + TrieNode* rootNode = new (allocator) TrieNode(StringRef()); + std::vector<TrieNode*> allNodes; + allNodes.reserve(_file.exportInfo.size()*2); + allNodes.push_back(rootNode); + for (const Export& entry : _file.exportInfo) { + rootNode->addSymbol(entry, allocator, allNodes); + } + + // Assign each node in the vector an offset in the trie stream, iterating + // until all uleb128 sizes have stabilized. + bool more; + do { + uint32_t offset = 0; + more = false; + for (TrieNode* node : allNodes) { + if (node->updateOffset(offset)) + more = true; + } + } while (more); + + // Serialize trie to ByteBuffer. + for (TrieNode* node : allNodes) { + node->appendToByteBuffer(_exportTrie); + } + _exportTrie.align(_is64 ? 8 : 4); +} + + void MachOFileLayout::computeSymbolTableSizes() { // MachO symbol tables have three ranges: locals, globals, and undefines const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist)); @@ -998,6 +1229,7 @@ void MachOFileLayout::writeLinkEditContent() { writeBindingInfo(); writeLazyBindingInfo(); // TODO: add weak binding info + writeExportInfo(); writeSymbolTable(); } } diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index cf0a9cf58d8..3bc05c32d1a 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -109,6 +109,7 @@ public: std::error_code addSymbols(const lld::File &atomFile, NormalizedFile &file); void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file); void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file); + void addExportInfo(const lld::File &, NormalizedFile &file); void addSectionRelocs(const lld::File &, NormalizedFile &file); void buildDataInCodeArray(const lld::File &, NormalizedFile &file); void addDependentDylibs(const lld::File &, NormalizedFile &file); @@ -1085,6 +1086,35 @@ void Util::addRebaseAndBindingInfo(const lld::File &atomFile, } } + +void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) { + if (_context.outputMachOType() == llvm::MachO::MH_OBJECT) + return; + + for (SectionInfo *sect : _sectionInfos) { + for (const AtomInfo &info : sect->atomsAndOffsets) { + const DefinedAtom *atom = info.atom; + if (atom->scope() != Atom::scopeGlobal) + continue; + if (_context.exportRestrictMode()) { + if (!_context.exportSymbolNamed(atom->name())) + continue; + } + Export exprt; + exprt.name = atom->name(); + exprt.offset = _atomToAddress[atom]; // FIXME: subtract base address + exprt.kind = EXPORT_SYMBOL_FLAGS_KIND_REGULAR; + if (atom->merge() == DefinedAtom::mergeAsWeak) + exprt.flags = EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; + else + exprt.flags = 0; + exprt.otherOffset = 0; + exprt.otherName = StringRef(); + nFile.exportInfo.push_back(exprt); + } + } +} + uint32_t Util::fileFlags() { // FIXME: these need to determined at runtime. if (_context.outputMachOType() == MH_OBJECT) { @@ -1128,6 +1158,7 @@ normalizedFromAtoms(const lld::File &atomFile, } util.addIndirectSymbols(atomFile, normFile); util.addRebaseAndBindingInfo(atomFile, normFile); + util.addExportInfo(atomFile, normFile); util.addSectionRelocs(atomFile, normFile); util.buildDataInCodeArray(atomFile, normFile); util.copyEntryPointAddress(normFile); diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index aa4249fc8cd..7fc6fa95a8f 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -235,7 +235,7 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section §ion, bool thumb = (symbolDescFlags & N_ARM_THUMB_DEF); if (atomType == DefinedAtom::typeUnknown) { // Mach-O needs a segment and section name. Concatentate those two - // with a / seperator (e.g. "seg/sect") to fit into the lld model + // with a / separator (e.g. "seg/sect") to fit into the lld model // of just a section name. std::string segSectName = section.segmentName.str() + "/" + section.sectionName.str(); @@ -676,10 +676,19 @@ normalizedDylibToAtoms(const NormalizedFile &normalizedFile, StringRef path, std::unique_ptr<MachODylibFile> file( new MachODylibFile(path, normalizedFile.installName)); // Tell MachODylibFile object about all symbols it exports. - for (auto &sym : normalizedFile.globalSymbols) { - assert((sym.scope & N_EXT) && "only expect external symbols here"); - bool weakDef = (sym.desc & N_WEAK_DEF); - file->addExportedSymbol(sym.name, weakDef, copyRefs); + if (!normalizedFile.exportInfo.empty()) { + // If exports trie exists, use it instead of traditional symbol table. + for (const Export &exp : normalizedFile.exportInfo) { + bool weakDef = (exp.flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); + // StringRefs from export iterator are ephemeral, so force copy. + file->addExportedSymbol(exp.name, weakDef, true); + } + } else { + for (auto &sym : normalizedFile.globalSymbols) { + assert((sym.scope & N_EXT) && "only expect external symbols here"); + bool weakDef = (sym.desc & N_WEAK_DEF); + file->addExportedSymbol(sym.name, weakDef, copyRefs); + } } // Tell MachODylibFile object about all dylibs it re-exports. for (const DependentDylib &dep : normalizedFile.dependentDylibs) { diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp index f83b860c69c..fcd843d4203 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp @@ -566,8 +566,10 @@ struct ScalarEnumerationTraits<ExportSymbolKind> { static void enumeration(IO &io, ExportSymbolKind &value) { io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_REGULAR", llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR); - io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCALl", + io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL", llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL); + io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE", + llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); } }; @@ -588,11 +590,12 @@ template <> struct MappingTraits<Export> { static void mapping(IO &io, Export &exp) { io.mapRequired("name", exp.name); - io.mapRequired("offset", exp.offset); + io.mapOptional("offset", exp.offset); io.mapOptional("kind", exp.kind, llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR); - io.mapOptional("flags", exp.flags); - io.mapOptional("other-offset", exp.otherOffset, Hex32(0)); + if (!io.outputting() || exp.flags) + io.mapOptional("flags", exp.flags); + io.mapOptional("other", exp.otherOffset, Hex32(0)); io.mapOptional("other-name", exp.otherName, StringRef()); } }; diff --git a/lld/test/mach-o/dylib-exports.yaml b/lld/test/mach-o/dylib-exports.yaml new file mode 100644 index 00000000000..0a00dfe1e95 --- /dev/null +++ b/lld/test/mach-o/dylib-exports.yaml @@ -0,0 +1,41 @@ +# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 -dylib \ +# RUN: %s %p/Inputs/libSystem.yaml -o %t && \ +# RUN: llvm-objdump -exports-trie %t | FileCheck %s +# +# +# Tests that exports trie builds properly. +# + +--- !mach-o +arch: x86_64 +file-type: MH_OBJECT +flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ] +sections: + - segment: __TEXT + section: __text + type: S_REGULAR + attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] + address: 0x0000000000000000 + content: [ 0xC3, 0xC3, 0xC3 ] +global-symbols: + - name: _myHidden + type: N_SECT + scope: [ N_EXT, N_PEXT ] + sect: 1 + value: 0x0000000000000000 + - name: _myRegular + type: N_SECT + scope: [ N_EXT ] + sect: 1 + value: 0x0000000000000001 + - name: _myWeak + type: N_SECT + scope: [ N_EXT ] + sect: 1 + desc: [ N_WEAK_DEF ] + value: 0x0000000000000002 +... + +# CHECK-NOT: _myHidden +# CHECK: _myRegular +# CHECK: _myWeak [weak_def] diff --git a/lld/test/mach-o/hello-world-armv6.yaml b/lld/test/mach-o/hello-world-armv6.yaml index f1d3803a3c8..c24d0897795 100644 --- a/lld/test/mach-o/hello-world-armv6.yaml +++ b/lld/test/mach-o/hello-world-armv6.yaml @@ -61,28 +61,10 @@ undefined-symbols: --- !mach-o arch: armv6 file-type: MH_DYLIB -flags: [ ] install-name: /usr/lib/libSystem.B.dylib -sections: - - segment: __TEXT - section: __text - type: S_REGULAR - attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] - address: 0x0000000000000000 - content: [ 0x55 ] - -global-symbols: +exports: - name: _printf - type: N_SECT - scope: [ N_EXT ] - sect: 1 - value: 0x0000000000000001 - name: dyld_stub_binder - type: N_SECT - scope: [ N_EXT ] - sect: 1 - value: 0x0000000000000001 - ... # CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main diff --git a/lld/test/mach-o/hello-world-armv7.yaml b/lld/test/mach-o/hello-world-armv7.yaml index b6e908c0fa1..54f737bda52 100644 --- a/lld/test/mach-o/hello-world-armv7.yaml +++ b/lld/test/mach-o/hello-world-armv7.yaml @@ -74,28 +74,10 @@ undefined-symbols: --- !mach-o arch: armv7 file-type: MH_DYLIB -flags: [ ] install-name: /usr/lib/libSystem.B.dylib -sections: - - segment: __TEXT - section: __text - type: S_REGULAR - attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] - address: 0x0000000000000000 - content: [ 0x55 ] - -global-symbols: +exports: - name: _printf - type: N_SECT - scope: [ N_EXT ] - sect: 1 - value: 0x0000000000000001 - name: dyld_stub_binder - type: N_SECT - scope: [ N_EXT ] - sect: 1 - value: 0x0000000000000001 - ... # CHECK: {{[0-9a-f]+}} (__TEXT,__text) external [Thumb] _main diff --git a/lld/test/mach-o/hello-world-x86.yaml b/lld/test/mach-o/hello-world-x86.yaml index ce25b9edede..d8f7b52d6ae 100644 --- a/lld/test/mach-o/hello-world-x86.yaml +++ b/lld/test/mach-o/hello-world-x86.yaml @@ -59,27 +59,10 @@ undefined-symbols: --- !mach-o arch: x86 file-type: MH_DYLIB -flags: [ ] install-name: /usr/lib/libSystem.B.dylib -sections: - - segment: __TEXT - section: __text - type: S_REGULAR - attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] - address: 0x0000000000000000 - content: [ 0x55 ] - -global-symbols: +exports: - name: _printf - type: N_SECT - scope: [ N_EXT ] - sect: 1 - value: 0x0000000000000001 - name: dyld_stub_binder - type: N_SECT - scope: [ N_EXT ] - sect: 1 - value: 0x0000000000000001 ... diff --git a/lld/test/mach-o/hello-world-x86_64.yaml b/lld/test/mach-o/hello-world-x86_64.yaml index 9cb7a1a97e2..985ab5f31cf 100644 --- a/lld/test/mach-o/hello-world-x86_64.yaml +++ b/lld/test/mach-o/hello-world-x86_64.yaml @@ -112,32 +112,11 @@ undefined-symbols: --- !mach-o arch: x86_64 file-type: MH_DYLIB -flags: [ ] install-name: /usr/lib/libSystem.B.dylib -sections: - - segment: __TEXT - section: __text - type: S_REGULAR - attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ] - address: 0x0000000000000000 - content: [ 0x55 ] - -global-symbols: +exports: - name: _fprintf - type: N_SECT - scope: [ N_EXT ] - sect: 1 - value: 0x0000000000000000 - name: dyld_stub_binder - type: N_SECT - scope: [ N_EXT ] - sect: 1 - value: 0x0000000000000000 - name: ___stdoutp - type: N_SECT - scope: [ N_EXT ] - sect: 1 - value: 0x0000000000000000 ... |