[lld] r217066 - [mach-o] Add support for using export tries
Nick Kledzik
kledzik at apple.com
Wed Sep 3 12:52:51 PDT 2014
Author: kledzik
Date: Wed Sep 3 14:52:50 2014
New Revision: 217066
URL: http://llvm.org/viewvc/llvm-project?rev=217066&view=rev
Log:
[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.
Added:
lld/trunk/test/mach-o/dylib-exports.yaml
Modified:
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
lld/trunk/test/mach-o/hello-world-armv6.yaml
lld/trunk/test/mach-o/hello-world-armv7.yaml
lld/trunk/test/mach-o/hello-world-x86.yaml
lld/trunk/test/mach-o/hello-world-x86_64.yaml
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp?rev=217066&r1=217065&r2=217066&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp Wed Sep 3 14:52:50 2014
@@ -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>
// 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>
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>
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>
}
}
+ 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) {}
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp?rev=217066&r1=217065&r2=217066&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp Wed Sep 3 14:52:50 2014
@@ -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 N
_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 N
<< " 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::writeLo
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::writeLazyBindingIn
_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::writeLinkEditConte
writeBindingInfo();
writeLazyBindingInfo();
// TODO: add weak binding info
+ writeExportInfo();
writeSymbolTable();
}
}
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=217066&r1=217065&r2=217066&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Wed Sep 3 14:52:50 2014
@@ -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
}
}
+
+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 &ato
}
util.addIndirectSymbols(atomFile, normFile);
util.addRebaseAndBindingInfo(atomFile, normFile);
+ util.addExportInfo(atomFile, normFile);
util.addSectionRelocs(atomFile, normFile);
util.buildDataInCodeArray(atomFile, normFile);
util.copyEntryPointAddress(normFile);
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=217066&r1=217065&r2=217066&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Wed Sep 3 14:52:50 2014
@@ -235,7 +235,7 @@ void atomFromSymbol(DefinedAtom::Content
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 NormalizedF
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) {
Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp?rev=217066&r1=217065&r2=217066&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp Wed Sep 3 14:52:50 2014
@@ -566,8 +566,10 @@ struct ScalarEnumerationTraits<ExportSym
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());
}
};
Added: lld/trunk/test/mach-o/dylib-exports.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/dylib-exports.yaml?rev=217066&view=auto
==============================================================================
--- lld/trunk/test/mach-o/dylib-exports.yaml (added)
+++ lld/trunk/test/mach-o/dylib-exports.yaml Wed Sep 3 14:52:50 2014
@@ -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]
Modified: lld/trunk/test/mach-o/hello-world-armv6.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/hello-world-armv6.yaml?rev=217066&r1=217065&r2=217066&view=diff
==============================================================================
--- lld/trunk/test/mach-o/hello-world-armv6.yaml (original)
+++ lld/trunk/test/mach-o/hello-world-armv6.yaml Wed Sep 3 14:52:50 2014
@@ -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
Modified: lld/trunk/test/mach-o/hello-world-armv7.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/hello-world-armv7.yaml?rev=217066&r1=217065&r2=217066&view=diff
==============================================================================
--- lld/trunk/test/mach-o/hello-world-armv7.yaml (original)
+++ lld/trunk/test/mach-o/hello-world-armv7.yaml Wed Sep 3 14:52:50 2014
@@ -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
Modified: lld/trunk/test/mach-o/hello-world-x86.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/hello-world-x86.yaml?rev=217066&r1=217065&r2=217066&view=diff
==============================================================================
--- lld/trunk/test/mach-o/hello-world-x86.yaml (original)
+++ lld/trunk/test/mach-o/hello-world-x86.yaml Wed Sep 3 14:52:50 2014
@@ -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
...
Modified: lld/trunk/test/mach-o/hello-world-x86_64.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/hello-world-x86_64.yaml?rev=217066&r1=217065&r2=217066&view=diff
==============================================================================
--- lld/trunk/test/mach-o/hello-world-x86_64.yaml (original)
+++ lld/trunk/test/mach-o/hello-world-x86_64.yaml Wed Sep 3 14:52:50 2014
@@ -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
...
More information about the llvm-commits
mailing list