#include "ExportTrie.h"
#include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
#include "llvm/ADT/Optional.h"
#include "llvm/BinaryFormat/MachO.h"
node->writeTo(buf);
}
+namespace {
+
+// Parse a serialized trie and invoke a callback for each entry.
+class TrieParser {
+public:
+ TrieParser(const uint8_t *buf, size_t size, const TrieEntryCallback &callback)
+ : start(buf), end(start + size), callback(callback) {}
+
+ void parse(const uint8_t *buf, const Twine &cumulativeString);
+
+ void parse() { parse(start, ""); }
+
+ const uint8_t *start;
+ const uint8_t *end;
+ const TrieEntryCallback &callback;
+};
+
+} // namespace
+
+void TrieParser::parse(const uint8_t *buf, const Twine &cumulativeString) {
+ if (buf >= end)
+ fatal("Node offset points outside export section");
+
+ unsigned ulebSize;
+ uint64_t terminalSize = decodeULEB128(buf, &ulebSize);
+ buf += ulebSize;
+ uint64_t flags = 0;
+ size_t offset;
+ if (terminalSize != 0) {
+ flags = decodeULEB128(buf, &ulebSize);
+ callback(cumulativeString, flags);
+ }
+ buf += terminalSize;
+ uint8_t numEdges = *buf++;
+ for (uint8_t i = 0; i < numEdges; ++i) {
+ const char *cbuf = reinterpret_cast<const char *>(buf);
+ StringRef substring = StringRef(cbuf, strnlen(cbuf, end - buf));
+ buf += substring.size() + 1;
+ offset = decodeULEB128(buf, &ulebSize);
+ buf += ulebSize;
+ parse(start + offset, cumulativeString + substring);
+ }
+}
+
+void parseTrie(const uint8_t *buf, size_t size,
+ const TrieEntryCallback &callback) {
+ if (size == 0)
+ return;
+
+ TrieParser(buf, size, callback).parse();
+}
+
} // namespace macho
} // namespace lld
#define LLD_MACHO_EXPORT_TRIE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
#include <vector>
std::vector<TrieNode *> nodes;
};
+using TrieEntryCallback =
+ llvm::function_ref<void(const llvm::Twine & /*name*/, uint64_t /*flags*/)>;
+
+void parseTrie(const uint8_t *buf, size_t size, const TrieEntryCallback &);
+
} // namespace macho
} // namespace lld
//===----------------------------------------------------------------------===//
#include "InputFiles.h"
+#include "ExportTrie.h"
#include "InputSection.h"
#include "OutputSection.h"
#include "SymbolTable.h"
}
// Initialize symbols.
- if (const load_command *cmd = findCommand(hdr, LC_SYMTAB)) {
- auto *c = reinterpret_cast<const symtab_command *>(cmd);
- const char *strtab = reinterpret_cast<const char *>(buf + c->stroff);
- ArrayRef<const nlist_64> nList(
- reinterpret_cast<const nlist_64 *>(buf + c->symoff), c->nsyms);
-
- symbols.reserve(c->nsyms);
-
- for (const nlist_64 &sym : nList) {
- StringRef name = strtab + sym.n_strx;
- // TODO: Figure out what to do about undefined symbols: ignore or warn
- // if unsatisfied? Also make sure we handle re-exported symbols
- // correctly.
- symbols.push_back(symtab->addDylib(name, this));
- }
+ if (const load_command *cmd = findCommand(hdr, LC_DYLD_INFO_ONLY)) {
+ auto *c = reinterpret_cast<const dyld_info_command *>(cmd);
+ parseTrie(buf + c->export_off, c->export_size,
+ [&](const Twine &name, uint64_t flags) {
+ symbols.push_back(symtab->addDylib(saver.save(name), this));
+ });
+ } else {
+ error("LC_DYLD_INFO_ONLY not found in " + getName());
}
}
list(APPEND LLD_TEST_DEPS
FileCheck count llc llvm-ar llvm-as llvm-bcanalyzer llvm-config llvm-cvtres
llvm-dis llvm-dwarfdump llvm-lib llvm-lipo llvm-mc llvm-nm llvm-objcopy
- llvm-objdump llvm-pdbutil llvm-readelf llvm-readobj not obj2yaml opt
- yaml2obj
+ llvm-objdump llvm-pdbutil llvm-readelf llvm-readobj llvm-strip not obj2yaml
+ opt yaml2obj
)
endif()
# RUN: @executable_path/libhello.dylib %t/libhello.o -o %t/libhello.dylib
# RUN: lld -flavor darwinnew -dylib -install_name \
# RUN: @executable_path/libgoodbye.dylib %t/libgoodbye.o -o %t/libgoodbye.dylib
+
+## Make sure we are using the export trie and not the symbol table when linking
+## against these dylibs.
+# RUN: llvm-strip %t/libhello.dylib
+# RUN: llvm-strip %t/libgoodbye.dylib
+# RUN: llvm-nm %t/libhello.dylib 2>&1 | FileCheck %s --check-prefix=NOSYM
+# RUN: llvm-nm %t/libgoodbye.dylib 2>&1 | FileCheck %s --check-prefix=NOSYM
+# NOSYM: no symbols
+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/dylink.o
# RUN: lld -flavor darwinnew -o %t/dylink -Z -L%t -lhello -lgoodbye %t/dylink.o
# RUN: llvm-objdump --bind -d %t/dylink | FileCheck %s