[lld-macho] Use export trie instead of symtab when linking against dylibs
Summary: This allows us to link against stripped dylibs. Moreover, it's simply more correct: The symbol table includes symbols that the dylib uses but doesn't export. This temporarily regresses our ability to do lazy symbol binding because dyld_stub_binder isn't in libSystem's export trie. Rather, it is in one of the sub-libraries libSystem re-exports. (This doesn't affect our tests since we are mocking out dyld_stub_binder there.) A follow-up diff will address this by adding support for sub-libraries. Depends on D79114. Reviewers: ruiu, pcc, MaskRay, smeenai, alexshap, gkm, Ktwu, christylee Subscribers: mgorny, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D79226
This commit is contained in:
parent
5d3feefa0d
commit
7bbdbacd00
|
@ -37,6 +37,7 @@
|
|||
#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"
|
||||
|
@ -232,5 +233,57 @@ void TrieBuilder::writeTo(uint8_t *buf) const {
|
|||
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
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define LLD_MACHO_EXPORT_TRIE_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -35,6 +36,11 @@ private:
|
|||
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
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InputFiles.h"
|
||||
#include "ExportTrie.h"
|
||||
#include "InputSection.h"
|
||||
#include "OutputSection.h"
|
||||
#include "SymbolTable.h"
|
||||
|
@ -245,21 +246,14 @@ DylibFile::DylibFile(MemoryBufferRef mb) : InputFile(DylibKind, mb) {
|
|||
}
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ if (NOT LLD_BUILT_STANDALONE)
|
|||
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()
|
||||
|
||||
|
|
|
@ -8,6 +8,15 @@
|
|||
# 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
|
||||
|
|
Loading…
Reference in New Issue